fix(tui): enable tool access in fullscreen mode via NativeAgent
Fullscreen TUI was calling modelClient directly, bypassing the NativeAgent tool loop entirely. Pass the agent through FullscreenTuiConfig → App and use agent.process() for message handling, which enables the full tool registry and executor.
This commit is contained in:
@@ -216,6 +216,7 @@ export function registerTuiCommand(program: Command): void {
|
|||||||
modelRouter,
|
modelRouter,
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
model: config.models.default.model,
|
model: config.models.default.model,
|
||||||
|
agent,
|
||||||
onExit: cleanup,
|
onExit: cleanup,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
@@ -259,6 +260,7 @@ export function registerTuiCommand(program: Command): void {
|
|||||||
modelRouter,
|
modelRouter,
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
model: config.models.default.model,
|
model: config.models.default.model,
|
||||||
|
agent,
|
||||||
onExit: cleanup,
|
onExit: cleanup,
|
||||||
});
|
});
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import { parseCommand, getHelpText, resolveModelAlias, getCommandCompletions } f
|
|||||||
import type { Message, ModelClient, TokenUsage } from '../../../models/types.js';
|
import type { Message, ModelClient, TokenUsage } from '../../../models/types.js';
|
||||||
import type { ModelRouter } from '../../../models/router.js';
|
import type { ModelRouter } from '../../../models/router.js';
|
||||||
import type { ManagedSession } from '../../../session/index.js';
|
import type { ManagedSession } from '../../../session/index.js';
|
||||||
|
import type { NativeAgent } from '../../../backends/native/agent.js';
|
||||||
|
|
||||||
export interface AppProps {
|
export interface AppProps {
|
||||||
session: ManagedSession;
|
session: ManagedSession;
|
||||||
@@ -14,6 +15,7 @@ export interface AppProps {
|
|||||||
modelRouter?: ModelRouter;
|
modelRouter?: ModelRouter;
|
||||||
systemPrompt: string;
|
systemPrompt: string;
|
||||||
model: string;
|
model: string;
|
||||||
|
agent?: NativeAgent;
|
||||||
onExit?: () => void;
|
onExit?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,6 +25,7 @@ export function App({
|
|||||||
modelRouter,
|
modelRouter,
|
||||||
systemPrompt,
|
systemPrompt,
|
||||||
model,
|
model,
|
||||||
|
agent,
|
||||||
onExit,
|
onExit,
|
||||||
}: AppProps): React.ReactElement {
|
}: AppProps): React.ReactElement {
|
||||||
const { exit } = useApp();
|
const { exit } = useApp();
|
||||||
@@ -156,19 +159,33 @@ export function App({
|
|||||||
|
|
||||||
if (command.type !== 'message' || isStreaming) return;
|
if (command.type !== 'message' || isStreaming) return;
|
||||||
|
|
||||||
// Add user message
|
// Add user message to UI (and session if no agent — agent adds it internally)
|
||||||
const userMessage: Message = { role: 'user', content: command.content };
|
const userMessage: Message = { role: 'user', content: command.content };
|
||||||
|
if (!agent) {
|
||||||
const messageWithTimestamp = session.addMessage(userMessage);
|
const messageWithTimestamp = session.addMessage(userMessage);
|
||||||
setMessages(prev => [...prev, messageWithTimestamp]);
|
setMessages(prev => [...prev, messageWithTimestamp]);
|
||||||
|
} else {
|
||||||
|
setMessages(prev => [...prev, { ...userMessage, timestamp: Date.now() }]);
|
||||||
|
}
|
||||||
setScrollOffset(0); // Auto-scroll to bottom
|
setScrollOffset(0); // Auto-scroll to bottom
|
||||||
|
|
||||||
// Stream response
|
// Process response
|
||||||
setIsStreaming(true);
|
setIsStreaming(true);
|
||||||
setStreamingContent('');
|
setStreamingContent('');
|
||||||
abortRef.current = false;
|
abortRef.current = false;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (modelClient.chatStream) {
|
if (agent) {
|
||||||
|
// agent.process() handles session history internally
|
||||||
|
const response = await agent.process(command.content);
|
||||||
|
|
||||||
|
const usage = agent.getUsage();
|
||||||
|
setTokenUsage({ inputTokens: usage.inputTokens, outputTokens: usage.outputTokens });
|
||||||
|
|
||||||
|
// Sync UI with session history (agent already added messages to session)
|
||||||
|
setMessages(session.getHistory());
|
||||||
|
} else if (modelClient.chatStream) {
|
||||||
|
// Fallback: direct streaming without tools
|
||||||
let fullContent = '';
|
let fullContent = '';
|
||||||
|
|
||||||
for await (const event of modelClient.chatStream({
|
for await (const event of modelClient.chatStream({
|
||||||
@@ -199,7 +216,7 @@ export function App({
|
|||||||
const assistantWithTimestamp = session.addMessage(assistantMessage);
|
const assistantWithTimestamp = session.addMessage(assistantMessage);
|
||||||
setMessages(prev => [...prev, assistantWithTimestamp]);
|
setMessages(prev => [...prev, assistantWithTimestamp]);
|
||||||
} else {
|
} else {
|
||||||
// Fallback to non-streaming
|
// Fallback: non-streaming without tools
|
||||||
const response = await modelClient.chat({
|
const response = await modelClient.chat({
|
||||||
messages: session.getHistory(),
|
messages: session.getHistory(),
|
||||||
system: systemPrompt,
|
system: systemPrompt,
|
||||||
@@ -225,7 +242,7 @@ export function App({
|
|||||||
setIsStreaming(false);
|
setIsStreaming(false);
|
||||||
setStreamingContent('');
|
setStreamingContent('');
|
||||||
}
|
}
|
||||||
}, [isStreaming, session, modelClient, modelRouter, systemPrompt, exit, onExit, messages.length, tokenUsage]);
|
}, [isStreaming, session, agent, modelClient, modelRouter, systemPrompt, exit, onExit, messages.length, tokenUsage]);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box flexDirection="column" height="100%">
|
<Box flexDirection="column" height="100%">
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { App } from './components/index.js';
|
|||||||
import type { ManagedSession } from '../../session/index.js';
|
import type { ManagedSession } from '../../session/index.js';
|
||||||
import type { ModelClient } from '../../models/types.js';
|
import type { ModelClient } from '../../models/types.js';
|
||||||
import type { ModelRouter } from '../../models/router.js';
|
import type { ModelRouter } from '../../models/router.js';
|
||||||
|
import type { NativeAgent } from '../../backends/native/agent.js';
|
||||||
|
|
||||||
export interface FullscreenTuiConfig {
|
export interface FullscreenTuiConfig {
|
||||||
session: ManagedSession;
|
session: ManagedSession;
|
||||||
@@ -11,6 +12,7 @@ export interface FullscreenTuiConfig {
|
|||||||
modelRouter?: ModelRouter;
|
modelRouter?: ModelRouter;
|
||||||
systemPrompt: string;
|
systemPrompt: string;
|
||||||
model: string;
|
model: string;
|
||||||
|
agent?: NativeAgent;
|
||||||
onExit?: () => void;
|
onExit?: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -27,6 +29,7 @@ export async function startFullscreenTui(config: FullscreenTuiConfig): Promise<v
|
|||||||
modelRouter: config.modelRouter,
|
modelRouter: config.modelRouter,
|
||||||
systemPrompt: config.systemPrompt,
|
systemPrompt: config.systemPrompt,
|
||||||
model: config.model,
|
model: config.model,
|
||||||
|
agent: config.agent,
|
||||||
onExit: config.onExit,
|
onExit: config.onExit,
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user