Conversation
|
Warning Review limit reachedOnly 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. View limit detailsLimit details: You’ve used all 10 included reviews currently available. Review configuration: ⚙️ Run configuration
📒 Files selected for processing (12)
Comment |
| const importDroppedThread = useEffectEvent( | ||
| async (ref: ScopedThreadRef, isActive: () => boolean) => { | ||
| const targetKey = attachmentTargetKey; | ||
| pendingDraftWork.begin(targetKey); |
There was a problem hiding this comment.
🟠 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; |
There was a problem hiding this comment.
🟠 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.
ApprovabilityVerdict: 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:
Adjust the Minimum Blocking Severity for this repo — including turning it Off — in Settings. You can add or adjust custom eligibility rules. Learn more. |
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
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
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.