@hachej/boring-agent 0.1.17 → 0.1.18
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{sandbox-handle-store-hK76cTjn.d.ts → agentPluginEvents-zyIvVjsA.d.ts} +28 -32
- package/dist/{chunk-F3CE5CNW.js → chunk-B5JECXMG.js} +5 -7
- package/dist/front/index.d.ts +23 -7
- package/dist/front/index.js +764 -421
- package/dist/front/styles.css +61 -0
- package/dist/{tool-ui-DSmWuqGe.d.ts → harness-DRrTn_5T.d.ts} +43 -24
- package/dist/server/index.d.ts +79 -10
- package/dist/server/index.js +243 -54
- package/dist/shared/index.d.ts +5 -3
- package/dist/shared/index.js +3 -1
- package/dist/tool-ui-DIFNGwYd.d.ts +20 -0
- package/docs/ACCESSIBILITY.md +55 -0
- package/docs/API.md +64 -0
- package/docs/CSP.md +40 -0
- package/docs/ERROR_CODES.md +54 -0
- package/docs/KNOWN_LIMITATIONS.md +100 -0
- package/docs/MIGRATION.md +50 -0
- package/docs/PERFORMANCE.md +68 -0
- package/docs/PLUGINS.md +108 -0
- package/docs/README.md +17 -0
- package/docs/RISKS-MULTI-TAB.md +46 -0
- package/docs/STYLING.md +71 -0
- package/docs/UI-SHADCN.md +56 -0
- package/docs/VERCEL_COSTS.md +103 -0
- package/docs/plans/AGENT_EVAL_FRAMEWORK.md +466 -0
- package/docs/plans/agent-package-spec.md +1777 -0
- package/docs/plans/harness-followup-capabilities.md +440 -0
- package/docs/plans/harness-tool-ui-capabilities.md +144 -0
- package/docs/plans/pi-followup-history-projection.md +229 -0
- package/docs/plans/pi-tools-migration.md +1061 -0
- package/docs/plans/reviews/pi-followup-history-codex-review.md +11 -0
- package/docs/plans/reviews/pi-followup-history-gpt-review.md +64 -0
- package/docs/plans/reviews/pi-followup-history-opus-review.md +43 -0
- package/docs/plans/reviews/pi-followup-history-xai-review.md +43 -0
- package/docs/plans/vercel-base-snapshot-template-plan.md +527 -0
- package/docs/plans/vercel-persistent-sandbox-adapter.md +553 -0
- package/docs/runtime.md +56 -0
- package/docs/tools.md +75 -0
- package/package.json +4 -3
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Verdict: **revise**
|
|
2
|
+
|
|
3
|
+
- `ChatPanel` posts all unposted follow-ups in parallel and marks them `posted` before ACK: [ChatPanel.tsx:635](/home/ubuntu/projects/worktrees/boring-ui-v2-followup-pi-history/packages/agent/src/front/ChatPanel.tsx:635). HTTP arrival can reorder Q1/Q2, while the server queues `piSession.followUp()` in arrival order: [createHarness.ts:364](/home/ubuntu/projects/worktrees/boring-ui-v2-followup-pi-history/packages/agent/src/server/harness/pi-coding-agent/createHarness.ts:364). This breaks FIFO UI ordering.
|
|
4
|
+
|
|
5
|
+
- Inline follow-up assistant turns still leak AI SDK chunks while also being projected. `data-pi-message-start` is emitted, but `start` is not filtered from `piEventToChunks()`: [createHarness.ts:562](/home/ubuntu/projects/worktrees/boring-ui-v2-followup-pi-history/packages/agent/src/server/harness/pi-coding-agent/createHarness.ts:562), [stream-adapter.ts:90](/home/ubuntu/projects/worktrees/boring-ui-v2-followup-pi-history/packages/agent/src/server/harness/pi-coding-agent/stream-adapter.ts:90). Since `ChatPanel` appends projection to `messages` and keys by `message.id`, this risks duplicate keys/rendering: [ChatPanel.tsx:624](/home/ubuntu/projects/worktrees/boring-ui-v2-followup-pi-history/packages/agent/src/front/ChatPanel.tsx:624), [ChatPanel.tsx:1117](/home/ubuntu/projects/worktrees/boring-ui-v2-followup-pi-history/packages/agent/src/front/ChatPanel.tsx:1117).
|
|
6
|
+
|
|
7
|
+
- Snapshot-only inline assistant text can duplicate too: the inline filter removes normal text deltas, but the `text_end` fallback still prepends `text-start`/`text-delta` even when `inlineTurnIndex > 0`: [createHarness.ts:572](/home/ubuntu/projects/worktrees/boring-ui-v2-followup-pi-history/packages/agent/src/server/harness/pi-coding-agent/createHarness.ts:572). The same text is also sent through `data-pi-message-end`.
|
|
8
|
+
|
|
9
|
+
- Persistence remains racy. `useAgentChat` saves raw AI SDK `messages` on ready, then `ChatPanel` separately saves projected `nextMessages`; either PUT can win: [useAgentChat.ts:150](/home/ubuntu/projects/worktrees/boring-ui-v2-followup-pi-history/packages/agent/src/front/hooks/useAgentChat.ts:150), [ChatPanel.tsx:690](/home/ubuntu/projects/worktrees/boring-ui-v2-followup-pi-history/packages/agent/src/front/ChatPanel.tsx:690). The manual save also skips the hook’s data-URL stripping, so projected file parts can bloat persisted history.
|
|
10
|
+
|
|
11
|
+
Tests: attempted targeted Vitest run, but the read-only filesystem blocked Vite config temp writes with `EROFS`.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# GPT Plan Review — pi-followup-history-projection.md
|
|
2
|
+
|
|
3
|
+
## Top 5 Risks / Ambiguities
|
|
4
|
+
|
|
5
|
+
1. **Message identity + de‑duplication is underspecified**
|
|
6
|
+
- `messageId: string` is mentioned, but the spec does not define *who* generates IDs (pi vs. adapter), their stability across reconnects, or how they relate to AI SDK `id`s.
|
|
7
|
+
- De‑duplication rules only reference duplicate user `message_start` events; assistant duplicates, retries, or reconnections aren’t covered.
|
|
8
|
+
|
|
9
|
+
2. **User text matching for queued → consumed mapping is brittle**
|
|
10
|
+
- Rule 3 relies on `find the first queued projected user with same text`. That will break for:
|
|
11
|
+
- minor text normalization differences (trimming, newline handling, markdown transforms).
|
|
12
|
+
- retries / resubmits with identical text.
|
|
13
|
+
- future support for edited messages.
|
|
14
|
+
- This is dangerous for correctness of the FIFO mapping and may cause visibly wrong pairings.
|
|
15
|
+
|
|
16
|
+
3. **Projection vs. AI SDK history boundary is fuzzy**
|
|
17
|
+
- Phase 1 rendering says: "render AI SDK messages before the first projected follow-up if needed" and later "projection may be folded back into persisted history."
|
|
18
|
+
- It doesn’t specify:
|
|
19
|
+
- when exactly projection becomes authoritative (first follow-up queued? first `data-pi-message-*` received?).
|
|
20
|
+
- how to avoid double-rendering or gaps if AI SDK reconstruction disagrees with the pi projection.
|
|
21
|
+
- how persisted history is updated/merged when the page reloads.
|
|
22
|
+
|
|
23
|
+
4. **Error/reconnect and partial-stream behavior is not covered**
|
|
24
|
+
- The spec does not state what happens when:
|
|
25
|
+
- the HTTP stream is cut mid‑follow‑up and the browser later reconnects and reloads prior session history.
|
|
26
|
+
- `pi-message-start` arrives but `pi-message-end` never does.
|
|
27
|
+
- `data-pi-message-*` events arrive out of order.
|
|
28
|
+
- Without explicit ordering and recovery rules, history projection can diverge from true pi session state.
|
|
29
|
+
|
|
30
|
+
5. **Follow-up execution ordering vs. UI FIFO semantics**
|
|
31
|
+
- UI plans a straightforward FIFO queue (`PendingFollowUp[]`) and assumes pi will execute in the same strict order.
|
|
32
|
+
- Spec doesn’t state whether pi guarantees:
|
|
33
|
+
- single-threaded, in-order execution of follow-ups under all modes (direct/local/remote).
|
|
34
|
+
- no cross-turn interleaving of assistant messages from different queued follow-ups.
|
|
35
|
+
- If pi ever supports concurrency or partial interleaving, the current projection model will misrepresent order.
|
|
36
|
+
|
|
37
|
+
## Must-Change / Clarifying Amendments
|
|
38
|
+
|
|
39
|
+
1. **Define message ID ownership and stability**
|
|
40
|
+
- Explicitly specify that `PiHistoryEvent.messageId` is generated and owned by pi, stable for a given message within a session, and monotonically ordered per turn.
|
|
41
|
+
- Clarify whether the browser may assume increasing order, and how to map (or not map) these IDs to AI SDK message IDs.
|
|
42
|
+
|
|
43
|
+
2. **Replace text-based user matching with ID‑based mapping**
|
|
44
|
+
- Change Rule 3 to associate queued user messages with a stable client-side `PendingFollowUp.id`, then have the server echo a `clientMessageId` (or similar) in `pi-message-start` for consumed user messages.
|
|
45
|
+
- This removes dependence on text equality, supports duplicate texts, and leaves room for future message edits.
|
|
46
|
+
|
|
47
|
+
3. **Tighten the authority boundary and fold‑back rules**
|
|
48
|
+
- Add precise rules for when the client switches from AI SDK `messages` to the projection tail (e.g. "after the first `data-pi-message-start` for a follow-up in this session").
|
|
49
|
+
- Specify how to construct canonical history on reload (e.g. from server-side persisted pi session projection only) so the hybrid phase doesn’t create divergent views.
|
|
50
|
+
|
|
51
|
+
4. **Specify ordering, error, and reconnection semantics**
|
|
52
|
+
- Document that `PiHistoryEvent`s are strictly ordered within a stream and describe the client behavior on missing `message_end` (e.g. time out to `status: 'done'` with a warning, or keep as `streaming` but visually stable).
|
|
53
|
+
- Define behavior on stream interruption: whether the client should discard local projection and refetch canonical history, or attempt to reconcile.
|
|
54
|
+
- Mention how to handle obviously out-of-order or duplicate events (idempotency expectations for each event type).
|
|
55
|
+
|
|
56
|
+
5. **Document execution-order guarantees (or constraints) for follow-ups**
|
|
57
|
+
- If pi guarantees serial, FIFO execution of follow-ups within a session, state this explicitly so the UI projection is known-correct.
|
|
58
|
+
- If not, update the projection model to support tags/parent IDs or per-follow-up threads so interleaving can be represented faithfully.
|
|
59
|
+
|
|
60
|
+
## Verdict
|
|
61
|
+
|
|
62
|
+
Concept and direction are sound: leveraging pi as the single source of truth for follow-up history while gradually layering over AI SDK is a good migration path. However, the current spec underdefines identity, ordering, and failure/reconnect behavior. Those gaps are high-risk for subtle history divergence bugs.
|
|
63
|
+
|
|
64
|
+
**Verdict: revise before implementation.** Tighten the identity/ordering/error semantics and remove text-based matching before treating this spec as implementation-complete.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
## Verdict: **Revise** — direction is right, but ship-blocking gaps
|
|
2
|
+
|
|
3
|
+
Direction is correct (pi events as authority, projection on the wire, reducer client-side). But several concrete gaps will produce the exact bugs the plan claims to fix.
|
|
4
|
+
|
|
5
|
+
### Concrete amendments
|
|
6
|
+
|
|
7
|
+
**1. Eliminate split-brain, don't sequence it.**
|
|
8
|
+
The plan keeps AI SDK assistant chunks "for the first turn" and only suppresses them after follow-ups. Two writers into one model = the same bug class. Pick one:
|
|
9
|
+
- emit pi-message events from turn 0 and have the client ignore AI SDK assistant text/tool/reasoning parts entirely when pi mode is on, **or**
|
|
10
|
+
- gate per-session: server flips a `pi-events-mode: on` data chunk before any content; client picks one reducer for the whole session.
|
|
11
|
+
Mixed mode reintroduces the merge/misplacement bugs.
|
|
12
|
+
|
|
13
|
+
**2. Define `toolResult` reducer rule explicitly.**
|
|
14
|
+
Section "Client reducer" lists 6 rules but says nothing about `pi-message-start/end role: 'toolResult'`. Pi web-ui attaches tool results to the owning assistant's `tool-*` part by `toolCallId`. Specify: on `pi-message-end toolResult`, locate part by `toolCallId` on the assistant and set its `output`/state. Don't append a standalone bubble.
|
|
15
|
+
|
|
16
|
+
**3. Tool/reasoning part identity is missing from the wire DTO.**
|
|
17
|
+
`pi-message-update assistant` must carry `{ partKind, partKey (toolCallId | reasoningId | textId), state, deltaOrSnapshot }` — not an opaque `event: AssistantMessageEvent`. Without explicit part keys, idempotency rule 6 ("by messageId + part key") has no `part key`. Also: `event: AssistantMessageEvent` couples wire to pi internals; define a stable DTO.
|
|
18
|
+
|
|
19
|
+
**4. Add `seq` + resume.**
|
|
20
|
+
No mention of ordering source-of-truth or reconnect. Add a monotonic `seq` per session on every `data-pi-*` chunk and a `GET /pi-messages?sinceSeq=` for resume. Otherwise a dropped SSE mid-stream leaves a corrupt projection with no recovery path.
|
|
21
|
+
|
|
22
|
+
**5. Persistence: the short-term plan loses data.**
|
|
23
|
+
"AI SDK `/messages` persistence remains for normal non-follow-up chats only" is undecidable at write time — a chat becomes follow-up retroactively. Result: refresh after a follow-up turn → history shows only first turn. Either:
|
|
24
|
+
- ship the canonical endpoint now (pi `session.state.messages` → UIMessage projector) and skip client-side persistence entirely when pi mode is on, **or**
|
|
25
|
+
- persist the pi-projected `UIMessage[]` from the reducer with the same `messageId`s for idempotent rehydrate.
|
|
26
|
+
The "long-term" item is actually ship-blocking.
|
|
27
|
+
|
|
28
|
+
**6. messageId stability invariant.**
|
|
29
|
+
Reducer assumes pi `messageId` is stable from `message_start` through `message_end`. Add a unit test pinning this against the pi runtime; if pi ever assigns the id only at end, the whole reducer breaks.
|
|
30
|
+
|
|
31
|
+
**7. FIFO needs server-side ordering too.**
|
|
32
|
+
Client FIFO is necessary but not sufficient (HTTP/2 reorder, retries). `POST /followup` should accept a client `seq` and the server should reject/queue out-of-order rather than relying on arrival order alone.
|
|
33
|
+
|
|
34
|
+
**8. Optimistic queued bubble reconciliation.**
|
|
35
|
+
Rule 5 says "replace/mark optimistic bubble as committed when pi emits real user message." Specify the match key — pi will assign its own `messageId`. Use a client-generated `clientNonce` echoed back on `/followup` response and surfaced on the pi user `message_start` (server attaches), otherwise reconciliation is heuristic on text equality and will misbehave with duplicates.
|
|
36
|
+
|
|
37
|
+
### Risk ranking
|
|
38
|
+
1. Split-brain during migration window (#1) — highest, recreates current bugs.
|
|
39
|
+
2. Reload data loss (#5) — user-visible regression.
|
|
40
|
+
3. Missing part-key DTO (#3) — silently corrupts tool/reasoning state.
|
|
41
|
+
4. No seq/resume (#4) — flaky on real networks.
|
|
42
|
+
|
|
43
|
+
Tests section is fine but add: reducer test for `toolResult` attach-by-toolCallId, and a "drop & resume" integration test.
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# xAI review — pi follow-up history projection
|
|
2
|
+
|
|
3
|
+
### Verdict: Revise
|
|
4
|
+
|
|
5
|
+
#### High Severity
|
|
6
|
+
- **File: packages/agent/src/front/ChatPanel.tsx**
|
|
7
|
+
**Issue: Potential race condition in follow-up posting and state updates.**
|
|
8
|
+
The `postPendingFollowUps` function is async and loops through pending items, but if `sessionId` changes mid-execution (e.g., via `useEffect` reset), it could process stale items or fail to update refs correctly. The `updatePendingMessages` callback uses `pendingMessagesRef.current`, but concurrent updates (e.g., from `onData` events) might overwrite state before the callback applies.
|
|
9
|
+
**Fix:** Add sessionId checks inside the loop in `postPendingFollowUps` to abort if session has changed. Use a more robust state update mechanism, like immer or ensuring atomicity with a lock.
|
|
10
|
+
|
|
11
|
+
- **File: packages/agent/src/front/ChatPanel.tsx**
|
|
12
|
+
**Issue: Stale logic in piMessages rebuilding and projection.**
|
|
13
|
+
`rebuildPiMessagesFromDataParts` and `mergeRebuiltPiMessages` assume data-pi-* parts are always present and correctly ordered, but if events arrive out-of-order (e.g., deltas before starts), messages could be incomplete or duplicated. The `useEffect` for rebuilding runs on every `messages` change, potentially causing excessive re-renders or loss of in-flight data.
|
|
14
|
+
**Fix:** Buffer data-pi-* parts in a ref and rebuild only on stream end (`status === 'ready'`). Add validation to skip rebuilding if parts are incomplete.
|
|
15
|
+
|
|
16
|
+
#### Medium Severity
|
|
17
|
+
- **File: packages/agent/src/front/ChatPanel.tsx**
|
|
18
|
+
**Issue: Inconsistent handling of projected vs. pi messages in display.**
|
|
19
|
+
`displayMessages` prioritizes `piMessages` if present, but falls back to `messages + projectedTailMessages`. If piMessages are rebuilt incorrectly, queued follow-ups might not show waiting bubbles, or statuses might mismatch (e.g., `projectedStatusById` could be stale).
|
|
20
|
+
**Fix:** Ensure `projectedFollowUps` are always merged into `piMessages` during rebuild, and clear projections only after confirmation.
|
|
21
|
+
|
|
22
|
+
- **File: packages/agent/src/server/http/routes/chat.ts**
|
|
23
|
+
**Issue: Follow-up idempotency logic may allow stale retries.**
|
|
24
|
+
The seq/nonce check in `/followup` prevents out-of-order but not concurrent duplicates if multiple requests hit simultaneously. `lastFollowUpBySession` is in-memory and not persisted, so server restarts could lose state.
|
|
25
|
+
**Fix:** Persist seq/nonce in a durable store (e.g., database) per session. Add mutex for concurrent requests.
|
|
26
|
+
|
|
27
|
+
- **File: packages/agent/src/server/harness/pi-coding-agent/createHarness.ts**
|
|
28
|
+
**Issue: Pi event emission order and seq numbering.**
|
|
29
|
+
`nextPiSeq()` increments globally per harness, but if events are interleaved across sessions, seqs might not be monotonic per message. Missing handling for tool results or reasoning if events arrive unexpectedly.
|
|
30
|
+
**Fix:** Make seq per-session or per-message. Add error handling for missing messageIds.
|
|
31
|
+
|
|
32
|
+
#### Low Severity
|
|
33
|
+
- **File: packages/agent/src/front/hooks/useAgentChat.ts**
|
|
34
|
+
**Issue: Persistence disable might cause data loss.**
|
|
35
|
+
With `persistMessages: false`, localStorage and server saves are skipped, but manual persistence in ChatPanel assumes piMessages are always rebuilt correctly. If rebuild fails, history is lost.
|
|
36
|
+
**Fix:** Add fallback to persist raw `messages` if piMessages rebuild fails.
|
|
37
|
+
|
|
38
|
+
- **File: packages/agent/src/front/ChatPanel.tsx**
|
|
39
|
+
**Issue: Timer and ref cleanup on session change.**
|
|
40
|
+
The `useEffect` for sessionId resets refs, but if `postPendingFollowUps` is in-flight, it might not abort cleanly, leading to stale posts.
|
|
41
|
+
**Fix:** Add an abort signal to `postPendingFollowUps` tied to sessionId.
|
|
42
|
+
|
|
43
|
+
No critical blockers (e.g., crashes), but races and staleness could cause UI inconsistencies or lost follow-ups. Revise to address high/medium issues before shipping.
|