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

@@ -1,6 +1,7 @@
import { tui, appStore } from "@tui/index";
import { getProviderInfo } from "@services/chat-tui-service";
import { addServer, connectServer } from "@services/mcp/index";
import * as brainService from "@services/brain";
import type { ChatServiceState } from "@services/chat-tui-service";
import type { AgentConfig } from "@/types/agent-config";
import type { PermissionScope, LearningScope } from "@/types/tui";
@@ -32,6 +33,9 @@ export interface RenderAppProps {
scope?: LearningScope,
editedContent?: string,
) => void;
handleBrainSetJwtToken?: (jwtToken: string) => Promise<void>;
handleBrainSetApiKey?: (apiKey: string) => Promise<void>;
handleBrainLogout?: () => Promise<void>;
handleExit: () => void;
showBanner: boolean;
state: ChatServiceState;
@@ -65,6 +69,42 @@ const defaultHandleMCPAdd = async (data: MCPAddFormData): Promise<void> => {
await connectServer(data.name);
};
const defaultHandleBrainSetJwtToken = async (jwtToken: string): Promise<void> => {
await brainService.setJwtToken(jwtToken);
const connected = await brainService.connect();
if (connected) {
const state = brainService.getState();
appStore.setBrainStatus("connected");
appStore.setBrainUser(state.user);
appStore.setBrainCounts(state.knowledgeCount, state.memoryCount);
appStore.setBrainShowBanner(false);
} else {
throw new Error("Failed to connect with the provided JWT token.");
}
};
const defaultHandleBrainSetApiKey = async (apiKey: string): Promise<void> => {
await brainService.setApiKey(apiKey);
const connected = await brainService.connect();
if (connected) {
const state = brainService.getState();
appStore.setBrainStatus("connected");
appStore.setBrainUser(state.user);
appStore.setBrainCounts(state.knowledgeCount, state.memoryCount);
appStore.setBrainShowBanner(false);
} else {
throw new Error("Failed to connect with the provided API key.");
}
};
const defaultHandleBrainLogout = async (): Promise<void> => {
await brainService.logout();
appStore.setBrainStatus("disconnected");
appStore.setBrainUser(null);
appStore.setBrainCounts(0, 0);
appStore.setBrainShowBanner(true);
};
export const renderApp = async (props: RenderAppProps): Promise<void> => {
const { displayName, model: defaultModel } = getProviderInfo(
props.state.provider,
@@ -95,6 +135,9 @@ export const renderApp = async (props: RenderAppProps): Promise<void> => {
onMCPAdd: props.handleMCPAdd ?? defaultHandleMCPAdd,
onPermissionResponse: props.handlePermissionResponse ?? (() => {}),
onLearningResponse: props.handleLearningResponse ?? (() => {}),
onBrainSetJwtToken: props.handleBrainSetJwtToken ?? defaultHandleBrainSetJwtToken,
onBrainSetApiKey: props.handleBrainSetApiKey ?? defaultHandleBrainSetApiKey,
onBrainLogout: props.handleBrainLogout ?? defaultHandleBrainLogout,
plan: props.plan,
});