Skip to content

fix(web): allow creating new sessions in projects from the web UI - #83

Open
justemu wants to merge 2 commits into
ai4s-research:masterfrom
justemu:fix/web-session-creation
Open

fix(web): allow creating new sessions in projects from the web UI#83
justemu wants to merge 2 commits into
ai4s-research:masterfrom
justemu:fix/web-session-creation

Conversation

@justemu

@justemu justemu commented Aug 6, 2026

Copy link
Copy Markdown

Summary

Fixes the "not running in the desktop app" error when creating a new session under a project from the web UI (Remote Access Gateway mode), and ensures the created session actually lands in the selected project directory.

Closes #81.

Problem

Two distinct issues when the web UI (browser) tries to create a session under a user-selected project:

1. Tauri-only call crashes in browser

The newSessionIn() function in Sidebar.tsx calls switchWorkspace(), which calls setWorkspace() — a Tauri-only command that throws when window.__TAURI_INTERNALS__ is absent (i.e., in a browser).

Sidebar.newSessionIn(project)
  → startDraftInWorkspace(project.path)
    → switchWorkspace({ path })
      → setWorkspace(path)  // throws: "not running in the desktop app"

2. Session silently lands in the wrong directory

Even after fixing the crash, three independent information paths are broken in web mode, so the session creation request never carries the selected directory:

Break point A — first-send ignores draftWorkspaces in web mode.
runtime.ts line 810:

const chosen = isTauri ? get().draftWorkspaces[draftSrc] : undefined;

isTauri is false in the browser, so chosen is always undefined. The user selected a project, switchWorkspace stored the path in draftWorkspaces, but the first-send logic never reads it.

Break point B — OpenCodeClient is scoped to /v1/whoami, not the selected project.
connect() lines 1459–1480:

if (isGatewayWeb) {
  directory = null;                        // ← cleared
  const who = await fetch('/v1/whoami');   // ← returns the HOST's active workspace
  directory = who.directory;
}

/v1/whoami returns the desktop host's currently active workspace — not the project the user clicked in the web UI. The OpenCodeClient is constructed with this directory, and all subsequent API calls (createSession, SSE, permissions, files) route through ?directory= using it.

Break point C — switchWorkspace stores the path but does not reconnect.
The original PR patch stored the path in draftWorkspaces but skipped connectRetry(). The OpenCodeClient instance kept its original directory from the initial connect() call, so the stored path was never used.

Fix

Introduce webOverrideDirectory — a module-level variable that carries the user-selected project directory in web mode and persists across reconnects.

switchWorkspace (web mode)

Set webOverrideDirectory = target.path, then call connectRetry() so the OpenCodeClient is reconstructed with the correct directory.

connect() (web mode)

Initialize directory = webOverrideDirectory. Only fall back to the /v1/whoami response when no override is set:

directory = webOverrideDirectory;
// ...
if (!directory) directory = who.directory ?? null;

first-send block

Read chosen from draftWorkspaces for both Tauri and web mode (no longer gated on isTauri). When web mode has a chosen directory, set webOverrideDirectory and connectRetry() before creating the session. The createSession() call uses dirQuery()?directory=PATH, so the session is created in the correct project.

Why this works end-to-end

OpenCodeClient.createSession() sends POST /session?directory=PATH. The directory field is set at construction time and used by dirQuery() for all directory-scoped calls: session creation, SSE event stream, permissions/questions, and file operations. By overriding it at connect() time, all downstream operations automatically scope to the selected project.

Testing

  • Added regression test: createSession with a directory sends ?directory= in the URL
  • Added regression test: createSession without a directory sends no query parameter
  • Manual testing: web UI "New Session" under a project creates the session in that project (not the host active workspace)

Files changed

  • apps/desktop/src/lib/runtime.tswebOverrideDirectory, switchWorkspace, connect(), first-send logic
  • apps/desktop/src/test/opencode-client.sessions.test.ts — 2 regression tests

