Skip to content

refactor: AI features cleanup wave 1 (providers, ViewModel, MCP, Copilot)#1111

Merged
datlechin merged 16 commits intomainfrom
worktree-jsonvalue-dedup
May 8, 2026
Merged

refactor: AI features cleanup wave 1 (providers, ViewModel, MCP, Copilot)#1111
datlechin merged 16 commits intomainfrom
worktree-jsonvalue-dedup

Conversation

@datlechin
Copy link
Copy Markdown
Member

Summary

Wave 1 of the AI features audit (see AI_FEATURES_AUDIT.md). 13 commits across 8 focused refactors. Production builds clean, AI test target runs.

What changed

  • JSONValue dedup: deleted Core/AI/Chat/JSONValue.swift and ChatToolJSONFormatter.swift. All chat tools, providers, and the MCP wire now share JsonValue. Encoding helpers live as native methods on the type.
  • Composer focus border: removed the animated multi-layer angular gradient (IntelligenceFocusBorder + IntelligenceShimmer). Replaced with a single 1pt Color.accentColor stroke, matching macOS HIG.
  • AIChatViewModel split: 1249-line god class decomposed into +Streaming, +SchemaContext, +ToolApproval, +MessageEditing, +SlashCommands, +Persistence. Main file now 293 lines. Replaced 3-boolean state machine (isStreaming/lastMessageFailed/pendingApproval) with a single StreamingState enum. Added re-entry guard on startStreaming(). Removed errorMessage didSet side effect, added explicit clearError().
  • Provider extracts: new String+AIEndpoint.swift (normalizedEndpoint()), new JSONValue+Encoding.swift. Anthropic, OpenAI-compatible, and Gemini all share endpoint normalization, JSON encoding, and a unified mapHTTPError (Gemini's 403 special case folded into the base via parameter). fetchAvailableModels standardized at 5s timeout.
  • Inline suggestion: replaced Timer debounce with Task<Void, Never>? + Task.sleep. Added sourceIdentity: ObjectIdentifier to InlineSuggestionSource; manager verifies identity before applying so source switches (Copilot ↔ AI Chat) cannot apply stale results. Lifted acceptCommand out of the shared InlineSuggestion struct entirely; Copilot tracks LSP commands in its own private [UUID: LSPCommand] map keyed by suggestion id. Debounce duration moved to AISettings.inlineSuggestionDebounceMs (default 500ms, clamped 50-5000).
  • MCP transport: split MCPHttpServerTransport.swift into MCPHttpConnectionContext, MCPHttpRequestRouter, MCPSseWriter. Migrated PairingExchangeStore from @unchecked Sendable + NSLock to actor. Tightened MCPAuthPolicy.sessionApprovals to private. Added : keep-alive SSE heartbeat every 30s.
  • Storage versioning: AIConversation gained schemaVersion: Int with backward-compatible decode. AISettings.includeSchema / includeCurrentQuery defaults are now consistent across regular init, init(from:), and default. CustomSlashCommandStorage.add() rejects duplicate names with a typed error surfaced via alert.
  • Copilot lifecycle: CopilotService.stop() wraps shutdown() RPC in a 10s withTaskGroup race. LSPTransport.stop() is now async, cancels the read Task, and explicitly closes stdin/stdout FileHandles before terminating the process. The read loop uses FileHandle.bytes AsyncSequence. Renamed CopilotSchemaContextCopilotPreambleBuilder. CopilotBinaryManager strips the com.apple.quarantine xattr after SHA-512 verify.

Files

  • 64 files changed, +2575 / -2291
  • Main file shrinkage: AIChatViewModel.swift 1249 → 293 lines

Test plan

  • xcodebuild build green for the production target
  • swiftlint lint --strict clean on every touched file
  • AI test classes pass (Conversation, Settings, ChatToolRegistry, ChatToolArgumentDecoder, AIChatViewModel Slash/Mention/Action subsets)
  • Full test target run (3 pre-existing test infra failures: fixError* for MongoDB/Redis assume plugin metadata loads in test target; OpenTableTabTests hits a pre-existing assertion in MainContentCoordinator+FilterState.swift:311. Out of scope for this PR.)
  • Manual smoke: open AI chat, send a message, verify streaming, accept inline suggestion in editor, exercise tool approval

Out of scope (Wave 2)

See section 4 of AI_FEATURES_AUDIT.md for the full backlog.

@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@datlechin datlechin force-pushed the worktree-jsonvalue-dedup branch from 0ab6b93 to 59e7dad Compare May 8, 2026 05:03
@datlechin datlechin merged commit 76c9c1f into main May 8, 2026
2 checks passed
@datlechin datlechin deleted the worktree-jsonvalue-dedup branch May 8, 2026 05:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant