- Complete architectural overhaul of useUnifiedCompletion hook - Unified state management: 8 separate states → single CompletionState interface - Simplified core logic: getWordAtCursor 194 lines → 42 lines (78% reduction) - Fixed infinite React update loops with ref-based input tracking - Smart triggering mechanism replacing aggressive auto-completion - Integrated @agent and @file mention system with system reminders - Added comprehensive agent loading and mention processing - Enhanced Tab/Arrow/Enter key handling with clean event management - Maintained 100% functional compatibility across all completion types Key improvements: • File path completion (relative, absolute, ~expansion, @references) • Slash command completion (/help, /model, etc.) • Agent completion (@agent-xxx with intelligent descriptions) • System command completion (PATH scanning with fallback) • Terminal-style Tab cycling, Enter confirmation, Escape cancellation • Preview mode with boundary calculation • History navigation compatibility • Empty directory handling with user feedback Architecture: Event-driven @mention detection → system reminder injection → LLM tool usage Performance: Eliminated 7-layer nested conditionals, reduced state synchronization issues Reliability: Fixed maximum update depth exceeded warnings, stable state management
2.7 KiB
2.7 KiB
Architecture Analysis - Agent Loop Breaking Issue
Root Cause Identified
1. Tool Call Format Issue
The AI is returning <function=ReadFile> instead of the correct Anthropic tool call format. This indicates the model is not receiving proper tool schemas.
2. Key Breaking Changes
Tool Description Async Issue
// Original (working)
description: string // Simple sync property
// Current (broken)
description?: () => Promise<string> // Async function
While both codebases have async description, the schema generation in claude.ts may have timing issues:
const toolSchemas = await Promise.all(
tools.map(async tool => ({
name: tool.name,
description: typeof tool.description === 'function'
? await tool.description() // Async resolution can fail
: tool.description,
input_schema: zodToJsonSchema(tool.inputSchema),
}))
)
Tool Name Mismatch
- FileReadTool actual name:
'View' - AI trying to call:
'ReadFile' - This indicates the tool schemas are not being properly passed to the model
3. Workflow Comparison
Original Workflow (Working)
- User input → processUserInput (simple file embedding)
- Query function → LLM with proper tool schemas
- LLM returns proper tool_use blocks
- Tools execute
- Recursive query continues
Current Workflow (Broken)
- User input → complex async processing
- Query function → LLM with potentially malformed schemas
- LLM returns wrong format (
<function=ReadFile>) - Tools don't execute
- Loop breaks
4. Critical Files Modified
- src/Tool.ts - Changed tool interface
- src/tools.ts - Added ToolRegistry complexity
- src/services/claude.ts - Modified schema generation
- src/utils/messages.tsx - Added complex @ processing (now reverted)
5. The Real Problem
The model (GLM-4.5) is receiving tool schemas but responding with a non-Anthropic format. This suggests:
- Wrong model provider configuration - GLM might not support Anthropic's tool format
- Schema generation timing issue - Async resolution fails
- Tool registry complexity - Breaking schema consistency
6. Solution Path
- Verify model compatibility - Ensure GLM-4.5 supports Anthropic tool format
- Simplify tool registration - Remove ToolRegistry complexity
- Fix async description - Make it synchronous or ensure proper await
- Consistent tool naming - Match actual tool names with documentation
Next Steps
- Check if GLM-4.5 is the issue (try with Claude model)
- Revert tool registration to simple synchronous approach
- Fix tool description to be synchronous
- Ensure proper tool schema format for the model provider