Skip to content

Add direct Goose Agent Mode - #607

Merged
AnthonyRonning merged 5 commits into
masterfrom
codex-goose-sdk-maple
Jul 11, 2026
Merged

Add direct Goose Agent Mode#607
AnthonyRonning merged 5 commits into
masterfrom
codex-goose-sdk-maple

Conversation

@AnthonyRonning

@AnthonyRonningAnthonyRonning commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • adds a desktop Agent Mode surface with folder-scoped sessions, normal-sidebar styling, chat deletion, concurrent session runs, permissions, cancellation, and image-tool support
  • embeds the official upstream Goose runtime directly behind Maple-owned Tauri commands and events; no Goose fork, submodule, ACP server, or external Goose binary is required
  • routes Goose through Maple's loopback maple-proxy with account-scoped credential handling and the released image request-body limit needed by read_image
  • makes GLM 5.2 the concrete recommended Agent Mode default while keeping Kimi and the rest of the model catalog selectable under More models
  • removes Maple's temporary GLM/Kimi SSE tool-call rewrite and passes maple-proxy responses through unchanged at the application wrapper boundary
  • removes investigation-only raw/debug presentation, including raw event fields, token-usage rows, MCP logging rows, synthetic image metadata, and the manual runtime-restart control
  • keeps saved chats browseable and deletable while a pre-registry proxy credential waits for the user's explicit one-time replacement
  • preserves Goose terminal notices that are intentionally live-only across the completion reload, without persisting them into future provider history
  • adds a reusable unauthenticated OS Flags client with a ten-minute success-only cache and gates only the desktop Agent Mode sidebar entry behind agent_mode

Why

Tinfoil's former GLM serving path could emit multiple tool-call fragments with the same index in one SSE event. Maple temporarily merged those fragments in proxy.rs; the Tinfoil GLM update now emits a Goose-compatible stream, so retaining an application-specific stream parser would add latency and maintenance risk without providing value. Kimi remains available on a best-effort basis until its provider path receives the same compatibility work.

The image-loading fix is independent and remains at the proxy layer: Goose's base64 image requests can exceed Axum's old default, so maple-proxy 0.1.10 and Maple's proxy invariant test are preserved without repeating a large-image GUI test in every launch cycle.

The agent_mode lookup uses OS Flags' public user endpoint without credentials. PR/local builds use flags-dev.opensecret.cloud, release builds use flags.opensecret.cloud, missing keys are off, and failed requests are not cached. The rest of Maple renders immediately; enabled desktop users see the Agent Mode entry after the asynchronous lookup. The route/runtime remains unchanged because this is a rollout gate, not an authorization boundary.

Validation

  • nix develop .. -c bun run test — 51 passed, including 7 flags-client tests
  • nix develop .. -c bun run typecheck
  • nix develop .. -c bun run format:check
  • nix develop .. -c bun run lint — 0 errors; only existing unrelated warnings
  • nix develop .. -c bun run build
  • nix develop ../.. -c cargo fmt --check
  • nix develop ../.. -c cargo clippy --all-targets --all-features --locked -- -D warnings
  • nix develop ../.. -c cargo test --all-targets --all-features — 60 passed
  • nix flake check
  • rebuilt macOS app GUI: GLM was selected by default; Kimi remained in More models; two separate shell calls in one GLM turn completed without parsing/truncation errors; a second tool turn completed; switching away and reloading preserved one populated thinking section, two completed tool rows, and the final response
  • exact macOS bundle feature-flag smoke: off rendered normal chat immediately and never showed Agent Mode; on rendered normal chat first, then showed Agent Mode and navigated successfully; React StrictMode produced one lookup per app launch
  • three independent post-baseline reviews found no high or critical security, correctness, rollout, or platform findings

Notes

  • Goose is pinned to official upstream commit b7eb1e9735833a7bf12ab92994a788fbc770f218 (Goose 1.42.0).
  • Commit 0537f99f is the squashed, validated Agent Mode baseline. 550c5ce adds generic flags infrastructure; 2dd2833 adds only the agent_mode entrypoint gate.
  • Broader product/architecture/incident notes moved to OpenSecretCloud/master PR #30; managed meta-repo and local flags environment support is in opensecret-workspaces PR #7.
  • Neither deployed OS Flags environment currently contains agent_mode, so the shipped behavior remains safely off until the flag is created and rolled out.
  • The branch remains draft while launch review continues.

