refactor(chat): simplify branching to block number display + AI query routing improvements#120
Merged
Merged
Conversation
- Replace branch path (A, B, C...) with sequential block numbers (1, 2, 3...) - Update BranchIndicator to show BlockNumberBadge with Hash icon - Remove branch creation UI from BlockEditDialog - Remove all branch-related props from BlockHeader and UnifiedMessageBlock - Keep database fields (parent_block_id, branch_path) reserved but unused Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The lint:fix script doesn't accept --silent parameter, causing pre-commit hook to fail even when lint passes. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The optimistic update in useCreateBlock was causing a visual flicker where an empty pending block would momentarily appear before being replaced by the actual block from the server. Changed to wait for server response before updating the cache, which provides a smoother UX without the intermediate empty state. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fixed inconsistent ErrorSection UI where the error icon was not properly positioned on the timeline. Now uses the same `absolute -left-[2rem] top-0` positioning as other sections (Thinking, ToolCall, Answer). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
When user asks "有什么笔记" (what notes do you have), the LLM generates an empty query parameter, causing tool execution failure. Changes: 1. memo_search tool: Treat empty query as "search all" (using "*" wildcard) 2. MemoParrot prompt: Add explicit examples for searching all notes - query: "*" for listing all memos - query: "Python" for keyword search This allows natural "list all" queries to work without errors. Fixes: ai.agent.event error "query cannot be empty" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add missing i18n keys for block number display - Fix handleEditConfirm to log instead of silently discarding edits - Add localStorage error logging in CompactToolCall - Remove unused props (blockId, conversationId) from BlockEditDialog - Update useBlockEditDialog hook signature - Add comprehensive test coverage for BranchIndicator - Add edge case tests for blockNumber (0, negative, large) - Fix test selectors and remove unused imports Refs #3 (PR review fixes) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This optimization eliminates unnecessary vector search for list/filter queries. **Problem**: All memo queries were routed through semantic vector search, including simple list queries like "有什么笔记" which should use SQL. **Solution**: Added a 4-layer query intent classifier: - Layer 1: List intent (0ms) → "有什么笔记" → SQL list - Layer 2: Filter intent (0ms) → "今天的笔记" → SQL filter - Layer 3: Keyword intent (0ms) → "Python" → BM25 - Layer 4: Semantic default → "如何部署" → Vector **New retrieval strategies**: - `memo_list_only`: Pure SQL list (fastest, ~10ms) - `memo_filter_only`: SQL with time filter - `memo_bm25_only`: BM25 keyword search (no embedding) - `memo_semantic_only`: Vector search (existing) **Performance impact**: | Query | Before | After | |-------|--------|-------| | "有什么笔记" | ~500ms (Embedding) | ~10ms (SQL) | Refs #8 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace `\u4e00-\u9fff` with `\p{Han}` for proper Unicode
character class matching in Go regexp.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Use predicted roundNumber (existing blocks count + 1) for optimistic block - Remove refetchBlocks() call after streaming completion - The streaming handler already updates block via optimistic updates This eliminates the flicker caused by: 1. Optimistic block with roundNumber=0 appearing briefly 2. Then being replaced by backend data with correct roundNumber 3. Then refetchBlocks() triggering another re-render Now the optimistic block appears with the correct roundNumber immediately, and no additional refetch is needed since all data is already streamed. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove fade-in, slide-in, and pulse animations that were causing visual "flicker" effects during streaming block creation. Changes: - Remove animate-in fade-in slide-in-from-top-1 from tool details expansion - Remove animate-in fade-in from thinking content expansion - Remove animate-pulse from running tool timeline node - Remove animate-pulse from streaming answer timeline node - Remove animate-in fade-in from pending state initialization - Remove animate-block-pulse from streaming block container Retain animate-spin for Loader2 components (spinner icons). Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove animate-block-pulse from streaming block container to prevent visual flicker/breathing effect during block creation. Other animations (fade-in, slide-in, pulse for timeline nodes) are preserved as they provide meaningful UI feedback. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement intelligent query routing to use SQL for list/filter queries
instead of forcing all queries through vector search.
Changes:
- Add MemoQueryClassifier with 4-layer intent classification:
* IntentList: List all memos ("有什么笔记", "*", etc.)
* IntentFilter: Time/tag filters ("今天的笔记", "#work")
* IntentKeyword: Simple keywords (BM25 search)
* IntentSemantic: Complex semantic queries (vector search)
- Add 3 new retrieval strategies in AdaptiveRetriever:
* memo_list_only: Pure SQL list (fastest)
* memo_filter_only: SQL with time filter using CEL
* memo_bm25_only: BM25 keyword search without embedding
- Fix semantic query classification by reordering checks:
* Check semantic patterns before short query pattern
* Prevents "如何部署服务" from being classified as keyword
- Add comprehensive unit tests for query classifier
- Remove duplicate time range extraction code
- Add timeout error handling with DeadlineExceeded check
Refs #119
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix the issue where thinking placeholder text like "正在思考..." was displayed as actual content in the Block's thinking section. Root cause: Backend was sending hardcoded Chinese text as thinking event content, which frontend couldn't distinguish from real content. Changes: - MemoParrot: Use "ai.states.thinking" key instead of "正在思考..." - AmazingParrot: Use "ai.states.thinking" key instead of "正在分析您的需求..." - UnifiedMessageBlock: Dynamically build placeholder filter list from i18n translations to catch all translated placeholders This ensures placeholder texts are filtered out from display, showing only genuine thinking content. Ref: Frontend already had translateThinkingSteps() to handle i18n keys. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix the issue where thinking section was not displayed when the only thinking content was placeholder text (e.g., "ai.states.thinking"). The problem was that the display condition checked `allThinkingContent.length > 0`, but `allThinkingContent` is filtered to exclude placeholders, causing the section to be hidden even when `thinkingSteps` existed. Changes: - Show thinking section when `thinkingSteps.length > 0` OR `streamingPhase === "thinking"` - Only allow expand/collapse toggle when there is real content - Only show expanded content view when there is real content This ensures the thinking section is always visible when thinking events exist, while the expandable content area only shows non-placeholder content. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Remove the edit button and related edit functionality from the AI chat Block footer to simplify the UI. Changes: - BlockFooter.tsx: Remove edit button, Pencil icon, and onEdit prop - UnifiedMessageBlock.tsx: Remove onEdit from props and component - ChatMessages.tsx: Remove edit dialog, handleEdit, and handleEditConfirm - Update test file to remove onEdit prop This simplifies the footer UX by removing the unimplemented edit feature. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Implement comprehensive performance optimizations for block streaming UI to achieve smooth, ChatGPT-like typing animation and real-time progress display. P0 optimizations: - Replace O(n) array traversal with O(1) Map lookup in useAIQueries.ts - Switch from StreamingText to StreamingMarkdown for sentence-level rendering - Leverage React 18 automatic batching instead of dual cache updates P1 optimizations: - Merge 6 useEffect hooks into 2 unified scroll handlers in ChatMessages.tsx - Add smart caching for messageBlocks conversion to avoid re-processing history - Reduce scroll trigger threshold from 50 to 15 characters for better responsiveness Type safety improvements: - Fix BlockBodyProps.parrotId type from string to ParrotAgentType enum - Use enum constants (ParrotAgentType.GEEK/EVOLUTION) instead of string literals - Fix BlockEvent to use 'meta' instead of 'metadata' field i18n fixes: - Add missing 'block_number' translation key to en.json and zh-Hant.json - Remove duplicate 'block_number' key in zh-Hant.json Refs #119 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
835cd87 to
de46286
Compare
hrygo
pushed a commit
that referenced
this pull request
Feb 8, 2026
- Remove unused Database import from ProgressIndicator - Fix Navigation i18n key path to ai.knowledge-graph.title - Merge duplicate ai.progress keys into first ai key (en.json, zh-Hans.json) - Apply auto-formatting fixes Refs #120 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hrygo
pushed a commit
that referenced
this pull request
Feb 8, 2026
- Remove unused Database import from ProgressIndicator - Fix Navigation i18n key path to ai.knowledge-graph.title - Merge duplicate ai.progress keys into first ai key (en.json, zh-Hans.json) - Apply auto-formatting fixes Refs #120 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
hrygo
added a commit
that referenced
this pull request
Feb 8, 2026
* feat(ai): add router optimization + progress feedback + fix i18n Backend changes: - Add four-layer intent routing (Cache → Rule → History → LLM) - Add RuleMatcher for fast zero-latency classification - Add router feedback collection with PostgreSQL storage - Add Prometheus metrics and tracing support - Add context delta builder for efficient context updates - Add preload analyzer and scheduler for optimization - Add sensitive input filter for security - Add migration for router_feedback table Frontend changes: - Add ProgressIndicator component with phase animations - Add QuickReplies component for suggested actions - Add shimmer keyframe animation to default.css - Update UnifiedMessageBlock with progress display - Update AIChat page to support new features i18n fixes: - Fix zh-Hant.json: add 335 missing translation keys - Translate ai.progress.phases to Traditional Chinese - Ensure all locale files are synchronized Refs #97 (Progressive Progress Feedback) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs(claude): add Critical Context + Code Change Boundaries sections - Add 🔑 Critical Context section with project structure table - Document key configuration (PostgreSQL container name, ports) - Add i18n completeness trap warning (check-i18n doesn't check zh-Hant.json) - Add Language-Specific Notes for TypeScript/React and Go - Add 🚫 Code Change Boundaries section with 4 workflow patterns - Update freshness status to v0.93.2 (2026-02-08) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * style(ai): align struct field initialization across modules - Standardize field alignment in deltaStats, DeltaStats, TracingContext structs - Improve i18n validation script with complete zh-Hant.json check - Add cross-reference to DEBUG_LESSONS.md for migration notes - Refine terminology: GraphQL/Proto → Proto/Schema - Update code-reviewer agent description format All tests pass, build successful. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(i18n): resolve duplicate ai keys and lint issues - Remove unused Database import from ProgressIndicator - Fix Navigation i18n key path to ai.knowledge-graph.title - Merge duplicate ai.progress keys into first ai key (en.json, zh-Hans.json) - Apply auto-formatting fixes Refs #120 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(ai): resolve golangci-lint issues - Fix matchPool.Get() type assertion in sensitive.go - Add slog error handling in analyzer.go async save - Fix defer close error handling in exporter.go - Fix http.NewRequest nil to http.NoBody in prometheus_test.go - Rename testErr to errTest for staticcheck compliance - Remove unused matchPool.Put to avoid SA6002 - Simplify regex pattern using \S* instead of [^\s]* - Remove unused fields and imports Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs(claude): add golangci-lint common pitfalls to Go coding standards Add "Go Lint 常见陷阱" section with: - Type assertion must use comma-ok pattern - Defer error checking requirements - Error comparison with errors.Is - HTTP nil body should use http.NoBody - error variable naming convention - Regex simplification patterns - sync.Pool usage restrictions This section captures lessons learned from fixing 18 golangci-lint issues in commit 14900ad, preventing future repetitions. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(web): set HTML lang attribute dynamically to prevent translation prompts - Update document.documentElement.lang in applyLocaleEarly() - Update document.documentElement.lang in loadLocale() - Map zh-Hans → zh-CN, zh-Hant → zh-TW for BCP 47 compliance This prevents Chrome/Google from offering to translate the page when the user's browser language matches the content language. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix(web): fix streaming event display and remove redundant FIFO queue This commit fixes two issues with AI chat streaming: 1. **Tool call metadata fix**: tool_use events were incorrectly using response.eventData (JSON parameters) as toolName instead of eventMeta.toolName. Now correctly displays tool names like "schedule_query" instead of JSON strings. 2. **Optimistic block recreation fix**: Added blockAlreadyExists check to prevent recreating blocks on every SSE event, which was clearing the accumulated eventStream. 3. **Simplification**: Removed FIFO queue infrastructure (~250 lines) as SSE events are serial by nature - no concurrent updates occur. Root causes: - tool_use handler: toolName: response.eventData → toolMeta?.toolName - Every SSE event triggered block recreation, resetting eventStream - FIFO queue was over-engineering for serial SSE stream Refs streaming UI debugging session Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs(debug): add lessons learned from streaming UI debugging Adds two new debug lessons: 1. Tool call metadata error - using eventData instead of eventMeta.toolName 2. Over-engineering: FIFO queue - SSE is serial, queue was always empty Key takeaways: - Diagnose before treating - add logs to confirm assumptions - SSE doesn't need queuing - events are inherently serial - Simplify over complexity - React Query has internal batching Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(web): remove redundant debug logs from streaming handlers - Remove console.log from eventTransformers.ts (extractToolCalls) - Remove console.log from ChatMessages.tsx (eventStream debugging) - Keep critical error logging in useAIQueries.ts These debug logs were added during the streaming UI fix investigation and are no longer needed now that the issue is resolved. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * docs(specs): add streaming tool calls technical specification Add comprehensive technical specification for implementing full streaming tool calls (Solution A) in AI chat system. Key decisions: - Adopt complete streaming mode (DeepSeek native support) - Progressive enhancement strategy with backward compatibility - New ChatStreamWithTools interface Expected improvements: - First tool call latency: ~800ms → ~200ms (75% reduction) - Perceived latency: 3-5s → <1s (60% reduction) Refs #125 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: 黄飞虹 <aaronwong1989@gmail.com> Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
yangxb2010000
pushed a commit
that referenced
this pull request
Feb 9, 2026
* feat(ccrunner): add session stats extraction and cost tracking - Add EventTypeSessionStats and SessionStatsData struct for statistics - Extend StreamMessage to parse CLI result messages (duration_ms, total_cost_usd, usage) - Add handleResultMessage() to extract and send session_stats event - Add total_cost_usd field to SessionSummary proto - Handle session_stats event in handler.go to set TotalCostUsd - Silence "unknown message type" warnings for system/control messages Frontend can now access session cost and statistics via SessionSummary.total_cost_usd. Refs cc-runner-message-handling-research.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(ccrunner): update architecture spec to v1.3 with session stats - Add session_stats event type documentation - Document complete CLI event type mapping table (system, thinking, status, tool_use, tool_result, assistant, user, answer, error, result, session_stats) - Add message flow transformation diagram with system/result handling - Add SessionStatistics section with data structures - Update version history to v1.3 Related to research in docs/research/cc-runner-message-handling-research.md Refs #63 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ccrunner): add session stats persistence and cost tracking Phase 1 implementation of CC Runner optimization plan: - Add agent_session_stats table for full session tracking - Token usage (input/output/cache) - Cost tracking (total_cost_usd) - Duration breakdown (thinking/tool/generation) - Tool usage and file operations - Add user_cost_settings table for budget management - Daily budget limits - Per-session cost thresholds - Alert preferences - Add agent_security_audit table for security logging - Risk level tracking - Command pattern matching - Action taken logging - Implement AgentStatsStore interface - PostgreSQL driver implementation - Async persister service with queue - Add cost alerting service - Threshold-based alerts - Daily budget warnings - Add SessionStatsData.ConversationID for database relationship - Add conversion method ToAgentSessionStats() Tests: 4/4 passing in ai/stats package Refs: docs/specs/cc-runner-optimization-plan.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): address security and error handling issues from quality review Phase 3 post-implementation fixes: Security fixes (CRITICAL): - Fix SQL injection in getDailyCostBreakdown - use parameterized query Changed from fmt.Sprintf to INTERVAL '1 day' * $2 syntax Error handling fixes (CRITICAL): - drainQueue: track and log data loss during shutdown - Heartbeat: return early on send failure - Add rows.Err() checks after all QueryContext iterations - Fix nilerr: distinguish sql.ErrNoRows from actual errors Code quality: - Use UTC for timezone consistency in validateDateRange - Add protoTime() helper for safe timestamp conversion - Remove unused protoTimePtr function All golangci-lint checks pass. Refs: docs/specs/cc-runner-optimization-plan.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ccrunner): complete backend integration for session stats (Phase 3) Backend gRPC handlers and store integration: RPC handlers (ai_service_stats.go): - GetSessionStats: retrieve single session by session_id - ListSessionStats: list sessions with pagination (limit/offset) - GetCostStats: aggregated N-day cost statistics with daily breakdown - GetUserCostSettings: user budget and alert preferences - SetUserCostSettings: update cost control settings Store layer: - AgentStatsStore interface with full CRUD operations - PostgreSQL driver implementation - SQLite stubs returning appropriate errors - persister shutdown coordination in v1.go Connect RPC wrappers: - Wrap all 5 stats methods for Connect HTTP/gRPC transcoding Frontend: - CostTrendChart component for visualizing cost trends - SessionSummaryPanel integration with stats display - i18n keys for stats UI All handlers include: - User authentication via auth.GetUserID() - User ownership verification - Proto-to-Store type conversion - Structured error logging Refs: docs/specs/cc-runner-optimization-plan.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(ccrunner): add comprehensive event handling tests Add cc_event_test.go with 69 test cases covering: - StreamMessageParsing: all CLI message types (10 tests) - GetContentBlocks: direct/nested content extraction (4 tests) - HandleResultMessage: Result message stats extraction (3 tests) - DispatchCallbackCoverage: event dispatch coverage (8 tests) - ConversationIDToSessionID: UUID v5 deterministic mapping (5 tests) - SessionStats: stats collection (6 tests) - StreamMessageEdgeCases: edge case handling (7 tests) - ContentBlockTypes: content block parsing (5 tests) - NestedMessageStructure: nested message handling (3 tests) - SessionStatsDataStructure: stats serialization (1 test) - EventMetaStructure: metadata structure (1 test) - UnknownMessageTypeHandling: unknown type tolerance (1 test) - SessionStatsConcurrency: concurrent safety (1 test) - CCRunnerConfigDefaults: config defaults (1 test) - ResultMessageVariations: Result message variants (4 tests) - SummarizeInput: input summary generation (5 tests) - BuildSystemPromptCoverage: system prompt building (3 tests) Add cc_event_tester.sh for quick test execution. Refs: docs/research/cc-runner-message-handling-research.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(release): prepare v0.81.0 release notes Update documentation for CC Runner Session Stats & Cost Tracking: CHANGELOG.md: - Add v0.81.0 entry with full feature breakdown - Database schema (3 new tables) - 5 new gRPC handlers - Frontend components (CostTrendChart, SessionSummaryPanel) - Async persister architecture - 69 test cases for event handling - Security fixes from quality review README.md: - Add "成本追踪" to features table - Add CC Runner optimization plan link to docs Version 0.81.0 marks the completion of the 3-phase CC Runner optimization plan with full session statistics and cost tracking. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): address code review findings from Loki Mode review Critical fixes: - Add AIService.Close() method for proper persister shutdown Prevents goroutine leaks and data loss on server shutdown High priority fixes: - Add maxOffset limit (10000) to prevent unbounded pagination - Use defer close(heartbeatDone) to ensure cleanup on panic Code review improvements: - Add sync.RWMutex for concurrent Close() calls - Proper error aggregation in Close() All golangci-lint checks pass. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): fix all remaining code review issues Performance optimizations: - parseStringArray: use strings.Builder for O(n) instead of O(n²) - Add partial index idx_session_stats_user_success for is_error=false queries Database fixes: - conversation_id: INTEGER (matching ai_conversation.id type) instead of BIGINT - Remove redundant index on user_cost_settings.user_id (UNIQUE provides index) - Standardize constraint name: chk_agent_session_stats_type Error handling: - GetMostExpensiveSession: log error instead of silently ignoring - Add slog import for structured logging All golangci-lint checks pass. Refs: docs/specs/cc-runner-optimization-plan.md Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(release): update CHANGELOG with all code review fixes Add performance optimizations and database improvements to v0.81.0 release notes: - parseStringArray O(n) performance fix - Partial index for is_error filtering - conversation_id type fix (BIGINT → INTEGER) - Constraint name standardization - Redundant index removal - GetMostExpensiveSession error logging Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(release): bump version to v0.91.0 - Update version.go to 0.91.0 - Update CHANGELOG.md header version Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(ccrunner): fix lint issues in cc_event_test.go - Fix unused write to err (use _ = instead) - Remove unused fields in TestCCRunnerConfigDefaults - Remove empty if branches - Add actual verification for generated SessionID - Add uuid import for UUID validation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * test(ccrunner): fix TestBuildSystemPromptCoverage assertion Update expected strings to match actual markdown format with **. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(release): add v0.9.2 release notes - CC Runner Session Stats & Cost Tracking - Database schema (3 new tables) - Backend API (5 RPCs) - Frontend components (CostTrendChart, SessionSummaryPanel) - 69 test cases, all passing - Security and performance fixes Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * docs(release): translate v0.9.2 release notes to Chinese Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * chore(release): bump version to 0.92.0 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(stats): use pq.Array for string slice serialization Fixes "sql: converting argument $18 type: unsupported type []string" error. PostgreSQL requires pq.Array to convert Go []string to SQL array. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(stats): properly handle JSONB for tools_used, TEXT[] for file_paths - tools_used (JSONB): use json.Marshal() - file_paths (TEXT[]): use pq.Array() Previous fix incorrectly used pq.Array for both. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(stats): remove conversation_id foreign key constraint Geek/Evolution modes operate independently and don't require ai_conversation entries. The FK constraint was causing save failures when conversation doesn't exist yet. - Remove fk_session_stats_conv constraint - Keep conversation_id as reference field for analytics Resolves: pq: insert or update on table "agent_session_stats" violates foreign key constraint "fk_session_stats_conv" Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(stats): always pass valid JSON/arrays for empty collections - tools_used: pass "[]" instead of nil for empty JSONB - file_paths: pass pq.Array([]string{}) instead of nil for empty TEXT[] Fixes: pq: invalid input syntax for type json Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(stats): comprehensive fixes from code review Multiple fixes based on thorough code review: 1. cc_runner.go: - Add tools and file paths deduplication (using map/set) - Add cost calculation fallback when CLI reports $0 - Fix TotalTokens to only count billed tokens (input+output) - Set ModelUsed to "claude-code" (constant, CLI doesn't report model) 2. persister.go: - Add idempotency protection with 5-second duplicate window - Use sync.Map for concurrent-safe session tracking - Add dedupEnabled flag for future control 3. agent_stats.go: - parseStringArray now always returns empty slice, not nil - Ensures consistency between read/write operations Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(stats): safely handle type assertion in dedup check Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * debug(ai): add logging to trace stream completion Add logging to track: - Backend: when Done: true message is sent with session summary - Frontend: stream loop progress, done signal reception, fallback usage This will help diagnose why Geek Mode sessions appear to hang instead of completing properly. Refs #65 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * debug(ai): add more logging to trace executeAgent flow Add logs at key points: - After ExecuteWithCallback completes - When preparing session summary - When checking if agent is SessionStatsProvider This will help identify where the code is getting stuck after session stats are received. Refs #65 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): resolve deadlock in streamOutput when stdout completes Root cause: After stdout goroutine completes, the stderr goroutine was still waiting on its select for either scanDone or streamCtx.Done(). But streamCtx.Done() wouldn't be signaled until stopStreams() is called, which is deferred and only runs when the function returns. This created a deadlock because the function couldn't return until both goroutines completed, but stderr couldn't complete until streamCtx was canceled. Fix: Call stopStreams() immediately after stdout scan completes, which signals streamCtx.Done() and causes the stderr goroutine to exit its select statement and complete. This resolves the issue where Geek Mode sessions would hang after receiving the result message from Claude Code CLI. Refs #65 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(web): remove ES module syntax from sw.js Service Workers don't support ES module syntax like 'export default'. Changed 'export default null;' to a comment to fix syntax error causing Service Worker registration to fail. Fixes browser console error: Uncaught SyntaxError: Unexpected token 'export' (at sw.js:155:1) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ai): enhance geek mode UI with tool results and session summary Frontend: - Add ExpandedSessionSummary component with detailed metrics - Duration breakdown with visual progress bar - Token usage (input/output/cache) - Cost analysis - Tool calls summary - Files modified (Evolution Mode) - Add tool results display in terminal-style cards - Fix type definitions for toolCallsRef and toolResults metadata Backend: - Fix scanner loop blocking issue in cc_runner (break vs return) - Add detailed logging for debugging stream completion - Simplify stderr handling to io.Copy Refs #120 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): complete session summary display with mode indicator - Add mode field to SessionSummary proto (geek/evolution/normal) - Update ExpandedSessionSummary to show mode badge with icon - Display mode prominently in header (Geek Mode / Evolution Mode) - Show all session stats: duration breakdown, tokens, cost, tools, files - Map agent_type to mode in frontend summary handling This resolves the incomplete session display issue where mode was missing. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(chat): restore beautiful markdown rendering in ChatMessages - Restore early version with精美 table/list styling - Tables: border, shadow-sm, bg-muted/50 header, hover effects - Lists: proper spacing (mb-2, space-y-1, pl-1) - Blockquotes: border-l-4, bg-muted/30, rounded-r-lg - Inline code: px-1.5 py-0.5 rounded-md bg-muted Reverts simplified styling that made markdown look ugly. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(chat): restore Tool Results Display with精美 styling - Add ToolResult type with name, outputSummary, duration, isError - Display tool results in terminal-style cards (slate-950 bg) - Show tool icon (Terminal for bash/run, File for others) - Add duration badge and error indicator - Keep beautiful markdown rendering from previous commit Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(chat): use ExpandedSessionSummary with精美的完整面板 - Replace SessionSummaryPanel with ExpandedSessionSummary - Shows full session stats with expandable card: - Mode badge (Geek/Evolution/Normal) with icon - Status indicator with color - Duration breakdown bar chart (thinking/tools/generation) - Token grid (input/output/cache) - Cost display with per-1K-token rate - Tool calls count with average time - Files modified with path list Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(summary): show full session ID instead of truncated - Remove .slice(0, 8) truncation - Add break-all for proper wrapping of long IDs - Keep select-all for easy copying Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(chat): message bubbles default to expanded - Change isFolded initial state from true to false - Users can still manually fold long messages Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(summary): ExpandedSessionSummary defaults to collapsed - Change isExpanded initial state from true to false - Users can click to expand and see full stats Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): track file modifications in SessionStats - Add RecordFileModification method to SessionStats - Extract file path from Write/Edit tool input - Update FilesModified count and FilePaths list - Handle both direct tool_use and nested tool_use in assistant messages Fixes: - FilesModified always showing 0 - FilePaths never populated Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * debug(ccrunner): add logging for SessionStats data flow - Log values returned by GetSessionStats() - Log when handleResultMessage updates TotalDurationMs - Log token usage updates from CLI This will help diagnose why SessionSummary shows incorrect values. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): preserve CLI-reported TotalDurationMs Problem: After handleResultMessage correctly set TotalDurationMs to CLI's reported value (12175ms), it was being overwritten by time.Since(StartTime) (28444ms) which includes backend overhead. Solution: Only override TotalDurationMs if CLI didn't provide it. The CLI's duration_ms is the actual execution time and should be used. This fixes: - TotalDurationMs now shows CLI's 12175ms instead of 28444ms - Frontend SessionSummary displays accurate duration Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * debug(ccrunner): add cache_read_tokens to GetSessionStats logging Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): isolate CLI config to reduce token usage - Add CLAUDE_CONFIG_DIR environment variable for Geek Mode sessions - Prevents loading main ~/.claude/history.jsonl (3891 lines, 1.3MB) - Creates isolated config at ~/.divinesense/claude-geek/user_{id}/ - Significantly reduces input_tokens for simple queries Before: input_tokens=84391 (loading entire main CLI history) After: input_tokens will only include Geek Mode context This resolves the issue where a simple message consumed 84K tokens due to cached history from main Claude Code CLI sessions. Technical details: - CLAUDE_CONFIG_DIR is set per-user to isolate sessions - Each user gets their own CLI history and config - Cache read tokens will now reflect only relevant Geek Mode context Refs #96 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): add detailed token logging to debug cache_read > input Add cache_write_tokens and cache_read_tokens to the log output, plus a flag indicating when cache_read exceeds input. This will help debug why Claude Code CLI sometimes reports cache_read_tokens > input_tokens, which appears to be an artifact of CLI's cumulative token accounting. Refs #96 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): address all code review findings P1 - High Priority: - Fix TotalDurationMs conditional logic: use <= 1 instead of == 0 to better handle edge cases where CLI reports minimal values P2 - Medium Priority: - Optimize RecordFileModification: O(1) map lookup instead of O(n) scan Added filePathsSet field to SessionStats for efficient deduplication - Add stderr sampling (10% rate) to preserve debug info without log flooding Changed from complete discard to sampled logging P3 - Low Priority: - Extract magic numbers to package-level constants: deepSeekInputCostPerMillion = 0.27 deepSeekOutputCostPerMillion = 2.25 - Unify log levels: changed key lifecycle events to Info level These changes improve: - Data accuracy: TotalDurationMs now handles edge cases correctly - Performance: file path deduplication is now O(1) instead of O(n) - Observability: stderr errors are now sampled for debugging - Maintainability: pricing constants are centralized Refs #96 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): improve error reporting with stderr context - Add stderrBuffer type to capture last 100 stderr lines - Include stderr content in error messages when CLI fails - This helps debug "exit status 1" errors by showing CLI error output Example error output before: "command exited with code 1: exit status 1" Example error output after: "command exited with code 1: exit status 1 (stderr: Error: ...)" Changes: - Add stderrBuffer struct with thread-safe line capture - Pass stderrBuffer to streamOutput as parameter - Modify executeWithSession to include stderr in error messages - Refactor stderr goroutine to use stderrBuffer.addLine() This will help identify the root cause of CLI failures like the "GeekMode execution failed" error reported by users. Refs #96 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): use main CLI config for authentication Issue: Geek Mode CLI failed with "Could not resolve authentication method" Root cause: CLAUDE_CONFIG_DIR pointed to isolated config without API credentials Trade-off: CLI will now load main CLI's history.jsonl (~1.3MB, 3891 lines) which increases initial token usage. This is acceptable since authentication is required for CLI to function. Alternative considered: Copy API credentials to isolated config - Rejected: Credentials stored in encrypted format, copying is complex - Rejected: CLI manages credentials internally, manual copying error-prone After authentication is working, we can optimize by: 1. Using CLI's --session-config-dir to point to existing session 2. Or implementing credential sync between main and isolated config Refs #96 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(ui): improve token display with clear cache labeling Changes to ExpandedSessionSummary Token panel: - Split Input into "New Input" (billed) and "Cache Read (free)" - Add visual indicators (colored dots) to distinguish billed vs free tokens - Use green color for Cache Read to indicate it's free - Rename "Total" to "Billed Total" for clarity - Calculate billed total as: new input + output (excluding cache read) This helps users understand: - What they're actually paying for (new input + output) - What's free (cache read) - The value of caching (green = saved money) Refs #96 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): improve session summary display clarity - Fix token calculation: input_tokens already represents "new input" per Anthropic API docs, no need to subtract cache_read_tokens - Remove hardcoded pricing estimates (use actual backend cost instead) - Add Cache Hit Rate indicator to show cache effectiveness - Only show token rows with values > 0 (hides confusing "0" entries) - Fix division by zero risk in tool calls average calculation - Improve cost display: show actual cost + cost per 1K billed tokens - Keep Files Modified card visible even when count is 0 Refs #96cb56e4 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): suppress gosec G404 for logging sampler Math/rand is acceptable for non-security sampling (logging rate limit). Add nolint comment to clarify intent. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): hide Files Modified card when count is zero Only show the Files Modified card when files are actually modified. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ccrunner): resolve goroutine leaks and race conditions - Fix streamCtx to derive from parent ctx for proper cancellation propagation - Fix Session.WriteInput() timer race condition with proper lock handling - Consolidate duplicate cmd.Wait() error handling - Remove inefficient map re-allocation in handleResultMessage - Add panic recovery to scanner goroutine to prevent deadlock Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(ui): use real SessionID in summary; remove console logs in production - Fix SessionID display: use real UUID from detailedStats instead of "conv_N" - Remove 18 unnecessary logs from cc_runner.go (raw line, received message, etc.) - Add terser drop_console for production builds - Add rollup-plugin-visualizer for bundle analysis Refs #9 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(chat): add timestamp display to chat messages - Add formatMessageTime() function with relative time display - Show message timestamp below each message bubble - User messages: right-aligned time - AI messages: left-aligned time - Use existing i18n keys from ConversationItem Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * fix(chat): increase timestamp contrast for user messages - User messages: text-white/70 (light mode) / text-slate-900/60 (dark mode) - AI messages: keep subtle low-contrast style - Improves readability on dark user message bubbles Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(chat): reduce timestamp font size and add 6 parrot themes - Reduce timestamp font from 10px to 8px for subtle display - Add GEEK (violet) and EVOLUTION (rose) themes - Add sound effects, catchphrases, behaviors for new themes - Extend ParrotAgentType enum with GEEK and EVOLUTION Refs #63 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(chat): apply WeChat-style timestamp display (outside bubble) - Move timestamp outside message bubble (WeChat style) - User messages: timestamp on right side - AI messages: timestamp on left side - Gray color (text-muted-foreground/60), 10px font - Vertically centered with bubble Refs #63 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> * feat(chat): implement WeChat-style centered timestamp - Timestamp displayed as centered row between messages - Only shows when gap from previous message > 3 minutes - Gray badge style (bg-muted/50, text-muted-foreground/60) - First message always shows timestamp - Shows after context-separator Refs #63 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> --------- Co-authored-by: 黄飞虹 <aaronwong1989@gmail.com> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
概述
Resolves #119
本 PR 包含两个主要改进:
前端重构
分支路径 → 块编号
改进前:
0/1/2,A.1.2,main/feature等改进后:
#1,#2,#3组件变更
BranchIndicatorBlockNumberIndicator,简化实现BlockSelectorBlockEditDialogblockId、conversationIdpropsuseBlockQueriesBug 修复
\p{Han}替代[一-龥]AI 查询路由增强
新增文件
ai/agent/tools/memo_query_intent.go- 智能意图分类器新增检索策略
memo_list_onlymemo_filter_onlymemo_bm25_onlymemo_semantic_only路由逻辑
代码质量改进
测试覆盖
BranchIndicator.test.tsxBlockHeader.test.tsxLint/构建
golangci-lint0 issuespnpm lint通过pnpm build通过提交清单
ff09aec5357994d96cc0fad0270807ba168c4a70f048eb1e1ed9cd10a141619b文件变更统计
Resolves
#119
Co-Authored-By: Claude Opus 4.6 noreply@anthropic.com