Implement Phase 4: tools, God Mode, and missing features

Backend:
- Add Tavily web search tool wrapper (tools/web_search.py)
- Add PDF reader + ChromaDB vector store tool (tools/pdf_reader.py)
- Bind tools to LLM calls via .bind_tools() in dynamic_graph_builder
- Implement God Mode using LangGraph interrupt_before + MemorySaver
- Add approve/reject/modify API endpoints for God Mode
- Add PDF upload endpoint with ingestion pipeline
- Add persistent run history (CouncilRun model + run_service + API)
- Add Alembic migration for council_runs table
- Enhance WebSocket to emit run_paused and run_resumed events
- Add tests for tools, God Mode, and run history

Frontend:
- Add God Mode approval UI (GodModePanel component)
- Add Auto-Pilot / God Mode toggle in Konferenzzimmer
- Add functional PDF upload handler
- Add Conditional Edge editor (EdgeSettingsPanel component)
- Add edge click selection in ArchitectCanvas
- Update Zustand store with edge selection and update actions
- Update types for God Mode, execution modes, and WS events
- Update API client with God Mode, PDF upload, and blueprint run endpoints
- Update WebSocket hook for paused/resumed events
- Add Vitest config and frontend tests (store, parser, types, API)

https://claude.ai/code/session_017U6idFgaqnYTXzPxA7mxMv
This commit is contained in:
Claude 2026-02-21 10:53:12 +00:00
parent c6d0c4a636
commit 001649a364
No known key found for this signature in database
31 changed files with 2502 additions and 81 deletions

View file

@ -5,14 +5,29 @@ import { WSMessage } from "@/app/types/council";
import { wsUrl } from "@/app/utils/api-client";
import { useCouncilStore } from "@/app/store/council-store";
export interface PauseInfo {
next_nodes: string[];
current_draft: string;
critic_score?: number;
iteration_count?: number;
}
interface Options {
run_id: string | null;
onComplete?: (result: string) => void;
onError?: (error: string) => void;
onPaused?: (info: PauseInfo) => void;
onResumed?: () => void;
}
// WebSocket hook for live agent status updates during a council run
export function useCouncilWebSocket({ run_id, onComplete, onError }: Options) {
export function useCouncilWebSocket({
run_id,
onComplete,
onError,
onPaused,
onResumed,
}: Options) {
const ws = useRef<WebSocket | null>(null);
const markNodeActive = useCouncilStore((s) => s.markNodeActive);
const clearActiveNode = useCouncilStore((s) => s.clearActiveNode);
@ -40,20 +55,29 @@ export function useCouncilWebSocket({ run_id, onComplete, onError }: Options) {
return;
}
switch (msg.type) {
case "node_enter":
if (msg.node_name) markNodeActive(msg.node_name);
switch (msg.event) {
case "node_active":
if (msg.node) markNodeActive(msg.node);
break;
case "node_exit":
case "run_paused":
clearActiveNode();
onPaused?.({
next_nodes: msg.next_nodes ?? [],
current_draft: msg.current_draft ?? "",
critic_score: msg.critic_score,
iteration_count: msg.iteration_count,
});
break;
case "run_resumed":
onResumed?.();
break;
case "run_complete":
clearActiveNode();
setActiveRun(null);
if (msg.result) onComplete?.(msg.result);
if (msg.final_draft) onComplete?.(msg.final_draft);
disconnect();
break;
case "run_error":
case "run_failed":
clearActiveNode();
setActiveRun(null);
if (msg.error) onError?.(msg.error);