feat: UI fixes + boocontext remainders — Memory project selector, agent event toasts, codecontext→boocontext left-overs

Fixes 3 remaining UI items from the component-wiring audit:
  - Memory page: project selector dropdown (Item 1)
  - Agent events: collision_warning + agent_message toasts via sonner (Item 2)
  - Reasoning delta already wired and working (Item 3)

Also picks up uncommitted boocontext rename changes from the subagent batch:
  - synthesisPipeline.ts tier tool names updated
  - tiers.ts STANDARD_TOOL_NAMES clears old codecontext tools
  - tool-utils.ts BUILT_IN_TOOLS updated
  - .env.example / README.md reference boocontext MCP
  - ROADMAP.md boocontext entry
  - codecontext/ dir + docs/codecontext-ts-plan.md removed (already gone from tree)
This commit is contained in:
2026-06-08 04:35:56 +00:00
parent fc281f5b78
commit 0ed506f1da
18 changed files with 54 additions and 1456 deletions

View File

@@ -32,10 +32,9 @@ import type { OpenAiMessage } from './inference/payload.js';
import type { InferenceContext, TurnArgs } from './inference/types.js';
export const SYNTHESIS_TOOLS: ReadonlySet<string> = new Set([
'get_codebase_overview',
'get_framework_analysis',
'get_semantic_neighborhoods',
'get_blast_radius',
'boocontext_boocontext_overview',
'boocontext_boocontext_symbols',
'boocontext_codesight_get_blast_radius',
]);
const TOP_N_FILES = 5;
@@ -103,11 +102,11 @@ export async function runSynthesisPass(p: SynthesisParams): Promise<boolean> {
}
// v1.13.15-b: when the tool result was inline-truncated by the wrapper
// (32k cap, see codecontext_client.ts:114), expand the full content from
// tmpfs for reference-file extraction. The synth payload still ships the
// truncated head (see buildPayload call below) so the token-budget
// contract holds. Graceful degradation: if readTruncation returns null
// (missing id, ENOENT) or throws, fall back to the truncated head.
// (32k cap), expand the full content from tmpfs for reference-file
// extraction. The synth payload still ships the truncated head (see
// buildPayload call below) so the token-budget contract holds. Graceful
// degradation: if readTruncation returns null (missing id, ENOENT) or
// throws, fall back to the truncated head.
let extractionSource = p.toolResultText;
if (p.truncated && p.outputPath) {
try {

View File

@@ -7,6 +7,11 @@ import { ALL_TOOLS, TOOLS_BY_NAME } from './registry.js';
// schemas in the system prompt). Pattern lift from eyaltoledano/claude-task-
// master (MIT + Commons Clause — pattern only, no code lift).
//
// v2.8.25: removed the 8 old codecontext tool names from STANDARD_TOOL_NAMES.
// The Go codecontext sidecar has been fully removed; boocontext MCP tools are
// appended at startup via appendMcpTools() and are NOT available at import
// time, so STANDARD_TOOL_NAMES only includes core tools + web/web/git.
//
// The env var is a CEILING. It only narrows; never expands an agent's
// declared whitelist. Default behavior (var unset) is unchanged: all tools.
export const CORE_TOOL_NAMES = [
@@ -21,14 +26,6 @@ export const STANDARD_TOOL_NAMES = [
'web_search',
'web_fetch',
'git_status',
'get_codebase_overview',
'get_file_analysis',
'get_symbol_info',
'search_symbols',
'get_dependencies',
'watch_changes',
'get_semantic_neighborhoods',
'get_framework_analysis',
] as const;
// Module-load validation: every name in CORE / STANDARD must exist in

View File

@@ -11,8 +11,10 @@ import { Analytics } from '@/pages/Analytics';
import { Results } from '@/pages/Results';
import { Memory } from '@/pages/Memory';
import { Toaster } from '@/components/ui/sonner';
import { toast } from 'sonner';
import { useUserEvents } from '@/hooks/useUserEvents';
import { useCoderUserEvents } from '@/hooks/useCoderUserEvents';
import { sessionEvents } from '@/hooks/sessionEvents';
import { useTheme } from '@/lib/theme';
import { SidebarDrawerProvider, useSidebarDrawer } from '@/hooks/useSidebarDrawer';
import { RightRailDrawerProvider, useRightRailDrawer } from '@/hooks/useRightRailDrawer';
@@ -77,6 +79,24 @@ function AppShell() {
useTheme();
useUserEvents();
useCoderUserEvents();
useEffect(() => {
const unsub = sessionEvents.subscribe((event) => {
if (event.type === 'collision_warning') {
toast.warning(`Multiple agents editing ${event.file_path}`, {
description: `Agents: ${event.agents.join(', ')}`,
});
} else if (event.type === 'agent_message') {
const truncated =
event.content.length > 80
? event.content.slice(0, 80) + '…'
: event.content;
toast.info(`Message from ${event.from_agent}`, {
description: truncated,
});
}
});
return unsub;
}, []);
const [showShortcuts, setShowShortcuts] = useState(false);
useEffect(() => {
const handler = (e: KeyboardEvent) => {

View File

@@ -7,14 +7,6 @@ export const BUILT_IN_TOOLS = new Set([
'find_files',
'git_status',
'skill_use',
'get_codebase_overview',
'get_file_analysis',
'get_symbol_info',
'search_symbols',
'get_dependencies',
'watch_changes',
'get_semantic_neighborhoods',
'get_framework_analysis',
]);
/**

View File

@@ -405,7 +405,19 @@ export function Memory() {
Topic-based memories, daily logs, and dream consolidation diaries.
</p>
</div>
</div>
</div>
{/* Project selector */}
<select
value={projectId ?? ''}
onChange={(e) => setProjectId(e.target.value)}
className="w-full rounded-md border border-input bg-background px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-ring"
>
{projects.map((p) => (
<option key={p.id} value={p.id}>
{p.name}
</option>
))}
</select>
</header>
{/* Tab bar */}