Summary by CodeRabbit

  • New Features
    • Added desktop Agent Mode with a new /agent page, including project/session management, model selection, streamed timelines, and permission controls with run cancellation.
    • Added feature-flag gating for Agent Mode availability.
    • Added an example/config option for OS flags base URL.
  • Bug Fixes
    • Improved logout, account deletion, and app restart/shutdown flows for Agent Mode and proxy state.
    • Hardened proxy start/stop and credentials handling to reduce lifecycle race conditions.
  • Documentation
    • Updated setup notes to clarify what the pre-commit hook runs and conditional Nix behavior.

@coderabbitai

coderabbitaiBot commented Jul 8, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 06fe41f7-0390-4f6e-8bb7-83b487193179

📥 Commits

Reviewing files that changed from the base of the PR and between 13e94e5 and 4a133bd.

📒 Files selected for processing (5)
  • frontend/src/billing/billingAccess.test.ts
  • frontend/src/billing/billingAccess.ts
  • frontend/src/components/Sidebar.tsx
  • frontend/src/components/UpgradePromptDialog.tsx
  • frontend/src/components/apikeys/ApiKeyDashboard.tsx
🚧 Files skipped from review as they are similar to previous changes (1)
  • frontend/src/components/Sidebar.tsx

📝 Walkthrough

Walkthrough

This PR adds Agent Mode across the Tauri backend and frontend, including streaming sessions, permissions, proxy coordination, feature-flagged navigation, account cleanup, and desktop lifecycle handling. It also updates Rust toolchains, CI configuration, environment variables, and pre-commit toolchain checks.

Changes

Agent Mode runtime and desktop integration

