Skip to content

feat: add proto setup interactive wizard with STT configuration - #92

Merged
mabry1985 merged 33 commits into
mainfrom
fix/telemetry-gate-and-malformed-toolcall-drop
Apr 24, 2026
Merged

mabry1985 merged 33 commits into
mainfrom
fix/telemetry-gate-and-malformed-toolcall-drop

Conversation

@mabry1985

@mabry1985 mabry1985 commented Apr 24, 2026

Copy link
Copy Markdown
Member

Summary

Interactive CLI command to configure model providers without manual JSON editing.

proto setup wizard flow:

  1. Provider selection — OpenAI, OpenAI-compatible, Anthropic, Gemini
  2. Base URL — smart defaults per provider, custom endpoint support
  3. API key — masked input, detects existing env vars
  4. Model discovery — live GET /models call, paginated selector
  5. Default model — pick from discovered models
  6. STT configuration — optional voice input setup, defaults to same provider endpoint
  7. Provider label — optional friendly name
  8. Persist — writes to ~/.proto/settings.json

Files added:

  • packages/cli/src/commands/setup.ts — yargs subcommand
  • packages/cli/src/commands/setup/handler.ts — wizard logic
  • packages/cli/src/commands/setup/modelDiscovery.ts/models endpoint client
  • packages/cli/src/ui/commands/setupCommand.ts/setup slash command
  • 16 unit tests

Files modified:

  • config.ts — register yargs command
  • BuiltinCommandLoader.ts — register slash command

Summary by CodeRabbit

  • New Features

    • Added CLI setup command for interactive provider, API key, and model configuration (with model discovery)
    • Added /memory subcommands to manage proposals (list, accept, reject)
    • Automatic evolve pass that can generate skill drafts/proposals after agent turns
    • Tool permission blocker that records repeated denials
  • Improvements

    • Cron jobs now persist across sessions
    • Better handling of malformed streaming tool-calls
    • Memory staleness warnings by memory type

Automaker and others added 30 commits April 14, 2026 16:22
- prepare-release.yml: fires on PR merge to dev (not main); version bump
  PR targets dev instead of main
- release.yml: triggers on dev→main PR merge instead of commit message
  on push; adds sync-back step to keep dev aligned with main after release

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(ui): apply ASCII logo gradient by X column, not string index

ink-gradient maps colors by character index across the whole string, so
the p descender (last two lines) always got the tail/pink color regardless
of its leftward visual position.

Fix: render each logo line separately with its own <Gradient>, padded to
logoWidth so column X maps to the same gradient fraction on every line.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

* fix(ui): remove Static windowing that caused messages to disappear

Ink's <Static> tracks rendered items by array INDEX, not React key.
It stores the last array length and slices from that index on each render.
When the array stops growing (constant length), the index overshoots
and nothing new is printed — causing streamed messages to vanish.

PR #45 introduced two patterns that broke this invariant:
1. STATIC_HISTORY_WINDOW=200 in MainContent.tsx — sliding window kept
   the array at a constant 204 items (3 fixed + 200 history + banner),
   so after the 201st history item nothing was ever printed by Static.
2. MAX_HISTORY_ITEMS=500 in useHistoryManager.ts — pruning the front
   of the array kept it at exactly 500 items, same effect.
3. Same AGENT_STATIC_HISTORY_WINDOW=200 windowing in AgentChatView.tsx.

Fix: pass all history items to Static (array only ever grows).
Remove TruncatedHistoryBanner from within Static (it can't update
once committed to the terminal anyway, and its conditional insertion
shifted existing indices on first appearance).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Automaker <automaker@localhost>
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
…rotection)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… failure

- schemaValidator: add Array.isArray guard so array tool params return
  'Value of params must be an object' immediately instead of reaching AJV
- openai converter: return plain string content for text-only tool messages
  instead of [{type:'text',...}] array — LiteLLM and most OpenAI-compatible
  local providers only accept string content and crash on array content parts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Single-text tool responses (validation errors, simple outputs) now return
content as a plain string instead of [{type:'text',text:'...'}] array.
Many OpenAI-compatible providers (LiteLLM, local models) only accept string
content in tool messages and crash with 'Can only get item pairs from a
mapping' on array content.

Multi-part responses (text+media, multi-text blocks, unsupported media
placeholders) keep array format to preserve all content parts.

Reverts the overly broad Array.isArray guard in schemaValidator — AJV already
rejects arrays for object-typed schemas, and the guard incorrectly blocked
valid array inputs for 2020-12 prefixItems schemas.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…on cascade

When a weak/local model hits max_tokens and produces empty responses,
tool errors accumulate in context causing subsequent calls to also fail
with NO_RESPONSE_TEXT. Add trimToolErrorsFromContext() to strip trailing
model-tool-call + user-tool-error pairs (up to 6 pairs), then attempt
one final recovery call with the cleaned context before giving up.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
When a model hits max_tokens mid-tool-call (producing Shell {}), the
truncation error gets re-added to context making the next turn also
overflow. At the start of each sendMessageStream, detect the cascade
(truncation-guidance marker in the last user turn) and pre-trim:
1. Remove the error tool-call pairs (trimToolErrorsFromContext)
2. Cap any large preceding tool responses to 10K chars

This prevents the Shell {} → error → Shell {} loop that affected both
weak models and frontier models (Claude Sonnet) on large tool outputs.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
… history

When dev→main is squash-merged, the tag-to-tag git log only shows
"chore: release" commits which get filtered, silently skipping the
Discord post. Add a fallback that checks origin/dev (which retains the
individual commits at release time) and a post-discord.yml workflow
for manual backfill.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
ACP tests were hardcoded to use `methodId: 'openai'` and the e2e
workflow passed OPENAI_API_KEY, which is not configured in CI. Since
protoCLI uses Anthropic as its primary provider, update everything to
use Anthropic auth:

- authMethods.ts: expose USE_ANTHROPIC instead of USE_OPENAI
- acp-integration.test.ts: change authenticate to methodId 'anthropic',
  update openaiModel selector to anthropicModel, skip qwen-oauth test
  (Qwen-specific model type, no equivalent in protoCLI)
- acp-cron.test.ts: same authenticate change
- e2e.yml: pass ANTHROPIC_API_KEY instead of OpenAI secrets

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
The LiteLLM gateway uses USE_OPENAI auth (OPENAI_API_KEY + OPENAI_BASE_URL
+ OPENAI_MODEL). The v0.25.17 change to Anthropic auth was incorrect.

Reverts all test and workflow changes back to openai methodId and
OPENAI_* secrets. The actual fix required is adding the three gateway
secrets (OPENAI_API_KEY, OPENAI_BASE_URL, OPENAI_MODEL) to GitHub
repository secrets.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
ACP tests require gateway credentials that are not configured in CI.
Since ACP is not currently in use, skip these tests automatically
when OPENAI_API_KEY is absent rather than failing the E2E job.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
- sdk.ts: route Langfuse-only log/metric exporters to OTLP endpoints
  instead of ConsoleLog/MetricExporter to prevent terminal spam
- loggingContentGenerator: wrap generateContentStream in llm.generate
  span; pass span into loggingStreamWrapper and close with token counts
  on success/error
- agent-headless: create agent.execute span under turn context; wrap
  runReasoningLoop in otelContext.with() for proper child span linkage
- harnessTelemetry: remove dead recordSprintContract() never called
- gemini.tsx: register shutdownTelemetry() in cleanup so OTel SDK
  flushes spans before interactive REPL exits

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
- Persist cron jobs to disk so scheduled tasks survive session restarts
- Inject capability manifest (active MCP tools) into system prompt to prevent hallucinated tool names
- Add per-type memory staleness thresholds (project=21d, reference=7d) with inline freshness warnings
- Route memory extractions through a proposal lane (/memory proposals|accept|reject) instead of writing directly
- Track repeated tool denials in permission-blockers.json and inject reminders into system prompt
- Add post-turn evolve pipeline: headless agent detects reusable workflow patterns every 3 turns and drafts SKILL.md candidates
- Formalize prompt section volatility tags (stable/workspace/run) with assemblePromptSections() and CACHE_BOUNDARY_SENTINEL for provider-side caching

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Automaker and others added 2 commits April 23, 2026 21:16
…op malformed tool_calls

- sdk.ts: useOtlp now requires config.getTelemetryEnabled(), so Langfuse-only
  users no longer spawn a gRPC exporter aimed at the localhost:4317 default
  and spam ECONNREFUSED. Closes the regression from 10c1bd0 that re-defaulted
  the endpoint.
- streamingToolCallParser.ts: getCompletedToolCalls() now returns malformed=true
  when every parse strategy (JSON.parse, string auto-close, jsonrepair) fails
  or jsonrepair returns a non-object. Inlined jsonrepair so the fallback can
  be distinguished from a successful repair.
- converter.ts: on a malformed tool_call during streaming, drop the functionCall
  entirely and emit a visible text note. Prevents poisoned tool_calls from
  entering conversation history, which was causing LiteLLM/Pydantic to fail
  subsequent turns with "Can only get item pairs from a mapping" when vLLM
  streams interleaved prose+JSON via a mismatched Qwen chat template.
- Tests: regression for Langfuse-only no-OTLP path; malformed-flag parser
  coverage; converter drops malformed stream chunks and emits recovery text.

Root cause remains upstream (vLLM --tool-call-parser qwen3_xml for Qwen3);
this is defense-in-depth so proto degrades gracefully instead of hard-failing.
Interactive CLI command to configure model providers without manual
JSON editing. Walks through provider selection, base URL, API key
(masked input), live model discovery via /models endpoint, default
model picker, and optional STT endpoint configuration.

STT defaults to the same base URL as the configured provider so
voice input works out of the box.

- proto setup (yargs subcommand)
- /setup (in-session slash command, points to terminal wizard)
- fetchAvailableModels() utility with OpenAI-standard parsing
- 16 unit tests for model discovery + slash command

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
@coderabbitai

coderabbitai Bot commented Apr 24, 2026

Copy link
Copy Markdown

Walkthrough

Adds an interactive CLI setup wizard and model discovery, introduces a proposal-based memory workflow with accept/reject, implements permission-blocking and a background skill-evolution pass, improves streaming tool-call parsing and cron job persistence, and adjusts telemetry gating and various prompt/cron/storage integrations.

Changes

