Add provider thread IDs and safe cross-thread reads#4575
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
| status: "starting", | ||
| providerName: activeSession?.provider ?? preferredProvider, | ||
| providerInstanceId: activeSession?.providerInstanceId ?? desiredInstanceId, | ||
| ...(thread.session?.providerThreadId |
There was a problem hiding this comment.
🟡 Medium Layers/ProviderCommandReactor.ts:445
When bindSessionToThread runs after a session restart, it copies providerThreadId from the stale thread.session snapshot taken before startSession was called. If the adapter emits a thread.started event during startSession and runtime ingestion projects the new provider-native thread ID before this thread.session.set dispatch is processed, this write overwrites the correct new providerThreadId with the old one. The thread then remains indexed and displayed under the wrong provider-native ID because no later thread.started event is guaranteed.
This affects three call sites in the diff, all of which copy providerThreadId from thread.session?.providerThreadId. Consider sourcing the providerThreadId from the freshly started session object (or from thread.session only when no newer value is available) rather than unconditionally from the pre-start snapshot.
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/orchestration/Layers/ProviderCommandReactor.ts around line 445:
When `bindSessionToThread` runs after a session restart, it copies `providerThreadId` from the stale `thread.session` snapshot taken before `startSession` was called. If the adapter emits a `thread.started` event during `startSession` and runtime ingestion projects the new provider-native thread ID before this `thread.session.set` dispatch is processed, this write overwrites the correct new `providerThreadId` with the old one. The thread then remains indexed and displayed under the wrong provider-native ID because no later `thread.started` event is guaranteed.
This affects three call sites in the diff, all of which copy `providerThreadId` from `thread.session?.providerThreadId`. Consider sourcing the `providerThreadId` from the freshly started `session` object (or from `thread.session` only when no newer value is available) rather than unconditionally from the pre-start snapshot.
| ? binding.resumeCursor.threadId | ||
| : undefined; | ||
| } | ||
| if (binding.provider === "claude") { |
There was a problem hiding this comment.
🟡 Medium thread-control/handlers.ts:36
readProviderThreadId checks for binding.provider === "claude", but the Claude driver kind is "claudeAgent". Claude bindings always fall through to the generic sessionId branch, so read_thread can't match a Claude provider-native thread ID stored in resume and returns ThreadReadNotFoundError instead of resolving the thread. Consider comparing against "claudeAgent".
| if (binding.provider === "claude") { | |
| if (binding.provider === "claudeAgent") { |
🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/mcp/toolkits/thread-control/handlers.ts around line 36:
`readProviderThreadId` checks for `binding.provider === "claude"`, but the Claude driver kind is `"claudeAgent"`. Claude bindings always fall through to the generic `sessionId` branch, so `read_thread` can't match a Claude provider-native thread ID stored in `resume` and returns `ThreadReadNotFoundError` instead of resolving the thread. Consider comparing against `"claudeAgent"`.
Summary
Copy Codex Thread ID/Copy Provider Thread IDcontext-menu actions in both sidebar variants.read_threadMCP tool that resolves either a T3 thread ID or a provider-native ID and returns bounded recent messages/activity without resuming, steering, or mutating the target thread.thread-readcapability on issued same-environment MCP credentials.Compatibility and safeguards
NULLprovider thread ID continue to decode.Copy Thread IDbehavior remains available and distinct.Verification
vp run --filter @t3tools/contracts --filter t3 --filter @t3tools/web typechecktest-t3-appenvironment launched successfully, migrations completed, and the pairing route was produced. Automated UI interaction could not be completed because the native preview bridge required authentication and the fallback in-app browser reported no available browser surfaces; no alternate browser was used to bypass that authentication constraint.Note
Add provider thread IDs to sessions and expose a
read_threadMCP toolproviderThreadId(e.g. Codex, Claude) on thread start and propagates it through session state changes, projections, and theOrchestrationSessioncontract.provider_thread_idin theprojection_thread_sessionstable and surfaces it viaProjectionSnapshotQuery.read_threadMCP tool in a newThreadControlToolkitthat fetches thread metadata and bounded message/activity history by T3 or provider thread ID, enforcing athread-readcapability check.thread-readcapability alongsidepreview.📊 Macroscope summarized d86586d. 13 files reviewed, 0 issues evaluated, 0 issues filtered, 0 comments posted
🗂️ Filtered Issues
No issues evaluated.