@noahbenjamin1994 noahbenjamin1994 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Thanks for addressing the visible error, but this does not yet create the session in the selected project: the web path is only stored in draftWorkspaces, while first-send still sets chosen only when isTauri, the existing OpenCodeClient remains scoped to /v1/whoami, and this patch skips the reconnect, so the session can silently land in the host's active workspace. Please carry the selected directory as client-local web state, use it consistently for session creation, SSE, permissions/questions, and files, and add a regression test asserting the created session's directory equals the selected project path; also note that the UI creates through /session?directory=PATH, not /v1/sessions.

justemu added a commit to justemu/open-science-1 that referenced this pull request Aug 8, 2026
…creation

Address review feedback on ai4s-research#83:

- Add webOverrideDirectory module-level variable to carry the user-selected
  project directory in web mode, persisted across reconnects
- In switchWorkspace for web mode: set webOverrideDirectory and call
  connectRetry() so the OpenCodeClient picks up the new directory
- In connect() for web mode: use webOverrideDirectory to override the
  /v1/whoami default, falling back to whoami only when no override is set
- In first-send block: read chosen from draftWorkspaces for both Tauri and
  web mode; when web mode has a chosen directory, scope the client to it
  before creating the session
- The session is created via /session?directory=PATH (not /v1/sessions),
  so the directory flows through dirQuery() on the OpenCodeClient
- Add regression tests: session creation with and without directory parameter
The web UI (Remote Access Gateway mode) threw 'not running in the desktop
app' when clicking 'New Session' under a project. This happened because
switchWorkspace() called setWorkspace() — a Tauri-only command — without
a gateway fallback.

Fix: when isGatewayWeb is true, skip the Tauri-only setWorkspace/
newDatedWorkspace calls and just aim the draft at the target path directly.
The gateway already routes session creation to the host's active workspace
via /v1/sessions.

Closes ai4s-research#81.
…creation

Address review feedback on ai4s-research#83:

- Add webOverrideDirectory module-level variable to carry the user-selected
  project directory in web mode, persisted across reconnects
- In switchWorkspace for web mode: set webOverrideDirectory and call
  connectRetry() so the OpenCodeClient picks up the new directory
- In connect() for web mode: use webOverrideDirectory to override the
  /v1/whoami default, falling back to whoami only when no override is set
- In first-send block: read chosen from draftWorkspaces for both Tauri and
  web mode; when web mode has a chosen directory, scope the client to it
  before creating the session
- The session is created via /session?directory=PATH (not /v1/sessions),
  so the directory flows through dirQuery() on the OpenCodeClient
- Add regression tests: session creation with and without directory parameter
@justemu
justemu force-pushed the fix/web-session-creation branch from 20b72c1 to 3737476 Compare August 12, 2026 16:35
@justemu

justemu commented Aug 12, 2026

Copy link
Copy Markdown
Author

Hi @noahbenjamin1994, thanks for the detailed review!

We've addressed all your feedback in the follow-up commit (20b72c1) and rebased onto the latest master to resolve merge conflicts. Here's what the fix commit covers:

webOverrideDirectory module-level variable — Carries the user-selected project directory in web mode, persisted across reconnects. Falls back to /v1/whoami only when no override is set.

switchWorkspace (web mode) — Sets webOverrideDirectory = target.path and calls connectRetry() so the OpenCodeClient is reconstructed with the correct directory.

connect() (web mode) — Initializes directory = webOverrideDirectory; only falls back to the /v1/whoami response when no override is set.

First-send block — Reads chosen from draftWorkspaces for both Tauri and web mode (no longer gated on isTauri). When web mode has a chosen directory, sets webOverrideDirectory and calls connectRetry() before creating the session.

Session creation — Uses /session?directory=PATH (via dirQuery()), so the directory flows through OpenCodeClient for all downstream operations (SSE, permissions/questions, files).

Regression tests — 2 new tests: createSession with directory sends ?directory=, without directory sends no query parameter.

The branch has been rebased onto the latest master (was 47 commits behind) to resolve merge conflicts with recent changes to runtime.ts. Could you please re-review when you get a chance? Thanks!

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.

[Bug] Web UI cannot create new sessions under projects — "not running in the desktop app"

2 participants