feat: associate threads with projects#8745
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 63e094a7cd
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| overlay?.lastKnownTitle ?? | ||
| "Untitled", | ||
| projectId: overlay?.projectId, | ||
| projectId: session.projectId ?? undefined, |
There was a problem hiding this comment.
Fallback to overlay projectId when ACP metadata is missing
When listSessions returns a session without _meta.projectId (which is common for older threads), mergeAcpSessionWithOverlay now forces projectId to session.projectId ?? undefined instead of reusing the cached overlay value. In that case the project association disappears in UI, and syncOverlaySnapshots immediately persists null, permanently erasing the previously stored projectId from local overlay data. This regresses migration behavior for existing sessions that only have project linkage in overlay storage.
Useful? React with 👍 / 👎.
projectId was stored only in browser localStorage, which is tied to the dev server port. When Vite picks a different port on restart, WebKit creates a separate localStorage and all project associations are lost. Thread project_id through the ACP backend: - on_new_session reads projectId from request meta - on_list_sessions returns projectId in _meta - New _goose/session/update_project extension method for moves - Frontend prefers backend projectId, falls back to overlay - createSession passes projectId to the backend - updateSession persists projectId changes to the backend - Extract thread_session_meta() helper to deduplicate _meta construction - Propagate projectId to forked sessions - Restore projectId in localStorage overlay for fallback resilience Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
63e094a to
76f1c12
Compare
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 76f1c12aa8
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: da64a30aba
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if ("projectId" in patch && acpSessionId) { | ||
| updateSessionProject(acpSessionId, patch.projectId ?? null).catch( | ||
| (err: unknown) => | ||
| console.error("Failed to update session project in backend:", err), | ||
| ); |
There was a problem hiding this comment.
Serialize project-update calls to prevent stale writes
updateSession fires updateSessionProject as an untracked async side effect each time projectId is patched, so multiple rapid moves of the same session (for example A → B from the sidebar) issue concurrent RPCs with no ordering guarantee. If the earlier request resolves last, the backend thread metadata is reverted to the older project while the UI shows the newer one until a reload, causing persistent project mis-association. Queue or coalesce per-session project updates so only the latest value is committed.
Useful? React with 👍 / 👎.
The GooseClient SDK source exposes listSessions() (not prefixed with unstable_), matching the upstream ACP SDK. CI rebuilds the SDK from source before running typecheck, so it sees listSessions. The previous commit incorrectly used unstable_listSessions which only existed in a stale pre-built dist. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2b93a8e806
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // Persist projectId change to ACP backend | ||
| const acpSessionId = updatedSession?.acpSessionId; | ||
| if ("projectId" in patch && acpSessionId) { | ||
| updateSessionProject(acpSessionId, patch.projectId ?? null).catch( |
There was a problem hiding this comment.
Serialize project metadata writes with session prep updates
updateSession fires updateSessionProject as an untracked async side effect, so the move-to-project path can send this RPC concurrently with acpPrepareSession follow-up calls that trigger provider/model metadata writes. On the backend, both on_update_session_project and other metadata setters use update_thread_metadata (read-modify-write), so concurrent requests can clobber each other and persist stale metadata depending on completion order. This means a single project move combined with provider/model changes can silently revert projectId; queue or await project updates before issuing other metadata-mutating RPCs for the same session.
Useful? React with 👍 / 👎.
The generated schema, meta, and TypeScript types were not committed alongside the backend changes that added _goose/session/update_project. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* main: (41 commits) removed the specific code owner for documentation change (#8749) fix(providers): handle missing delta field in streaming chunks (#8700) refactor(providers): extract http_status module and rename handle_status_openai_compat (#8620) fix(providers/openai): accept streaming chunks with both reasoning fields (#8715) feat: associate threads with projects (#8745) upgrade goose sdk and tui to be compatible with the latest agentclientprotocol/sdk package (#8667) feat: extend goose2 context window ux with auto-compaction (#8721) improve goose2 agent management flows (#8737) alexhancock/tui-improvements (#8736) fix: add strict:false to Responses API tools and gpt-5.4 to known models (#8636) persist and reliably apply chat model selection (#8734) merge goose-acp crate into goose (#8726) docs: AGENTS.md section on goose2 desktop backend architecture (#8732) feat: goose2 message bubble + action tray (#8720) consolidate provider ACP methods onto inventory (#8710) ci: declare and enforce MSRV of 1.91.1 (#8670) fix(ui): correct grammar in apps view description (#8668) (#8679) Stop load openai fast model for openapi compatible custom endpoint (#8644) feat(hooks): add Husky git hooks for ui/goose2 (#8577) fix: links in chat could not be opened (#8544) ...
* main: (34 commits) fix(goose-server): cache TLS cert to disk to avoid slow startup on first launch (#8174) feat: add Exa AI-powered search tool (#8487) fix: preprompt would show after loading session (#8744) commands to acp+ migration: extensions management (#8733) feat: desktop notification when goose finishes a task (#8647) harden code review skill for async state and default-resolution bugs (#8740) Feature/at agent mention (#8571) fix: removed hardcoded dependency of goose-acp-macro (#8753) perf: split agent setup into staged phases to reduce startup blocking (#8746) Add /skills command (#8600) Replace deprecated Claude ACP package links (#8625) removed the specific code owner for documentation change (#8749) fix(providers): handle missing delta field in streaming chunks (#8700) refactor(providers): extract http_status module and rename handle_status_openai_compat (#8620) fix(providers/openai): accept streaming chunks with both reasoning fields (#8715) feat: associate threads with projects (#8745) upgrade goose sdk and tui to be compatible with the latest agentclientprotocol/sdk package (#8667) feat: extend goose2 context window ux with auto-compaction (#8721) improve goose2 agent management flows (#8737) alexhancock/tui-improvements (#8736) ...
projectIdtoThreadMetadataand expose it via session info_meta, so the backend is the source of truth for session-project associations_goose/session/update_projectcustom RPC method to update a session's project association after creationprojectIdthrough session creation flow (UI → ACP tracker →newSession) so new sessions are associated with the correct project from the startchatSessionStoreto persist project changes to the backend and prefer the backend'sprojectIdover the localStorage overlay🤖 Generated with Claude Code