Skip to content

STA-251: add external coding agent integrations - #1541

Merged
glenntws merged 11 commits into
mainfrom
codex-subscription-integration
Aug 15, 2026
Merged

glenntws merged 11 commits into
mainfrom
codex-subscription-integration

Conversation

@jakobFNF

@jakobFNF jakobFNF commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor
  • add a generic external-agent runtime boundary to agent-core
  • integrate Codex, Claude Code, and OpenCode through ACP
  • support Codex subscription inference with either the Codex harness or the Stagewise harness
  • translate plans, tool calls, approvals, file changes, streaming output, images, and structured user input into the native Stagewise UI
  • expose native Stagewise structured user input to external coding agents through a local MCP server
  • discover available models, thinking-effort options, context windows, and subscription usage from supported agents
  • Fixes feat: Support OpenAI subscriptions #1500

Note

High Risk
Large new subprocess/ACP surface area touching tool execution, file-edit approvals, OAuth/token reads, and session persistence; mistakes could affect security or data outside mounted workspaces.

Overview
Adds external coding agents (Codex, Claude Code, OpenCode) as first-class provider instances by wiring a new AcpAgentRuntime into agent-core through externalAgentRuntimeFactory, while the native Stagewise agent keeps its existing path.

The runtime spawns bundled or user-installed CLIs over Agent Client Protocol, maps streaming sessions, tool calls, diffs, shell output, plans, images, and permissions into native Stagewise message parts, and routes smart / always-ask / always-allow approval (including workspace auto-approve for in-mount edits). A local MCP server + HTTP callback bridge exposes stagewise_request_user_input so agents can drive the same structured question UI as the built-in agent.

Build & CI: bundle:acp esbuild step ships codex-acp, claude-agent-acp, and stagewise-mcp-server artifacts; monorepo smoke tests now run the packaged app from an isolated temp directory with NODE_PATH unset.

Providers: Registry gains ACP harness types plus codex-stagewise (ChatGPT OAuth via Codex CLI auth, OpenAI Responses middleware for utility calls). Model discovery and subscription usage limits are added for Codex, Claude Code, and OpenCode. Utility-model resolution skips external-agent instances so title/compression stay on API-capable models; preferences block duplicate local-agent connections.

Reviewed by Cursor Bugbot for commit f8bb1d2. Bugbot is set up for automated code reviews on this repo. Configure here.

@vercel

vercel Bot commented Aug 10, 2026 •

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
website Ready Ready Preview Aug 15, 2026 8:25am

Request Review

@CLAassistant

CLAassistant commented Aug 10, 2026 •

Copy link
Copy Markdown

CLA assistant check
All committers have signed the CLA.

@coderabbitai

coderabbitai Bot commented Aug 10, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This change adds ACP external-agent support across agent-core, browser runtime services, provider preferences, model selection, structured user questions, tool rendering, and local-agent setup. It adds Codex, Claude Code, and OpenCode integrations with bundled ACP and MCP executables.

Changes

ACP external agents and provider integration

Layer / File(s) Summary
Contracts, bundling, and provider catalog
apps/browser/package.json, apps/browser/scripts/..., apps/browser/src/shared/..., apps/browser/src/backend/agents/providers/...
Adds ACP build commands, provider contracts, provider definitions, model discovery metadata, and provider registration.
Process lifecycle and provider adapters
apps/browser/src/backend/agents/acp/..., apps/browser/src/backend/agents/providers/{codex,claude-code,opencode}/...
Adds executable discovery, ACP process management, provider adapters, Codex authentication, and model discovery.
ACP runtime, prompts, tools, and MCP bridge
apps/browser/src/backend/agents/acp/...
Adds session persistence, prompt construction, streamed output, tool mapping, permissions, elicitation, cancellation recovery, and authenticated MCP callbacks.
Agent-core runtime and question contracts
packages/agent-core/src/..., apps/browser/src/shared/karton-contracts/..., apps/browser/src/backend/services/toolbox/...
Adds external runtime lifecycle support, external turn execution, structured question contracts, question handling, context-window state, and session abort cleanup.
Preferences and browser interface
apps/browser/src/backend/services/preferences.ts, apps/browser/src/ui/..., apps/browser/src/shared/provider-instance-helpers.ts
Adds local-agent availability checks, duplicate prevention, utility-model filtering, provider logos, external-agent tool rendering, installation guidance, and context-window display.

Estimated code review effort: 5 (Critical) | ~120 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 12.64% 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the pull request's main change: adding external coding agent integrations.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex-subscription-integration

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@greptile-apps

greptile-apps Bot commented Aug 10, 2026 •

Copy link
Copy Markdown

Greptile Summary

This PR adds a generic ACP runtime and external coding-agent integrations for Codex, Claude Code, and OpenCode.

  • Bundles and launches external ACP agents across packaged desktop environments.
  • Maps external-agent prompts, tools, plans, approvals, images, and structured input into Stagewise.
  • Adds provider discovery, model/thinking metadata, subscription usage, session persistence, and UI support.
  • Extends CI smoke tests to verify packaged applications in an isolated environment.

Confidence Score: 5/5

The PR appears safe to merge because no blocking failure remains within the scope of the previous review threads.

No blocking failure remains.

Important Files Changed

Filename Overview
apps/browser/src/backend/agents/acp/runtime.ts Implements serialized ACP sessions, turn lifecycle management, streamed output mapping, approvals, structured input, cancellation, and session persistence.
apps/browser/src/backend/agents/acp/form-lifecycle.ts Coordinates one active Stagewise structured-input form and publishes completed or cancelled results.
apps/browser/src/backend/agents/acp/stagewise-mcp-bridge.ts Provides an authenticated loopback callback bridge for structured external-agent input requests.
apps/browser/src/backend/agents/acp/process-client.ts Manages ACP subprocess startup, protocol initialization, callback dispatch, cancellation, and shutdown.
packages/agent-core/src/host/external-agent-runtime.ts Defines the host-agnostic runtime boundary used to delegate agent turns to external coding agents.

