Skip to content

fix(composer): read dropped threads across environments - #15210

Open
Bil0000 wants to merge 1 commit into
pingdotgg:mainfrom
Bil0000:t3code/cross-environment-thread-drag
Open

Bil0000 wants to merge 1 commit into
pingdotgg:mainfrom
Bil0000:t3code/cross-environment-thread-drag

Conversation

@Bil0000

@Bil0000 Bil0000 commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Replacement for #14255 against current main at f391794. The API refuses to reopen the original because its base branch was deleted, and refuses to change the base of a closed PR.

What changed

Dropping a sidebar thread into a composer on another environment now attaches a saved transcript file. The destination agent can read it through the existing file attachment path, including after the source disconnects. Same-environment drops keep their live thread references.

Why

A thread ID from the source server is not readable on the destination server. The client now reads the source through an authenticated HTTP endpoint that preserves the complete visible timeline, inherited history, tool output, and saved text context. Normal UI history reads are bounded and strip tool details, so they cannot provide this export. The transfer uses existing connection authentication, file limits, upload handling, and draft preparation guards. Results are discarded if the destination draft changes while loading. The source rejects timeline JSON above the file attachment limit before transfer; the client still checks the complete file size.

Validation and limits

  • 116 focused tests pass across HTTP permissions and history export, remote authentication and credential refresh, transcript files, composer context, attachment upload, and contracts.
  • The Opus audit size fix adds a multibyte oversized-export regression check; focused endpoint and contract tests and server/web type checks pass.
  • Server, web, mobile, and client-runtime type checks pass. Targeted lint and formatting pass; existing composer lint warnings remain.
  • This is a snapshot. Later source messages and source attachment bytes are not copied. The source server must include the new endpoint, and normal attachment limits apply.

UI verification

The native Browser panel could not reach the isolated loopback dev server: navigation returned ERR_CONNECTION_REFUSED, while a local HTTP check returned 200. No browser pass or before/after media is claimed.

Checklist

  • This PR is small and focused
  • I explained what changed and why
  • I included before/after screenshots for any UI changes
  • I included a video for animation/interaction changes

Model: GPT-6 Astra. Harness: Codex. Independent audit: Claude Opus 5.5 via T3 delegation.

Current main verification

The original net changes are preserved exactly. Only two import conflicts with current main were resolved. All 183 focused tests pass across 13 files. Server, web, mobile, client-runtime, and contracts type checks pass under Node 24.13.1. Targeted lint exits 0 with composer warnings outside the added lines; formatting passes for all 12 changed files.

No new browser pass or interaction media is claimed. The prior maintainer request for direction approval and interaction evidence remains open.

Update model: GPT-6.1 Sol, High. Harness: Codex.

@coderabbitai

coderabbitai Bot commented Oct 3, 2026

Copy link
Copy Markdown

Warning

Review limit reached

Only developers with an assigned seat can use this organization's usage-based review budget, and seats here are assigned manually. Ask an admin to assign a seat, or change the review continuation mode in Billing.

Next included review available in 7 minutes.

Check out review usage here.

View limit details

Limit details: You’ve used all 10 included reviews currently available.

Learn how review limits work.

Review configuration:

⚙️ Run configuration
  • Configuration used: Repository: pingdotgg/t3code/.coderabbit.yaml
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 06488b1f-1ae8-4875-85ea-6c116857253f
📥 Commits

Reviewing files that changed from the base of the PR and between f391794 and 642b645.

📒 Files selected for processing (12)
  • apps/server/src/orchestration-v2/http.test.ts
  • apps/server/src/orchestration-v2/http.ts
  • apps/web/src/components/chat/ChatComposer.tsx
  • apps/web/src/lib/threadContextAttachment.test.ts
  • apps/web/src/lib/threadContextAttachment.ts
  • docs/internals/performance-regressions.md
  • docs/user/composer.md
  • packages/client-runtime/src/state/environmentHttpAuth.test.ts
  • packages/client-runtime/src/state/orchestration.ts
  • packages/client-runtime/src/state/threadTranscriptHttp.ts
  • packages/contracts/src/environmentHttp.ts
  • packages/contracts/src/orchestrationV2.ts
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@github-actions github-actions Bot added vouch:trusted PR author is trusted by repo permissions or the VOUCHED list. size:L 100-499 changed lines (additions + deletions). labels Oct 3, 2026
const importDroppedThread = useEffectEvent(
async (ref: ScopedThreadRef, isActive: () => boolean) => {
const targetKey = attachmentTargetKey;
pendingDraftWork.begin(targetKey);

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.

🟠 High chat/ChatComposer.tsx:6119

A cross-environment thread drop is rejected if the user fills the attachment limit while loadThreadTranscript is awaiting, so the already-requested transcript is lost and addComposerAttachments reports an attachment-limit error. importDroppedThread only calls pendingDraftWork.begin and does not reserve an attachment slot; reserve one before the await and release it in finally so concurrent attachments cannot consume the drop's slot.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/web/src/components/chat/ChatComposer.tsx around line 6119:

A cross-environment thread drop is rejected if the user fills the attachment limit while `loadThreadTranscript` is awaiting, so the already-requested transcript is lost and `addComposerAttachments` reports an attachment-limit error. `importDroppedThread` only calls `pendingDraftWork.begin` and does not reserve an attachment slot; reserve one before the await and release it in `finally` so concurrent attachments cannot consume the drop's slot.

);
let sizeBytes = 0;
for (const row of projection.visibleTurnItems) {
sizeBytes += projectedRowEncodedBytes(row) + 1;

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.

🟠 High orchestration-v2/http.ts:222

A transcript whose visibleTurnItems fit within PROVIDER_SEND_TURN_MAX_FILE_BYTES can still be rejected by addComposerAttachments: the client adds a JSONL header containing the title, IDs, timestamp, and description plus its newline, pushing the generated File over fileStagingLimit. Include the serialized header and newline in this budget, or reserve equivalent headroom.

🤖 Copy this AI Prompt to have your agent fix this:
In file @apps/server/src/orchestration-v2/http.ts around line 222:

A transcript whose `visibleTurnItems` fit within `PROVIDER_SEND_TURN_MAX_FILE_BYTES` can still be rejected by `addComposerAttachments`: the client adds a JSONL header containing the title, IDs, timestamp, and description plus its newline, pushing the generated `File` over `fileStagingLimit`. Include the serialized header and newline in this budget, or reserve equivalent headroom.

@macroscopeapp

macroscopeapp Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Approvability

Verdict: Not approved

Macroscope's review found this PR not approvable — This PR introduces a new cross-environment transcript-export and attachment workflow spanning the server, client runtime, contracts, and composer rather than making a contained fix. Two unresolved High-severity findings also identify concrete attachment-slot and size-budget failures in the new path.

Not approved because:

  • 2 blocking correctness issues found at or above your repo's Minimum Blocking Severity

Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:L 100-499 changed lines (additions + deletions). vouch:trusted PR author is trusted by repo permissions or the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant