feat(ui,workbench): composer and timeline on attachment references - #516
feat(ui,workbench): composer and timeline on attachment references#516Zerlight wants to merge 9 commits into
Conversation
|
Your Claude subscription has hit its usage limit. It resets at 11:30am (UTC). Re-trigger Pullfrog after the reset, or add an Add repo secret → · Model settings → · Setup docs → · Ask in Discord →
|
Greptile SummaryThis PR moves composer uploads and timeline rendering onto durable attachment references, adds plain
Confidence Score: 4/5The PR should not merge until attachment metadata exceeding the new limits fails locally or is introduced under a new wire version, rather than leaving compatible clients waiting indefinitely. The attachment architecture and lease protections are well covered, but the unversioned wire-schema tightening creates a concrete hanging request for valid legacy metadata; the stale preview race additionally retains attachment bytes until a later switch. Files Needing Attention: packages/foundation/schema/src/wire/attachment.ts, packages/foundation/schema/src/wire/resource.ts, packages/client/core/src/client/attachment-channel.ts, packages/client/workbench/src/surface/workbench.tsx
|
| Filename | Overview |
|---|---|
| packages/foundation/schema/src/wire/attachment.ts | Adds metadata limits to attachment wire frames, but the breaking validation change lacks protocol-versioning or matching client-side guards. |
| packages/client/core/src/client/attachment-channel.ts | Adds upload size protection and defensive byte caching, but does not guard newly constrained names or MIME types. |
| packages/client/workbench/src/surface/workbench.tsx | Integrates ref-backed submission and timeline preview resolution; stale asynchronous resolutions can retain object URLs after a session switch. |
| packages/client/workbench/src/surface/prompt-attachments.ts | Implements attachment staging, ref conversion, temporary timeline overlays, and object-URL ownership. |
| packages/host/engine/src/attachment/ingest.ts | Stores daemon-held bytes as immutable attachment records and converts legacy inline images into durable prompt references. |
| packages/host/engine/src/session/lifecycle-service.ts | Integrates attachment admission, ingestion, persistence, and materialization into turn submission and rewrite flows. |
| packages/presentation/ui/src/chat/attachment-preview.tsx | Adds generation-aware preview resolution with bounded retries, though discarded results cannot release resolver-created resources. |
| apps/daemon/src/attachment-store.ts | Makes attachment commit fail transactionally when its upload lease has already been swept. |
Sequence Diagram
sequenceDiagram
participant UI as Composer
participant Client as LinkCodeClient
participant Host as Engine
participant Store as Attachment Store
participant Agent as Harness
UI->>Client: putAttachment(bytes, metadata)
Client->>Host: upload.begin + chunks + commit
Host->>Store: Persist blob, record, and lease
Store-->>Client: attachmentId
UI->>Client: turn.submit(attachment_ref)
Client->>Host: Prompt blocks with attachmentId
Host->>Store: Admit and root attachment
Host->>Store: Read immutable bytes
Host->>Agent: Materialized inline image/file
Host-->>UI: Text-only live echo
UI->>Host: conversation.read
Host-->>UI: Durable attachment resource_link
UI->>Client: attachment.read
Client-->>UI: Cached bytes / preview URL
Reviews (1): Last reviewed commit: "fix(engine,workbench): sniff legacy inli..." | Re-trigger Greptile
6c61d89 to
bf0ffd1
Compare
There was a problem hiding this comment.
Greptile has paused reviews on this repository — it used its 100 free open-source review credits for this billing period. Reviews resume automatically on September 23. To continue before then, an organization admin can keep reviews running past the free credits — those bill as normal usage.
|
Your Claude subscription has hit its usage limit. It resets at 11:30am (UTC). Re-trigger Pullfrog after the reset, or add an Add repo secret → · Model settings → · Setup docs → · Ask in Discord →
|
… cap the put size
…t refs in the mock
…inline images in the mock
…refuse refs on capability-less harnesses early
bf0ffd1 to
103d954
Compare
|
Your Claude subscription has hit its usage limit. It resets at 11:30am (UTC). Re-trigger Pullfrog after the reset, or add an Add repo secret → · Model settings → · Setup docs → · Ask in Discord →
|
|
Review round on this PR (Greptile, two inline threads), fixed on the top of the stack. 795f0b3 — |

Summary
Phase 3 of CODE-627 — Conversation turn graph & immutable attachment store. Linear: https://linear.app/arcbox/issue/CODE-637/featuiworkbench-composer-and-timeline-on-attachment-references
Stack: #515 ← this PR (
ruocheng/code-637, baseruocheng/code-625) ← #517. Merge bottom-up; this PR's diff is only its own commits.Against a capable daemon the composer uploads through the chunked protocol and sends
attachment_refblocks; the timeline resolves refs throughattachment.readand the blob cache; affordances follow the daemon-declared capability and theATTACHMENT_SUPPORTstub is deleted. Plain sends go throughturn.submit, legacy inline images are stored as refs on the durable row, and the dev mock admits and ingests refs.Commits
Verification
Every commit passed
pnpm check:ciandpnpm testat its own tip; the stack tip (1d942a62; the same tree as the originally gated73fc5ff2plus the two review fixes below on 628/629) is atpnpm check:ci0 errors,pnpm test3408 passed / 1 skipped. Adversarial reviewers (one per axis, isolated read-only worktrees) reviewed the branch; each P1/P2 was reproduced with a failing test or a probe step before its fix — the round-by-round record is in the Linear issue's comments. A headless-Chrome probe ofdev:mockattaches an image, sends, and sees the ref-backed image render; frame sizes confirm no attachment base64 on the wire.Checklist
pnpm check:ciandpnpm testboth pass (no Rust changes)dev:mockin headless ChromeAGENTS.mdand module docs in this branch)