Reviews (13): Last reviewed commit: "fix(stagewise): discard stale ACP sessio..." | Re-trigger Greptile

Comment thread apps/browser/src/backend/agents/acp/runtime.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 18

Caution

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

⚠️ Outside diff range comments (1)
packages/agent-core/src/agents/base-agent.ts (1)

3241-3285: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Unguarded awaits on the external runtime skip required local cleanup. Each lifecycle method awaits a call into an out-of-process external agent runtime with no error containment. The external process can die or reject at any time. A rejection then propagates out of the lifecycle method and skips the local state cleanup that the caller performs after it.

  • packages/agent-core/src/agents/base-agent.ts#L3241-L3285: wrap await externalStop in a try/catch that logs and reports the failure. A rejection here makes internalStop reject after local cleanup already finished, so stop() skips setIsWorkingFalse() at line 968 and the UI keeps showing the agent as working. flushQueue() skips its runStep() at line 954, and recoverInterruptedRun() skips setting _pendingSyntheticContinuation.
  • packages/agent-core/src/agents/base-agent.ts#L3873-L3873: wrap await this.externalRuntime?.teardown() in a try/catch. AgentManager.onTeardown loops over activeAgents calling agent.onTeardown() with no try/catch, so one rejecting teardown aborts the loop and leaks every remaining agent's resources.

The same root cause affects respondToApproval at line 861, which is flagged separately because it also wedges approval state.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/agent-core/src/agents/base-agent.ts` around lines 3241 - 3285,
Contain failures from external runtime lifecycle calls so local cleanup and
subsequent agents continue even when the out-of-process runtime rejects: in
internalStop around externalStop
(packages/agent-core/src/agents/base-agent.ts:3241-3285), wrap the await in
try/catch, log the failure, and report it without rethrowing; in onTeardown at
externalRuntime.teardown (packages/agent-core/src/agents/base-agent.ts:3873),
apply the same contained logging/reporting behavior so AgentManager.onTeardown
can continue its loop. The separately flagged respondToApproval path requires
the same treatment but is not a direct change site for this comment.
🧹 Nitpick comments (3)
apps/browser/src/backend/agents/providers/codex/app-server-client.ts (1)

31-34: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer the application Logger over Console.

The constructor types logger as Pick<Console, 'debug' | 'warn'>, and both call sites (models.ts and chatgpt-auth.ts) pass the global console. AcpProcessClient in apps/browser/src/backend/agents/acp/process-client.ts uses Pick<Logger, 'debug' | 'warn'> instead. Use the same Logger type here so ACP process output reaches the structured log sinks.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/browser/src/backend/agents/providers/codex/app-server-client.ts` around
lines 31 - 34, Update the AcpProcessClient constructor logger parameter to use
Pick<Logger, 'debug' | 'warn'> instead of Pick<Console, 'debug' | 'warn'>, and
ensure both callers in models.ts and chatgpt-auth.ts pass the application Logger
so output reaches structured logging.
apps/browser/src/backend/agents/providers/opencode/acp-adapter.ts (1)

24-48: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Extract the approval mapping and the MCP timeout constant.

environment (Line 25) and processKeyForApproval (Line 47) repeat the same expression approvalMode === 'alwaysAllow' ? 'allow' : 'ask'. The two values must stay equal, because the process cache key must match the configured permission. Extract one helper. Also name the 12 * 60 * 60 * 1_000 timeout.