Cohort / File(s) Summary
Setup CLI Command & Discovery
packages/cli/src/commands/setup.ts, packages/cli/src/commands/setup/handler.ts, packages/cli/src/commands/setup/modelDiscovery.ts, packages/cli/src/commands/setup/modelDiscovery.test.ts, packages/cli/src/config/config.ts, packages/cli/src/services/BuiltinCommandLoader.ts
Adds setup CLI command and interactive wizard that discovers OpenAI-compatible models, normalizes base URLs, handles auth/token entry or env reuse, prompts STT/voice options, merges and persists provider configs and keys, and includes robust model-discovery error handling and tests.
Memory Proposals & Review Workflow
packages/core/src/memory/proposalStore.ts, packages/core/src/memory/memoryExtractor.ts, packages/core/src/memory/memoryAge.ts, packages/core/src/memory/index.ts, packages/core/src/memory/memoryStore.ts
Introduces proposals directory and APIs to list/accept/reject proposals; extractor now emits proposals (not direct memories); adds type-aware staleness thresholds and warnings; memory index includes staleness notices.
Permission Blocker Service & Integration
packages/core/src/services/permissionBlockerService.ts, packages/core/src/config/config.ts, packages/core/src/config/storage.ts, packages/core/src/core/coreToolScheduler.ts
New PermissionBlockerService that persists per-tool denial counts, exposes blocked-tools listing and prompt note; Config wires service; scheduler records denials when confirmations are cancelled.
Prompt Assembly, Capability Manifest & Client
packages/core/src/core/prompts.ts, packages/core/src/core/client.ts, packages/core/src/core/client.test.ts
Adds volatility-aware prompt sections and assemblePromptSections helper with cache boundary sentinel; adds buildCapabilityManifest for MCP tools; client now assembles segmented system prompt and appends permission-blocker note; tests updated to mock prompt assembly.
Streaming Tool-Call Parsing & Converter
packages/core/src/core/openaiContentGenerator/streamingToolCallParser.ts, packages/core/src/core/openaiContentGenerator/converter.ts, packages/core/src/core/openaiContentGenerator/converter.test.ts, packages/core/src/core/openaiContentGenerator/streamingToolCallParser.test.ts
Improves parsing via parseArgsBuffer (JSON.parse → quote-close → jsonrepair), flags unrecoverable tool calls as malformed, returns empty args for malformed cases, and has converter emit recovery text instead of invalid function calls; adds tests for malformed and edge cases.
Cron Scheduler Persistence
packages/core/src/services/cronScheduler.ts, packages/core/src/services/cronScheduler.test.ts, packages/core/src/config/config.ts, packages/core/src/config/storage.ts
CronScheduler gains optional disk persistence (constructor persistPath), loads/saves jobs across sessions, excludes expired jobs, and updates exit summary wording; Config/Storage provide project-scoped persist path; tests updated.
Skill Evolution Service & Hook Integration
packages/core/src/services/evolveService.ts, packages/core/src/index.ts, packages/cli/src/ui/hooks/useGeminiStream.ts
Adds runEvolvePass to periodically review recent messages and propose skill drafts/proposals; exported from core; Gemini stream hook triggers non-blocking evolve pass post-turn with silent error handling.
Memory Commands & Setup UI
packages/cli/src/ui/commands/memoryCommand.ts, packages/cli/src/ui/commands/setupCommand.ts, packages/cli/src/ui/commands/setupCommand.test.ts
Adds /memory subcommands: proposals, accept, reject to manage proposals; adds built-in /setup slash command that instructs running proto setup in terminal; includes unit tests.
Telemetry & Miscellaneous Updates
packages/core/src/telemetry/sdk.ts, packages/core/src/telemetry/sdk.test.ts, packages/core/src/services/memory-consolidation.ts, packages/core/src/core/openaiContentGenerator/*
Gates OTLP exporter creation on telemetry-enabled config (preventing default localhost exporters when only Langfuse is configured); adds regression test; updates memory-consolidation calls to new isStale signature and adjusts streaming conversion tests/behavior.
Public API & Exports
packages/core/src/index.ts, packages/core/src/memory/index.ts
Re-exports runEvolvePass and exposes proposal-store utilities in memory index to make new services available to consumers.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 64.71% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main feature: adding an interactive setup wizard for configuring model providers with STT support.
Description check ✅ Passed The description is comprehensive and well-structured, covering the wizard flow, files added/modified, and key implementation details. It aligns well with the template requirements and provides sufficient context for reviewers.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/telemetry-gate-and-malformed-toolcall-drop

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/core/src/core/coreToolScheduler.ts (1)

1193-1201: ⚠️ Potential issue | 🟠 Major

Only record denials for explicit user rejection, not generic aborts.

Line 1193 includes signal.aborted, but Line 1199 persists a denial unconditionally in that branch. Session/tool aborts can then be miscounted as permission denials, leading to incorrect persistent blocking behavior.

💡 Suggested fix
-    if (outcome === ToolConfirmationOutcome.Cancel || signal.aborted) {
+    const wasExplicitDeny = outcome === ToolConfirmationOutcome.Cancel;
+    if (wasExplicitDeny || signal.aborted) {
       // Use custom cancel message from payload if provided, otherwise use default
       const cancelMessage =
         payload?.cancelMessage || 'User did not allow tool call';
       this.setStatusInternal(callId, 'cancelled', cancelMessage);
-      // Record the denial so persistent blockers can warn the agent next session
-      this.config
-        .getPermissionBlockerService?.()
-        ?.recordDenial(toolCall.request.name);
+      if (wasExplicitDeny) {
+        // Record explicit denial so persistent blockers reflect user intent.
+        this.config
+          .getPermissionBlockerService?.()
+          ?.recordDenial(toolCall.request.name);
+      }
     } else if (outcome === ToolConfirmationOutcome.ModifyWithEditor) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/core/coreToolScheduler.ts` around lines 1193 - 1201, The
current branch treats both explicit user cancellation and generic aborts the
same, causing recordDenial to run even for aborted signals; change the logic so
only explicit user rejections trigger persistent denials: keep the cancel
message and setStatusInternal(callId, 'cancelled', ...), but call
this.config.getPermissionBlockerService?.()?.recordDenial(toolCall.request.name)
only when outcome === ToolConfirmationOutcome.Cancel (i.e., not when
signal.aborted) so aborts are not recorded as denials.
🧹 Nitpick comments (6)
packages/core/src/services/evolveService.ts (2)

54-59: Fix evolveSkilsDir typo for clarity and future safety.

evolveSkilsDir is misspelled in variable names and context key (Lines 54, 99, 122). Rename to evolveSkillsDir consistently to reduce accidental key mismatches later.

Also applies to: 99-100, 122-123

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/services/evolveService.ts` around lines 54 - 59, Rename the
misspelled identifier evolveSkilsDir to evolveSkillsDir everywhere in this
module: update the variable declaration (const evolveSkilsDir), all references
that read/write it, and any context key strings or object properties named
"evolveSkilsDir" to "evolveSkillsDir" (e.g., usages around where the variable is
created and later accessed). Ensure consistency for any functions or methods
referencing it (search for evolveSkilsDir and replace), and update any exported
names or imports from other files if they reference the old identifier so
callers use evolveSkillsDir instead.

62-63: Avoid swallowing directory creation failures silently.

Lines 62-63 suppress all mkdir errors, which makes operational failures hard to debug. At least log the error at debug level before continuing.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/services/evolveService.ts` around lines 62 - 63, The two
await fs.mkdir calls for evolveSkilsDir and proposalsDir currently swallow all
errors; change them to capture errors and log at debug level before continuing
(e.g., replace .catch(() => {}) with .catch(err => logger.debug(...) ) or wrap
each mkdir in try/catch), referencing the mkdir calls for evolveSkilsDir and
proposalsDir in evolveService.ts; ensure you use the repository's existing
logger instance (e.g., processLogger or logger) and include the error object and
path in the debug message.
packages/core/src/telemetry/sdk.test.ts (1)

299-301: Optional: assert NodeSDK was constructed before indexing the first call.

Adding expect(sdkCalls.length).toBe(1) before dereferencing sdkCalls[0] makes failures clearer and avoids accidental undefined access in this test path.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/telemetry/sdk.test.ts` around lines 299 - 301, The test
dereferences sdkCalls[0] without confirming NodeSDK was actually constructed;
add an assertion like expect(sdkCalls.length).toBe(1) (or similar) before
accessing sdkCalls[0] so the test fails with a clear message instead of throwing
on undefined—update the assertions around NodeSDK/mock.calls and the
spanProcessors extraction to include this check (references: NodeSDK, sdkCalls,
spanProcessors).
packages/core/src/services/permissionBlockerService.ts (1)

61-71: Consider edge case: denial count could grow unbounded.

The count increments indefinitely. While this is fine for the prompt display ("denied 5x"), consider whether there's value in capping it or adding decay logic for very old denials.

This is a minor consideration for future enhancement — the current implementation is functionally correct.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/services/permissionBlockerService.ts` around lines 61 - 71,
The recordDenial method in permissionBlockerService currently increments denial
counts without bound (recordDenial → this.denials), which could lead to
unbounded growth; modify recordDenial to enforce a max cap (e.g., clamp count to
MAX_DENIAL_COUNT) and/or implement decay by resetting or halving counts older
than a threshold using lastSeenAt so very old denials don’t accumulate; update
the DenialRecord handling in recordDenial and any persistent save/load logic so
the cap/decay is respected when using saveToDisk and when reading from
this.denials.
packages/core/src/services/cronScheduler.ts (1)

291-292: Consider batching disk writes in tick().

saveToDisk() is called inside the loop for each fired job. If multiple jobs fire in the same tick, this causes redundant disk writes.

♻️ Suggested optimization
   tick(now?: Date): void {
     const currentDate = now ?? new Date();
     const currentMs = currentDate.getTime();
+    let dirty = false;
 
     for (const job of this.jobs.values()) {
       // Check expiry
       if (currentMs >= job.expiresAt) {
         this.jobs.delete(job.id);
+        dirty = true;
         continue;
       }
       // ... matching logic ...
 
       if (!job.recurring) {
         this.jobs.delete(job.id);
       }
 
-      this.saveToDisk();
+      dirty = true;
 
       if (this.onFire) {
         this.onFire(job);
       }
     }
+
+    if (dirty) {
+      this.saveToDisk();
+    }
   }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/services/cronScheduler.ts` around lines 291 - 292, The code
currently calls saveToDisk() inside the per-job loop in tick(), causing
redundant writes when multiple jobs fire in the same tick; change tick() to
batch writes by deferring saveToDisk() until after the loop (or set a dirty flag
like "needsPersist" inside the loop and call saveToDisk() once if set),
referencing the CronScheduler.tick() loop and the saveToDisk() method so only a
single disk write occurs per tick even when multiple jobs fire.
packages/core/src/core/prompts.ts (1)

1278-1295: Consider deterministic sorting to reduce prompt churn.

Ordering currently follows insertion order of Map/arrays. Sorting servers and tool names before render makes capability manifests stable across runs and reduces avoidable prompt diffs.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/core/prompts.ts` around lines 1278 - 1295, The MCP tools
and skills are rendered in insertion order causing non-deterministic prompt
churn; update the rendering in the block that uses mcpToolsByServer and
activeSkills so you iterate deterministically: for mcpToolsByServer, get server
keys, sort them, and for each server sort the tools list (prior to tools.join)
before pushing the line; for activeSkills, sort the activeSkills array (or a
shallow copy) by skill.name before slicing descriptions and emitting
`/skill.name` lines; keep the same symbols mcpToolsByServer, tools, skill, and
activeSkills so only the iteration order changes.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cli/src/commands/setup/handler.ts`:
- Around line 543-544: The code is persisting raw environment secrets into
settings by calling settings.setValue(scope, `env.${envKey}`, apiKey) with the
value returned from promptApiKey(); change this so you do NOT write back an
env-sourced secret. Update promptApiKey() usage (or its return) to indicate
source (e.g., return { key, source } or provide a boolean like isFromEnv) and in
the handler guard the write: only call settings.setValue(scope, `env.${envKey}`,
apiKey) when the key was entered interactively (not sourced from process.env);
if you still need to record that the env key exists, store a non-secret sentinel
(e.g., 'ENV') or a metadata flag instead of the raw secret.
- Around line 377-488: The promptText and promptMaskedText helpers directly
toggle stdin.setRawMode and write to stdout, bypassing the CLI's Ink-based UI;
replace these raw-mode implementations with Ink-driven components used by the
setup wizard (so the interactive prompting composes with the rest of
packages/cli). Refactor calls to promptText and promptMaskedText into Ink
prompts (e.g., create a PromptText and MaskedPrompt React components) that
render using Ink hooks (useInput/useStdout) and return values via
props/callbacks or a Promise wrapper used by the handler; remove direct
stdin.setRawMode/stdout.write usage from promptText/promptMaskedText (or convert
them into adapters that simply mount the Ink component and resolve when it
completes) so all terminal I/O is handled through Ink's input/output APIs and
the components can be composed with the existing CLI UI.
- Around line 321-324: The version-presence check incorrectly only matches
numeric versions so a base like '/v1beta' doesn't count and you end up appending
'/v1' to produce '/v1beta/v1'; update the check around the normalised variable
(the "Ensure /v1 is present" block that tests normalised.match(...)) to use a
regex that accepts alphanumeric version segments (e.g., '/v' followed by letters
and/or digits) instead of only digits so paths like '/v1beta' are treated as
valid and you won't append '/v1'.
- Around line 37-42: The Anthropic preset is incorrectly using
AuthType.USE_OPENAI; update the anthropic preset object in handler.ts to set
authType to AuthType.USE_ANTHROPIC so the CLI saves and routes Anthropic
credentials through the correct auth flow (modify the anthropic object's
authType property accordingly).

In `@packages/cli/src/commands/setup/modelDiscovery.ts`:
- Around line 89-99: The code in modelDiscovery.ts appends "/v1" by checking
only purely numeric version suffixes; update the regex checks on the normalised
variable to treat versioned bases like "/v1beta" as already-versioned. Replace
the existing /\/v\d+$/ and /\/v\d+\// tests with patterns that allow
alphanumeric version suffixes (e.g. /\/v\d+[A-Za-z0-9_-]*$/ and
/\/v\d+[A-Za-z0-9_-]*\//) so strings like "/v1beta" or "/v2alpha" are detected
and "/v1" is not appended.

In `@packages/core/src/core/openaiContentGenerator/streamingToolCallParser.ts`:
- Around line 306-312: The error log in streamingToolCallParser.ts currently
emits raw buffer previews via debugLogger.error (the call that includes index,
bufferPreview: buffer.slice(0,200), bufferLength), which can leak sensitive
data; change this to avoid logging raw content by removing bufferPreview or
replacing it with a non-sensitive artifact (e.g., bufferLength plus a
deterministic hash/digest of the preview or a fully redacted marker). Update the
debugLogger.error invocation in the parsing routine that handles malformed
tool_call arguments (the function invoking debugLogger.error with index and
buffer) to only emit structural metadata (index, bufferLength) and optionally a
SHA-256 or other stable hash of the slice instead of the plain text preview.

In `@packages/core/src/core/prompts.ts`:
- Around line 1280-1293: The code currently injects raw manifest fields into the
system prompt in the mcpToolsByServer loop and the activeSkills loop (see the
for (const [server, tools] of mcpToolsByServer) block and the for (const skill
of activeSkills) block), so sanitize server, each tool, skill.name and
skill.description before formatting: strip or replace newlines and control
characters, remove or escape markdown-sensitive characters (e.g., *, _, `, #, >,
-, [, ], (, )), trim and then apply existing truncation for descriptions; use
the sanitized values when building lines and when joining tools to prevent
prompt-structure injection.

In `@packages/core/src/memory/proposalStore.ts`:
- Around line 81-107: acceptProposal and rejectProposal currently trust
proposalFilePath and can rename/unlink arbitrary files; before performing
fs.rename or fs.unlink validate that proposalFilePath resolves inside the
proposals directory for the given scope. Use getMemoryDir(scope, cwd) (or
getMemoryDir for reject by deriving scope if available) and compute an absolute
resolved path for both memoryDir and proposalFilePath (e.g., path.resolve) then
ensure the proposal path is a child of memoryDir (e.g., check
path.relative(memoryDir, proposalPath) does not start with '..' and is not equal
to '..'); if the check fails return null (for acceptProposal) or false (for
rejectProposal) and do not perform fs operations. Also keep existing mkdir and
regenerateIndex calls only after the validation passes.

In `@packages/core/src/services/evolveService.ts`:
- Around line 37-49: The code uses a process-global turnsSinceLastReview and
lacks an in-flight guard, causing cadence to be shared across Configs and
allowing overlapping runEvolvePass executions; change to per-Config state (e.g.,
a WeakMap<Config, { turns: number; running: boolean }>) keyed by the Config
instance and update runEvolvePass to read/increment the per-Config turns counter
(using SKILL_REVIEW_INTERVAL) and return early per-instance, and add an
in-flight guard (set running=true before the async work in runEvolvePass and
clear it in a finally block) so concurrent calls for the same Config are
serialized.

---

Outside diff comments:
In `@packages/core/src/core/coreToolScheduler.ts`:
- Around line 1193-1201: The current branch treats both explicit user
cancellation and generic aborts the same, causing recordDenial to run even for
aborted signals; change the logic so only explicit user rejections trigger
persistent denials: keep the cancel message and setStatusInternal(callId,
'cancelled', ...), but call
this.config.getPermissionBlockerService?.()?.recordDenial(toolCall.request.name)
only when outcome === ToolConfirmationOutcome.Cancel (i.e., not when
signal.aborted) so aborts are not recorded as denials.

---

Nitpick comments:
In `@packages/core/src/core/prompts.ts`:
- Around line 1278-1295: The MCP tools and skills are rendered in insertion
order causing non-deterministic prompt churn; update the rendering in the block
that uses mcpToolsByServer and activeSkills so you iterate deterministically:
for mcpToolsByServer, get server keys, sort them, and for each server sort the
tools list (prior to tools.join) before pushing the line; for activeSkills, sort
the activeSkills array (or a shallow copy) by skill.name before slicing
descriptions and emitting `/skill.name` lines; keep the same symbols
mcpToolsByServer, tools, skill, and activeSkills so only the iteration order
changes.

In `@packages/core/src/services/cronScheduler.ts`:
- Around line 291-292: The code currently calls saveToDisk() inside the per-job
loop in tick(), causing redundant writes when multiple jobs fire in the same
tick; change tick() to batch writes by deferring saveToDisk() until after the
loop (or set a dirty flag like "needsPersist" inside the loop and call
saveToDisk() once if set), referencing the CronScheduler.tick() loop and the
saveToDisk() method so only a single disk write occurs per tick even when
multiple jobs fire.

In `@packages/core/src/services/evolveService.ts`:
- Around line 54-59: Rename the misspelled identifier evolveSkilsDir to
evolveSkillsDir everywhere in this module: update the variable declaration
(const evolveSkilsDir), all references that read/write it, and any context key
strings or object properties named "evolveSkilsDir" to "evolveSkillsDir" (e.g.,
usages around where the variable is created and later accessed). Ensure
consistency for any functions or methods referencing it (search for
evolveSkilsDir and replace), and update any exported names or imports from other
files if they reference the old identifier so callers use evolveSkillsDir
instead.
- Around line 62-63: The two await fs.mkdir calls for evolveSkilsDir and
proposalsDir currently swallow all errors; change them to capture errors and log
at debug level before continuing (e.g., replace .catch(() => {}) with .catch(err
=> logger.debug(...) ) or wrap each mkdir in try/catch), referencing the mkdir
calls for evolveSkilsDir and proposalsDir in evolveService.ts; ensure you use
the repository's existing logger instance (e.g., processLogger or logger) and
include the error object and path in the debug message.

In `@packages/core/src/services/permissionBlockerService.ts`:
- Around line 61-71: The recordDenial method in permissionBlockerService
currently increments denial counts without bound (recordDenial → this.denials),
which could lead to unbounded growth; modify recordDenial to enforce a max cap
(e.g., clamp count to MAX_DENIAL_COUNT) and/or implement decay by resetting or
halving counts older than a threshold using lastSeenAt so very old denials don’t
accumulate; update the DenialRecord handling in recordDenial and any persistent
save/load logic so the cap/decay is respected when using saveToDisk and when
reading from this.denials.

In `@packages/core/src/telemetry/sdk.test.ts`:
- Around line 299-301: The test dereferences sdkCalls[0] without confirming
NodeSDK was actually constructed; add an assertion like
expect(sdkCalls.length).toBe(1) (or similar) before accessing sdkCalls[0] so the
test fails with a clear message instead of throwing on undefined—update the
assertions around NodeSDK/mock.calls and the spanProcessors extraction to
include this check (references: NodeSDK, sdkCalls, spanProcessors).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 3ee776bc-2737-48f6-977a-954de4c84625

📥 Commits

Reviewing files that changed from the base of the PR and between 27aee4d and fc08b40.

⛔ Files ignored due to path filters (1)
  • packages/core/src/core/__snapshots__/prompts.test.ts.snap is excluded by !**/*.snap
📒 Files selected for processing (33)
  • packages/cli/src/commands/setup.ts
  • packages/cli/src/commands/setup/handler.ts
  • packages/cli/src/commands/setup/modelDiscovery.test.ts
  • packages/cli/src/commands/setup/modelDiscovery.ts
  • packages/cli/src/config/config.ts
  • packages/cli/src/services/BuiltinCommandLoader.ts
  • packages/cli/src/ui/commands/memoryCommand.ts
  • packages/cli/src/ui/commands/setupCommand.test.ts
  • packages/cli/src/ui/commands/setupCommand.ts
  • packages/cli/src/ui/hooks/useGeminiStream.ts
  • packages/core/src/config/config.ts
  • packages/core/src/config/storage.ts
  • packages/core/src/core/client.test.ts
  • packages/core/src/core/client.ts
  • packages/core/src/core/coreToolScheduler.ts
  • packages/core/src/core/openaiContentGenerator/converter.test.ts
  • packages/core/src/core/openaiContentGenerator/converter.ts
  • packages/core/src/core/openaiContentGenerator/streamingToolCallParser.test.ts
  • packages/core/src/core/openaiContentGenerator/streamingToolCallParser.ts
  • packages/core/src/core/prompts.ts
  • packages/core/src/index.ts
  • packages/core/src/memory/index.ts
  • packages/core/src/memory/memoryAge.ts
  • packages/core/src/memory/memoryExtractor.ts
  • packages/core/src/memory/memoryStore.ts
  • packages/core/src/memory/proposalStore.ts
  • packages/core/src/services/cronScheduler.test.ts
  • packages/core/src/services/cronScheduler.ts
  • packages/core/src/services/evolveService.ts
  • packages/core/src/services/memory-consolidation.ts
  • packages/core/src/services/permissionBlockerService.ts
  • packages/core/src/telemetry/sdk.test.ts
  • packages/core/src/telemetry/sdk.ts

Comment thread packages/cli/src/commands/setup/handler.ts
Comment thread packages/cli/src/commands/setup/handler.ts Outdated
Comment on lines +377 to +488
function promptText(label: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
stdout.write(label);

if (!stdin.setRawMode) {
reject(
new Error(
'Raw mode not available. Please run in an interactive terminal.',
),
);
return;
}

const wasRaw = stdin.isRaw;
stdin.setRawMode(true);
stdin.resume();
stdin.setEncoding('utf8');

let input = '';

const onData = (chunk: string) => {
for (const char of chunk) {
switch (char) {
case '\r':
case '\n':
stdin.removeListener('data', onData);
stdin.setRawMode(wasRaw);
stdout.write('\n');
resolve(input);
return;
case '\x03': // Ctrl+C
stdin.removeListener('data', onData);
stdin.setRawMode(wasRaw);
stdout.write('\n');
reject(new Error('Interrupted'));
return;
case '\x08': // Backspace
case '\x7F': // Delete
if (input.length > 0) {
input = input.slice(0, -1);
stdout.write('\x1B[D \x1B[D');
}
break;
default:
if (char.charCodeAt(0) >= 32) {
input += char;
stdout.write(char);
}
break;
}
}
};

stdin.on('data', onData);
});
}

