Add BRAIN_DISABLED flag and fix Ollama tool call formatting

Features:
  - Add BRAIN_DISABLED feature flag to hide all Brain functionality
  - When enabled, hides Brain banner, status indicator, menu, and commands
  - Flag location: src/constants/brain.ts

  Fixes:
  - Fix Ollama 400 error by properly formatting tool_calls in messages
  - Update OllamaMessage type to include tool_calls field
  - Fix Brain menu keyboard not working (add missing modes to isMenuOpen)

  UI Changes:
  - Remove "^Tab toggle mode" hint from status bar
  - Remove "ctrl+t to hide todos" hint from status bar

  Files modified:
  - src/constants/brain.ts (add BRAIN_DISABLED flag)
  - src/types/ollama.ts (add tool_calls to OllamaMessage)
  - src/providers/ollama/chat.ts (format tool_calls in messages)
  - src/tui-solid/components/header.tsx (hide Brain UI when disabled)
  - src/tui-solid/components/status-bar.tsx (remove hints)
  - src/tui-solid/components/command-menu.tsx (filter brain command)
  - src/tui-solid/components/input-area.tsx (fix isMenuOpen modes)
  - src/tui-solid/routes/session.tsx (skip brain menu when disabled)
  - src/services/brain.ts (early return when disabled)
  - src/services/chat-tui/initialize.ts (skip brain init when disabled)
This commit is contained in:
2026-02-02 13:25:38 -05:00
parent 2eadda584a
commit c839fc4d68
114 changed files with 17243 additions and 273 deletions

View File

@@ -19,6 +19,8 @@ import {
buildCompletePrompt,
} from "@services/prompt-builder";
import { initSuggestionService } from "@services/command-suggestion-service";
import * as brainService from "@services/brain";
import { BRAIN_DISABLED } from "@constants/brain";
import { addContextFile } from "@services/chat-tui/files";
import type { ProviderName, Message } from "@/types/providers";
import type { ChatSession } from "@/types/index";
@@ -147,6 +149,39 @@ const initializeTheme = async (): Promise<void> => {
}
};
/**
* Initialize brain service and update store state
* Skipped when BRAIN_DISABLED flag is true
*/
const initializeBrain = async (): Promise<void> => {
// Skip brain initialization when disabled
if (BRAIN_DISABLED) {
appStore.setBrainStatus("disconnected");
appStore.setBrainShowBanner(false);
return;
}
try {
appStore.setBrainStatus("connecting");
const connected = await brainService.initialize();
if (connected) {
const state = brainService.getState();
appStore.setBrainStatus("connected");
appStore.setBrainUser(state.user);
appStore.setBrainCounts(state.knowledgeCount, state.memoryCount);
appStore.setBrainShowBanner(false);
} else {
appStore.setBrainStatus("disconnected");
appStore.setBrainShowBanner(true);
}
} catch {
appStore.setBrainStatus("disconnected");
appStore.setBrainShowBanner(true);
}
};
/**
* Rebuild system prompt when interaction mode changes
* Updates both the state and the first message in the conversation
@@ -178,9 +213,13 @@ export const initializeChatService = async (
const initialMode = appStore.getState().interactionMode;
const state = await createInitialState(options, initialMode);
await validateProvider(state);
await buildSystemPrompt(state, options);
await initializeTheme();
// Run provider validation and system prompt building in parallel
// These are independent and both involve async operations
await Promise.all([
validateProvider(state),
buildSystemPrompt(state, options),
initializeTheme(),
]);
const session = await initializeSession(state, options);
@@ -188,9 +227,18 @@ export const initializeChatService = async (
state.messages.push({ role: "system", content: state.systemPrompt });
}
await addInitialContextFiles(state, options.files);
await initializePermissions();
// Run these in parallel - they're independent
await Promise.all([
addInitialContextFiles(state, options.files),
initializePermissions(),
]);
initSuggestionService(process.cwd());
// Initialize brain service (non-blocking, errors silently handled)
initializeBrain().catch(() => {
// Silently fail - brain is optional
});
return { state, session };
};

View File

@@ -366,7 +366,7 @@ export const handleMessage = async (
const modeLabel = interactionMode === "ask" ? "Ask" : "Code Review";
callbacks.onLog(
"system",
`${modeLabel} mode: Read-only tools only (Ctrl+Tab to switch modes)`,
`${modeLabel} mode: Read-only tools only (Ctrl+M to switch modes)`,
);
}