Add debug log panel, centered modals, and fix multiple UX issues
Features:
- Add /logs command to toggle debug log panel (20% width on right)
- Debug panel shows API calls, streaming events, tool calls, state changes
- Add /help submenus with detailed command explanations
- Center all modal dialogs in the terminal window
Bug Fixes:
- Fix streaming content not displaying (add fallback when streaming fails)
- Fix permission modal shortcut key mismatch ('a' → 'l' for local scope)
- Fix agent prompt accumulation when switching agents multiple times
- Fix permission modal using brittle index for "No" option
Improvements:
- Restrict git commands (add, commit, push, etc.) unless user explicitly requests
- Unify permission options across all UI components
- Add Ollama model selection when switching to Ollama provider
- Store base system prompt to prevent agent prompt stacking
New files:
- src/tui-solid/components/debug-log-panel.tsx
- src/tui-solid/components/centered-modal.tsx
- src/tui-solid/components/help-menu.tsx
- src/tui-solid/components/help-detail.tsx
- src/constants/help-content.ts
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { saveSession } from "@services/session";
|
||||
import { showHelp } from "@commands/components/chat/commands/show-help";
|
||||
import { clearConversation } from "@commands/components/chat/history/clear-conversation";
|
||||
import { appStore } from "@tui/index";
|
||||
import { showContextFiles } from "@commands/components/chat/context/show-context-files";
|
||||
import { removeFile } from "@commands/components/chat/context/remove-file";
|
||||
import { showContext } from "@commands/components/chat/history/show-context";
|
||||
@@ -24,8 +24,8 @@ const COMMAND_REGISTRY: Map<string, CommandHandler> = new Map<
|
||||
string,
|
||||
CommandHandler
|
||||
>([
|
||||
["help", () => showHelp()],
|
||||
["h", () => showHelp()],
|
||||
["help", () => appStore.setMode("help_menu")],
|
||||
["h", () => appStore.setMode("help_menu")],
|
||||
["clear", (ctx: CommandContext) => clearConversation(ctx.state)],
|
||||
["c", (ctx: CommandContext) => clearConversation(ctx.state)],
|
||||
["files", (ctx: CommandContext) => showContextFiles(ctx.state.contextFiles)],
|
||||
@@ -106,6 +106,17 @@ const COMMAND_REGISTRY: Map<string, CommandHandler> = new Map<
|
||||
},
|
||||
],
|
||||
["mcp", async (ctx: CommandContext) => handleMCP(ctx.args)],
|
||||
[
|
||||
"logs",
|
||||
() => {
|
||||
appStore.toggleDebugLog();
|
||||
const { debugLogVisible } = appStore.getState();
|
||||
appStore.addLog({
|
||||
type: "system",
|
||||
content: `Debug logs panel ${debugLogVisible ? "enabled" : "disabled"}`,
|
||||
});
|
||||
},
|
||||
],
|
||||
]);
|
||||
|
||||
export default COMMAND_REGISTRY;
|
||||
|
||||
@@ -26,6 +26,7 @@ import { agentLoader } from "@services/agent-loader";
|
||||
|
||||
interface ExecuteContext {
|
||||
state: ChatServiceState | null;
|
||||
baseSystemPrompt: string | null;
|
||||
}
|
||||
|
||||
const createHandleExit = (): (() => void) => (): void => {
|
||||
@@ -51,16 +52,22 @@ const createHandleAgentSelect =
|
||||
(ctx.state as ChatServiceState & { currentAgent?: string }).currentAgent =
|
||||
agentId;
|
||||
|
||||
if (agent.prompt) {
|
||||
const basePrompt = ctx.state.systemPrompt;
|
||||
ctx.state.systemPrompt = `${agent.prompt}\n\n${basePrompt}`;
|
||||
// Use the stored base prompt to avoid accumulation when switching agents
|
||||
const basePrompt = ctx.baseSystemPrompt ?? ctx.state.systemPrompt;
|
||||
|
||||
if (
|
||||
ctx.state.messages.length > 0 &&
|
||||
ctx.state.messages[0].role === "system"
|
||||
) {
|
||||
ctx.state.messages[0].content = ctx.state.systemPrompt;
|
||||
}
|
||||
if (agent.prompt) {
|
||||
ctx.state.systemPrompt = `${agent.prompt}\n\n${basePrompt}`;
|
||||
} else {
|
||||
// Reset to base prompt if agent has no custom prompt
|
||||
ctx.state.systemPrompt = basePrompt;
|
||||
}
|
||||
|
||||
// Update the system message in the conversation
|
||||
if (
|
||||
ctx.state.messages.length > 0 &&
|
||||
ctx.state.messages[0].role === "system"
|
||||
) {
|
||||
ctx.state.messages[0].content = ctx.state.systemPrompt;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -81,6 +88,15 @@ const createHandleProviderSelect =
|
||||
const config = await getConfig();
|
||||
config.set("provider", providerId as "copilot" | "ollama");
|
||||
await config.save();
|
||||
|
||||
// Load models for the new provider and update the store
|
||||
const models = await loadModels(providerId as "copilot" | "ollama");
|
||||
appStore.setAvailableModels(models);
|
||||
|
||||
// If Ollama is selected and has models, open model selector
|
||||
if (providerId === "ollama" && models.length > 0) {
|
||||
appStore.setMode("model_select");
|
||||
}
|
||||
};
|
||||
|
||||
const createHandleCascadeToggle =
|
||||
@@ -131,10 +147,13 @@ const createHandleSubmit =
|
||||
const execute = async (options: ChatTUIOptions): Promise<void> => {
|
||||
const ctx: ExecuteContext = {
|
||||
state: null,
|
||||
baseSystemPrompt: null,
|
||||
};
|
||||
|
||||
const { state, session } = await initializeChatService(options);
|
||||
ctx.state = state;
|
||||
// Store the original system prompt before any agent modifications
|
||||
ctx.baseSystemPrompt = state.systemPrompt;
|
||||
|
||||
if (options.printMode && options.initialPrompt) {
|
||||
await executePrintMode(state, options.initialPrompt);
|
||||
|
||||
Reference in New Issue
Block a user