function promptMaskedText(label: string): Promise<string> {
return new Promise<string>((resolve, reject) => {
stdout.write(label);

if (!stdin.setRawMode) {
reject(
new Error(
'Raw mode not available. Please run in an interactive terminal.',
),
);
return;
}

const wasRaw = stdin.isRaw;
stdin.setRawMode(true);
stdin.resume();
stdin.setEncoding('utf8');

let input = '';

const onData = (chunk: string) => {
for (const char of chunk) {
switch (char) {
case '\r':
case '\n':
stdin.removeListener('data', onData);
stdin.setRawMode(wasRaw);
stdout.write('\n');
resolve(input);
return;
case '\x03': // Ctrl+C
stdin.removeListener('data', onData);
stdin.setRawMode(wasRaw);
stdout.write('\n');
reject(new Error('Interrupted'));
return;
case '\x08':
case '\x7F':
if (input.length > 0) {
input = input.slice(0, -1);
stdout.write('\x1B[D \x1B[D');
}
break;
default:
if (char.charCodeAt(0) >= 32) {
input += char;
stdout.write('*');
}
break;
}
}
};

stdin.on('data', onData);
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion | 🟠 Major

Move the wizard prompts onto Ink instead of manual raw-mode I/O.

These helpers toggle raw mode and paint the terminal directly, which bypasses the CLI’s UI framework and will be harder to compose with the rest of packages/cli.

As per coding guidelines, packages/cli/**/*.{ts,tsx}: Use Ink (React for CLI) for building terminal user interfaces.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/setup/handler.ts` around lines 377 - 488, The
promptText and promptMaskedText helpers directly toggle stdin.setRawMode and
write to stdout, bypassing the CLI's Ink-based UI; replace these raw-mode
implementations with Ink-driven components used by the setup wizard (so the
interactive prompting composes with the rest of packages/cli). Refactor calls to
promptText and promptMaskedText into Ink prompts (e.g., create a PromptText and
MaskedPrompt React components) that render using Ink hooks (useInput/useStdout)
and return values via props/callbacks or a Promise wrapper used by the handler;
remove direct stdin.setRawMode/stdout.write usage from
promptText/promptMaskedText (or convert them into adapters that simply mount the
Ink component and resolve when it completes) so all terminal I/O is handled
through Ink's input/output APIs and the components can be composed with the
existing CLI UI.

Comment thread packages/cli/src/commands/setup/handler.ts Outdated
Comment thread packages/cli/src/commands/setup/modelDiscovery.ts Outdated
Comment on lines +306 to +312
debugLogger.error(
'Failed to parse tool_call arguments; marking malformed',
{
index,
bufferPreview: buffer.slice(0, 200),
bufferLength: buffer.length,
},

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Avoid logging raw tool-call argument previews.

Lines 306-312 log the first 200 characters of a malformed arguments buffer at error level. These buffers can easily contain file contents, prompts, secrets, or PII, so a parser failure becomes a sensitive-data logging path. Log only structural metadata here, or a fully redacted/hash-based preview.

🔒 Suggested change
     debugLogger.error(
       'Failed to parse tool_call arguments; marking malformed',
       {
         index,
-        bufferPreview: buffer.slice(0, 200),
         bufferLength: buffer.length,
+        depth: this.depths.get(index) ?? 0,
+        inString: this.inStrings.get(index) ?? false,
       },
     );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/core/openaiContentGenerator/streamingToolCallParser.ts`
around lines 306 - 312, The error log in streamingToolCallParser.ts currently
emits raw buffer previews via debugLogger.error (the call that includes index,
bufferPreview: buffer.slice(0,200), bufferLength), which can leak sensitive
data; change this to avoid logging raw content by removing bufferPreview or
replacing it with a non-sensitive artifact (e.g., bufferLength plus a
deterministic hash/digest of the preview or a fully redacted marker). Update the
debugLogger.error invocation in the parsing routine that handles malformed
tool_call arguments (the function invoking debugLogger.error with index and
buffer) to only emit structural metadata (index, bufferLength) and optionally a
SHA-256 or other stable hash of the slice instead of the plain text preview.

Comment on lines +1280 to +1293
for (const [server, tools] of mcpToolsByServer) {
lines.push(` • ${server}: ${tools.join(', ')}`);
}
sections.push(lines.join('\n'));
}

if (activeSkills.length > 0) {
const lines: string[] = ['**Skills (invoke via /skill or agent tool):**'];
for (const skill of activeSkills) {
const desc = skill.description
? ` — ${skill.description.slice(0, 80)}${skill.description.length > 80 ? '…' : ''}`
: '';
lines.push(` • /${skill.name}${desc}`);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Sanitize manifest fields before embedding into the system prompt.

Line 1281 and Line 1292 inject server, tool, skill.name, and skill.description directly into markdown. If any of these contain newlines/markdown control text, they can break prompt structure and inject unintended instructions.

🔧 Suggested hardening diff
+function sanitizePromptText(value: string): string {
+  return value
+    .replace(/[\r\n\t]+/g, ' ')
+    .replace(/[<>`]/g, '')
+    .trim();
+}
+
 export function buildCapabilityManifest(
   mcpToolsByServer: Map<string, string[]>,
   activeSkills: Array<{ name: string; description: string }>,
 ): string | null {
   const sections: string[] = [];
@@
   if (mcpToolsByServer.size > 0) {
     const lines: string[] = ['**MCP tools available this session:**'];
     for (const [server, tools] of mcpToolsByServer) {
-      lines.push(`  • ${server}: ${tools.join(', ')}`);
+      const safeServer = sanitizePromptText(server);
+      const safeTools = tools.map(sanitizePromptText);
+      lines.push(`  • ${safeServer}: ${safeTools.join(', ')}`);
     }
     sections.push(lines.join('\n'));
   }
@@
     for (const skill of activeSkills) {
-      const desc = skill.description
-        ? ` — ${skill.description.slice(0, 80)}${skill.description.length > 80 ? '…' : ''}`
+      const safeName = sanitizePromptText(skill.name);
+      const safeDescription = sanitizePromptText(skill.description ?? '');
+      const desc = safeDescription
+        ? ` — ${safeDescription.slice(0, 80)}${safeDescription.length > 80 ? '…' : ''}`
         : '';
-      lines.push(`  • /${skill.name}${desc}`);
+      lines.push(`  • /${safeName}${desc}`);
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/core/prompts.ts` around lines 1280 - 1293, The code
currently injects raw manifest fields into the system prompt in the
mcpToolsByServer loop and the activeSkills loop (see the for (const [server,
tools] of mcpToolsByServer) block and the for (const skill of activeSkills)
block), so sanitize server, each tool, skill.name and skill.description before
formatting: strip or replace newlines and control characters, remove or escape
markdown-sensitive characters (e.g., *, _, `, #, >, -, [, ], (, )), trim and
then apply existing truncation for descriptions; use the sanitized values when
building lines and when joining tools to prevent prompt-structure injection.

Comment on lines +81 to +107
export async function acceptProposal(
proposalFilePath: string,
scope: MemoryScope,
cwd?: string,
): Promise<string | null> {
const memoryDir = getMemoryDir(scope, cwd);
const destPath = path.join(memoryDir, path.basename(proposalFilePath));

try {
await fs.mkdir(memoryDir, { recursive: true });
await fs.rename(proposalFilePath, destPath);
await regenerateIndex(scope, cwd);
return destPath;
} catch {
return null;
}
}

/**
* Reject (delete) a proposal file.
*/
export async function rejectProposal(
proposalFilePath: string,
): Promise<boolean> {
try {
await fs.unlink(proposalFilePath);
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Enforce proposals-directory boundary before rename/delete.

Line 91 and Line 106 trust proposalFilePath without validation. This allows moving/deleting arbitrary files if an unexpected path reaches these APIs.

🔒 Suggested guardrail diff
 export const PROPOSALS_DIR_NAME = 'proposals';
+
+function isPathInside(parentDir: string, candidatePath: string): boolean {
+  const rel = path.relative(parentDir, candidatePath);
+  return rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
+}
@@
 export async function acceptProposal(
   proposalFilePath: string,
   scope: MemoryScope,
   cwd?: string,
 ): Promise<string | null> {
+  const proposalsDir = getProposalsDir(scope, cwd);
+  const resolvedSource = path.resolve(proposalFilePath);
+  const resolvedProposalsDir = path.resolve(proposalsDir);
+  if (!isPathInside(resolvedProposalsDir, resolvedSource)) return null;
+
   const memoryDir = getMemoryDir(scope, cwd);
-  const destPath = path.join(memoryDir, path.basename(proposalFilePath));
+  const destPath = path.join(memoryDir, path.basename(resolvedSource));
@@
-    await fs.rename(proposalFilePath, destPath);
+    await fs.rename(resolvedSource, destPath);
@@
 export async function rejectProposal(
-  proposalFilePath: string,
+  proposalFilePath: string,
+  scope: MemoryScope,
+  cwd?: string,
 ): Promise<boolean> {
+  const proposalsDir = getProposalsDir(scope, cwd);
+  const resolvedSource = path.resolve(proposalFilePath);
+  const resolvedProposalsDir = path.resolve(proposalsDir);
+  if (!isPathInside(resolvedProposalsDir, resolvedSource)) return false;
+
   try {
-    await fs.unlink(proposalFilePath);
+    await fs.unlink(resolvedSource);
     return true;
   } catch {
     return false;
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/memory/proposalStore.ts` around lines 81 - 107,
acceptProposal and rejectProposal currently trust proposalFilePath and can
rename/unlink arbitrary files; before performing fs.rename or fs.unlink validate
that proposalFilePath resolves inside the proposals directory for the given
scope. Use getMemoryDir(scope, cwd) (or getMemoryDir for reject by deriving
scope if available) and compute an absolute resolved path for both memoryDir and
proposalFilePath (e.g., path.resolve) then ensure the proposal path is a child
of memoryDir (e.g., check path.relative(memoryDir, proposalPath) does not start
with '..' and is not equal to '..'); if the check fails return null (for
acceptProposal) or false (for rejectProposal) and do not perform fs operations.
Also keep existing mkdir and regenerateIndex calls only after the validation
passes.

Comment on lines +37 to +49
let turnsSinceLastReview = 0;

/**
* Call after each agent turn completes. Runs skill candidate detection every
* SKILL_REVIEW_INTERVAL turns. Fire-and-forget; errors are logged only.
*/
export async function runEvolvePass(
config: Config,
recentMessages: Array<{ role: string; text: string }>,
): Promise<void> {
turnsSinceLastReview++;
if (turnsSinceLastReview < SKILL_REVIEW_INTERVAL) return;
turnsSinceLastReview = 0;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Global turn state can cross-contaminate sessions and allow overlapping runs.

Lines 37-49 use a process-global counter, so separate Config instances share cadence. Also, there is no in-flight guard around Lines 88-103, so multiple evolve passes can overlap under fast consecutive turns.

Suggested fix
-let turnsSinceLastReview = 0;
+type EvolveState = { turnsSinceLastReview: number; inProgress: boolean };
+const evolveStateByConfig = new WeakMap<Config, EvolveState>();
+
+function getEvolveState(config: Config): EvolveState {
+  let state = evolveStateByConfig.get(config);
+  if (!state) {
+    state = { turnsSinceLastReview: 0, inProgress: false };
+    evolveStateByConfig.set(config, state);
+  }
+  return state;
+}
@@
 export async function runEvolvePass(
   config: Config,
   recentMessages: Array<{ role: string; text: string }>,
 ): Promise<void> {
-  turnsSinceLastReview++;
-  if (turnsSinceLastReview < SKILL_REVIEW_INTERVAL) return;
-  turnsSinceLastReview = 0;
+  const state = getEvolveState(config);
+  if (state.inProgress) return;
+
+  state.turnsSinceLastReview++;
+  if (state.turnsSinceLastReview < SKILL_REVIEW_INTERVAL) return;
+  state.turnsSinceLastReview = 0;
@@
-  try {
+  state.inProgress = true;
+  try {
@@
   } catch (err) {
     logger.debug('Evolve pass skipped:', err);
+  } finally {
+    state.inProgress = false;
   }
 }

Also applies to: 88-107

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/core/src/services/evolveService.ts` around lines 37 - 49, The code
uses a process-global turnsSinceLastReview and lacks an in-flight guard, causing
cadence to be shared across Configs and allowing overlapping runEvolvePass
executions; change to per-Config state (e.g., a WeakMap<Config, { turns: number;
running: boolean }>) keyed by the Config instance and update runEvolvePass to
read/increment the per-Config turns counter (using SKILL_REVIEW_INTERVAL) and
return early per-instance, and add an in-flight guard (set running=true before
the async work in runEvolvePass and clear it in a finally block) so concurrent
calls for the same Config are serialized.

@github-actions

github-actions Bot commented Apr 24, 2026

Copy link
Copy Markdown
Contributor

Code Coverage Summary

Package Lines Statements Functions Branches
CLI 54.33% 54.33% 65.59% 78.79%
Core 71.14% 71.14% 74.4% 80.41%
CLI Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   54.33 |    78.79 |   65.59 |   54.33 |                   
 src               |   66.54 |     64.8 |   73.68 |   66.54 |                   
  gemini.tsx       |   61.02 |    63.15 |      75 |   61.02 | ...06,514-517,526 
  ...ractiveCli.ts |   58.33 |    58.06 |      50 |   58.33 | ...20,435,439-562 
  ...liCommands.ts |   83.77 |    69.76 |     100 |   83.77 | ...12,247,249,377 
  ...ActiveAuth.ts |   94.11 |    82.35 |     100 |   94.11 | 27-30             
 ...cp-integration |    6.22 |    33.33 |    12.5 |    6.22 |                   
  acpAgent.ts      |    3.12 |        0 |       0 |    3.12 | 67-121,124-578    
  authMethods.ts   |   17.85 |      100 |       0 |   17.85 | 11-22,25-29,32-37 
  errorCodes.ts    |       0 |        0 |       0 |       0 | 1-22              
  ...DirContext.ts |     100 |      100 |     100 |     100 |                   
 ...ration/service |   68.65 |    83.33 |   66.66 |   68.65 |                   
  filesystem.ts    |   68.65 |    83.33 |   66.66 |   68.65 | ...32,77-94,97-98 
 ...ration/session |   63.91 |    60.61 |    74.5 |   63.91 |                   
  ...ryReplayer.ts |      76 |    79.41 |      90 |      76 | ...19-220,228-229 
  Session.ts       |   56.05 |    48.09 |    62.5 |   56.05 | ...1408,1414-1417 
  ...entTracker.ts |   90.85 |    84.84 |      90 |   90.85 | ...35,199,251-260 
  index.ts         |       0 |        0 |       0 |       0 | 1-40              
  ...ssionUtils.ts |   74.59 |    73.07 |     100 |   74.59 | ...73-189,204-206 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ssion/emitters |   92.48 |    87.12 |      92 |   92.48 |                   
  BaseEmitter.ts   |    82.6 |       75 |      80 |    82.6 | 23-24,50-51       
  ...ageEmitter.ts |     100 |    83.33 |     100 |     100 | 84-86             
  PlanEmitter.ts   |     100 |      100 |     100 |     100 |                   
  ...allEmitter.ts |   91.37 |    86.79 |     100 |   91.37 | ...28-229,318,326 
  index.ts         |       0 |        0 |       0 |       0 | 1-10              
 src/commands      |   70.63 |      100 |   15.38 |   70.63 |                   
  auth.ts          |      44 |      100 |       0 |      44 | ...50,59-63,66-67 
  extensions.tsx   |   96.55 |      100 |      50 |   96.55 | 37                
  hooks.tsx        |   66.66 |      100 |       0 |   66.66 | 20-24             
  mcp.ts           |   94.73 |      100 |      50 |   94.73 | 28                
  setup.ts         |   84.61 |      100 |       0 |   84.61 | 18-19             
 src/commands/auth |   45.07 |    95.65 |   64.28 |   45.07 |                   
  handler.ts       |   28.29 |    93.75 |   16.66 |   28.29 | 55-349            
  ...veSelector.ts |     100 |    96.66 |     100 |     100 | 58                
 ...nds/extensions |   84.53 |    88.95 |   81.81 |   84.53 |                   
  consent.ts       |   71.65 |    89.28 |   42.85 |   71.65 | ...85-141,156-162 
  disable.ts       |     100 |      100 |     100 |     100 |                   
  enable.ts        |     100 |      100 |     100 |     100 |                   
  install.ts       |    75.6 |    66.66 |   66.66 |    75.6 | ...39-142,145-153 
  link.ts          |     100 |      100 |     100 |     100 |                   
  list.ts          |     100 |      100 |     100 |     100 |                   
  new.ts           |     100 |      100 |     100 |     100 |                   
  settings.ts      |   99.15 |      100 |   83.33 |   99.15 | 151               
  uninstall.ts     |    37.5 |      100 |   33.33 |    37.5 | 23-45,57-64,67-70 
  update.ts        |   96.32 |      100 |     100 |   96.32 | 101-105           
  utils.ts         |   60.24 |    28.57 |     100 |   60.24 | ...81,83-87,89-93 
 ...les/mcp-server |       0 |        0 |       0 |       0 |                   
  example.ts       |       0 |        0 |       0 |       0 | 1-60              
 src/commands/mcp  |   91.28 |    82.97 |   88.88 |   91.28 |                   
  add.ts           |     100 |    96.66 |     100 |     100 | 213               
  list.ts          |   91.22 |    80.76 |      80 |   91.22 | ...19-121,146-147 
  reconnect.ts     |   76.72 |    71.42 |   85.71 |   76.72 | 35-48,153-175     
  remove.ts        |     100 |       80 |     100 |     100 | 21-25             
 ...commands/setup |    23.4 |    81.25 |   21.42 |    23.4 |                   
  handler.ts       |    7.99 |      100 |       0 |    7.99 | 57-578            
  ...lDiscovery.ts |   93.75 |    81.25 |     100 |   93.75 | ...,86-87,103-104 
 src/config        |      91 |     80.3 |   84.12 |      91 |                   
  auth.ts          |   86.66 |    77.55 |     100 |   86.66 | ...92-193,209-210 
  config.ts        |   86.78 |    81.61 |   72.22 |   86.78 | ...1166,1188-1189 
  keyBindings.ts   |   95.95 |       50 |     100 |   95.95 | 160-163           
  ...idersScope.ts |      92 |       90 |     100 |      92 | 11-12             
  sandboxConfig.ts |   54.16 |    23.07 |   66.66 |   54.16 | ...44,54-68,73-89 
  settings.ts      |   80.69 |    82.05 |   81.81 |   80.69 | ...98-699,775-792 
  ...ingsSchema.ts |     100 |      100 |     100 |     100 |                   
  ...tedFolders.ts |   96.29 |       94 |     100 |   96.29 | ...88-190,205-206 
  webSearch.ts     |   42.37 |       25 |     100 |   42.37 | ...6,86-93,96-112 
 ...nfig/migration |   94.56 |    78.94 |   83.33 |   94.56 |                   
  index.ts         |   93.93 |    88.88 |     100 |   93.93 | 85-86             
  scheduler.ts     |   96.55 |    77.77 |     100 |   96.55 | 19-20             
  types.ts         |       0 |        0 |       0 |       0 | 1                 
 ...ation/versions |   93.63 |     94.5 |     100 |   93.63 |                   
  ...-v2-shared.ts |     100 |      100 |     100 |     100 |                   
  v1-to-v2.ts      |   81.75 |    90.19 |     100 |   81.75 | ...28-229,231-247 
  v2-to-v3.ts      |     100 |      100 |     100 |     100 |                   
 src/constants     |   93.02 |    94.11 |   66.66 |   93.02 |                   
  ...dardApiKey.ts |     100 |      100 |     100 |     100 |                   
  codingPlan.ts    |   92.74 |    94.11 |   66.66 |   92.74 | ...00-301,309-321 
 src/core          |   51.51 |    33.33 |   33.33 |   51.51 |                   
  auth.ts          |    9.52 |      100 |       0 |    9.52 | 21-48             
  initializer.ts   |   84.37 |    33.33 |     100 |   84.37 | 41,55-58          
  theme.ts         |   38.46 |      100 |       0 |   38.46 | 17-24             
 src/generated     |     100 |      100 |     100 |     100 |                   
  git-commit.ts    |     100 |      100 |     100 |     100 |                   
 src/i18n          |   43.69 |    76.19 |   38.88 |   43.69 |                   
  index.ts         |   26.11 |    76.92 |   26.66 |   26.11 | ...35-236,246-257 
  languages.ts     |   98.27 |       75 |     100 |   98.27 | 88                
 src/i18n/locales  |       0 |        0 |       0 |       0 |                   
  de.js            |       0 |        0 |       0 |       0 | 1-1965            
  en.js            |       0 |        0 |       0 |       0 | 1-2006            
  ja.js            |       0 |        0 |       0 |       0 | 1-1459            
  pt.js            |       0 |        0 |       0 |       0 | 1-1957            
  ru.js            |       0 |        0 |       0 |       0 | 1-1964            
  zh.js            |       0 |        0 |       0 |       0 | 1-1811            
 ...nonInteractive |   68.34 |    71.68 |   68.88 |   68.34 |                   
  session.ts       |    73.1 |    69.52 |   81.81 |    73.1 | ...03-604,612-622 
  types.ts         |    42.5 |      100 |   33.33 |    42.5 | ...74-575,578-579 
 ...active/control |   77.48 |       88 |      80 |   77.48 |                   
  ...rolContext.ts |    7.69 |        0 |       0 |    7.69 | 47-79             
  ...Dispatcher.ts |   91.63 |    91.66 |   88.88 |   91.63 | ...54-372,387,390 
  ...rolService.ts |       8 |        0 |       0 |       8 | 46-179            
 ...ol/controllers |    7.32 |       80 |   13.79 |    7.32 |                   
  ...Controller.ts |   19.32 |      100 |      60 |   19.32 | 81-118,127-210    
  ...Controller.ts |       0 |        0 |       0 |       0 | 1-56              
  ...Controller.ts |    3.96 |      100 |   11.11 |    3.96 | ...61-379,389-494 
  ...Controller.ts |   14.06 |      100 |       0 |   14.06 | ...82-117,130-133 
  ...Controller.ts |    5.72 |      100 |       0 |    5.72 | ...72-384,393-418 
 .../control/types |       0 |        0 |       0 |       0 |                   
  serviceAPIs.ts   |       0 |        0 |       0 |       0 | 1                 
 ...Interactive/io |   97.57 |    92.91 |   96.15 |   97.57 |                   
  ...putAdapter.ts |    97.3 |    91.75 |     100 |    97.3 | ...1272,1297-1298 
  ...putAdapter.ts |      96 |    91.66 |   85.71 |      96 | 51-52             
  ...nputReader.ts |     100 |    94.73 |     100 |     100 | 67                
  ...putAdapter.ts |   98.23 |      100 |   89.47 |   98.23 | 70-71,111-112     
 src/patches       |       0 |        0 |       0 |       0 |                   
  is-in-ci.ts      |       0 |        0 |       0 |       0 | 1-17              
 src/services      |   89.24 |     87.2 |   96.87 |   89.24 |                   
  ...mandLoader.ts |     100 |      100 |     100 |     100 |                   
  ...killLoader.ts |     100 |      100 |     100 |     100 |                   
  ...andService.ts |     100 |      100 |     100 |     100 |                   
  ...mandLoader.ts |   86.61 |    82.14 |     100 |   86.61 | ...29-334,339-344 
  ...omptLoader.ts |    75.1 |    80.64 |   83.33 |    75.1 | ...03-204,270-271 
  audioCapture.ts  |   98.33 |    93.75 |     100 |   98.33 | 71                
  ...nd-factory.ts |    91.2 |    93.33 |     100 |    91.2 | 119-126           
  ...ation-tool.ts |     100 |    95.45 |     100 |     100 | 125               
  ...and-parser.ts |   89.74 |    85.71 |     100 |   89.74 | 59-62             
  sttClient.ts     |   93.33 |       75 |     100 |   93.33 | 28-29             
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...ght/generators |   85.95 |    86.42 |   90.47 |   85.95 |                   
  DataProcessor.ts |   85.68 |    86.46 |   92.85 |   85.68 | ...1110,1114-1121 
  ...tGenerator.ts |   98.21 |    85.71 |     100 |   98.21 | 46                
  ...teRenderer.ts |   45.45 |      100 |       0 |   45.45 | 13-51             
 .../insight/types |       0 |       50 |      50 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 |                   
  ...sightTypes.ts |       0 |        0 |       0 |       0 | 1                 
 ...mpt-processors |   97.27 |    94.04 |     100 |   97.27 |                   
  ...tProcessor.ts |     100 |      100 |     100 |     100 |                   
  ...eProcessor.ts |   94.52 |    84.21 |     100 |   94.52 | 46-47,93-94       
  ...tionParser.ts |     100 |      100 |     100 |     100 |                   
  ...lProcessor.ts |   97.41 |    95.65 |     100 |   97.41 | 95-98             
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/test-utils    |   93.63 |    83.33 |      80 |   93.63 |                   
  ...omMatchers.ts |   69.69 |       50 |      50 |   69.69 | 32-35,37-39,45-47 
  ...andContext.ts |     100 |      100 |     100 |     100 |                   
  render.tsx       |     100 |      100 |     100 |     100 |                   
 src/ui            |   68.33 |    67.92 |   48.64 |   68.33 |                   
  App.tsx          |     100 |      100 |     100 |     100 |                   
  AppContainer.tsx |    73.6 |    57.52 |   42.85 |    73.6 | ...1250,1656-1662 
  ...tionNudge.tsx |    9.58 |      100 |       0 |    9.58 | 24-94             
  ...ackDialog.tsx |   29.23 |      100 |       0 |   29.23 | 25-75             
  ...tionNudge.tsx |    7.69 |      100 |       0 |    7.69 | 25-103            
  colors.ts        |   56.36 |      100 |   29.41 |   56.36 | ...49,51-52,60-61 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  keyMatchers.ts   |   91.83 |    88.46 |     100 |   91.83 | 25-26,54-55       
  ...tic-colors.ts |     100 |      100 |     100 |     100 |                   
  textConstants.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/auth       |   29.54 |    46.34 |   26.08 |   29.54 |                   
  AuthDialog.tsx   |   51.95 |     47.5 |   28.57 |   51.95 | ...53,672,674,676 
  ...nProgress.tsx |       0 |        0 |       0 |       0 | 1-64              
  useAuth.ts       |     2.3 |      100 |       0 |     2.3 | 45-595            
 src/ui/commands   |   51.99 |    79.53 |   43.78 |   51.99 |                   
  aboutCommand.ts  |     100 |      100 |     100 |     100 |                   
  agentsCommand.ts |    64.7 |      100 |       0 |    64.7 | ...30,35-36,39-41 
  ...odeCommand.ts |     100 |      100 |     100 |     100 |                   
  arenaCommand.ts  |   32.65 |    67.64 |    37.5 |   32.65 | ...52-557,636-641 
  authCommand.ts   |     100 |      100 |     100 |     100 |                   
  btwCommand.ts    |     100 |    90.32 |     100 |     100 | 25,199,213        
  bugCommand.ts    |   76.47 |    66.66 |      50 |   76.47 | 21-22,57-66       
  clearCommand.ts  |   89.65 |    55.55 |      50 |   89.65 | 23-24,49-50,68-69 
  ...essCommand.ts |   63.15 |       50 |      50 |   63.15 | ...47-148,162-165 
  ...extCommand.ts |    4.65 |      100 |       0 |    4.65 | ...8,93-96,99-375 
  copyCommand.ts   |   96.22 |      100 |      50 |   96.22 | 15-16             
  ...ryCommand.tsx |   59.19 |    73.07 |    37.5 |   59.19 | ...15-216,224-232 
  docsCommand.ts   |   95.23 |       80 |      50 |   95.23 | 20-21             
  editorCommand.ts |     100 |      100 |     100 |     100 |                   
  exportCommand.ts |   55.97 |    91.66 |   33.33 |   55.97 | ...48-349,356-357 
  ...onsCommand.ts |   44.09 |    85.71 |   27.27 |   44.09 | ...35-236,244-245 
  helpCommand.ts   |     100 |      100 |     100 |     100 |                   
  hooksCommand.ts  |   42.72 |       60 |   33.33 |   42.72 | ...86-116,123-124 
  ideCommand.ts    |   41.91 |    69.23 |   21.42 |   41.91 | ...08-209,212-226 
  index.ts         |       0 |        0 |       0 |       0 | 1-20              
  initCommand.ts   |    81.7 |       70 |      50 |    81.7 | ...67,81-86,88-93 
  ...ghtCommand.ts |   69.23 |       40 |   66.66 |   69.23 | ...97-111,116-129 
  ...ageCommand.ts |   89.24 |    82.35 |   76.92 |   89.24 | ...20-323,345-346 
  mcpCommand.ts    |   85.71 |      100 |      50 |   85.71 | 14-15             
  memoryCommand.ts |   44.63 |    84.61 |   23.07 |   44.63 | ...69,574-575,593 
  modelCommand.ts  |   57.31 |       80 |   66.66 |   57.31 | 24-33,51-77       
  notesCommand.ts  |    9.32 |      100 |       0 |    9.32 | 27-30,33-151      
  ...onsCommand.ts |     100 |      100 |     100 |     100 |                   
  quitCommand.ts   |   93.75 |      100 |      50 |   93.75 | 15-16             
  ...oreCommand.ts |   92.24 |     87.5 |     100 |   92.24 | ...,83-88,129-130 
  resumeCommand.ts |     100 |      100 |     100 |     100 |                   
  rewindCommand.ts |    62.5 |      100 |       0 |    62.5 | 17-22             
  ...ngsCommand.ts |     100 |      100 |     100 |     100 |                   
  setupCommand.ts  |     100 |      100 |     100 |     100 |                   
  ...hubCommand.ts |   80.12 |    63.63 |      60 |   80.12 | ...69-172,175-178 
  skillsCommand.ts |   12.28 |      100 |       0 |   12.28 | ...91-109,112-139 
  statsCommand.ts  |   76.92 |       75 |      50 |   76.92 | ...36,50-51,65-66 
  ...aryCommand.ts |    4.61 |      100 |       0 |    4.61 | 21-24,27-322      
  teamCommand.ts   |   15.55 |      100 |       0 |   15.55 | ...70-271,274-298 
  ...tupCommand.ts |     100 |      100 |     100 |     100 |                   
  themeCommand.ts  |     100 |      100 |     100 |     100 |                   
  toolsCommand.ts  |   95.12 |      100 |      50 |   95.12 | 18-19             
  trustCommand.ts  |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
  vimCommand.ts    |   42.85 |      100 |       0 |   42.85 | 14-15,18-28       
  voiceCommand.ts  |   35.08 |      100 |       0 |   35.08 | 29-51,55-73       
 src/ui/components |   56.76 |    72.57 |   58.39 |   56.76 |                   
  AboutBox.tsx     |     100 |      100 |     100 |     100 |                   
  AnsiOutput.tsx   |     100 |      100 |     100 |     100 |                   
  ApiKeyInput.tsx  |   18.91 |      100 |       0 |   18.91 | 30-95             
  AppHeader.tsx    |   89.58 |       50 |     100 |   89.58 | 33-38             
  ...odeDialog.tsx |     9.7 |      100 |       0 |     9.7 | 35-47,50-182      
  AsciiArt.ts      |     100 |      100 |     100 |     100 |                   
  ...Indicator.tsx |   13.95 |      100 |       0 |   13.95 | 18-58             
  ...TextInput.tsx |   63.22 |    70.27 |      50 |   63.22 | ...12,220-222,240 
  Composer.tsx     |   89.89 |    58.33 |      50 |   89.89 | ...-55,73,112,125 
  ...itDisplay.tsx |   55.81 |      100 |      50 |   55.81 | 22-38,42-43       
  ...entPrompt.tsx |     100 |      100 |     100 |     100 |                   
  ...ryDisplay.tsx |   75.89 |    62.06 |     100 |   75.89 | ...,88,93-108,113 
  ...geDisplay.tsx |   90.47 |       75 |     100 |   90.47 | 20-21             
  ...ification.tsx |   28.57 |      100 |       0 |   28.57 | 16-36             
  ...gProfiler.tsx |       0 |        0 |       0 |       0 | 1-36              
  ...ogManager.tsx |    8.42 |      100 |       0 |    8.42 | 53-563            
  ...ngsDialog.tsx |    8.44 |      100 |       0 |    8.44 | 37-195            
  ExitWarning.tsx  |     100 |      100 |     100 |     100 |                   
  ...ustDialog.tsx |     100 |      100 |     100 |     100 |                   
  Footer.tsx       |   75.22 |       35 |     100 |   75.22 | ...74,87-91,93-97 
  ...ngSpinner.tsx |   54.28 |       50 |      50 |   54.28 | 31-48,61          
  Header.tsx       |   94.49 |    78.57 |     100 |   94.49 | 95,97,102-105     
  Help.tsx         |   98.74 |    68.75 |     100 |   98.74 | 74,129            
  ...emDisplay.tsx |    68.9 |     42.1 |     100 |    68.9 | ...19-225,228,231 
  ...ngeDialog.tsx |     100 |      100 |     100 |     100 |                   
  InputPrompt.tsx  |   79.19 |    75.08 |     100 |   79.19 | ...1306-1322,1364 
  ...Shortcuts.tsx |   21.11 |      100 |       0 |   21.11 | ...5,48-50,66-124 
  ...Indicator.tsx |     100 |      100 |     100 |     100 |                   
  ...firmation.tsx |   91.42 |      100 |      50 |   91.42 | 26-31             
  MainContent.tsx  |   18.05 |      100 |       0 |   18.05 | 25-92             
  ...geDisplay.tsx |       0 |        0 |       0 |       0 | 1-41              
  ModelDialog.tsx  |   75.13 |    40.98 |     100 |   75.13 | ...17-433,478-482 
  ...tsDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...fications.tsx |   18.18 |      100 |       0 |   18.18 | 15-58             
  ...onsDialog.tsx |    2.18 |      100 |       0 |    2.18 | 62-133,148-986    
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...icePrompt.tsx |   88.14 |    83.87 |     100 |   88.14 | ...01-105,133-138 
  PrepareLabel.tsx |   91.66 |    76.19 |     100 |   91.66 | 73-75,77-79,110   
  ...geDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...ngDisplay.tsx |   21.42 |      100 |       0 |   21.42 | 13-39             
  RewindDialog.tsx |       0 |        0 |       0 |       0 | 1-217             
  RewindPicker.tsx |    3.35 |      100 |       0 |    3.35 | 48-70,89-394      
  ...ionPicker.tsx |   94.18 |    92.85 |     100 |   94.18 | 79,194-202        
  ...ryDisplay.tsx |     100 |      100 |     100 |     100 |                   
  ...putPrompt.tsx |   72.56 |       80 |      40 |   72.56 | ...06-109,114-117 
  ...ngsDialog.tsx |   66.75 |    72.66 |     100 |   66.75 | ...72-780,786-787 
  ...ionDialog.tsx |    87.8 |      100 |   33.33 |    87.8 | 36-39,44-51       
  ...putPrompt.tsx |    15.9 |      100 |       0 |    15.9 | 20-63             
  ...Indicator.tsx |   44.44 |      100 |       0 |   44.44 | 12-17             
  ...MoreLines.tsx |      28 |      100 |       0 |      28 | 18-40             
  ...ionPicker.tsx |    7.86 |      100 |       0 |    7.86 | 21-131            
  StatsDisplay.tsx |   98.66 |    93.33 |     100 |   98.66 | 199-201           
  StatusBar.tsx    |      12 |      100 |       0 |      12 | ...4,44-49,66-163 
  ...nsDisplay.tsx |   84.09 |    57.14 |     100 |   84.09 | ...16-118,125-127 
  ...ffDisplay.tsx |   18.42 |      100 |       0 |   18.42 | 16-18,25-58       
  ThemeDialog.tsx  |   90.95 |    44.44 |      75 |   90.95 | ...16-117,159-161 
  Tips.tsx         |      75 |       60 |      75 |      75 | 23,48-49,52-62    
  TodoDisplay.tsx  |     100 |      100 |     100 |     100 |                   
  ...tsDisplay.tsx |     100 |     87.5 |     100 |     100 | 31-32             
  ...oryBanner.tsx |       0 |        0 |       0 |       0 | 1-26              
  TrustDialog.tsx  |     100 |    81.81 |     100 |     100 | 71-86             
  ...ification.tsx |   36.36 |      100 |       0 |   36.36 | 15-22             
  ...MicButton.tsx |   11.11 |      100 |       0 |   11.11 | 26-81             
  ...ackDialog.tsx |    7.84 |      100 |       0 |    7.84 | 24-134            
 ...nts/agent-view |   24.89 |    89.36 |    12.5 |   24.89 |                   
  ...tChatView.tsx |     8.1 |      100 |       0 |     8.1 | 53-283            
  ...tComposer.tsx |    9.95 |      100 |       0 |    9.95 | 57-308            
  AgentFooter.tsx  |   17.07 |      100 |       0 |   17.07 | 28-66             
  AgentHeader.tsx  |   15.38 |      100 |       0 |   15.38 | 27-64             
  AgentTabBar.tsx  |    8.25 |      100 |       0 |    8.25 | 35-55,60-167      
  ...oryAdapter.ts |     100 |     91.3 |     100 |     100 | 102,108-109,137   
  index.ts         |       0 |        0 |       0 |       0 | 1-12              
 ...mponents/arena |    5.89 |      100 |       0 |    5.89 |                   
  ArenaCards.tsx   |       4 |      100 |       0 |       4 | 24-129,134-290    
  ...ectDialog.tsx |    5.28 |      100 |       0 |    5.28 | 32-260            
  ...artDialog.tsx |   10.34 |      100 |       0 |   10.34 | 26-147            
  ...tusDialog.tsx |    5.63 |      100 |       0 |    5.63 | 33-75,80-288      
  ...topDialog.tsx |    6.17 |      100 |       0 |    6.17 | 33-213            
 ...nts/extensions |   45.28 |    33.33 |      60 |   45.28 |                   
  ...gerDialog.tsx |   44.31 |    34.14 |      75 |   44.31 | ...71-480,483-488 
  index.ts         |       0 |        0 |       0 |       0 | 1-9               
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...tensions/steps |   54.77 |    94.23 |   66.66 |   54.77 |                   
  ...ctionStep.tsx |   95.12 |    92.85 |   85.71 |   95.12 | 84-86,89          
  ...etailStep.tsx |    6.18 |      100 |       0 |    6.18 | 17-128            
  ...nListStep.tsx |   88.35 |    94.73 |      80 |   88.35 | 51-52,58-71,105   
  ...electStep.tsx |   13.46 |      100 |       0 |   13.46 | 20-70             
  ...nfirmStep.tsx |   19.56 |      100 |       0 |   19.56 | 23-65             
  index.ts         |     100 |      100 |     100 |     100 |                   
 ...mponents/hooks |   78.26 |    69.64 |      85 |   78.26 |                   
  ...etailStep.tsx |   96.52 |       75 |     100 |   96.52 | 33,37,50,59       
  ...etailStep.tsx |   98.13 |    82.35 |     100 |   98.13 | 41-42             
  ...abledStep.tsx |     100 |      100 |     100 |     100 |                   
  ...sListStep.tsx |     100 |      100 |     100 |     100 |                   
  ...entDialog.tsx |   47.66 |    50.94 |   66.66 |   47.66 | ...06,410-423,427 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-13              
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...components/mcp |   18.82 |    84.37 |   77.77 |   18.82 |                   
  ...entDialog.tsx |    3.64 |      100 |       0 |    3.64 | 41-717            
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-30              
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |   96.42 |    87.09 |     100 |   96.42 | 21,96-97          
 ...ents/mcp/steps |    7.31 |      100 |       0 |    7.31 |                   
  ...icateStep.tsx |    7.58 |      100 |       0 |    7.58 | 27-197            
  ...electStep.tsx |   10.95 |      100 |       0 |   10.95 | 16-88             
  ...etailStep.tsx |    5.26 |      100 |       0 |    5.26 | 31-247            
  ...rListStep.tsx |    5.88 |      100 |       0 |    5.88 | 20-176            
  ...etailStep.tsx |   10.41 |      100 |       0 |   10.41 | ...1,67-79,82-139 
  ToolListStep.tsx |    7.14 |      100 |       0 |    7.14 | 16-146            
 ...nents/messages |   73.63 |    75.88 |   59.18 |   73.63 |                   
  ...ionDialog.tsx |   65.11 |       73 |   42.85 |   65.11 | ...20,538,556-558 
  BtwMessage.tsx   |   76.31 |       50 |     100 |   76.31 | 34-42             
  ...onMessage.tsx |   91.93 |    82.35 |     100 |   91.93 | 57-59,61,63       
  ...nMessages.tsx |   77.35 |      100 |      70 |   77.35 | ...31-244,248-260 
  DiffRenderer.tsx |   93.19 |    86.17 |     100 |   93.19 | ...09,237-238,304 
  ...ssMessage.tsx |    12.5 |      100 |       0 |    12.5 | 18-59             
  ...sMessages.tsx |   16.17 |      100 |       0 |   16.17 | ...1,85-95,99-104 
  ...ryMessage.tsx |   12.82 |      100 |       0 |   12.82 | 22-59             
  ...onMessage.tsx |   73.07 |    55.81 |   33.33 |   73.07 | ...34-436,443-445 
  ...upMessage.tsx |   95.09 |     87.5 |     100 |   95.09 | 40-43,55          
  ToolMessage.tsx  |   82.07 |    71.95 |      90 |   82.07 | ...13-418,492-494 
 ...ponents/shared |   77.03 |    76.86 |   90.56 |   77.03 |                   
  ...ctionList.tsx |   99.03 |    95.65 |     100 |   99.03 | 85                
  ...tonSelect.tsx |   97.14 |    66.66 |     100 |   97.14 | 72                
  EnumSelector.tsx |     100 |    96.42 |     100 |     100 | 58                
  MaxSizedBox.tsx  |   81.13 |    81.96 |   88.88 |   81.13 | ...12-513,618-619 
  MultiSelect.tsx  |    5.59 |      100 |       0 |    5.59 | 34-41,44-193      
  ...tonSelect.tsx |     100 |      100 |     100 |     100 |                   
  ...eSelector.tsx |     100 |       60 |     100 |     100 | 40-45             
  TextInput.tsx    |    7.14 |      100 |       0 |    7.14 | 39-222            
  text-buffer.ts   |   82.07 |    75.59 |   96.87 |   82.07 | ...1897,1924,1986 
  ...er-actions.ts |   86.71 |    67.79 |     100 |   86.71 | ...07-608,809-811 
 ...ents/subagents |    32.1 |      100 |       0 |    32.1 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  reducers.tsx     |    12.1 |      100 |       0 |    12.1 | 33-190            
  types.ts         |     100 |      100 |     100 |     100 |                   
  utils.ts         |   10.95 |      100 |       0 |   10.95 | ...1,56-57,60-102 
 ...bagents/create |    9.13 |      100 |       0 |    9.13 |                   
  ...ionWizard.tsx |    7.28 |      100 |       0 |    7.28 | 34-299            
  ...rSelector.tsx |   14.75 |      100 |       0 |   14.75 | 26-85             
  ...onSummary.tsx |    4.26 |      100 |       0 |    4.26 | 27-331            
  ...tionInput.tsx |    8.63 |      100 |       0 |    8.63 | 23-177            
  ...dSelector.tsx |   33.33 |      100 |       0 |   33.33 | 20-21,26-27,36-63 
  ...nSelector.tsx |    37.5 |      100 |       0 |    37.5 | 20-21,26-27,36-58 
  ...EntryStep.tsx |   12.76 |      100 |       0 |   12.76 | 34-78             
  ToolSelector.tsx |    4.16 |      100 |       0 |    4.16 | 31-253            
 ...bagents/manage |    8.43 |      100 |       0 |    8.43 |                   
  ...ctionStep.tsx |   10.25 |      100 |       0 |   10.25 | 21-103            
  ...eleteStep.tsx |   20.93 |      100 |       0 |   20.93 | 23-62             
  ...tEditStep.tsx |   25.53 |      100 |       0 |   25.53 | ...2,37-38,51-124 
  ...ctionStep.tsx |    2.29 |      100 |       0 |    2.29 | 28-449            
  ...iewerStep.tsx |   15.21 |      100 |       0 |   15.21 | 18-66             
  ...gerDialog.tsx |    6.74 |      100 |       0 |    6.74 | 35-341            
 ...agents/runtime |    7.83 |      100 |       0 |    7.83 |                   
  ...onDisplay.tsx |    7.83 |      100 |       0 |    7.83 | ...72-502,511-549 
 ...mponents/views |   48.59 |    69.23 |      30 |   48.59 |                   
  ContextUsage.tsx |    5.07 |      100 |       0 |    5.07 | ...30-145,148-424 
  ...sionsList.tsx |   87.69 |    73.68 |     100 |   87.69 | 65-72             
  McpStatus.tsx    |   89.53 |    60.52 |     100 |   89.53 | ...72,175-177,262 
  SkillsList.tsx   |   27.27 |      100 |       0 |   27.27 | 18-35             
  ToolsList.tsx    |     100 |      100 |     100 |     100 |                   
 src/ui/contexts   |   76.49 |    79.92 |    87.5 |   76.49 |                   
  ...ewContext.tsx |   65.77 |      100 |      75 |   65.77 | ...22-225,231-241 
  AppContext.tsx   |      40 |      100 |       0 |      40 | 17-22             
  ...igContext.tsx |   81.81 |       50 |     100 |   81.81 | 15-16             
  ...ssContext.tsx |   83.83 |       83 |     100 |   83.83 | ...1049,1054-1056 
  ...owContext.tsx |   89.28 |       80 |   66.66 |   89.28 | 34,47-48,60-62    
  ...onContext.tsx |   47.02 |     62.5 |   71.42 |   47.02 | ...36-239,243-246 
  ...gsContext.tsx |   83.33 |       50 |     100 |   83.33 | 17-18             
  ...usContext.tsx |     100 |      100 |     100 |     100 |                   
  ...ngContext.tsx |   71.42 |       50 |     100 |   71.42 | 17-20             
  ...nsContext.tsx |   89.47 |       50 |     100 |   89.47 | 117-118           
  ...teContext.tsx |   85.71 |       50 |     100 |   85.71 | 160-161           
  ...deContext.tsx |   76.08 |    72.72 |     100 |   76.08 | 47-48,52-59,77-78 
 src/ui/editors    |   93.33 |    85.71 |   66.66 |   93.33 |                   
  ...ngsManager.ts |   93.33 |    85.71 |   66.66 |   93.33 | 49,63-64          
 src/ui/hooks      |   75.51 |    78.97 |   79.53 |   75.51 |                   
  ...dProcessor.ts |   83.02 |     81.9 |     100 |   83.02 | ...86-387,406-433 
  keyToAnsi.ts     |    3.92 |      100 |       0 |    3.92 | 19-77             
  ...dProcessor.ts |   94.77 |    70.58 |     100 |   94.77 | ...75-276,281-282 
  ...dProcessor.ts |   76.08 |    58.33 |   66.66 |   76.08 | ...88,712,731-735 
  ...amingState.ts |   12.22 |      100 |       0 |   12.22 | 54-158            
  ...agerDialog.ts |   88.23 |      100 |     100 |   88.23 | 20,24             
  ...odeCommand.ts |   58.82 |      100 |     100 |   58.82 | 28,33-48          
  ...enaCommand.ts |      85 |      100 |     100 |      85 | 23-24,29          
  ...aInProcess.ts |   19.81 |    66.66 |      25 |   19.81 | 57-175            
  ...Completion.ts |   92.77 |    89.09 |     100 |   92.77 | ...86-187,220-223 
  ...ifications.ts |   88.05 |    94.73 |     100 |   88.05 | 84-93             
  ...tIndicator.ts |     100 |    93.75 |     100 |     100 | 63                
  ...ntProgress.ts |   38.37 |      100 |   16.66 |   38.37 | ...9,82-88,91-106 
  ...ketedPaste.ts |    23.8 |      100 |       0 |    23.8 | 19-38             
  ...lanUpdates.ts |     100 |       92 |     100 |     100 | 59,158            
  ...ompletion.tsx |   94.87 |    80.55 |     100 |   94.87 | ...02-203,205-206 
  ...dMigration.ts |   90.62 |       75 |     100 |   90.62 | 38-40             
  useCompletion.ts |    92.4 |     87.5 |     100 |    92.4 | 68-69,93-94,98-99 
  ...ialogClose.ts |   22.22 |      100 |     100 |   22.22 | 67-109            
  ...orSettings.ts |     100 |      100 |     100 |     100 |                   
  ...itHandling.ts |   45.16 |      100 |     100 |   45.16 | 46-98             
  ...ionUpdates.ts |   93.45 |     92.3 |     100 |   93.45 | ...83-287,300-306 
  ...agerDialog.ts |   88.88 |      100 |     100 |   88.88 | 21,25             
  ...backDialog.ts |   50.75 |    77.77 |   33.33 |   50.75 | ...56-171,192-193 
  useFocus.ts      |     100 |      100 |     100 |     100 |                   
  ...olderTrust.ts |     100 |      100 |     100 |     100 |                   
  ...ggestions.tsx |   89.15 |     64.7 |     100 |   89.15 | ...19-121,146-147 
  ...miniStream.ts |   70.32 |    68.09 |      80 |   70.32 | ...1951,1960-1962 
  ...BranchName.ts |    90.9 |     92.3 |     100 |    90.9 | 19-20,55-58       
  ...itDiffStat.ts |    7.69 |      100 |       0 |    7.69 | 26-79             
  ...oryManager.ts |   98.41 |    93.33 |     100 |   98.41 | 43                
  ...ooksDialog.ts |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...stListener.ts |     100 |      100 |     100 |     100 |                   
  ...ssageDrain.ts |   72.72 |       40 |     100 |   72.72 | 25-26,28-31       
  ...nAuthError.ts |   76.19 |       50 |     100 |   76.19 | 39-40,43-45       
  ...ionEffects.ts |   30.58 |     37.5 |     100 |   30.58 | ...12-119,123-124 
  ...putHistory.ts |   92.59 |    85.71 |     100 |   92.59 | 63-64,72,94-96    
  ...storyStore.ts |     100 |    94.11 |     100 |     100 | 69                
  ...rdHandling.ts |   33.87 |      100 |      50 |   33.87 | 92,101-249        
  useKeypress.ts   |     100 |      100 |     100 |     100 |                   
  ...rdProtocol.ts |   36.36 |      100 |       0 |   36.36 | 24-31             
  ...unchEditor.ts |    8.97 |      100 |       0 |    8.97 | 20-67,74-125      
  ...gIndicator.ts |     100 |      100 |     100 |     100 |                   
  useLogger.ts     |   21.05 |      100 |       0 |   21.05 | 15-37             
  useMcpDialog.ts  |    87.5 |      100 |     100 |    87.5 | 19,23             
  ...oryMonitor.ts |     100 |      100 |     100 |     100 |                   
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...delCommand.ts |     100 |       75 |     100 |     100 | 22                
  ...raseCycler.ts |   84.48 |    76.47 |     100 |   84.48 | ...47,50-51,67-69 
  ...uggestions.ts |   50.73 |       28 |     100 |   50.73 | ...81-183,201-203 
  ...lScheduler.ts |   85.06 |    94.73 |     100 |   85.06 | ...05-208,295-305 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-7               
  ...umeCommand.ts |   94.54 |    68.75 |     100 |   94.54 | 60-61,79          
  ...ompletion.tsx |   90.59 |    83.33 |     100 |   90.59 | ...01,104,137-140 
  ...ectionList.ts |   96.59 |    94.62 |     100 |   96.59 | ...82-183,237-240 
  ...moryStatus.ts |       0 |        0 |       0 |       0 | 1-29              
  ...sionPicker.ts |   91.66 |    72.34 |     100 |   91.66 | ...45-246,250-251 
  ...ngsCommand.ts |   18.75 |      100 |       0 |   18.75 | 10-25             
  ...ellHistory.ts |   91.74 |    79.41 |     100 |   91.74 | ...74,122-123,133 
  ...oryCommand.ts |       0 |        0 |       0 |       0 | 1-73              
  ...Completion.ts |   80.97 |     84.4 |   91.66 |   80.97 | ...69-471,479-487 
  ...tateAndRef.ts |     100 |      100 |     100 |     100 |                   
  ...eateDialog.ts |   88.23 |      100 |     100 |   88.23 | 14,18             
  ...rminalSize.ts |   76.19 |      100 |      50 |   76.19 | 21-25             
  ...emeCommand.ts |    8.04 |      100 |       0 |    8.04 | 25-112            
  useTimer.ts      |   88.09 |    85.71 |     100 |   88.09 | 44-45,51-53       
  ...lMigration.ts |       0 |        0 |       0 |       0 |                   
  ...rustModify.ts |     100 |      100 |     100 |     100 |                   
  useVoice.ts      |   93.24 |    77.77 |     100 |   93.24 | 58-62             
  ...elcomeBack.ts |   69.44 |    54.54 |     100 |   69.44 | ...85,89-90,96-98 
  ...indowTitle.ts |     100 |    91.66 |     100 |     100 | 42                
  vim.ts           |   83.54 |     79.5 |     100 |   83.54 | ...44,748-756,765 
 src/ui/layouts    |   79.24 |    38.46 |     100 |   79.24 |                   
  ...AppLayout.tsx |   81.94 |       40 |     100 |   81.94 | 42-44,50-57,75-77 
  ...AppLayout.tsx |   73.52 |    33.33 |     100 |   73.52 | 30-35,37-39       
 src/ui/models     |   56.25 |    85.71 |      40 |   56.25 |                   
  ...ableModels.ts |   56.25 |    85.71 |      40 |   56.25 | ...3,80-81,98-100 
 ...noninteractive |     100 |      100 |    7.69 |     100 |                   
  ...eractiveUi.ts |     100 |      100 |    7.69 |     100 |                   
 src/ui/state      |   94.91 |    81.81 |     100 |   94.91 |                   
  extensions.ts    |   94.91 |    81.81 |     100 |   94.91 | 68-69,88          
 src/ui/themes     |      99 |    58.66 |     100 |      99 |                   
  ansi-light.ts    |     100 |      100 |     100 |     100 |                   
  ansi.ts          |     100 |      100 |     100 |     100 |                   
  atom-one-dark.ts |     100 |      100 |     100 |     100 |                   
  ayu-light.ts     |     100 |      100 |     100 |     100 |                   
  ayu.ts           |     100 |      100 |     100 |     100 |                   
  color-utils.ts   |     100 |      100 |     100 |     100 |                   
  default-light.ts |     100 |      100 |     100 |     100 |                   
  default.ts       |     100 |      100 |     100 |     100 |                   
  dracula.ts       |     100 |      100 |     100 |     100 |                   
  github-dark.ts   |     100 |      100 |     100 |     100 |                   
  github-light.ts  |     100 |      100 |     100 |     100 |                   
  googlecode.ts    |     100 |      100 |     100 |     100 |                   
  no-color.ts      |     100 |      100 |     100 |     100 |                   
  qwen-dark.ts     |     100 |      100 |     100 |     100 |                   
  qwen-light.ts    |     100 |      100 |     100 |     100 |                   
  ...tic-tokens.ts |     100 |      100 |     100 |     100 |                   
  ...-of-purple.ts |     100 |      100 |     100 |     100 |                   
  theme-manager.ts |   87.08 |    79.68 |     100 |   87.08 | ...03-312,317-318 
  theme.ts         |     100 |    28.98 |     100 |     100 | 272-461           
  xcode.ts         |     100 |      100 |     100 |     100 |                   
 src/ui/utils      |   67.95 |    83.56 |   78.16 |   67.95 |                   
  ...Colorizer.tsx |   82.78 |    88.23 |     100 |   82.78 | ...10-111,197-223 
  ...nRenderer.tsx |   59.31 |    38.23 |     100 |   59.31 | ...33-139,149-151 
  ...wnDisplay.tsx |   85.75 |    88.05 |     100 |   85.75 | ...76-284,317-342 
  QueryGuard.ts    |   85.71 |      100 |   66.66 |   85.71 | 61-62,65-66       
  ...eRenderer.tsx |   77.88 |    76.19 |     100 |   77.88 | 54-82             
  ...boardUtils.ts |   59.61 |    58.82 |     100 |   59.61 | ...,86-88,107-149 
  commandUtils.ts  |   93.54 |    88.63 |     100 |   93.54 | ...43,147,149-150 
  computeStats.ts  |     100 |      100 |     100 |     100 |                   
  displayUtils.ts  |   60.46 |      100 |      50 |   60.46 | 19-35             
  formatters.ts    |    94.8 |    98.07 |     100 |    94.8 | 101-104           
  highlight.ts     |   98.63 |       95 |     100 |   98.63 | 93                
  isNarrowWidth.ts |     100 |      100 |     100 |     100 |                   
  ...olDetector.ts |    7.22 |      100 |       0 |    7.22 | ...24-125,128-129 
  layoutUtils.ts   |     100 |      100 |     100 |     100 |                   
  ...nUtilities.ts |   69.84 |    85.71 |     100 |   69.84 | 75-91,100-101     
  ...mConstants.ts |     100 |      100 |     100 |     100 |                   
  ...storyUtils.ts |   59.68 |    67.69 |      90 |   59.68 | ...40,388,393-415 
  ...ickerUtils.ts |     100 |      100 |     100 |     100 |                   
  terminalSetup.ts |    4.37 |      100 |       0 |    4.37 | 44-393            
  textUtils.ts     |   96.52 |    94.44 |    87.5 |   96.52 | 19-20,148-149     
  updateCheck.ts   |     100 |    80.95 |     100 |     100 | 30-42             
 ...i/utils/export |    2.38 |        0 |       0 |    2.38 |                   
  collect.ts       |    0.87 |      100 |       0 |    0.87 | 40-394,401-697    
  index.ts         |     100 |      100 |     100 |     100 |                   
  normalize.ts     |    1.23 |      100 |       0 |    1.23 | 17-336            
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |      40 |      100 |       0 |      40 | 11-13             
 ...ort/formatters |    3.38 |      100 |       0 |    3.38 |                   
  html.ts          |    9.61 |      100 |       0 |    9.61 | ...28,34-76,82-84 
  json.ts          |      50 |      100 |       0 |      50 | 14-15             
  jsonl.ts         |     3.5 |      100 |       0 |     3.5 | 14-76             
  markdown.ts      |    0.94 |      100 |       0 |    0.94 | 13-295            
 src/utils         |   68.67 |    89.61 |    93.7 |   68.67 |                   
  acpModelUtils.ts |     100 |      100 |     100 |     100 |                   
  ...tification.ts |   92.59 |    71.42 |     100 |   92.59 | 36-37             
  checks.ts        |   33.33 |      100 |       0 |   33.33 | 23-28             
  cleanup.ts       |   65.38 |      100 |   66.66 |   65.38 | 28-37             
  commands.ts      |     100 |      100 |     100 |     100 |                   
  commentJson.ts   |     100 |    93.75 |     100 |     100 | 30                
  deepMerge.ts     |     100 |       90 |     100 |     100 | 41-43,49          
  ...ScopeUtils.ts |   97.56 |    88.88 |     100 |   97.56 | 67                
  ...arResolver.ts |   94.28 |    88.46 |     100 |   94.28 | 28-29,125-126     
  errors.ts        |   98.27 |       95 |     100 |   98.27 | 44-45             
  events.ts        |     100 |      100 |     100 |     100 |                   
  gitUtils.ts      |   91.91 |    84.61 |     100 |   91.91 | 78-81,124-127     
  ...AutoUpdate.ts |    51.2 |       90 |      50 |    51.2 | 87-152            
  ...lationInfo.ts |     100 |      100 |     100 |     100 |                   
  languageUtils.ts |   97.87 |    96.42 |     100 |   97.87 | 132-133           
  math.ts          |       0 |        0 |       0 |       0 | 1-15              
  ...onfigUtils.ts |     100 |      100 |     100 |     100 |                   
  ...iveHelpers.ts |   96.84 |    93.28 |     100 |   96.84 | ...87-488,586,599 
  package.ts       |   88.88 |       80 |     100 |   88.88 | 33-34             
  processUtils.ts  |     100 |      100 |     100 |     100 |                   
  readStdin.ts     |   79.62 |       90 |      80 |   79.62 | 33-40,52-54       
  relaunch.ts      |   98.07 |    76.92 |     100 |   98.07 | 70                
  resolvePath.ts   |   66.66 |       25 |     100 |   66.66 | 12-13,16,18-19    
  sandbox.ts       |       0 |        0 |       0 |       0 | 1-984             
  settingsUtils.ts |   86.32 |    90.59 |   94.44 |   86.32 | ...38,569,632-644 
  spawnWrapper.ts  |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |     100 |      100 |     100 |     100 |                   
  stdioHelpers.ts  |     100 |       60 |     100 |     100 | 23,32             
  systemInfo.ts    |      99 |     90.9 |     100 |      99 | 172               
  ...InfoFields.ts |   86.13 |    65.78 |     100 |   86.13 | ...10-111,132-133 
  ...entEmitter.ts |     100 |      100 |     100 |     100 |                   
  ...upWarnings.ts |   91.17 |    82.35 |     100 |   91.17 | 67-68,73-74,77-78 
  version.ts       |     100 |       50 |     100 |     100 | 11                
  windowTitle.ts   |     100 |      100 |     100 |     100 |                   
  ...WithBackup.ts |    62.1 |    77.77 |     100 |    62.1 | 93,107,118-157    
-------------------|---------|----------|---------|---------|-------------------
Core Package - Full Text Report
-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   71.14 |    80.41 |    74.4 |   71.14 |                   
 src               |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/__mocks__/fs  |       0 |        0 |       0 |       0 |                   
  promises.ts      |       0 |        0 |       0 |       0 | 1-48              
 src/agents        |    59.6 |    83.33 |   56.75 |    59.6 |                   
  ...chestrator.ts |   75.83 |     82.6 |     100 |   75.83 | ...49-159,210-217 
  ...ound-store.ts |   97.95 |     90.9 |     100 |   97.95 | 61                
  index.ts         |     100 |      100 |     100 |     100 |                   
  mailbox.ts       |      80 |    78.57 |      80 |      80 | 55-57,74-75,89-97 
  team-config.ts   |    6.48 |      100 |       0 |    6.48 | 43-176            
  team-registry.ts |   45.45 |      100 |       0 |   45.45 | ...34,37-38,41-42 
 src/agents/arena  |   64.56 |    66.66 |   68.49 |   64.56 |                   
  ...gentClient.ts |   79.47 |    88.88 |   81.81 |   79.47 | ...68-183,189-204 
  ArenaManager.ts  |    61.9 |    63.09 |   67.27 |    61.9 | ...1611,1620-1630 
  arena-events.ts  |   64.44 |      100 |      50 |   64.44 | ...71-175,178-183 
  index.ts         |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...gents/backends |   76.77 |    85.23 |    72.6 |   76.77 |                   
  ITermBackend.ts  |   97.97 |    93.93 |     100 |   97.97 | ...78-180,255,307 
  ...essBackend.ts |   92.81 |     85.5 |   82.85 |   92.81 | ...15-235,294,390 
  TmuxBackend.ts   |    90.7 |    76.55 |   97.36 |    90.7 | ...87,697,743-747 
  detect.ts        |   31.25 |      100 |       0 |   31.25 | 34-88             
  index.ts         |     100 |      100 |     100 |     100 |                   
  iterm-it2.ts     |     100 |     92.1 |     100 |     100 | 37-38,106         
  tmux-commands.ts |    6.64 |      100 |    3.03 |    6.64 | ...93-363,386-503 
  types.ts         |     100 |      100 |     100 |     100 |                   
 ...agents/runtime |   76.17 |     73.4 |   74.25 |   76.17 |                   
  agent-core.ts    |   62.88 |    62.73 |   56.52 |   62.88 | ...1309,1336-1382 
  agent-events.ts  |    87.5 |      100 |      75 |    87.5 | 259-263           
  ...t-headless.ts |    80.5 |    71.11 |      55 |    80.5 | ...87-388,391-392 
  ...nteractive.ts |   85.71 |    83.33 |   80.64 |   85.71 | ...18,720,722,725 
  ...statistics.ts |   98.19 |    82.35 |     100 |   98.19 | 127,151,192,225   
  agent-types.ts   |     100 |      100 |     100 |     100 |                   
  compaction.ts    |   88.76 |    66.66 |     100 |   88.76 | ...24-128,135-136 
  index.ts         |     100 |      100 |     100 |     100 |                   
 src/config        |   69.33 |    71.33 |   58.53 |   69.33 |                   
  config.ts        |   67.44 |    66.66 |   54.26 |   67.44 | ...2370,2377-2380 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  models.ts        |     100 |      100 |     100 |     100 |                   
  storage.ts       |   79.74 |    92.72 |    75.6 |   79.74 | ...88-292,303-304 
 ...nfirmation-bus |   74.35 |    52.17 |      90 |   74.35 |                   
  message-bus.ts   |   72.22 |       50 |      90 |   72.22 | ...18-120,123-124 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/core          |   78.44 |    80.16 |   89.34 |   78.44 |                   
  agentCore.ts     |   81.25 |    76.19 |     100 |   81.25 | ...21,162,168,171 
  baseLlmClient.ts |     100 |    96.42 |     100 |     100 | 113               
  ...pointStore.ts |     100 |      100 |     100 |     100 |                   
  client.ts        |   73.11 |    73.85 |   91.66 |   73.11 | ...1199,1251-1252 
  ...tGenerator.ts |   80.48 |    55.17 |     100 |   80.48 | ...13,315,322-325 
  ...lScheduler.ts |   70.46 |    77.14 |   89.65 |   70.46 | ...1722,1779-1783 
  geminiChat.ts    |   72.29 |    82.31 |   81.25 |   72.29 | ...56-867,901-904 
  geminiRequest.ts |     100 |      100 |     100 |     100 |                   
  logger.ts        |   82.25 |    81.81 |     100 |   82.25 | ...57-361,407-421 
  ...tyDefaults.ts |     100 |      100 |     100 |     100 |                   
  ...olExecutor.ts |   92.59 |       75 |      50 |   92.59 | 41-42             
  ...on-helpers.ts |   74.74 |    46.15 |     100 |   74.74 | ...86,192,197-206 
  prompts.ts       |   81.66 |    87.05 |   64.28 |   81.66 | ...1263,1273-1300 
  tokenLimits.ts   |     100 |    88.23 |     100 |     100 | 43-44             
  ...okTriggers.ts |   99.31 |     90.9 |     100 |   99.31 | 124,135           
  turn.ts          |   91.13 |    87.03 |     100 |   91.13 | ...85,398-399,447 
 ...ntentGenerator |   87.91 |    69.28 |   91.17 |   87.91 |                   
  ...tGenerator.ts |   87.25 |    64.66 |    87.5 |   87.25 | ...45-652,656-657 
  converter.ts     |   90.35 |    73.97 |     100 |   90.35 | ...99,542-557,580 
  index.ts         |       0 |        0 |       0 |       0 | 1-21              
 ...ntentGenerator |   75.87 |    61.84 |   94.11 |   75.87 |                   
  ...tGenerator.ts |   73.49 |    61.64 |   93.75 |   73.49 | ...57-463,481-482 
  index.ts         |     100 |    66.66 |     100 |     100 | 45                
 ...ntentGenerator |   91.06 |    67.96 |      85 |   91.06 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tGenerator.ts |   91.02 |    67.96 |      85 |   91.02 | ...37,547-548,576 
 ...ntentGenerator |   75.91 |    82.74 |   91.89 |   75.91 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  converter.ts     |   73.42 |    80.14 |      90 |   73.42 | ...1495,1516-1525 
  errorHandler.ts  |     100 |      100 |     100 |     100 |                   
  index.ts         |       0 |        0 |       0 |       0 | 1-94              
  ...tGenerator.ts |   48.78 |    91.66 |   77.77 |   48.78 | ...10-163,166-167 
  pipeline.ts      |   83.75 |    78.78 |     100 |   83.75 | ...40-641,643-654 
  ...CallParser.ts |   91.42 |    89.61 |     100 |   91.42 | ...48-352,382-383 
 ...rator/provider |   96.07 |    87.73 |   93.75 |   96.07 |                   
  dashscope.ts     |   96.29 |    87.09 |   93.33 |   96.29 | ...10-211,287-288 
  deepseek.ts      |   90.76 |       75 |     100 |   90.76 | 40-41,45-46,59-60 
  default.ts       |   97.56 |      100 |   85.71 |   97.56 | 85-86             
  index.ts         |     100 |      100 |     100 |     100 |                   
  modelscope.ts    |     100 |      100 |     100 |     100 |                   
  openrouter.ts    |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 |                   
 src/extension     |   60.36 |    79.75 |   78.22 |   60.36 |                   
  ...-converter.ts |   63.79 |    47.82 |      90 |   63.79 | ...86-787,796-828 
  ...ionManager.ts |    44.7 |    84.12 |   65.11 |    44.7 | ...1320,1341-1360 
  ...onSettings.ts |   93.46 |    93.05 |     100 |   93.46 | ...17-221,228-232 
  ...-converter.ts |   54.88 |    94.44 |      60 |   54.88 | ...35-146,158-192 
  github.ts        |   44.94 |    88.52 |      60 |   44.94 | ...53-359,398-451 
  index.ts         |     100 |      100 |     100 |     100 |                   
  marketplace.ts   |   97.29 |    93.75 |     100 |   97.29 | ...64,184-185,274 
  npm.ts           |   49.82 |    76.08 |      75 |   49.82 | ...05-407,414-418 
  override.ts      |   94.11 |    88.88 |     100 |   94.11 | 63-64,81-82       
  settings.ts      |   66.26 |      100 |      50 |   66.26 | 81-108,143-149    
  storage.ts       |   94.73 |       90 |     100 |   94.73 | 41-42             
  ...ableSchema.ts |     100 |      100 |     100 |     100 |                   
  variables.ts     |   88.75 |    83.33 |     100 |   88.75 | ...28-231,234-237 
 src/followup      |   44.88 |    92.71 |   68.42 |   44.88 |                   
  followupState.ts |   95.83 |    89.18 |     100 |   95.83 | 153-155,210-211   
  forkedQuery.ts   |      30 |      100 |      50 |      30 | 122-249           
  index.ts         |     100 |      100 |     100 |     100 |                   
  overlayFs.ts     |   95.06 |       84 |     100 |   95.06 | 78,108,122,133    
  speculation.ts   |    13.4 |      100 |   16.66 |    13.4 | 88-458,518-563    
  ...onToolGate.ts |     100 |    96.29 |     100 |     100 | 93                
  ...nGenerator.ts |   38.27 |    95.12 |   33.33 |   38.27 | ...00-302,337-367 
 src/generated     |       0 |        0 |       0 |       0 |                   
  git-commit.ts    |       0 |        0 |       0 |       0 | 1-10              
 src/hooks         |   77.44 |     84.8 |   85.24 |   77.44 |                   
  ...on-checker.ts |     100 |      100 |     100 |     100 |                   
  ...Aggregator.ts |   96.17 |       90 |     100 |   96.17 | ...74,276-277,350 
  ...entHandler.ts |   86.07 |       84 |   80.76 |   86.07 | ...88,641-642,652 
  hookPlanner.ts   |   78.18 |       72 |    90.9 |   78.18 | ...18-236,244-245 
  hookRegistry.ts  |   79.74 |    74.28 |     100 |   79.74 | ...59,361,363,365 
  hookRunner.ts    |   57.83 |    73.33 |   66.66 |   57.83 | ...47-557,610-611 
  hookSystem.ts    |   83.22 |      100 |   86.95 |   83.22 | ...46-362,368-384 
  index.ts         |     100 |      100 |     100 |     100 |                   
  trustedHooks.ts  |     9.3 |      100 |       0 |     9.3 | 24-122            
  types.ts         |   89.61 |    94.66 |   85.18 |   89.61 | ...45-346,406-410 
 src/ide           |   72.67 |    83.92 |   75.92 |   72.67 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  detect-ide.ts    |     100 |      100 |     100 |     100 |                   
  ide-client.ts    |    64.2 |    81.48 |   66.66 |    64.2 | ...9-970,999-1007 
  ideContext.ts    |     100 |      100 |     100 |     100 |                   
  process-utils.ts |   84.84 |    71.79 |     100 |   84.84 | ...37,151,193-194 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/lsp           |   33.39 |    43.75 |   44.91 |   33.39 |                   
  ...nfigLoader.ts |   70.27 |    35.89 |   94.73 |   70.27 | ...20-422,426-432 
  ...ionFactory.ts |    4.29 |      100 |       0 |    4.29 | ...20-371,377-394 
  ...Normalizer.ts |   23.09 |    13.72 |   30.43 |   23.09 | ...04-905,909-924 
  ...verManager.ts |   10.47 |       75 |      25 |   10.47 | ...56-675,681-711 
  ...eLspClient.ts |   17.89 |      100 |       0 |   17.89 | ...37-244,254-258 
  ...LspService.ts |   45.87 |    62.13 |   66.66 |   45.87 | ...1282,1299-1309 
  constants.ts     |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mcp           |   78.74 |    75.68 |   75.92 |   78.74 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...h-provider.ts |   86.95 |      100 |   33.33 |   86.95 | ...,93,97,101-102 
  ...h-provider.ts |   73.74 |    54.45 |     100 |   73.74 | ...64-871,878-880 
  ...en-storage.ts |   98.62 |    97.72 |     100 |   98.62 | 87-88             
  oauth-utils.ts   |   70.58 |    85.29 |    90.9 |   70.58 | ...70-290,315-344 
  ...n-provider.ts |   89.83 |    95.83 |   45.45 |   89.83 | ...43,147,151-152 
 .../token-storage |   79.48 |    86.66 |   86.36 |   79.48 |                   
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   82.75 |    82.35 |   92.85 |   82.75 | ...62-172,180-181 
  ...en-storage.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...en-storage.ts |   68.14 |    82.35 |   64.28 |   68.14 | ...81-295,298-314 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/memory        |   15.82 |       75 |    7.69 |   15.82 |                   
  ...tterParser.ts |   13.04 |      100 |       0 |   13.04 | 20-51,57-72       
  index.ts         |     100 |      100 |     100 |     100 |                   
  memoryAge.ts     |   32.07 |      100 |       0 |   32.07 | 36-46,53-68,75-84 
  ...yExtractor.ts |   13.68 |      100 |       0 |   13.68 | 35-189            
  memoryPrompt.ts  |     100 |      100 |     100 |     100 |                   
  memoryScan.ts    |   21.05 |      100 |       0 |   21.05 | 19-24,31-40       
  memoryStore.ts   |    7.75 |       75 |   18.18 |    7.75 | 52-364            
  proposalStore.ts |    9.87 |      100 |       0 |    9.87 | 20-111            
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/mocks         |       0 |        0 |       0 |       0 |                   
  msw.ts           |       0 |        0 |       0 |       0 | 1-9               
 src/models        |   88.44 |    81.65 |    87.3 |   88.44 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nfigErrors.ts |   74.22 |       44 |   84.61 |   74.22 | ...,67-74,106-117 
  ...igResolver.ts |    99.3 |    87.09 |     100 |    99.3 | 127               
  modelRegistry.ts |     100 |    97.72 |     100 |     100 | 164               
  modelsConfig.ts  |   84.51 |    82.17 |   83.33 |   84.51 | ...1069,1098-1099 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/output        |     100 |      100 |     100 |     100 |                   
  ...-formatter.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/permissions   |   68.39 |    87.29 |   48.27 |   68.39 |                   
  ...classifier.ts |   30.88 |    57.14 |   33.33 |   30.88 | ...07-230,234-235 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...on-manager.ts |   78.62 |       79 |      84 |   78.62 | ...65-772,792-801 
  rule-parser.ts   |   97.97 |     95.7 |     100 |   97.97 | ...23-824,968-970 
  ...-semantics.ts |   58.28 |    85.27 |    30.2 |   58.28 | ...1604-1614,1643 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/prompts       |   29.09 |      100 |      25 |   29.09 |                   
  mcp-prompts.ts   |   18.18 |      100 |       0 |   18.18 | 11-19             
  ...t-registry.ts |   31.81 |      100 |   28.57 |   31.81 | ...45,51-58,71-76 
 src/services      |   65.41 |    79.13 |   77.72 |   65.41 |                   
  baselineCheck.ts |    3.65 |      100 |       0 |    3.65 | 25-93,100-132     
  ...VerifyGate.ts |   88.81 |    91.42 |     100 |   88.81 | 91-99,139-146     
  ...ionService.ts |   80.63 |    85.31 |   81.81 |   80.63 | ...78-813,828-861 
  ...ingService.ts |   68.39 |    48.38 |   85.71 |   68.39 | ...25-437,453-454 
  cronScheduler.ts |    86.2 |    90.32 |   94.11 |    86.2 | ...20,124-133,198 
  evolveService.ts |   15.78 |      100 |       0 |   15.78 | 43-190            
  ...eryService.ts |   80.43 |    95.45 |      75 |   80.43 | ...19-134,140-141 
  ...temService.ts |   89.76 |     85.1 |   88.88 |   89.76 | ...89,191,266-273 
  fileTracker.ts   |   98.21 |     90.9 |     100 |   98.21 | 43                
  gitService.ts    |   66.29 |     90.9 |   55.55 |   66.29 | ...03-113,116-120 
  ...reeService.ts |    67.5 |    65.21 |    87.5 |    67.5 | ...24,830-847,865 
  ...derService.ts |   42.85 |    22.22 |   66.66 |   42.85 | ...03-108,117-118 
  ...ionService.ts |   97.94 |    96.61 |     100 |   97.94 | 104-105,266-267   
  ...solidation.ts |     5.9 |      100 |       0 |     5.9 | 65-339            
  microcompact.ts  |   85.71 |       68 |     100 |   85.71 | ...59,76-77,79-80 
  ...leSelector.ts |   94.03 |       75 |     100 |   94.03 | ...40,243-244,285 
  ...kerService.ts |    5.63 |      100 |       0 |    5.63 | 21-109            
  ...EditVerify.ts |   11.11 |      100 |       0 |   11.11 | 19-76             
  ...MapService.ts |    83.2 |    79.31 |      90 |    83.2 | ...30,343,392-415 
  scopeLock.ts     |   31.91 |      100 |   14.28 |   31.91 | ...,87-88,104-116 
  sessionNotes.ts  |   33.89 |      100 |      40 |   33.89 | 89-147            
  ...ionService.ts |   79.23 |    73.19 |   88.88 |   79.23 | ...53-674,682-706 
  ...ionService.ts |   83.46 |    78.53 |   83.33 |   83.46 | ...1017,1023-1028 
  ...actService.ts |   28.04 |       50 |   33.33 |   28.04 | ...20-121,128-142 
  task-store.ts    |     8.2 |      100 |       0 |     8.2 | 106-586           
 .../sessionMemory |   32.89 |    95.23 |    37.5 |   32.89 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  prompts.ts       |    6.77 |      100 |       0 |    6.77 | ...65-166,179-221 
  sessionMemory.ts |   13.18 |      100 |       0 |   13.18 | 58-176            
  ...emoryUtils.ts |   85.22 |    95.23 |   64.28 |   85.22 | ...68-172,176-177 
 src/skills        |   76.46 |    80.14 |   77.77 |   76.46 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  skill-load.ts    |   90.83 |    77.77 |     100 |   90.83 | ...28,148,160-162 
  skill-manager.ts |   71.68 |    80.76 |   73.91 |   71.68 | ...95-703,706-715 
  types.ts         |     100 |      100 |     100 |     100 |                   
 src/subagents     |    80.7 |    82.74 |    92.1 |    80.7 |                   
  ...tin-agents.ts |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...nt-manager.ts |    71.6 |    73.88 |      88 |    71.6 | ...-932,1008-1009 
  types.ts         |     100 |      100 |     100 |     100 |                   
  validation.ts    |   92.34 |    96.51 |     100 |   92.34 | 50-55,59-64,68-73 
 src/telemetry     |   65.26 |    84.01 |    69.9 |   65.26 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  constants.ts     |     100 |      100 |     100 |     100 |                   
  ...-exporters.ts |   36.76 |      100 |   22.22 |   36.76 | ...84,87-88,91-92 
  ...sTelemetry.ts |    7.25 |      100 |       0 |    7.25 | ...59-177,186-203 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-111             
  ...t.circular.ts |       0 |        0 |       0 |       0 | 1-128             
  loggers.ts       |    49.4 |     61.4 |   52.38 |    49.4 | ...1123,1126-1150 
  metrics.ts       |   75.93 |    86.74 |   76.92 |   75.93 | ...09-846,849-878 
  sanitize.ts      |      80 |    83.33 |     100 |      80 | 35-36,41-42       
  sdk.ts           |   90.05 |    75.75 |     100 |   90.05 | ...31,237-238,244 
  ...etry-utils.ts |     100 |      100 |     100 |     100 |                   
  ...l-decision.ts |     100 |      100 |     100 |     100 |                   
  ...panContext.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |   77.31 |    85.08 |   81.81 |   77.31 | ...1105,1108-1137 
  uiTelemetry.ts   |   91.87 |    96.15 |   78.57 |   91.87 | ...67-168,174-181 
 ...ry/qwen-logger |    68.3 |    81.52 |   64.91 |    68.3 |                   
  event-types.ts   |       0 |        0 |       0 |       0 |                   
  qwen-logger.ts   |    68.3 |    81.31 |   64.28 |    68.3 | ...1040,1078-1079 
 src/test-utils    |   92.85 |    94.28 |   77.41 |   92.85 |                   
  config.ts        |     100 |      100 |     100 |     100 |                   
  index.ts         |     100 |      100 |     100 |     100 |                   
  mock-tool.ts     |   91.02 |    93.54 |   75.86 |   91.02 | ...31,195-196,209 
  ...aceContext.ts |     100 |      100 |     100 |     100 |                   
 src/tools         |   71.46 |    77.48 |   74.24 |   71.46 |                   
  agent.ts         |   76.12 |     86.5 |   76.19 |   76.12 | ...1032,1041-1046 
  ...erQuestion.ts |   87.89 |     73.8 |    90.9 |   87.89 | ...44-345,349-350 
  browser-tool.ts  |   55.51 |    44.44 |   94.11 |   55.51 | ...77-978,980-981 
  cron-create.ts   |   97.61 |    88.88 |   83.33 |   97.61 | 30-31             
  cron-delete.ts   |   96.55 |      100 |   83.33 |   96.55 | 26-27             
  cron-list.ts     |   96.36 |      100 |   83.33 |   96.36 | 25-26             
  diffOptions.ts   |     100 |      100 |     100 |     100 |                   
  edit.ts          |   80.03 |    83.83 |      75 |   80.03 | ...49-550,633-683 
  exitPlanMode.ts  |   85.81 |    86.95 |     100 |   85.81 | ...24-129,157-169 
  glob.ts          |   91.57 |    88.33 |   84.61 |   91.57 | ...20,163,293,296 
  grep.ts          |    71.3 |    87.34 |   68.42 |    71.3 | ...90,530,538-545 
  ls.ts            |   96.72 |    90.14 |     100 |   96.72 | 169-174,205,209   
  lsp.ts           |   72.58 |    60.29 |   90.32 |   72.58 | ...1202,1204-1205 
  mailbox-tools.ts |   96.42 |      100 |   83.33 |   96.42 | 39-40,117-118     
  ...nt-manager.ts |   46.44 |       60 |    42.1 |   46.44 | ...89-507,510-547 
  mcp-client.ts    |   29.34 |    70.83 |   45.45 |   29.34 | ...1425,1431-1434 
  mcp-tool.ts      |   90.46 |     87.5 |   96.55 |   90.46 | ...11-612,662-663 
  memoryTool.ts    |   74.68 |     80.7 |   90.47 |   74.68 | ...41-350,463-547 
  ...iable-tool.ts |     100 |    84.61 |     100 |     100 | 102,109           
  read-file.ts     |   94.47 |    88.63 |      80 |   94.47 | ...74,80-83,86-87 
  repoMap.ts       |   59.42 |      100 |   33.33 |   59.42 | ...,47-61,109-112 
  ripGrep.ts       |   96.24 |    90.76 |     100 |   96.24 | ...73,276,354-355 
  ...-transport.ts |    6.34 |      100 |       0 |    6.34 | 47-145            
  shell.ts         |   85.31 |    78.12 |   85.71 |   85.31 | ...66-470,664-665 
  skill.ts         |   94.08 |    88.88 |   84.61 |   94.08 | ...16,255-258,262 
  task-create.ts   |   59.03 |      100 |   33.33 |   59.03 | ...,36-59,105-108 
  task-get.ts      |      50 |      100 |   33.33 |      50 | ...29,32-57,88-91 
  task-list.ts     |   47.82 |      100 |   33.33 |   47.82 | ...,40-72,113-116 
  task-output.ts   |    59.7 |      100 |   33.33 |    59.7 | ...30,33-50,87-90 
  task-ready.ts    |   39.44 |      100 |   33.33 |   39.44 | ...,35-93,132-135 
  task-stop.ts     |      50 |      100 |   33.33 |      50 | ...30,33-61,96-99 
  task-update.ts   |   86.56 |      100 |      75 |   86.56 | 33-38,156-167     
  tool-error.ts    |     100 |      100 |     100 |     100 |                   
  tool-names.ts    |     100 |      100 |     100 |     100 |                   
  tool-registry.ts |   62.56 |    65.38 |   57.57 |   62.56 | ...43-552,559-575 
  tools.ts         |   83.11 |    89.58 |   77.77 |   83.11 | ...35-436,452-458 
  web-fetch.ts     |   85.41 |    58.33 |   91.66 |   85.41 | ...58-259,261-262 
  write-file.ts    |   79.24 |    79.36 |   69.23 |   79.24 | ...46-449,461-496 
 ...ols/web-search |   79.93 |    74.13 |   78.94 |   79.93 |                   
  base-provider.ts |    72.5 |    57.14 |     100 |    72.5 | 44-48,63-66,75-76 
  index.ts         |   82.94 |    80.43 |   85.71 |   82.94 | ...80-188,196-200 
  types.ts         |       0 |        0 |       0 |       0 | 1                 
  utils.ts         |      60 |       50 |      50 |      60 | 35-42             
 ...arch/providers |   77.41 |    68.42 |   88.88 |   77.41 |                   
  ...e-provider.ts |   17.64 |      100 |       0 |   17.64 | 16-33             
  ...e-provider.ts |   83.33 |    55.55 |     100 |   83.33 | 57-58,61-62,76-80 
  ...y-provider.ts |   90.56 |       80 |     100 |   90.56 | 66-70             
 src/utils         |   84.48 |    87.09 |   88.56 |   84.48 |                   
  LruCache.ts      |       0 |        0 |       0 |       0 | 1-41              
  ...ssageQueue.ts |     100 |      100 |     100 |     100 |                   
  ...cFileWrite.ts |   76.08 |    44.44 |     100 |   76.08 | 61-70,72          
  ...essEmitter.ts |   10.86 |      100 |       0 |   10.86 | ...,95-99,114-190 
  browser.ts       |    7.69 |      100 |       0 |    7.69 | 17-56             
  ...igResolver.ts |     100 |      100 |     100 |     100 |                   
  cronDisplay.ts   |   42.85 |    23.07 |     100 |   42.85 | 26-31,33-45,47-54 
  cronParser.ts    |   89.74 |    85.71 |     100 |   89.74 | ...,63-64,183-186 
  debugLogger.ts   |   96.12 |    93.75 |   93.75 |   96.12 | 164-168           
  editHelper.ts    |   92.67 |    82.14 |     100 |   92.67 | ...52-454,463-464 
  editor.ts        |   96.98 |    93.87 |     100 |   96.98 | ...93-194,196-197 
  ...arResolver.ts |   94.28 |    88.88 |     100 |   94.28 | 28-29,125-126     
  ...entContext.ts |     100 |       95 |     100 |     100 | 83                
  errorParsing.ts  |   96.92 |       95 |     100 |   96.92 | 36-37             
  ...rReporting.ts |   88.46 |       90 |     100 |   88.46 | 69-74             
  errors.ts        |    68.7 |    77.27 |   53.33 |    68.7 | ...86-202,206-212 
  fetch.ts         |   71.97 |    72.22 |   71.42 |   71.97 | ...38,144,157,182 
  fileUtils.ts     |   87.96 |     81.4 |   94.73 |   87.96 | ...85-791,805-811 
  formatters.ts    |   54.54 |       50 |     100 |   54.54 | 12-16             
  ...eUtilities.ts |   89.21 |    86.66 |     100 |   89.21 | 16-17,49-55,65-66 
  ...rStructure.ts |   94.36 |    94.28 |     100 |   94.36 | ...17-120,330-335 
  getPty.ts        |    12.5 |      100 |       0 |    12.5 | 21-34             
  ...noreParser.ts |    92.3 |    89.36 |     100 |    92.3 | ...15-116,186-187 
  gitUtils.ts      |   36.66 |    76.92 |      50 |   36.66 | ...4,88-89,97-148 
  iconvHelper.ts   |     100 |      100 |     100 |     100 |                   
  ...rePatterns.ts |     100 |      100 |     100 |     100 |                   
  ...ionManager.ts |     100 |       90 |     100 |     100 | 26                
  jsonl-utils.ts   |    8.87 |      100 |       0 |    8.87 | ...51-184,190-196 
  ...-detection.ts |     100 |      100 |     100 |     100 |                   
  ...yDiscovery.ts |   82.01 |    73.21 |     100 |   82.01 | ...74-377,398-399 
  ...tProcessor.ts |   93.63 |       90 |     100 |   93.63 | ...96-302,384-385 
  ...Inspectors.ts |   61.53 |      100 |      50 |   61.53 | 18-23             
  ...kerChecker.ts |   84.04 |    78.94 |     100 |   84.04 | 68-69,79-84,92-98 
  openaiLogger.ts  |   86.27 |    82.14 |     100 |   86.27 | ...05-107,130-135 
  partUtils.ts     |     100 |      100 |     100 |     100 |                   
  pathReader.ts    |     100 |      100 |     100 |     100 |                   
  paths.ts         |   95.69 |    94.52 |     100 |   95.69 | ...,71-72,104-105 
  ...ectSummary.ts |    3.75 |      100 |       0 |    3.75 | 27-119            
  ...tIdContext.ts |     100 |      100 |     100 |     100 |                   
  ...rDetection.ts |   58.57 |       76 |     100 |   58.57 | ...4,88-89,95-100 
  ...noreParser.ts |   85.45 |    81.48 |     100 |   85.45 | ...59,65-66,72-73 
  rateLimit.ts     |      90 |    84.37 |     100 |      90 | 68,79-81          
  readManyFiles.ts |   85.95 |    85.71 |     100 |   85.95 | ...80-182,198-209 
  retry.ts         |   67.91 |    73.68 |     100 |   67.91 | ...82,200,207-208 
  ripgrepUtils.ts  |   46.53 |    83.33 |   66.66 |   46.53 | ...32-233,245-322 
  ...tchOptions.ts |   55.88 |       50 |      75 |   55.88 | ...29-130,151-152 
  safeJsonParse.ts |   74.07 |    83.33 |     100 |   74.07 | 40-46             
  ...nStringify.ts |     100 |      100 |     100 |     100 |                   
  ...aConverter.ts |   90.78 |    87.87 |     100 |   90.78 | ...41-42,93,95-96 
  ...aValidator.ts |     100 |    82.85 |     100 |     100 | 15-39,93-94,125   
  ...r-launcher.ts |   76.52 |     87.5 |   66.66 |   76.52 | ...33,135,153-191 
  shell-utils.ts   |   84.23 |    90.84 |     100 |   84.23 | ...1035,1042-1046 
  ...lAstParser.ts |   92.34 |    86.47 |    92.3 |   92.34 | ...1139-1141,1151 
  ...nlyChecker.ts |   95.75 |    92.39 |     100 |   95.75 | ...00-301,313-314 
  streamStall.ts   |   97.43 |    92.85 |     100 |   97.43 | 75                
  ...tGenerator.ts |     100 |     90.9 |     100 |     100 | 129               
  symlink.ts       |   77.77 |       50 |     100 |   77.77 | 44,54-59          
  ...emEncoding.ts |   96.36 |    91.17 |     100 |   96.36 | 59-60,124-125     
  ...Serializer.ts |   99.07 |    91.22 |     100 |   99.07 | 90,156-158        
  testUtils.ts     |   53.33 |      100 |   33.33 |   53.33 | ...53,59-64,70-72 
  textUtils.ts     |      60 |      100 |   66.66 |      60 | 36-55             
  thoughtUtils.ts  |     100 |    92.85 |     100 |     100 | 71                
  ...-converter.ts |   94.59 |    85.71 |     100 |   94.59 | 35-36             
  tool-utils.ts    |    93.6 |     91.3 |     100 |    93.6 | ...58-159,162-163 
  truncation.ts    |     100 |     90.9 |     100 |     100 | 52,71             
  ...aceContext.ts |   96.22 |       92 |   93.33 |   96.22 | ...15-116,133,160 
  yaml-parser.ts   |      92 |    83.67 |     100 |      92 | 49-53,65-69       
 ...ils/filesearch |   96.17 |     91.4 |     100 |   96.17 |                   
  crawlCache.ts    |     100 |      100 |     100 |     100 |                   
  crawler.ts       |   96.22 |     92.3 |     100 |   96.22 | 66-67             
  fileSearch.ts    |   93.22 |    87.14 |     100 |   93.22 | ...30-231,233-234 
  ignore.ts        |     100 |      100 |     100 |     100 |                   
  result-cache.ts  |     100 |     92.3 |     100 |     100 | 46                
 ...uest-tokenizer |   56.63 |    74.52 |   74.19 |   56.63 |                   
  ...eTokenizer.ts |   41.86 |    76.47 |   69.23 |   41.86 | ...70-443,453-507 
  index.ts         |     100 |      100 |     100 |     100 |                   
  ...tTokenizer.ts |   68.39 |    69.49 |    90.9 |   68.39 | ...24-325,327-328 
  ...ageFormats.ts |      76 |      100 |   33.33 |      76 | 45-48,55-56       
  textTokenizer.ts |     100 |      100 |     100 |     100 |                   
  types.ts         |       0 |        0 |       0 |       0 | 1                 
-------------------|---------|----------|---------|---------|-------------------

For detailed HTML reports, please see the 'coverage-reports-22.x-ubuntu-latest' artifact from the main CI run.

- Fix Anthropic preset using wrong AuthType (USE_OPENAI → USE_ANTHROPIC)
- Fix URL normalisation clobbering /v1beta and other versioned paths
  (Gemini, custom endpoints) — both in modelDiscovery and STT URL builder
- Don't persist API keys that came from env vars (prevent silent
  promotion of env-only secrets to plaintext settings.json)
- Add regression tests for /v1beta and /v1/path URL patterns (16→18)

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (1)
packages/cli/src/commands/setup/handler.ts (1)

392-503: 🛠️ Refactor suggestion | 🟠 Major

Use Ink prompts here instead of manual raw-mode I/O.

These helpers bypass the CLI UI framework and will be hard to compose with the rest of packages/cli. Please move text and masked input onto Ink components/adapters instead of toggling raw mode directly. As per coding guidelines, packages/cli/**/*.{ts,tsx}: Use Ink (React for CLI) for building terminal user interfaces.

#!/bin/bash
# Verify the setup handler is doing manual terminal I/O while the CLI package uses Ink patterns.
rg -n "setRawMode\\(|stdout\\.write\\(|stdin\\.on\\('data'" packages/cli/src/commands/setup/handler.ts
fd -e ts -e tsx . packages/cli/src | xargs rg -n "from ['\"]ink['\"]|useInput\\(|render\\("
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/setup/handler.ts` around lines 392 - 503, The
promptText and promptMaskedText helpers perform manual raw-mode terminal I/O
(stdin.setRawMode, stdin.on('data'), stdout.write) which bypasses the project's
Ink-based CLI UI; replace these functions with Ink-based prompts/adapters (e.g.,
ink-text-input or Ink's useInput within React components) so input and masked
input are rendered and handled as Ink components instead of toggling raw mode
directly; remove usage of stdin.setRawMode, stdin.resume, stdin.on('data'), and
stdout.write inside promptText and promptMaskedText and refactor callers to
render an Ink component that returns the entered value (plain or masked) via
props/callbacks or a promise adapter that mounts/unmounts the Ink component.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@packages/cli/src/commands/setup/handler.ts`:
- Line 95: Remove the direct process.exit(...) calls from the shared
runSetupWizard handler and any helper functions it calls (referenced in this
file around runSetupWizard and the blocks corresponding to the
success/cancel/failure flows), and instead return an explicit status value or
throw an Error to indicate success, cancellation, or failure; update
runSetupWizard to propagate that status/exception to its caller and ensure the
top-level CLI entrypoint (the command handlers that call runSetupWizard) decides
whether to call process.exit based on the returned status or caught exception.
- Around line 572-577: When sttConfig is null the code currently leaves previous
STT values intact; update the block handling sttConfig so that the else branch
explicitly disables voice and clears stale STT settings: in the handler where
sttConfig is checked (the block calling settings.setValue(scope,
'voice.enabled', ...), settings.setValue(scope, 'voice.sttEndpoint', ...) and
settings.setValue(scope, 'voice.sttEnvKey', ...)), add an else that calls
settings.setValue(scope, 'voice.enabled', false) and clears or sets ''/null for
'voice.sttEndpoint' and 'voice.sttEnvKey' to ensure the old backend is not left
active.
- Line 74: The call to fetchAvailableModels(baseUrl, apiKey) omits
preset.authType so discovery always uses OpenAI-style Authorization and parsing;
update the call to pass preset.authType and update fetchAvailableModels to
accept an authType parameter (or branch inside setup handler before calling) and
handle provider-specific headers and response parsing for "openai" vs
"anthropic" vs "gemini" (e.g., use X-Api-Key + anthropic-version for Anthropic,
x-goog-api-key / query params for Gemini) or short-circuit and skip
auto-discovery for non-OpenAI-compatible presets; locate uses of
fetchAvailableModels and preset.authType to implement the branch and ensure
model-parser logic inside fetchAvailableModels (or the new branch) correctly
maps each provider's response shape to the common models format.

---

Duplicate comments:
In `@packages/cli/src/commands/setup/handler.ts`:
- Around line 392-503: The promptText and promptMaskedText helpers perform
manual raw-mode terminal I/O (stdin.setRawMode, stdin.on('data'), stdout.write)
which bypasses the project's Ink-based CLI UI; replace these functions with
Ink-based prompts/adapters (e.g., ink-text-input or Ink's useInput within React
components) so input and masked input are rendered and handled as Ink components
instead of toggling raw mode directly; remove usage of stdin.setRawMode,
stdin.resume, stdin.on('data'), and stdout.write inside promptText and
promptMaskedText and refactor callers to render an Ink component that returns
the entered value (plain or masked) via props/callbacks or a promise adapter
that mounts/unmounts the Ink component.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 117d0959-c659-4041-854f-340f6d2eeec2

📥 Commits

Reviewing files that changed from the base of the PR and between fc08b40 and fdc01ed.

📒 Files selected for processing (3)
  • packages/cli/src/commands/setup/handler.ts
  • packages/cli/src/commands/setup/modelDiscovery.test.ts
  • packages/cli/src/commands/setup/modelDiscovery.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/cli/src/commands/setup/modelDiscovery.ts
  • packages/cli/src/commands/setup/modelDiscovery.test.ts


// Step 4: Discover models
writeStdoutLine('\n⏳ Discovering models...\n');
const { models, error } = await fetchAvailableModels(baseUrl, apiKey);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

Anthropic API official docs: list models required headers x-api-key anthropic-version Gemini API official docs: models.list REST endpoint and authentication format

💡 Result:

Anthropic API (Claude): List models endpoint: GET https://api.anthropic.com/v1/models Required headers: - X-Api-Key: $ANTHROPIC_API_KEY (your secret API key from console) - anthropic-version: 2023-06-01 (or current version) Example: curl https://api.anthropic.com/v1/models \ -H 'anthropic-version: 2023-06-01' \ -H "X-Api-Key: $ANTHROPIC_API_KEY" Content-Type: application/json is also typically required for API calls, but since this is GET with no body, it may be optional. Gemini API (Google Generative Language API): List models endpoint: GET https://generativelanguage.googleapis.com/v1beta/models Query params (optional): pageSize (max 1000, default 50), pageToken Authentication: Header x-goog-api-key: $GEMINI_API_KEY (API key from Google AI Studio) No body. Content-Type: application/json optional for GET. Example (inferred from docs patterns): curl "https://generativelanguage.googleapis.com/v1beta/models" \ -H "x-goog-api-key: $GEMINI_API_KEY" Note: Vertex AI has a different endpoint (projects.locations.models.list) using OAuth, but the query refers to the direct Gemini API.

Citations:


🏁 Script executed:

# First, let's find the files mentioned in the review
fd -t f "handler.ts" packages/cli

Repository: protoLabsAI/protoCLI

Length of output: 149


🏁 Script executed:

# Check the handler.ts file around line 74
head -80 packages/cli/src/commands/setup/handler.ts | tail -20

Repository: protoLabsAI/protoCLI

Length of output: 734


🏁 Script executed:

# Look at the fetchAvailableModels function definition
fd -t f "modelDiscovery.ts" packages/cli

Repository: protoLabsAI/protoCLI

Length of output: 114


🏁 Script executed:

# Examine the modelDiscovery.ts file - first check its size
wc -l packages/cli/src/commands/setup/modelDiscovery.ts

Repository: protoLabsAI/protoCLI

Length of output: 118


🏁 Script executed:

# Check the fetch call and parser sections mentioned in review (lines 28-45 and 101-143)
cat -n packages/cli/src/commands/setup/modelDiscovery.ts | sed -n '25,50p'

Repository: protoLabsAI/protoCLI

Length of output: 990


🏁 Script executed:

# Check the parser section
cat -n packages/cli/src/commands/setup/modelDiscovery.ts | sed -n '98,150p'

Repository: protoLabsAI/protoCLI

Length of output: 1696


🏁 Script executed:

# Look for preset definitions with authType
fd -t f "preset" packages/cli | head -20

Repository: protoLabsAI/protoCLI

Length of output: 46


🏁 Script executed:

# Search for authType mentions in the codebase
rg "authType" packages/cli -B 2 -A 2

Repository: protoLabsAI/protoCLI

Length of output: 50376


🏁 Script executed:

# Find PROVIDER_PRESETS definition
rg "PROVIDER_PRESETS" packages/cli -B 5 -A 10

Repository: protoLabsAI/protoCLI

Length of output: 8158


🏁 Script executed:

# Search for preset type definition
rg "PROVIDER_PRESETS\s*[:=]" packages/cli -A 30

Repository: protoLabsAI/protoCLI

Length of output: 2233


🏁 Script executed:

# Look for preset-related files
fd -t f "preset" packages/cli

Repository: protoLabsAI/protoCLI

Length of output: 46


🏁 Script executed:

# Check for Anthropic and Gemini preset definitions
rg -i "anthropic|gemini" packages/cli/src/commands/setup -B 2 -A 2

Repository: protoLabsAI/protoCLI

Length of output: 2769


Pass preset.authType to fetchAvailableModels() to support Anthropic and Gemini model discovery.

The call on line 74 passes only baseUrl and apiKey, but the discovery function hardcodes Authorization: Bearer ... headers and the parser only handles OpenAI-style response shapes. Anthropic requires X-Api-Key + anthropic-version headers, and Gemini requires x-goog-api-key header with query parameters. The preset object (with authType) is available but not passed to the discovery function, so Anthropic and Gemini presets cannot discover models during setup. Either branch the discovery logic by preset.authType to use the correct headers and response parsing for each provider, or skip auto-discovery for non-OpenAI-compatible presets.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/setup/handler.ts` at line 74, The call to
fetchAvailableModels(baseUrl, apiKey) omits preset.authType so discovery always
uses OpenAI-style Authorization and parsing; update the call to pass
preset.authType and update fetchAvailableModels to accept an authType parameter
(or branch inside setup handler before calling) and handle provider-specific
headers and response parsing for "openai" vs "anthropic" vs "gemini" (e.g., use
X-Api-Key + anthropic-version for Anthropic, x-goog-api-key / query params for
Gemini) or short-circuit and skip auto-discovery for non-OpenAI-compatible
presets; locate uses of fetchAvailableModels and preset.authType to implement
the branch and ensure model-parser logic inside fetchAvailableModels (or the new
branch) correctly maps each provider's response shape to the common models
format.

return;
}
writeStderrLine('Setup cancelled — no model selected.\n');
process.exit(1);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Remove process.exit() from this shared wizard handler.

runSetupWizard() is documented as reusable from both proto setup and /setup, so these exits will terminate the entire interactive session on success, cancel, or failure instead of just ending the wizard. Return a status or throw, and let the top-level CLI entrypoint decide whether the process should exit.

Also applies to: 136-143

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/setup/handler.ts` at line 95, Remove the direct
process.exit(...) calls from the shared runSetupWizard handler and any helper
functions it calls (referenced in this file around runSetupWizard and the blocks
corresponding to the success/cancel/failure flows), and instead return an
explicit status value or throw an Error to indicate success, cancellation, or
failure; update runSetupWizard to propagate that status/exception to its caller
and ensure the top-level CLI entrypoint (the command handlers that call
runSetupWizard) decides whether to call process.exit based on the returned
status or caught exception.

Comment on lines +572 to +577
// Persist voice / STT settings
if (sttConfig) {
settings.setValue(scope, 'voice.enabled', sttConfig.enabled);
settings.setValue(scope, 'voice.sttEndpoint', sttConfig.endpoint);
settings.setValue(scope, 'voice.sttEnvKey', sttConfig.envKey);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Skipping STT should not keep the previous voice backend active.

When sttConfig is null, this leaves any existing voice.enabled, voice.sttEndpoint, and voice.sttEnvKey untouched. Re-running setup and choosing “Skip for now” can therefore keep /voice pointed at the old provider even though the wizard implied voice was skipped. Add an explicit else branch that disables voice and clears stale STT settings.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@packages/cli/src/commands/setup/handler.ts` around lines 572 - 577, When
sttConfig is null the code currently leaves previous STT values intact; update
the block handling sttConfig so that the else branch explicitly disables voice
and clears stale STT settings: in the handler where sttConfig is checked (the
block calling settings.setValue(scope, 'voice.enabled', ...),
settings.setValue(scope, 'voice.sttEndpoint', ...) and settings.setValue(scope,
'voice.sttEnvKey', ...)), add an else that calls settings.setValue(scope,
'voice.enabled', false) and clears or sets ''/null for 'voice.sttEndpoint' and
'voice.sttEnvKey' to ensure the old backend is not left active.

@mabry1985
mabry1985 merged commit b21c3de into main Apr 24, 2026
7 checks passed
@mabry1985
mabry1985 deleted the fix/telemetry-gate-and-malformed-toolcall-drop branch April 24, 2026 06:42
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