♻️ Proposed refactor
+const MCP_TIMEOUT_MS = 12 * 60 * 60 * 1_000;
+
+function bashPermission(approvalMode: string): string {
+  return approvalMode === 'alwaysAllow' ? 'allow' : 'ask';
+}
+
 export const openCodeAcpAdapter: AcpAdapter = {
   async environment(env, approvalMode) {
-    const permission = approvalMode === 'alwaysAllow' ? 'allow' : 'ask';
+    const permission = bashPermission(approvalMode);
-          mcp_timeout: Math.max(
-            numberValue(experimental.mcp_timeout) ?? 0,
-            12 * 60 * 60 * 1_000,
-          ),
+          mcp_timeout: Math.max(
+            numberValue(experimental.mcp_timeout) ?? 0,
+            MCP_TIMEOUT_MS,
+          ),
   processKeyForApproval(approvalMode) {
-    return approvalMode === 'alwaysAllow' ? 'allow' : 'ask';
+    return bashPermission(approvalMode);
   },
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/browser/src/backend/agents/providers/opencode/acp-adapter.ts` around
lines 24 - 48, Extract the repeated approval mapping from environment and
processKeyForApproval into a shared helper, and use it in both methods so the
configured permission and cache key remain identical. Replace the inline MCP
timeout calculation in environment with a named constant representing the
12-hour timeout.
apps/browser/src/backend/agents/providers/codex/stagewise-harness.ts (1)

56-67: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Key blocks by type and id.

textBlock looks up blocks by id only. If a text part and a reasoning part ever share an id, the second lookup returns the first block and appends reasoning text into the text block. Include the type in the key to remove that coupling.

♻️ Proposed refactor
-    const existing = blocks.get(id);
+    const key = `${type}:${id}`;
+    const existing = blocks.get(key);
     if (existing) return existing;
     const block = { type, text: '', providerMetadata } as TextBlock;
-    blocks.set(id, block);
+    blocks.set(key, block);
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/browser/src/backend/agents/providers/codex/stagewise-harness.ts` around
lines 56 - 67, Update the blocks lookup and storage in textBlock so entries are
keyed by both type and id, ensuring text and reasoning parts with the same id
create and retrieve separate blocks while preserving existing reuse behavior for
matching type-id pairs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/browser/src/backend/agents/acp/adapter.ts`:
- Around line 132-142: Update the Node version probe in prepareAcpProcess,
specifically the execFileAsync call, to include an appropriate timeout option so
a non-terminating node --version process cannot leave startup pending. Preserve
the existing version parsing and minimumNodeMajor validation behavior.
- Around line 111-116: Ensure Windows shell launches quote executable paths and
arguments before passing them to cmd.exe: in
apps/browser/src/backend/agents/acp/adapter.ts:111-116, document or redesign
needsShell to enforce this requirement; in
apps/browser/src/backend/agents/acp/process-client.ts:65-70, quote
launch.command and launch.args when launch.shell is true; and in
apps/browser/src/backend/agents/providers/codex/app-server-client.ts:57-61,
quote executable whenever needsShell(executable) returns true, including paths
and values containing spaces or shell metacharacters.

In `@apps/browser/src/backend/agents/acp/form-lifecycle.ts`:
- Around line 53-65: Update the userInput promise handling in the form lifecycle
flow so the promise returned by requestUserInput always has a rejection handler
attached before Promise.race executes. Preserve the existing cancellation result
and cleanup behavior while ensuring a later rejection after cancelled wins
cannot become unhandled.

In `@apps/browser/src/backend/agents/acp/process-client.ts`:
- Around line 109-122: Update the spawn-and-initialize flow in start to bound
the initialize request with the existing timeout mechanism, ensuring an
unresponsive agent causes initialization to fail. Wrap the sequence so every
start failure invokes this.close() before rethrowing the original error.

In `@apps/browser/src/backend/agents/acp/runtime.test.ts`:
- Around line 620-642: Update the “hides Claude internal plan files” test to
derive the home directory with os.homedir() instead of process.env.HOME, and use
that value when constructing both Claude plan file paths. Preserve the existing
assertion and test behavior across platforms.

In `@apps/browser/src/backend/agents/acp/stagewise-mcp-bridge.ts`:
- Around line 69-75: Update AcpMcpBridge.close to call
server.closeAllConnections() after awaiting server.close(), ensuring idle
keep-alive sockets are closed during shutdown on Node 22.12+.

In `@apps/browser/src/backend/agents/providers/codex/acp-adapter.ts`:
- Around line 26-28: Update sessionModeForApproval to use Codex’s broader
agent-full-access mode for alwaysAllow, while preserving read-only for alwaysAsk
and the existing smart behavior. In runtime.ts, assign alwaysAllow a distinct
new Codex session key so it does not reuse the smart process key and can
establish the increased-access session.

In `@apps/browser/src/backend/agents/providers/codex/app-server-client.ts`:
- Around line 152-159: Update CodexAppServerClient.close to preserve an error
listener on the child process instead of removing all listeners, preventing
kill-related error events from becoming uncaught. After sending SIGTERM, add a
bounded fallback that sends SIGKILL if the process remains running, including
the shell-wrapper case, while keeping shutdown idempotent and avoiding unbounded
timers.
- Around line 123-150: Make start idempotent by caching its in-flight/completed
promise and returning that promise on subsequent calls instead of spawning
another process; update the start flow and its process assignment accordingly.
Reset the cached start promise in both close and handleExit so the client can
start cleanly after shutdown or unexpected exit, while preserving discoverModels
and refreshChatGptAccount behavior.

In `@apps/browser/src/backend/agents/providers/codex/models.ts`:
- Around line 33-43: Update the Codex model mapping around the returned object
to use the per-model context_window/contextWindow value when provided, and fall
back to a named context-window constant only when absent. Remove the hardcoded
258_000 value while preserving the existing model capability and reasoning
fields.

In `@apps/browser/src/backend/agents/providers/opencode/provider.ts`:
- Around line 100-104: Update discoverOpenCodeModels around the execFileAsync
call for “models --verbose” to enforce a finite timeout; retain the
child-process handle, race execution against the timeout, kill the child when
the timeout wins, and route the timeout through the existing discovery error
path.
- Around line 38-89: Rename the local const output binding in
parseOpenCodeModels to avoid colliding with the function’s output parameter, and
update the output modality references to use the new binding.

In `@apps/browser/src/backend/services/preferences.ts`:
- Around line 2054-2059: Update preferences.getLocalAgentAvailability to safely
look up PROVIDER_TYPE_DISPLAY_INFO for unknown typeId values, following the
guarded lookup pattern already used near the existing reference, and return the
established unavailable/error result instead of dereferencing undefined. Reuse
the resulting displayInfo.displayName in the error message, and call
this.assertNotDisposed() at the start of the method to match other public
methods.

In
`@apps/browser/src/backend/services/toolbox/tools/user-interaction/ask-user-questions.ts`:
- Around line 162-164: Re-validate the flat-parsed input in the
ask-user-questions tool by passing it through
askUserQuestionsToolInputSchema.parse and remove the unsafe
AskUserQuestionsToolInput cast, while retaining
askUserQuestionsToolInputSchemaFlat as the provider-facing inputSchema. In
apps/browser/src/backend/services/toolbox/tools/user-interaction/ask-user-questions.ts
lines 162-164, update the parse flow accordingly; in
apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts
lines 94-97, add a comment beside the two schema exports explaining the flat
variant’s strict-mode purpose and that callers must re-validate with
askUserQuestionsToolInputSchema before treating values as
AskUserQuestionsToolInput.

In
`@apps/browser/src/ui/screens/main/agent-chat/chat/_components/message-part-ui/tools/external-agent.tsx`:
- Around line 29-51: Update the external tool status logic around isFinished,
label, and resultText to derive an explicit error state from part.state ===
'output-error' before treating output-* states as finished. Failed calls must
display a failed label instead of Changed, plan status, or Finished/Running, and
errorText must take precedence so it remains visible even when plan or location
data exists.

In
`@apps/browser/src/ui/screens/main/agent-chat/chat/_components/model-select.tsx`:
- Around line 306-310: Update the runtime context-window fallback logic around
runtimeContextWindow so zero is treated as unknown, not as a valid size. Use a
truthiness check before overriding the catalog context-window value, ensuring
the footer retains the catalog denominator and does not render “0k context.”

In `@packages/agent-core/src/agents/base-agent.ts`:
- Around line 861-863: Update sendToolApprovalResponse around the
externalRuntime.respondToApproval call to contain any rejection from the
external runtime, ensuring resolveApproval always executes afterward. Preserve
the handledExternally result for successful responses, but allow local approval
state to resolve even when the external call fails, including the corresponding
path around the later occurrence.
- Around line 2354-2359: In runExternalStep, re-check this._stepGeneration
against the captured stepGeneration after the awaited saveState and before
reading queuedMessages or invoking onIdle/emitNotificationEvent. Return
immediately when the generation changed, so a stopped turn neither emits done
nor schedules runStep; preserve the existing success behavior when the
generation still matches.

---

Outside diff comments:
In `@packages/agent-core/src/agents/base-agent.ts`:
- Around line 3241-3285: Contain failures from external runtime lifecycle calls
so local cleanup and subsequent agents continue even when the out-of-process
runtime rejects: in internalStop around externalStop
(packages/agent-core/src/agents/base-agent.ts:3241-3285), wrap the await in
try/catch, log the failure, and report it without rethrowing; in onTeardown at
externalRuntime.teardown (packages/agent-core/src/agents/base-agent.ts:3873),
apply the same contained logging/reporting behavior so AgentManager.onTeardown
can continue its loop. The separately flagged respondToApproval path requires
the same treatment but is not a direct change site for this comment.

---

Nitpick comments:
In `@apps/browser/src/backend/agents/providers/codex/app-server-client.ts`:
- Around line 31-34: Update the AcpProcessClient constructor logger parameter to
use Pick<Logger, 'debug' | 'warn'> instead of Pick<Console, 'debug' | 'warn'>,
and ensure both callers in models.ts and chatgpt-auth.ts pass the application
Logger so output reaches structured logging.

In `@apps/browser/src/backend/agents/providers/codex/stagewise-harness.ts`:
- Around line 56-67: Update the blocks lookup and storage in textBlock so
entries are keyed by both type and id, ensuring text and reasoning parts with
the same id create and retrieve separate blocks while preserving existing reuse
behavior for matching type-id pairs.

In `@apps/browser/src/backend/agents/providers/opencode/acp-adapter.ts`:
- Around line 24-48: Extract the repeated approval mapping from environment and
processKeyForApproval into a shared helper, and use it in both methods so the
configured permission and cache key remain identical. Replace the inline MCP
timeout calculation in environment with a named constant representing the
12-hour timeout.
🪄 Autofix

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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 3743ac56-7872-416c-ac8e-fd1cafb6cd4a

📥 Commits

Reviewing files that changed from the base of the PR and between 065cf5f and d1c7fa1.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (69)
  • apps/browser/.gitignore
  • apps/browser/package.json
  • apps/browser/scripts/bundle-acp-agents.ts
  • apps/browser/src/backend/agents/acp/adapter-registry.ts
  • apps/browser/src/backend/agents/acp/adapter.test.ts
  • apps/browser/src/backend/agents/acp/adapter.ts
  • apps/browser/src/backend/agents/acp/elicitation-mapper.ts
  • apps/browser/src/backend/agents/acp/form-lifecycle.ts
  • apps/browser/src/backend/agents/acp/process-client.ts
  • apps/browser/src/backend/agents/acp/prompt-builder.test.ts
  • apps/browser/src/backend/agents/acp/prompt-builder.ts
  • apps/browser/src/backend/agents/acp/runtime.test.ts
  • apps/browser/src/backend/agents/acp/runtime.ts
  • apps/browser/src/backend/agents/acp/stagewise-mcp-bridge.ts
  • apps/browser/src/backend/agents/acp/stagewise-mcp-server.ts
  • apps/browser/src/backend/agents/acp/tool-mapper.ts
  • apps/browser/src/backend/agents/providers/claude-code/acp-adapter.ts
  • apps/browser/src/backend/agents/providers/claude-code/provider.ts
  • apps/browser/src/backend/agents/providers/codex/acp-adapter.ts
  • apps/browser/src/backend/agents/providers/codex/app-server-client.ts
  • apps/browser/src/backend/agents/providers/codex/chatgpt-auth.ts
  • apps/browser/src/backend/agents/providers/codex/codex-harness.ts
  • apps/browser/src/backend/agents/providers/codex/models.ts
  • apps/browser/src/backend/agents/providers/codex/stagewise-harness.test.ts
  • apps/browser/src/backend/agents/providers/codex/stagewise-harness.ts
  • apps/browser/src/backend/agents/providers/external-agent.ts
  • apps/browser/src/backend/agents/providers/opencode/acp-adapter.ts
  • apps/browser/src/backend/agents/providers/opencode/provider.test.ts
  • apps/browser/src/backend/agents/providers/opencode/provider.ts
  • apps/browser/src/backend/agents/providers/opencode/tool-normalizer.ts
  • apps/browser/src/backend/agents/providers/registry.ts
  • apps/browser/src/backend/main.ts
  • apps/browser/src/backend/services/agent-core-bridge/host-models.ts
  • apps/browser/src/backend/services/agent-core-bridge/host.test.ts
  • apps/browser/src/backend/services/preferences.test.ts
  • apps/browser/src/backend/services/preferences.ts
  • apps/browser/src/backend/services/toolbox/index.ts
  • apps/browser/src/backend/services/toolbox/tools/user-interaction/ask-user-questions.ts
  • apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts
  • apps/browser/src/shared/karton-contracts/ui/agent/tools/types.ts
  • apps/browser/src/shared/karton-contracts/ui/index.ts
  • apps/browser/src/shared/karton-contracts/ui/shared-types.ts
  • apps/browser/src/shared/model-thinking-capabilities.test.ts
  • apps/browser/src/shared/model-thinking-capabilities.ts
  • apps/browser/src/shared/provider-instance-helpers.test.ts
  • apps/browser/src/shared/provider-instance-helpers.ts
  • apps/browser/src/ui/components/provider-instance-logo.tsx
  • apps/browser/src/ui/screens/main/agent-chat/chat/_components/chat-history.tsx
  • apps/browser/src/ui/screens/main/agent-chat/chat/_components/footer-status-card/index.tsx
  • apps/browser/src/ui/screens/main/agent-chat/chat/_components/message-part-ui/tools/ask-user-questions.tsx
  • apps/browser/src/ui/screens/main/agent-chat/chat/_components/message-part-ui/tools/external-agent.tsx
  • apps/browser/src/ui/screens/main/agent-chat/chat/_components/message-part-ui/tools/unknown.tsx
  • apps/browser/src/ui/screens/main/agent-chat/chat/_components/model-presets-shared.ts
  • apps/browser/src/ui/screens/main/agent-chat/chat/_components/model-select.tsx
  • apps/browser/src/ui/screens/main/agent-chat/chat/_components/panel-footer.tsx
  • apps/browser/src/ui/screens/main/agent-chat/chat/_lib/chat-history-scroll-event.ts
  • apps/browser/src/ui/screens/settings/sections/model-presets-section.tsx
  • apps/browser/src/ui/screens/settings/sections/models-providers-section.tsx
  • apps/browser/src/ui/utils/model-thinking.ts
  • packages/agent-core/src/agents/base-agent.ts
  • packages/agent-core/src/host/external-agent-runtime.ts
  • packages/agent-core/src/host/host.ts
  • packages/agent-core/src/host/index.ts
  • packages/agent-core/src/services/agent-manager/agent-manager.ts
  • packages/agent-core/src/services/agent-manager/state-mutations/simple.ts
  • packages/agent-core/src/services/agent-manager/universal-toolbox.ts
  • packages/agent-core/src/types/agent.ts
  • packages/agent-shell/src/engine/session-manager.test.ts
  • packages/agent-shell/src/engine/session-manager.ts

Comment on lines +111 to +116
export function needsShell(
command: string,
platform: NodeJS.Platform = process.platform,
): boolean {
return platform === 'win32' && /\.(?:cmd|bat)$/i.test(command);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Unquoted command passed to cmd.exe when needsShell enables the shell. needsShell returns true for Windows .cmd and .bat files. Every caller then sets shell: true on spawn. With shell: true, Node joins the command and arguments into one string for cmd.exe and applies no quoting. A resolved path that contains a space, for example C:\Program Files\nodejs\codex.cmd, breaks the launch. Paths supplied through CODEX_PATH, CLAUDE_CODE_EXECUTABLE, or OPENCODE_EXECUTABLE can also carry shell metacharacters into cmd.exe.

  • apps/browser/src/backend/agents/acp/adapter.ts#L111-L116: document the quoting requirement of needsShell, or return a prepared, quoted command instead of a boolean.
  • apps/browser/src/backend/agents/acp/process-client.ts#L65-L70: quote launch.command and launch.args when launch.shell is true.
  • apps/browser/src/backend/agents/providers/codex/app-server-client.ts#L57-L61: quote executable when needsShell(executable) returns true.
🧰 Tools
🪛 ast-grep (0.45.0)

[warning] Importing child_process exposes a command-execution surface; ensure any command/argument built from input is validated, and prefer execFile/spawn with an argument array over exec.
Context: import { execFile } from 'node:child_process';
Note: [CWE-78] Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection').

(detect-child-process-typescript)

📍 Affects 3 files
  • apps/browser/src/backend/agents/acp/adapter.ts#L111-L116 (this comment)
  • apps/browser/src/backend/agents/acp/process-client.ts#L65-L70
  • apps/browser/src/backend/agents/providers/codex/app-server-client.ts#L57-L61
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/browser/src/backend/agents/acp/adapter.ts` around lines 111 - 116,
Ensure Windows shell launches quote executable paths and arguments before
passing them to cmd.exe: in
apps/browser/src/backend/agents/acp/adapter.ts:111-116, document or redesign
needsShell to enforce this requirement; in
apps/browser/src/backend/agents/acp/process-client.ts:65-70, quote
launch.command and launch.args when launch.shell is true; and in
apps/browser/src/backend/agents/providers/codex/app-server-client.ts:57-61,
quote executable whenever needsShell(executable) returns true, including paths
and values containing spaces or shell metacharacters.

Source: Linters/SAST tools

Comment thread apps/browser/src/backend/agents/acp/adapter.ts
Comment thread apps/browser/src/backend/agents/acp/form-lifecycle.ts
Comment thread apps/browser/src/backend/agents/acp/process-client.ts Outdated
Comment thread apps/browser/src/backend/agents/acp/runtime.test.ts
Comment on lines +162 to +164
const params = askUserQuestionsToolInputSchemaFlat.parse(
input,
) as unknown as AskUserQuestionsToolInput;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

The flat parse is cast to a stronger type without re-validation. askUserQuestionsToolInputSchemaFlat makes options, defaultValue, and the other per-type fields optional for every type value. AskUserQuestionsToolInput derives from askUserQuestionsToolInputSchema, which requires options with min(1) for radio-group and checkbox-group. Casting the flat parse result to the structured type asserts guarantees the flat schema never checked.

  • apps/browser/src/backend/services/toolbox/tools/user-interaction/ask-user-questions.ts#L162-L164: after the flat parse, pass the result through askUserQuestionsToolInputSchema.parse(...) and remove the as unknown as AskUserQuestionsToolInput cast. Keep the flat schema as the tool's inputSchema for provider strict-mode compatibility.
  • apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts#L94-L97: add a comment next to the two exports that records why the flat variant exists and that callers must re-validate with askUserQuestionsToolInputSchema before treating the value as AskUserQuestionsToolInput.

External ACP agents now reach this path through ExternalAgentRuntimeContext.requestUserInput, which accepts unknown, so no upstream schema constrains the payload.

📍 Affects 2 files
  • apps/browser/src/backend/services/toolbox/tools/user-interaction/ask-user-questions.ts#L162-L164 (this comment)
  • apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts#L94-L97
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/browser/src/backend/services/toolbox/tools/user-interaction/ask-user-questions.ts`
around lines 162 - 164, Re-validate the flat-parsed input in the
ask-user-questions tool by passing it through
askUserQuestionsToolInputSchema.parse and remove the unsafe
AskUserQuestionsToolInput cast, while retaining
askUserQuestionsToolInputSchemaFlat as the provider-facing inputSchema. In
apps/browser/src/backend/services/toolbox/tools/user-interaction/ask-user-questions.ts
lines 162-164, update the parse flow accordingly; in
apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts
lines 94-97, add a comment beside the two schema exports explaining the flat
variant’s strict-mode purpose and that callers must re-validate with
askUserQuestionsToolInputSchema before treating values as
AskUserQuestionsToolInput.

Comment on lines +306 to +310
const runtimeContextWindow = useKartonState((s) =>
openAgent
? s.agents.instances[openAgent]?.state.contextWindowSize
: undefined,
);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Treat a zero runtime context-window size as unknown.

Line 364 only rejects undefined. If the runtime reports 0, Line 373 renders 0k context and Line 372 writes contextWindowRaw: 0, which replaces the catalog value that the footer token bar uses as a denominator. Use a truthiness check so an unknown size keeps the catalog value.

🛡️ Proposed fix
       const usesRuntimeContext =
-        runtimeContextWindow !== undefined &&
+        !!runtimeContextWindow &&
         entry.modelId === selectedModel &&
         entry.instanceId ===
           (selectedProviderInstanceId ?? DEFAULT_INSTANCE_ID);

Also applies to: 363-375

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/browser/src/ui/screens/main/agent-chat/chat/_components/model-select.tsx`
around lines 306 - 310, Update the runtime context-window fallback logic around
runtimeContextWindow so zero is treated as unknown, not as a valid size. Use a
truthiness check before overriding the catalog context-window value, ensuring
the footer retains the catalog denominator and does not render “0k context.”

Comment thread packages/agent-core/src/agents/base-agent.ts Outdated
Comment thread packages/agent-core/src/agents/base-agent.ts

@cubic-dev-ai cubic-dev-ai 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.

All reported issues were addressed across 4 files (changes from recent commits).

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

Comment thread apps/browser/src/backend/services/preferences.ts
Comment thread apps/browser/src/backend/agents/acp/runtime.ts

@cubic-dev-ai cubic-dev-ai 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.

2 issues found and verified against the latest diff

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts">

<violation number="1" location="apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts:63">
P2: The flat schema accepts defaults invalid for the selected control, so checkbox defaults such as `'true'` are silently rendered as unchecked. Make defaults conditional on `type`, matching `questionFieldSchema`.</violation>

<violation number="2" location="apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts:69">
P1: A flattened radio or checkbox-group can omit `options`, then opening its form throws on `field.options.map`. Preserve the per-type required `options` constraint when accepting flat input, or normalize/reject these fields before storing them.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic

min: z.number().optional(),
max: z.number().optional(),
required: z.boolean().optional(),
options: z.array(questionFieldOptionSchema).min(1).optional(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: A flattened radio or checkbox-group can omit options, then opening its form throws on field.options.map. Preserve the per-type required options constraint when accepting flat input, or normalize/reject these fields before storing them.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts, line 69:

<comment>A flattened radio or checkbox-group can omit `options`, then opening its form throws on `field.options.map`. Preserve the per-type required `options` constraint when accepting flat input, or normalize/reject these fields before storing them.</comment>

<file context>
@@ -0,0 +1,129 @@
+  min: z.number().optional(),
+  max: z.number().optional(),
+  required: z.boolean().optional(),
+  options: z.array(questionFieldOptionSchema).min(1).optional(),
+  allowOther: z.boolean().optional(),
+  defaultValues: z.array(z.string()).optional(),
</file context>

Comment thread apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts Outdated
type: z.enum(['input', 'radio-group', 'checkbox', 'checkbox-group']),
inputType: z.enum(['text', 'email', 'number', 'password']).optional(),
placeholder: z.string().optional(),
defaultValue: z.union([z.string(), z.number(), z.boolean()]).optional(),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: The flat schema accepts defaults invalid for the selected control, so checkbox defaults such as 'true' are silently rendered as unchecked. Make defaults conditional on type, matching questionFieldSchema.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts, line 63:

<comment>The flat schema accepts defaults invalid for the selected control, so checkbox defaults such as `'true'` are silently rendered as unchecked. Make defaults conditional on `type`, matching `questionFieldSchema`.</comment>

<file context>
@@ -0,0 +1,129 @@
+  type: z.enum(['input', 'radio-group', 'checkbox', 'checkbox-group']),
+  inputType: z.enum(['text', 'email', 'number', 'password']).optional(),
+  placeholder: z.string().optional(),
+  defaultValue: z.union([z.string(), z.number(), z.boolean()]).optional(),
+  minLength: z.number().optional(),
+  maxLength: z.number().optional(),
</file context>

Comment thread apps/browser/src/backend/agents/acp/elicitation-mapper.ts
Comment thread apps/browser/src/backend/services/agent-core-bridge/host-models.ts Outdated
Comment thread apps/browser/src/backend/agents/acp/process-client.ts
Comment thread packages/agent-core/src/agents/base-agent.ts
Comment thread packages/agent-core/src/types/agent.ts
Comment thread apps/browser/package.json
Comment thread apps/browser/src/backend/agents/acp/runtime.ts
Comment thread apps/browser/src/backend/agents/acp/runtime.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

♻️ Duplicate comments (2)
apps/browser/src/backend/agents/providers/codex/app-server-client.ts (1)

127-145: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Make process startup idempotent.

discoverModels and refreshChatGptAccount each call start.
Each call spawns a new codex app-server process and overwrites
this.process.
The previous process remains running. Its exit is then ignored by
handleExit.

Cache the in-flight or completed startup promise. Reset that promise in
close and handleExit.

Proposed fix
+  private startPromise: Promise<void> | null = null;
+
+  private ensureStarted(): Promise<void> {
+    this.startPromise ??= this.start().catch((error) => {
+      this.startPromise = null;
+      throw error;
+    });
+    return this.startPromise;
+  }
+
   public async discoverModels(): Promise<CodexModel[]> {
-    await this.start();
+    await this.ensureStarted();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/browser/src/backend/agents/providers/codex/app-server-client.ts` around
lines 127 - 145, Make app-server startup idempotent by caching the in-flight or
completed startup promise used by the start method, so repeated calls from
discoverModels and refreshChatGptAccount reuse the same process instead of
spawning another. Reset the cached startup promise in both close and handleExit,
while preserving existing process lifecycle and exit handling.
apps/browser/src/backend/agents/acp/runtime.test.ts (1)

632-643: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Build the plan path with nodePath.join to keep the test platform independent.

Line 632 concatenates homedir() with forward slashes. On Windows homedir() returns a backslash path, so planPath becomes a mixed-separator string such as C:\Users\x/.claude/plans/test.md. If the Claude adapter derives its hidden path prefix with nodePath.join, the prefix uses backslashes and the prefix match fails. Use nodePath.join for both the locations entry and the diff path.

♻️ Proposed fix
-    const planPath = `${homedir()}/.claude/plans/test.md`;
+    const planPath = nodePath.join(homedir(), '.claude', 'plans', 'test.md');
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/browser/src/backend/agents/acp/runtime.test.ts` around lines 632 - 643,
Update the planPath construction in the runtime test to use
nodePath.join(homedir(), ...) instead of string concatenation, and reuse that
normalized path for both the locations entry and the diff path in
runtime.upsertTool.
🧹 Nitpick comments (3)
packages/agent-core/src/host/models.ts (1)

208-210: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Document the default when the method is omitted.

Callers treat only an explicit false as a rejection, so an unimplemented method or a true return both allow the entry. State that contract in the doc comment so hosts do not assume a missing implementation blocks utility calls.

♻️ Proposed doc update
-  /** Returns whether an entry can serve internal utility requests. */
+  /**
+   * Returns whether an entry can serve internal utility requests.
+   *
+   * Callers reject an entry only when this returns `false`. Hosts that
+   * omit this method allow every entry.
+   */
   supportsUtilityCalls?(entry: UtilityModelEntry): boolean;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/agent-core/src/host/models.ts` around lines 208 - 210, Update the
doc comment for supportsUtilityCalls to state that omitted or undefined
implementations, and an explicit true result, allow utility calls; only an
explicit false rejects them.
apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.test.ts (1)

13-19: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the rejection reason, and add a positive-path case.

Line 18 uses a bare .toThrow(). The test passes for any thrown error, including one unrelated to the flattened-field mismatch. Assert the failing path or message. The suite also has no case that a valid nested input parses, so an over-strict schema change would not fail either test.

♻️ Proposed change
-    expect(() => askUserQuestionsToolInputSchema.parse(flattened)).toThrow();
+    const result = askUserQuestionsToolInputSchema.safeParse(flattened);
+    expect(result.success).toBe(false);
+    expect(result.error?.issues[0]?.path).toContain('fields');
+  });
+
+  it('accepts a valid nested input', () => {
+    expect(() =>
+      askUserQuestionsToolInputSchema.parse(
+        input([
+          {
+            type: 'radio-group',
+            questionId: 'mode',
+            label: 'Mode',
+            options: [{ value: 'a', label: 'A' }],
+          },
+        ]),
+      ),
+    ).not.toThrow();
   });

Adjust the option shape to match the nested schema.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.test.ts`
around lines 13 - 19, Update the tests around askUserQuestionsToolInputSchema to
assert the specific validation path or message for flattened input being
rejected, rather than using a bare toThrow. Add a positive case proving valid
nested option input parses successfully, and adjust the test fixture’s option
shape to match the nested schema.
packages/agent-core/src/agents/shared/history-compression/index.ts (1)

272-272: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

The new supportsUtilityCalls guard can skip every candidate, and both call sites then report a misleading error. When the guard rejects all entries, no attempt runs, lastError stays undefined, and each function throws a generic "all models failed" error. An external-agent-only preset reaches this path.

  • packages/agent-core/src/agents/shared/history-compression/index.ts#L272-L272: track whether any attempt ran in the loop and in the fallback branch at lines 304-310, then throw a distinct "no utility-capable model configured" error at line 332.
  • packages/agent-core/src/agents/shared/title-generation/index.ts#L166-L166: apply the same attempt tracking and throw the distinct error at line 267.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@packages/agent-core/src/agents/shared/history-compression/index.ts` at line
272, Track whether any model attempt runs in the history-compression loop and
its fallback branch in
packages/agent-core/src/agents/shared/history-compression/index.ts (lines
272-272 and 304-310), then have the error path at line 332 report a distinct “no
utility-capable model configured” error when none ran; apply the same attempt
tracking and distinct error handling in
packages/agent-core/src/agents/shared/title-generation/index.ts (line 166, with
the error at line 267).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Duplicate comments:
In `@apps/browser/src/backend/agents/acp/runtime.test.ts`:
- Around line 632-643: Update the planPath construction in the runtime test to
use nodePath.join(homedir(), ...) instead of string concatenation, and reuse
that normalized path for both the locations entry and the diff path in
runtime.upsertTool.

In `@apps/browser/src/backend/agents/providers/codex/app-server-client.ts`:
- Around line 127-145: Make app-server startup idempotent by caching the
in-flight or completed startup promise used by the start method, so repeated
calls from discoverModels and refreshChatGptAccount reuse the same process
instead of spawning another. Reset the cached startup promise in both close and
handleExit, while preserving existing process lifecycle and exit handling.

---

Nitpick comments:
In
`@apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.test.ts`:
- Around line 13-19: Update the tests around askUserQuestionsToolInputSchema to
assert the specific validation path or message for flattened input being
rejected, rather than using a bare toThrow. Add a positive case proving valid
nested option input parses successfully, and adjust the test fixture’s option
shape to match the nested schema.

In `@packages/agent-core/src/agents/shared/history-compression/index.ts`:
- Line 272: Track whether any model attempt runs in the history-compression loop
and its fallback branch in
packages/agent-core/src/agents/shared/history-compression/index.ts (lines
272-272 and 304-310), then have the error path at line 332 report a distinct “no
utility-capable model configured” error when none ran; apply the same attempt
tracking and distinct error handling in
packages/agent-core/src/agents/shared/title-generation/index.ts (line 166, with
the error at line 267).

In `@packages/agent-core/src/host/models.ts`:
- Around line 208-210: Update the doc comment for supportsUtilityCalls to state
that omitted or undefined implementations, and an explicit true result, allow
utility calls; only an explicit false rejects them.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: dda0571c-a885-40aa-a760-96f2068dc929

📥 Commits

Reviewing files that changed from the base of the PR and between 222d470 and ca9b0f4.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml
📒 Files selected for processing (30)
  • apps/browser/package.json
  • apps/browser/src/backend/agents/acp/adapter.test.ts
  • apps/browser/src/backend/agents/acp/adapter.ts
  • apps/browser/src/backend/agents/acp/elicitation-mapper.ts
  • apps/browser/src/backend/agents/acp/form-lifecycle.ts
  • apps/browser/src/backend/agents/acp/process-client.ts
  • apps/browser/src/backend/agents/acp/prompt-builder.test.ts
  • apps/browser/src/backend/agents/acp/prompt-builder.ts
  • apps/browser/src/backend/agents/acp/runtime.test.ts
  • apps/browser/src/backend/agents/acp/runtime.ts
  • apps/browser/src/backend/agents/acp/tool-mapper.ts
  • apps/browser/src/backend/agents/providers/codex/app-server-client.ts
  • apps/browser/src/backend/agents/providers/opencode/acp-adapter.ts
  • apps/browser/src/backend/agents/providers/opencode/provider.ts
  • apps/browser/src/backend/agents/providers/opencode/tool-normalizer.ts
  • apps/browser/src/backend/services/agent-core-bridge/host-models.ts
  • apps/browser/src/backend/services/agent-core-bridge/host.test.ts
  • apps/browser/src/backend/services/preferences.test.ts
  • apps/browser/src/backend/services/preferences.ts
  • apps/browser/src/backend/services/toolbox/tools/user-interaction/ask-user-questions.ts
  • apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.test.ts
  • apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts
  • apps/browser/src/ui/screens/main/agent-chat/chat/_components/message-part-ui/tools/external-agent.tsx
  • packages/agent-core/src/agents/base-agent.ts
  • packages/agent-core/src/agents/shared/history-compression/index.ts
  • packages/agent-core/src/agents/shared/title-generation.test.ts
  • packages/agent-core/src/agents/shared/title-generation/index.ts
  • packages/agent-core/src/host/models.ts
  • packages/agent-core/src/services/agent-manager/state-mutations/simple.ts
  • packages/agent-core/src/store/state-annotation.md
🚧 Files skipped from review as they are similar to previous changes (16)
  • packages/agent-core/src/services/agent-manager/state-mutations/simple.ts
  • apps/browser/package.json
  • apps/browser/src/backend/services/agent-core-bridge/host.test.ts
  • apps/browser/src/backend/agents/providers/opencode/tool-normalizer.ts
  • apps/browser/src/backend/agents/providers/opencode/acp-adapter.ts
  • apps/browser/src/backend/agents/acp/adapter.test.ts
  • apps/browser/src/shared/karton-contracts/ui/agent/tools/ask-user-questions.ts
  • apps/browser/src/ui/screens/main/agent-chat/chat/_components/message-part-ui/tools/external-agent.tsx
  • apps/browser/src/backend/services/toolbox/tools/user-interaction/ask-user-questions.ts
  • apps/browser/src/backend/agents/acp/form-lifecycle.ts
  • apps/browser/src/backend/agents/acp/elicitation-mapper.ts
  • apps/browser/src/backend/agents/acp/tool-mapper.ts
  • apps/browser/src/backend/services/preferences.test.ts
  • apps/browser/src/backend/services/preferences.ts
  • packages/agent-core/src/agents/base-agent.ts
  • apps/browser/src/backend/agents/acp/prompt-builder.ts

@cubic-dev-ai cubic-dev-ai 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.

1 existing issue remains and no new issues found across 31 files (changes from recent commits).

Requires human review: Auto-approval blocked because this review re-detected 1 unresolved issue already reported by Cubic.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread packages/agent-core/src/agents/base-agent.ts
Comment thread apps/browser/src/backend/agents/acp/adapter.ts
Comment thread apps/browser/src/backend/agents/acp/runtime.ts
@glenntws
glenntws force-pushed the codex-subscription-integration branch from 69716d5 to f8bb1d2 Compare August 15, 2026 08:23
@glenntws
glenntws merged commit a78f163 into main Aug 15, 2026
11 of 14 checks passed
@glenntws
glenntws deleted the codex-subscription-integration branch August 15, 2026 08:24

@cursor cursor 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.

Cursor Bugbot has reviewed your changes using high effort and found 1 potential issue.

There are 2 total unresolved issues (including 1 from previous review).

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit f8bb1d2. Configure here.

codexHome || nodePath.join(homedir(), '.codex'),
'auth.json',
);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Codex auth ignores shell CODEX_HOME

Medium Severity

getCodexChatGptAuth resolves auth.json from Electron process.env.CODEX_HOME or os.homedir(), while CodexAppServerClient launches the CLI with the login-shell environment. Users who set CODEX_HOME in their shell profile can get working model discovery/usage via app-server but failed ChatGPT auth for the Stagewise Codex harness, or refresh tokens in one home and read them from another.

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit f8bb1d2. Configure here.

This branch was successfully deployed

1 active and 1 inactive deployments
Dev — f8bb1d27 Deployed Aug 15, 2026 by glenntws via Build Browser (darwin-arm64) #6198
Preview — f8bb1d27 Deployed Aug 15, 2026 by vercel[bot]
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.

feat: Support OpenAI subscriptions

3 participants