Layer / File(s)Summary
Runtime and lifecycle
frontend/src-tauri/src/agent.rs, frontend/src-tauri/src/lib.rs
Adds account-scoped Agent runtime commands, streaming timeline projection, permissions, cancellation rollback, persistence, and shutdown handling during exit or restart.
Proxy orchestration
frontend/src-tauri/src/proxy.rs, frontend/src/services/proxyService.ts
Serializes proxy lifecycle operations, adds Agent credential tracking and readiness reconciliation, and separates manual proxy ownership from Agent Mode.
Frontend Agent experience
frontend/src/components/AgentMode.tsx, frontend/src/services/agentRuntimeService.ts, frontend/src/routes/agent.tsx, frontend/src/components/Sidebar.tsx
Adds the /agent route, feature-flagged navigation, session management, model and permission selectors, event-driven timeline rendering, and operation fencing.
Account cleanup flows
frontend/src/components/AccountMenu.tsx, frontend/src/components/DeleteAccountDialog.tsx, frontend/src/components/GuestPaymentWarningDialog.tsx, frontend/src/components/VerificationModal.tsx
Stops Agent Mode and resets proxy credentials during logout, deletion, and history cleanup, with retained cleanup blocks and failure states.
Supporting contracts and validation
frontend/src/services/flags.ts, frontend/src/services/agentModels.ts, frontend/src/services/agentTimeline.ts, frontend/src/billing/billingService.ts
Adds feature-flag fetching and caching, model reconciliation, timeline helpers, normalized billing access, and updated billing context initialization.
Toolchain and configuration
.githooks/pre-commit, .github/workflows/*, flake.nix, frontend/src-tauri/Cargo.toml, frontend/src-tauri/capabilities/default.json
Updates Rust 1.94.1 pins, Tauri dependencies and permissions, CI formatting, environment variables, and conditional Bun/Cargo/Nix pre-commit checks.

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

Sequence Diagram(s)

sequenceDiagram
participant User
participant Sidebar
participant AgentMode
participant ProxyService
participant TauriAgentRuntime
User->>Sidebar: Select Agent Mode
Sidebar->>AgentMode: Navigate to /agent
AgentMode->>ProxyService: Ensure Agent proxy is ready
ProxyService->>TauriAgentRuntime: Start or reconcile proxy
AgentMode->>TauriAgentRuntime: Start runtime and send message
TauriAgentRuntime->>AgentMode: Stream timeline and permission events
AgentMode->>User: Render session timeline
Loading

Possibly related PRs

Poem

A rabbit hops through Agent Mode bright,
Streams little thoughts from day to night.
Proxies tidy, sessions bloom,
Rust tools guard the developer’s room.
“Bun!” cries the hare, “all checks now run—
With Nix nearby, we still get it done!”

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title clearly summarizes the main change: adding a direct Goose-powered Agent Mode.
Linked Issues check✅ PassedCheck skipped because no linked issues were found for this pull request.
Out of Scope Changes check✅ PassedCheck skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex-goose-sdk-maple

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

@cloudflare-workers-and-pages

cloudflare-workers-and-pagesBot commented Jul 8, 2026

Copy link
Copy Markdown

Deploying maple with Cloudflare Pages Cloudflare Pages

Latest commit:4a133bd
Status: ✅ Deploy successful!
Preview URL:https://7ea83396.maple-ca8.pages.dev
Branch Preview URL:https://codex-goose-sdk-maple.maple-ca8.pages.dev

View logs

@AnthonyRonning
AnthonyRonningforce-pushed the codex-goose-sdk-maple branch 3 times, most recently from e1a638b to fe73a02CompareJuly 9, 2026 23:36
@AnthonyRonningAnthonyRonning changed the title Add direct Goose Agent Mode experimentAdd direct Goose Agent ModeJul 10, 2026
@AnthonyRonning
AnthonyRonning marked this pull request as ready for review July 11, 2026 01:18

@devin-ai-integrationdevin-ai-integrationBot 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.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 1 additional finding.

Open in Devin Review

@coderabbitaicoderabbitaiBot 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

🧹 Nitpick comments (8)
frontend/src/routeTree.gen.ts (1)

24-24: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff

Configure route generation to preserve import conventions.

This generated import uses a relative path and single quotes. Configure the route generator to emit @/routes/agent with double quotes; a manual edit will be overwritten on regeneration. As per coding guidelines, “Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React code” and “Use 2-space indentation, double quotes”.

🤖 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 `@frontend/src/routeTree.gen.ts` at line 24, Configure the route generator
responsible for routeTree.gen.ts to emit aliased imports using "`@/routes/agent`"
and double quotes, rather than manually editing the generated file; update its
formatting/import settings and regenerate the route tree to verify the
convention persists.

Source: Coding guidelines

frontend/src/services/agentModels.test.ts (1)

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

Use the configured path alias for this service import.

Replace the relative import with @/services/agentModels. As per coding guidelines, “Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React.”

Proposed fix
-} from "./agentModels";+} from "`@/services/agentModels`";
🤖 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 `@frontend/src/services/agentModels.test.ts` around lines 3 - 8, Update the
import in the agentModels test to use the configured "`@/services/agentModels`"
path alias instead of the relative "./agentModels" path, preserving the existing
imported symbols.

Source: Coding guidelines

frontend/src/services/agentModels.ts (1)

3-4: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use camelCase for these exported constants.DEFAULT_AGENT_MODEL and PRIMARY_AGENT_MODEL_IDS violate the TypeScript naming rule here; rename them and update the references in frontend/src/components/AgentMode.tsx and frontend/src/services/agentModels.test.ts.

🤖 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 `@frontend/src/services/agentModels.ts` around lines 3 - 4, Rename the exported
constants DEFAULT_AGENT_MODEL and PRIMARY_AGENT_MODEL_IDS in agentModels.ts to
camelCase names, then update all references in AgentMode.tsx and
agentModels.test.ts to use the new identifiers consistently.

Source: Coding guidelines

frontend/src/services/flags.test.ts (1)

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

Use the @ alias for the internal import.

Proposed fix
-import { FlagsClient, type FlagsFetch } from "./flags";+import { FlagsClient, type FlagsFetch } from "`@/services/flags`";

As per coding guidelines, “Use path aliases (@/* maps to ./src/*) for imports in TypeScript/React.”

🤖 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 `@frontend/src/services/flags.test.ts` at line 2, Update the import in the
flags test to use the configured @ path alias instead of the relative "./flags"
path, while preserving the existing FlagsClient and FlagsFetch imports.

Source: Coding guidelines

frontend/src/services/agentTimeline.ts (1)

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

Use the configured TypeScript path alias.

Proposed fix
-import type { AgentTimelineItem } from "./agentRuntimeService";+import type { AgentTimelineItem } from "`@/services/agentRuntimeService`";

As per coding guidelines, frontend/src/**/*.{ts,tsx} must use path aliases (@/* maps to ./src/*).

🤖 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 `@frontend/src/services/agentTimeline.ts` at line 1, Replace the relative
import in the agentTimeline module with the configured @ path alias, preserving
the existing AgentTimelineItem type import from agentRuntimeService.

Source: Coding guidelines

frontend/src/services/agentTimeline.test.ts (1)

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

Use the configured TypeScript path alias.

Replace the relative service imports with @/services/....

Proposed fix
-import type { AgentTimelineItem } from "./agentRuntimeService";-import { coalesceAdjacentThinkingItems, hasRenderableThinkingText } from "./agentTimeline";+import type { AgentTimelineItem } from "`@/services/agentRuntimeService`";+import { coalesceAdjacentThinkingItems, hasRenderableThinkingText } from "`@/services/agentTimeline`";

As per coding guidelines, frontend/src/**/*.{ts,tsx} must use path aliases (@/* maps to ./src/*).

🤖 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 `@frontend/src/services/agentTimeline.test.ts` around lines 2 - 3, Update the
imports in the agentTimeline test to use the configured `@/services/`... path
aliases instead of relative ./ paths, including both agentRuntimeService and
agentTimeline imports.

Source: Coding guidelines

frontend/src-tauri/src/agent.rs (1)

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

Use the required Rust logging macros.

Replace these new log::warn! calls with log::info! or log::error! according to severity.

As per coding guidelines, frontend/src-tauri/src/**/*.rs requires log::info! and log::error! for Rust logging.

Also applies to: 974-979, 2537-2540

🤖 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 `@frontend/src-tauri/src/agent.rs` around lines 391 - 395, Replace the
`log::warn!` calls in the error-handling branches around the pending permission
cancellation and the additionally referenced locations with the required logging
macros: use `log::error!` for failed operations and `log::info!` where the
condition is informational, preserving each existing message and error context.

Source: Coding guidelines

frontend/src/services/proxyService.ts (1)

364-389: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Consider bounding the backend auth probe with a timeout.

checkProxyBackendAuth awaits fetch(...) with no AbortController/timeout. If the local proxy accepts the connection but stalls, ensureProxyReadyInner (which is on the serialized enqueueProxyOperation tail) can hang indefinitely, blocking every subsequent proxy operation. A short timeout would fail fast into the existing unknown_error/retry path.

Separately, when !status.running this returns "auth_error", which pushes the caller into the key-refresh/revoke branch even though the real cause is a proxy that failed to start. That's a benign misclassification today, but worth confirming it doesn't burn an unnecessary API key rotation.

♻️ Example: add an abort timeout
- try {- const response = await fetch(`http://${host}:${status.config.port}/v1/models`);+ try {+ const response = await fetch(`http://${host}:${status.config.port}/v1/models`, {+ signal: AbortSignal.timeout(5000)+ });
🤖 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 `@frontend/src/services/proxyService.ts` around lines 364 - 389, Add a short
AbortController-based timeout to the fetch in checkProxyBackendAuth, passing its
signal and ensuring the controller is cleaned up so stalled probes fail into the
existing unknown_error path. Also verify the !status.running return value does
not trigger unnecessary API-key refresh or revocation in ensureProxyReadyInner;
adjust the status handling or caller branch if needed to distinguish a stopped
backend from an authentication failure.
🤖 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 `@frontend/src-tauri/src/agent.rs`:
- Around line 1125-1159: Move the autogenerated-title persistence in the setup
flow so it occurs only after configure_session_agent succeeds, or restore the
original session snapshot whenever setup fails. Update the logic around
should_restore_autogenerated_title and configure_session_agent to ensure
provider, mode, or extension setup errors do not leave an empty session renamed.
- Around line 274-281: Replace renderer-controlled account scoping in
account_scope, agent_list_sessions, and agent_load_session with a Rust-tracked
authenticated-account identity; validate the caller’s requested user_id against
that identity or ignore it, and derive the session-manager scope exclusively
from the authenticated account before reopening account_session_manager.
In `@frontend/src/billing/billingService.ts`:
- Around line 89-91: Scope the cached Bearer token to the authenticated account
in BillingService: update updateOpenSecret to compare the verified account
identity on the incoming and current OpenSecretContextType, and clear or replace
the cached token when that identity changes; preserve it only for the same
account. Ensure BillingServiceProvider’s context refresh cannot reuse a token
across account switches, and apply the same identity handling to the token
access logic around the referenced additional lines.
---
Nitpick comments:
In `@frontend/src-tauri/src/agent.rs`:
- Around line 391-395: Replace the `log::warn!` calls in the error-handling
branches around the pending permission cancellation and the additionally
referenced locations with the required logging macros: use `log::error!` for
failed operations and `log::info!` where the condition is informational,
preserving each existing message and error context.
In `@frontend/src/routeTree.gen.ts`:
- Line 24: Configure the route generator responsible for routeTree.gen.ts to
emit aliased imports using "`@/routes/agent`" and double quotes, rather than
manually editing the generated file; update its formatting/import settings and
regenerate the route tree to verify the convention persists.
In `@frontend/src/services/agentModels.test.ts`:
- Around line 3-8: Update the import in the agentModels test to use the
configured "`@/services/agentModels`" path alias instead of the relative
"./agentModels" path, preserving the existing imported symbols.
In `@frontend/src/services/agentModels.ts`:
- Around line 3-4: Rename the exported constants DEFAULT_AGENT_MODEL and
PRIMARY_AGENT_MODEL_IDS in agentModels.ts to camelCase names, then update all
references in AgentMode.tsx and agentModels.test.ts to use the new identifiers
consistently.
In `@frontend/src/services/agentTimeline.test.ts`:
- Around line 2-3: Update the imports in the agentTimeline test to use the
configured `@/services/`... path aliases instead of relative ./ paths, including
both agentRuntimeService and agentTimeline imports.
In `@frontend/src/services/agentTimeline.ts`:
- Line 1: Replace the relative import in the agentTimeline module with the
configured @ path alias, preserving the existing AgentTimelineItem type import
from agentRuntimeService.
In `@frontend/src/services/flags.test.ts`:
- Line 2: Update the import in the flags test to use the configured @ path alias
instead of the relative "./flags" path, while preserving the existing
FlagsClient and FlagsFetch imports.
In `@frontend/src/services/proxyService.ts`:
- Around line 364-389: Add a short AbortController-based timeout to the fetch in
checkProxyBackendAuth, passing its signal and ensuring the controller is cleaned
up so stalled probes fail into the existing unknown_error path. Also verify the
!status.running return value does not trigger unnecessary API-key refresh or
revocation in ensureProxyReadyInner; adjust the status handling or caller branch
if needed to distinguish a stopped backend from an authentication failure.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 19d7ab74-abe1-40c8-88d5-9da5f7b82e89

📥 Commits

Reviewing files that changed from the base of the PR and between 568633a and 2dd2833.

⛔ Files ignored due to path filters (2)
  • flake.lock is excluded by !**/*.lock
  • frontend/src-tauri/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (41)
  • .githooks/pre-commit
  • .github/workflows/desktop-build.yml
  • .github/workflows/desktop-pr-build.yml
  • .github/workflows/release.yml
  • .github/workflows/rust-tests.yml
  • README.md
  • flake.nix
  • frontend/.env.example
  • frontend/src-tauri/Cargo.toml
  • frontend/src-tauri/capabilities/default.json
  • frontend/src-tauri/src/agent.rs
  • frontend/src-tauri/src/lib.rs
  • frontend/src-tauri/src/proxy.rs
  • frontend/src/billing/billingService.ts
  • frontend/src/components/AccountMenu.tsx
  • frontend/src/components/AgentMode.tsx
  • frontend/src/components/BillingServiceProvider.tsx
  • frontend/src/components/DeleteAccountDialog.tsx
  • frontend/src/components/DeleteChatDialog.tsx
  • frontend/src/components/GuestPaymentWarningDialog.tsx
  • frontend/src/components/Sidebar.tsx
  • frontend/src/components/VerificationModal.tsx
  • frontend/src/components/apikeys/ProxyConfigSection.tsx
  • frontend/src/routeTree.gen.ts
  • frontend/src/routes/__root.tsx
  • frontend/src/routes/agent.tsx
  • frontend/src/services/agentAuthLifecycle.test.ts
  • frontend/src/services/agentAuthLifecycle.ts
  • frontend/src/services/agentModels.test.ts
  • frontend/src/services/agentModels.ts
  • frontend/src/services/agentOperationFence.test.ts
  • frontend/src/services/agentOperationFence.ts
  • frontend/src/services/agentRuntimeService.ts
  • frontend/src/services/agentTimeline.test.ts
  • frontend/src/services/agentTimeline.ts
  • frontend/src/services/flags.test.ts
  • frontend/src/services/flags.ts
  • frontend/src/services/proxyService.test.ts
  • frontend/src/services/proxyService.ts
  • frontend/src/vite-env.d.ts
  • scripts/ci/_common.sh

Comment on lines +274 to +281
fn account_scope(user_id: &str) -> Result<String, String> {
let user_id = user_id.trim();
if user_id.is_empty() {
return Err("Agent Mode requires a signed-in account".to_string());
}
let digest = Sha256::digest(user_id.as_bytes());
Ok(format!("{digest:x}"))
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Do not trust the renderer-supplied user_id for account scoping.account_scope only hashes the input, and agent_list_sessions / agent_load_session reopen account_session_manager from that scope when no runtime is active, so a Tauri caller can point at another locally stored account by passing a different ID. Derive the scope from a Rust-tracked authenticated account instead.

🤖 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 `@frontend/src-tauri/src/agent.rs` around lines 274 - 281, Replace
renderer-controlled account scoping in account_scope, agent_list_sessions, and
agent_load_session with a Rust-tracked authenticated-account identity; validate
the caller’s requested user_id against that identity or ignore it, and derive
the session-manager scope exclusively from the authenticated account before
reopening account_session_manager.

Comment on lines +1125 to +1159
if should_restore_autogenerated_title {
session_manager
.update(&session.id)
.system_generated_name(prompt_title)
.apply()
.await
.map_err(|e| format!("Failed to name Agent session: {e}"))?;
session = session_manager
.get_session(&session.id, false)
.await
.map_err(|e| format!("Failed to load named Goose session: {e}"))?;
emit_agent_event(
&app_handle,
AgentEventEnvelope {
event_type: "sessionUpdated".to_string(),
session_id: Some(session.id.clone()),
run_id: Some(run_id.clone()),
item: None,
status: None,
session: Some(session_summary(&session)),
message: None,
},
);
}
let agent = configure_session_agent(&agent_manager, &session, &model, &mode).await?;
Ok((agent, turn_snapshot))
}
.await;
let (agent, task_turn_snapshot) = match setup_result {
Ok(setup) => setup,
Err(error) => {
agent_manager
.unregister_cancel_token(&request.session_id)
.await;
return Err(error);

Copy link
Copy Markdown

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

Do not rename the session before fallible agent setup.

Line 1127 persists the generated title before configure_session_agent. If provider, mode, or extension setup fails, the error path only unregisters the token, leaving an empty session renamed for a prompt that never ran. Configure first, or restore the snapshot on setup failure.

🤖 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 `@frontend/src-tauri/src/agent.rs` around lines 1125 - 1159, Move the
autogenerated-title persistence in the setup flow so it occurs only after
configure_session_agent succeeds, or restore the original session snapshot
whenever setup fails. Update the logic around should_restore_autogenerated_title
and configure_session_agent to ensure provider, mode, or extension setup errors
do not leave an empty session renamed.

Comment on lines +89 to +91
updateOpenSecret(os: OpenSecretContextType): void {
this.os = os;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Scope the cached billing token to the authenticated account.

updateOpenSecret swaps contexts but preserves the global token. After an account switch, the next request can successfully use the previous account’s Bearer token, exposing or operating on its billing state. Key the token by verified account identity, or clear it only when that identity changes.

Based on supplied frontend/src/billing/billingApi.ts:83-109 and frontend/src/components/BillingServiceProvider.tsx:4-13, the token is a Bearer credential and the singleton is refreshed during render.

Also applies to: 256-257

🤖 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 `@frontend/src/billing/billingService.ts` around lines 89 - 91, Scope the
cached Bearer token to the authenticated account in BillingService: update
updateOpenSecret to compare the verified account identity on the incoming and
current OpenSecretContextType, and clear or replace the cached token when that
identity changes; preserve it only for the same account. Ensure
BillingServiceProvider’s context refresh cannot reuse a token across account
switches, and apply the same identity handling to the token access logic around
the referenced additional lines.

Sign up for freeto 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

@AnthonyRonning