Skip to content

Latest commit

 

History

History
347 lines (282 loc) · 19.6 KB

File metadata and controls

347 lines (282 loc) · 19.6 KB

quickcode — Completed Features


Batch 1 — Core Platform (pre-PLAN.md)

Feature Files Status
Multi-turn LLM sessions (Anthropic, OpenAI, Google) src/provider/, src/session/mod.rs
File tools: read, write, edit, glob, grep src/tools/
Shell execution (bash tool) with permission prompts src/tools/bash.rs, src/permission/
LSP integration (type structure, status tracking) src/lsp/mod.rs
HTTP API server with SSE event streaming src/server/
SQLite storage (sessions, messages, parts, todos) src/storage/mod.rs
Session management: fork, compact, revert, abort src/session/mod.rs, src/server/routes/session.rs
Snapshot/revert via git stash src/snapshot/mod.rs
MCP server (tools over stdio) src/mcp/mod.rs
Plugin system ($QUICKCODE_HOME/plugin/) src/plugin/mod.rs
Permission rules (allow/deny/ask) src/permission/mod.rs
TUI: ratatui terminal UI with chat, welcome, error overlays src/tui/mod.rs
Config: JSONC loading, provider API keys, agent overrides src/config/mod.rs
Basic auth middleware (QUICKCODE_SERVER_PASSWORD) src/server/mod.rs
Subtask agent tool (spawn sub-agents) src/tools/subtask.rs
Todo tool src/tools/todo_tool.rs
Apply-patch tool src/tools/apply_patch.rs
VCS: git diff, status endpoints src/vcs.rs, src/server/routes/vcs.rs

Batch 2 — PLAN.md Features (completed 2026-03-26)

Feature 1 — Onboarding flow

Goal: Replace bare ENV-var setup with an interactive first-run wizard.

  • AppMode::Onboarding { step: OnboardingStep } added to TUI
  • OnboardingStep enum: SelectProvider → EnterApiKey → SelectModel → Complete
  • First-run detection: checks GET /provider for any authenticated provider
  • render_onboarding(): provider picker, masked API key input (Tab to reveal), model picker, completion screen
  • save_provider_key(): calls PUT /auth/{provider_id} and writes to $QUICKCODE_HOME/config.jsonc
  • save_default_model(): calls PATCH /config to update runtime model
  • PATCH /config endpoint added to src/server/routes/config.rs
  • Files: src/tui/mod.rs, src/server/routes/config.rs, src/server/mod.rs

Feature 2 — Provider per agent

Goal: Each agent can have its own provider_id/model_id, switchable at runtime.

  • AgentRegistry.agents changed from HashMap to Arc<RwLock<HashMap<String, AgentInfo>>>
  • All read methods (get, list, list_primary, default_agent) are now async
  • set_model(agent_name, model) and set_temperature(agent_name, temp) mutation methods added
  • PATCH /agent/:name endpoint with UpdateAgentBody { model, temperature, top_p }
  • TUI AgentModelPicker mode: press m on agent in agent list to switch model
  • All call sites in session/mod.rs and server/routes/agent.rs updated to .await
  • Files: src/agents/mod.rs, src/session/mod.rs, src/server/routes/agent.rs, src/server/mod.rs

Feature 3 — Multi-agent support

Goal: Multiple sessions run concurrently; TUI shows all active sessions.

  • AgentPane struct: session_id, agent_name, title, messages, thinking, spinner_frame, input, cursor_pos, scroll, max_scroll, token_summary, error, pasted_blocks
  • TuiApp uses panes: Vec<AgentPane> + active_pane: usize replacing single-session fields
  • spawn_agent_session(agent_name) creates a new session and appends a new pane
  • Ctrl+N key binding to spawn additional agent sessions
  • Bus event routing updated: all handlers dispatch to correct pane by session_id
  • Files: src/tui/mod.rs

Feature 4 — TUI updates

Goal: List all agents, switch between sessions, see token usage in header.

  • AppMode::AgentList: table of agents with name/mode/model/active columns; F2 to open
  • AppMode::SessionSwitcher: table of active panes with agent/title/status/tokens; F3/Ctrl+W to open
  • AppMode::AgentModelPicker: model picker for an agent, opened with m from agent list
  • AppMode::TaskList: F4 opens SPEC task list
  • Chat header updated: [pane/total agent_name] title Ntokens format
  • Status bar updated with F2/F3/F4 hints
  • fetch_agents() helper calls GET /agent
  • Files: src/tui/mod.rs

Feature 5 — Copy-paste support

Goal: Paste code without breaking TUI; large pastes become placeholders.

  • EnableBracketedPaste added before event loop; DisableBracketedPaste on cleanup
  • Event::Paste(text) handler: pastes ≤3 lines / ≤200 chars go inline; larger become [Pasted Text #N, M lines]
  • PastedBlock { index, content, line_count } stored in pane.pasted_blocks
  • expand_pasted_blocks() replaces placeholders with real content before sending
  • Placeholder text rendered in dim/italic style in input box
  • Files: src/tui/mod.rs

Feature 6 — Session token tracking

Goal: Track tokens used per session per agent; display live counter.

  • 4 new columns on session table: total_input_tokens, total_output_tokens, total_cost_usd, token_by_agent TEXT
  • Migration guards in init_db() (ALTER TABLE ADD COLUMN) for existing databases
  • session_add_tokens(db, session_id, input, output, cost, agent) — atomic += SQL update
  • session_get_token_summary(db, session_id) — returns TokenSummary with per-agent breakdown
  • TokenSummary and AgentTokenUsage structs added to src/models/mod.rs
  • Token accumulation wired into StreamEvent::FinishStep handler in session/mod.rs
  • GET /session/:id/stats endpoint returns TokenSummary
  • Live counter displayed in TUI chat header via pane.token_summary
  • Files: src/models/mod.rs, src/storage/mod.rs, src/session/mod.rs, src/server/routes/session.rs, src/server/mod.rs, src/tui/mod.rs

Feature 7 — SPEC.md task tracker

Goal: List all remaining unimplemented spec items as queryable tasks.

  • src/server/routes/tasks.rs: SpecTask struct + 14 embedded backlog items
  • GET /tasks endpoint returns the full list
  • TUI TaskList mode (F4): 3-column table (section, title, priority) with cursor highlight
  • SPEC_TASKS_DISPLAY static array embedded in TUI for offline viewing
  • Files: src/server/routes/tasks.rs, src/server/routes/mod.rs, src/server/mod.rs, src/tui/mod.rs

Batch 3 — PLAN.md Features (completed 2026-03-26)

Feature A — Markdown rendering in TUI (spec-8.1-pulldown-cmark)

  • pulldown-cmark = "0.10" added to Cargo.toml
  • src/tui/markdown.rs: markdown_to_lines() converts markdown to styled ratatui Line objects
    • Handles: headings (cyan+bold), bold, italic, inline code (yellow), fenced code blocks (yellow), bullet lists, paragraphs, horizontal rules
    • 4 unit tests (plain text, bold, code block, empty input)
  • src/tui/mod.rs: mod markdown; added; Role::Assistant rendering calls markdown_to_lines() instead of plain line split
  • Files: Cargo.toml, src/tui/markdown.rs, src/tui/mod.rs

Feature B — GitHub Copilot provider (spec-8.2-copilot)

  • src/provider/copilot.rs: Full LlmProvider implementation using Copilot API
    • Token auto-detection: GITHUB_TOKEN env → ~/.config/github-copilot/hosts.jsongh auth token
    • Short-lived API token cache with auto-refresh (60s buffer before expiry)
    • OpenAI-compatible API at https://api.githubcopilot.com/chat/completions
    • Models: gpt-4o, gpt-4o-mini, claude-3.5-sonnet
  • src/provider/mod.rs: CopilotProvider::detect() called in ProviderRegistry::new(), pub mod copilot; added
  • Files: src/provider/copilot.rs, src/provider/mod.rs

Feature C — Session lifecycle integration tests (spec-12.2)

  • src/provider/mock.rs: MockProvider implementing LlmProvider — returns pre-configured responses without network
    • new(responses: Vec<String>) and with_response(text) constructors
    • Stream emits TextDelta then FinishStep with 10/5 token usage
  • src/provider/mod.rs: new_empty() and new_with_providers(Vec<Box<dyn LlmProvider>>) added
  • src/session/mod.rs: #[cfg(test)] module with test_fork_session integration test
  • Files: src/provider/mock.rs, src/provider/mod.rs, src/session/mod.rs

Feature D — HTTP endpoint contract tests (spec-12.3)

  • 14 new tests added to src/server/mod.rs #[cfg(test)] block:
    • Session: delete, update title, list messages (empty), get stats
    • Agents: list (200 + array), PATCH model
    • Config: PATCH model
    • Misc: list permissions, list tasks (14 items), get path, list questions, list skills, list commands, get VCS
  • Files: src/server/mod.rs

Feature E — MCP server real tool execution (spec-3.10)

  • src/mcp.rs: McpServer extended with 6 optional context fields (db, bus, permission, questions, providers, agents)
    • with_session_support() constructor wires all context fields
    • build_tool_context() helper builds ephemeral ToolContext for MCP calls
    • tools/call handler now calls tool.execute(args, &ctx).await instead of returning stub
  • src/main.rs: McpServer::new() replaced with McpServer::with_session_support()
  • Files: src/mcp.rs, src/main.rs


Batch 4 — PLAN.md Features (completed 2026-03-26)

Feature F — Always-allow permission rules (spec-11.2-always-rules)

  • Rule struct gains #[serde(default)] pub always: bool; Action derives PartialEq
  • evaluate_rules updated with 2-pass logic: always-allow short-circuits first, then last-match-wins
  • All Rule { } literals in tools, config, storage updated with always: false
  • 2 new tests: test_always_allow_bypasses_deny, test_always_deny_does_not_short_circuit
  • Files: src/models/mod.rs, src/permission/mod.rs, src/tools/mod.rs, src/tools/subtask.rs, src/config/mod.rs, src/storage/mod.rs

Feature G — GitLab AI provider (spec-8.2-gitlab)

  • src/provider/gitlab.rs: GitLabProvider using OpenAI-compatible GitLab AI gateway
    • Auto-detects GITLAB_TOKEN or CI_JOB_TOKEN; configurable via GITLAB_AI_BASE_URL
    • Models: Claude 3.5 Sonnet, Claude 3 Haiku, Mistral 7B Instruct
    • Reuses OpenAI SSE parser
  • src/provider/mod.rs: auto-detection + registration in ProviderRegistry::new()
  • Files: src/provider/gitlab.rs, src/provider/mod.rs

Feature H — Real Bedrock streaming (spec-7.1-bedrock-streaming)

  • hmac = "0.12", async-stream = "0.3", url = "2" added to Cargo.toml
  • sign_request_v4(): full AWS SigV4 signing with HMAC-SHA256 (no AWS SDK dependency)
  • parse_bedrock_event_stream(): binary AWS EventStream frame parser yields TextDelta + FinishStep
  • BedrockProvider::stream() replaced — calls converse-stream endpoint with signed requests
  • Files: Cargo.toml, src/provider/bedrock.rs

Feature I — WebSocket event stream (spec-5.1-websocket)

  • src/server/routes/ws.rs: ws_events handler using WebSocketUpgrade; relays all bus events as JSON text frames; handles client disconnect gracefully
  • GET /ws route added alongside GET /event (SSE)
  • Files: src/server/routes/ws.rs, src/server/routes/mod.rs, src/server/mod.rs

Feature J — Hot-reload skills (spec-9.4-skills-reload)

  • notify = "6" added to Cargo.toml
  • BusEvent::SkillsReloaded added to bus event enum
  • Background watcher task in main.rs: watches $QUICKCODE_HOME/skill/ with 500ms debounce, publishes SkillsReloaded on changes
  • is_session_event in session/mod.rs and handle_tui_event in tui/mod.rs updated for exhaustive match
  • Files: Cargo.toml, src/bus.rs, src/main.rs, src/session/mod.rs, src/tui/mod.rs

Feature K — LiteLLM dummy tool injection (spec-11.3-litellm)

  • In OpenAIProvider::stream(): detects provider_id.contains("litellm") or LITELLM_PROXY env var
  • Injects a _noop ToolDefinition when tools list is empty and LiteLLM is detected
  • Files: src/provider/openai.rs


Batch 5 — PLAN.md Features (completed 2026-03-26) — FINAL BATCH

Feature L — Fuzzy file picker in TUI (spec-8.1-fuzzy)

  • fuzzy-matcher = "0.3" added to Cargo.toml
  • AppMode::FilePicker { query, all_files, results, cursor } added to TUI
  • scan_files_sync(root): walks directory with ignore crate (respects .gitignore), caps at 10k entries
  • filter_files(all, query): SkimMatcherV2 fuzzy scoring, returns top 50 matches
  • Ctrl+P key binding in Chat mode opens the picker
  • Full key handling: Up/Down navigate, Enter inserts path into input, Esc cancels, typing re-filters
  • render_file_picker(): centered popup overlay (80%×60%) with query input box + highlighted file list
  • Files: Cargo.toml, src/tui/mod.rs

Feature M — Syntax highlighting in TUI (spec-8.1-syntect)

  • syntect = { version = "5", features = ["default-syntaxes", "default-themes", "parsing", "regex-fancy"] } added to Cargo.toml
  • src/tui/highlight.rs: highlight_code(code, lang) using syntect HighlightLines with base16-ocean.dark theme; converts syntect Colorratatui Color::Rgb; falls back to plain yellow on error
  • src/tui/markdown.rs: code blocks now buffer text into code_buffer, capture fenced language tag, call highlight_code() at End(CodeBlock) instead of rendering plain yellow spans
  • mod highlight; added to src/tui/mod.rs
  • Files: Cargo.toml, src/tui/highlight.rs, src/tui/markdown.rs, src/tui/mod.rs

Batch 6 — PLAN.md Spec Gaps (completed 2026-03-27)

gap-3: Bash output truncated to 30 KB

Spec Appendix B: Bash tool output must be truncated at 30 KB. MAX_OUTPUT_BYTES = 30 * 1024 and truncate_combined() were already in place — verified correct. Files: src/tools/bash.rs

gap-4: Glob / grep result limits enforced (100)

Spec Appendix B: Max 100 glob results, max 100 grep matches. Changed MAX_RESULTS / MAX_MATCHES from 1000 → 100. Added cap integration tests. Files: src/tools/glob_tool.rs, src/tools/grep_tool.rs

gap-5: Auth middleware uses QUICKCODE_SERVER_USERNAME

Spec §9.3: Updated basic_auth_middleware to read QUICKCODE_SERVER_USERNAME (default "quickcode") and validate both username and password. Files: src/server/mod.rs

gap-6: ~/.quickcode/quickcode.jsonc config path added

Spec §9.1 item 3: Added ~/.quickcode/quickcode.jsonc load step in load_config(). Files: src/config/mod.rs

gap-7: Web fetch response size limited to 5 MB

Spec Appendix B: Added Content-Length pre-check and streaming byte cap before body decode. Files: src/tools/web_fetch.rs

gap-8: QUICKCODE_MODELS_* env vars honoured

Spec §9.3: Renamed OPENCODE_*QUICKCODE_* for all three models-cache env vars. Files: src/provider/models_cache.rs

gap-1: PatchPart computed at FinishStep

Spec §3.8 / §6.7: Added step_snapshot_id tracking; calls Snapshot::patch() at FinishStep and writes a PatchPart to DB + bus. Files: src/session/mod.rs

gap-2: LSP diagnostics after write/edit (real implementation)

Spec §7.10: Extended LspClient reader to handle textDocument/publishDiagnostics notifications. Added notify_open(), get_stored_diagnostics(), and get_file_diagnostics(). Added lsp: Option<Arc<LspManager>> to ToolContext. Replaced the 100 ms stub in write.rs; added equivalent call in edit.rs. Files: src/lsp/mod.rs, src/tools/mod.rs, src/tools/write.rs, src/tools/edit.rs, src/session/mod.rs, src/mcp.rs

gap-9: Session share URL generated and persisted

Spec §5.1: share_session generates https://share.quickcode.dev/s/<id>, persists it via session_update, and returns it idempotently. Files: src/server/routes/session.rs

gap-10: Agent-level permission rules merged into ruleset

Spec §7.7: Added permission: Option<Vec<Rule>> to AgentOverride. Session processing now extends permission_rules with agent-specific rules from config. Files: src/config/mod.rs, src/session/mod.rs

gap-11: Model variant selection wired into session processing

Spec §7.1 / §11.8: resolve_model_variant() (already existed) is now called after model info lookup to use the best variant's model ID. Files: src/session/mod.rs

gap-12: Bash tool uses PTY via portable-pty

Spec §8.1: Replaced tokio::process::Command with portable_pty. Spawns bash -c inside a PTY slave; reads merged stdout+stderr from master until exit or timeout. Files: src/tools/bash.rs

gap-13: Multi-tenant workspace context threaded through session routes

Spec §5.1: Added resolve_workspace() helper; list_sessions filters by workspace; create_session accepts workspace in body/header/query and sets session.workspace_id. Files: src/server/routes/session.rs

gap-14: Integration tests for spec §12.2

Added to src/tools/mod.rs exec_tests:

  • test_write_tool_on_disk_verify — confirms file exists on disk after write
  • test_edit_tool_basic_replace — writes then edits, verifies on-disk content
  • test_bash_tool_permission_denied — deny rule blocks bash execution
  • test_glob_result_cap — glob never returns more than 100 results
  • test_grep_result_cap — grep never returns more than 100 matches Doom-loop tests already existed in src/permission/mod.rs. Files: src/tools/mod.rs

Final State

All PLAN.md gaps implemented. 84 tests passing. The only intentionally deferred item is spec-8.1-tree-sitter (tree-sitter AST parsing) which requires per-language grammar bindings and is out of scope.

Test coverage

  • 84 unit + integration tests passing (cargo test)
  • Full server route coverage: all major endpoints tested with correct status codes
  • Markdown renderer unit tests (including updated syntect code block test)
  • Session lifecycle tests (fork, create) using MockProvider
  • Permission always-allow rules: 2 dedicated tests
  • Tool execution: bash, write on-disk, edit, glob, grep (gap-14)
  • Permission deny rule enforcement (gap-14)
  • Result cap enforcement: glob ≤100, grep ≤100 (gap-14)

Batch 7 — Agent Memory System + Project Init (completed 2026-03-27)

memory_write / memory_read / memory_delete / memory_list tools

  • New memory table in SQLite schema (idempotent, id TEXT PRIMARY KEY with deterministic sha2-derived key)
  • Storage CRUD: memory_set, memory_get, memory_delete, memory_delete_by_session, memory_list
  • Four new tools registered in ToolRegistry:
    • memory_write — upsert by (scope, project_id, session_id, key)
    • memory_read — retrieve by coordinates
    • memory_delete — remove a single entry
    • memory_list — list all accessible entries, optionally filtered by scope and wildcard pattern
  • Three scopes:
    • session — short-term, lives within a single session (project_id + session_id)
    • project — long-term, shared across all sessions of a project
    • global — long-term, not tied to any project

QUICKCODE.md project context

  • POST /project/init route added: scans project files (README, manifests, etc.), calls LLM to generate QUICKCODE.md, writes it to the worktree root, sets project.time_initialized
  • Falls back to a static template if no LLM provider is authenticated
  • QUICKCODE.md content is automatically injected into every session's system prompt (step 4a in SessionProcessor::process)
  • Persisted project-scope memory entries are also injected into the system prompt (step 4b)

Supporting changes

  • ToolContext gained project_id: ProjectId field; all construction sites updated (session/mod.rs, mcp.rs, test helpers)
  • session::default_model made pub (used by the init route)
  • storage::SCHEMA made pub (used by memory test helper)
  • 6 new integration tests in tools::memory_tests (write/read session, project, global scope; delete; list+pattern; invalid scope)
  • Test count: 84 → 90