@poncho-ai/cli 0.36.9 → 0.38.0

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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @poncho-ai/cli@0.36.9 build /home/runner/work/poncho-ai/poncho-ai/packages/cli
2
+ > @poncho-ai/cli@0.38.0 build /home/runner/work/poncho-ai/poncho-ai/packages/cli
3
3
  > tsup src/index.ts src/cli.ts --format esm --dts
4
4
 
5
5
  CLI Building entry: src/cli.ts, src/index.ts
@@ -7,12 +7,12 @@
7
7
  CLI tsup v8.5.1
8
8
  CLI Target: es2022
9
9
  ESM Build start
10
+ ESM dist/index.js 3.10 KB
10
11
  ESM dist/cli.js 94.00 B
11
- ESM dist/index.js 917.00 B
12
- ESM dist/run-interactive-ink-KDWRD7FT.js 56.86 KB
13
- ESM dist/chunk-IZLDZWPA.js 572.09 KB
14
- ESM ⚡️ Build success in 69ms
12
+ ESM dist/chunk-U643TWFX.js 601.19 KB
13
+ ESM dist/run-interactive-ink-CE7U47S5.js 23.38 KB
14
+ ESM ⚡️ Build success in 105ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 4212ms
16
+ DTS ⚡️ Build success in 4659ms
17
17
  DTS dist/cli.d.ts 20.00 B
18
- DTS dist/index.d.ts 7.07 KB
18
+ DTS dist/index.d.ts 12.83 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,249 @@
1
1
  # @poncho-ai/cli
2
2
 
3
+ ## 0.38.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#95](https://github.com/cesr/poncho-ai/pull/95) [`21ee02a`](https://github.com/cesr/poncho-ai/commit/21ee02a577cd0a85823cc3922dd0dc54c630f417) Thanks [@cesr](https://github.com/cesr)! - perf: eliminate per-conversation archive egress on the hot read path
8
+
9
+ Three related fixes that together dramatically reduce database and
10
+ server→browser egress for any long-lived conversation:
11
+ - `conversationStore.get()` no longer loads the `tool_result_archive`
12
+ column. Callers that actually need to reseed the harness archive —
13
+ run entry points, cron runs, reminder firings — must now use the new
14
+ `conversationStore.getWithArchive()` method instead.
15
+ - The `GET /api/conversations/:id` response strips `_toolResultArchive`
16
+ alongside the already-stripped `_continuationMessages` and
17
+ `_harnessMessages`, so the browser never receives the archive payload.
18
+ - Adds a cheap `GET /api/conversations/:id/status` endpoint backed by a
19
+ new `getStatusSnapshot()` method that reads only summary columns (no
20
+ `data` blob). The web UI poll loops now hit this endpoint every 2s
21
+ and only refetch the full conversation when `updatedAt`,
22
+ `messageCount`, or the pending-approval counts actually change.
23
+
24
+ The SQL upsert was also updated to preserve `tool_result_archive` via
25
+ `COALESCE(excluded, conversations.tool_result_archive)` so that updates
26
+ on conversations loaded via the light `get()` do not clobber the
27
+ existing archive.
28
+
29
+ - [#100](https://github.com/cesr/poncho-ai/pull/100) [`ef4fe5d`](https://github.com/cesr/poncho-ai/commit/ef4fe5d1fd4bb31c201fd240f4524b64f01e3e6d) Thanks [@cesr](https://github.com/cesr)! - feat: Slack-style message threads
30
+
31
+ Users can now fork any persisted message into one or more threads. Each
32
+ thread is a new conversation whose initial history is a snapshot of the
33
+ parent up to and including the anchor message; replies in the thread
34
+ evolve independently of the parent. Multiple threads per parent message
35
+ are supported.
36
+
37
+ ## Web UI
38
+ - Hover any message in the main pane to reveal a "Reply in thread" pill
39
+ positioned just below the bubble (offset varies by role). The pill is
40
+ invisible by default and only appears on hover; a delayed-hide bridges
41
+ the empty space between message and pill so the user can move the
42
+ mouse onto it without it flickering off.
43
+ - Once a thread exists on a message, the pill is replaced by an
44
+ always-visible badge (`"N replies · 5m ago"`, count bold + meta muted).
45
+ Multiple threads stack vertically under the message, each with its own
46
+ badge. Hovering a badge reveals an outside-positioned `×` delete with
47
+ the same two-step "× → sure?" confirmation as the sidebar
48
+ conversation-delete.
49
+ - Clicking a badge opens the thread in a right-side panel that mirrors
50
+ the existing browser-panel pattern: a flex sibling of `.main-chat`
51
+ with a 1px drag-resize handle. The panel has its own composer
52
+ (independent file uploads, paste-to-attach, attachment preview)
53
+ rendered alongside the main composer so users can keep typing in the
54
+ parent conversation. Vertical padding matches the main composer so
55
+ both chatboxes line up at the same baseline.
56
+ - The pinned parent message and replies inside the panel render through
57
+ the same DOM construction logic as the main pane (assistant avatar +
58
+ markdown, user bubble + file thumbnails). Reply submissions stream
59
+ token-by-token via SSE (parsed model:chunk events feed an optimistic
60
+ assistant placeholder; a thinking-indicator shows until the first
61
+ chunk lands).
62
+ - The open thread is reflected in the URL hash (`#thread=<id>`) so a
63
+ page reload restores the panel. Switching conversations or closing
64
+ the panel clears the hash and any sticky drag-resize widths.
65
+
66
+ ## DB
67
+ - New `parent_message_id TEXT` column on `conversations` (migration 6)
68
+ plus a partial index on `(parent_conversation_id, parent_message_id)
69
+ WHERE parent_message_id IS NOT NULL`.
70
+ - The existing `parent_conversation_id` plumbing is reused; subagents
71
+ and threads coexist on that column, discriminated by whether
72
+ `parent_message_id` is set (subagents leave it `NULL`).
73
+ - `threadMeta` (snapshot length + cached parent-message summary)
74
+ round-trips inside the conversation `data` blob.
75
+
76
+ ## API
77
+ - `GET /api/conversations/:id/threads` → `{ threads: ApiThreadSummary[] }`
78
+ - `POST /api/conversations/:id/threads { parentMessageId, title? }` →
79
+ 201 `{ thread, conversationId }` |
80
+ 404 `PARENT_MESSAGE_NOT_FOUND` |
81
+ 409 `MESSAGE_ID_REQUIRED` (anchor lacks a stable id) |
82
+ 409 `ANCHOR_IN_FLIGHT` (anchor is the streaming tail of a live run)
83
+ - The two `SUBAGENT_READ_ONLY` gates on `/messages` and `/continue` are
84
+ now keyed on `subagentMeta` rather than `parentConversationId` so
85
+ threads remain writable.
86
+ - New `ApiThreadSummary`, `ApiThreadListResponse`,
87
+ `ApiCreateThreadRequest`, `ApiCreateThreadResponse` types in
88
+ `@poncho-ai/sdk`. New `AgentClient.listThreads` /
89
+ `AgentClient.createThread` wrappers in `@poncho-ai/client`.
90
+
91
+ ## Storage interface
92
+ - `ConversationStore.listThreads(parentConversationId)` and the
93
+ matching `StorageEngine.conversations.listThreads(...)`. External
94
+ implementers of these interfaces will need to add the method.
95
+ - `Conversation` / `ConversationCreateInit` / `ConversationSummary`
96
+ gained optional `parentMessageId` and `threadMeta` fields.
97
+
98
+ ## Fork semantics
99
+ - Stable `metadata.id` on every persisted message: `randomUUID()` is
100
+ hoisted once per turn and reused for both the user message and the
101
+ in-flight assistant message across all persist sites (cli messaging
102
+ run, cli `/messages` handler, cron path). `buildAssistantMetadata`
103
+ takes an optional `{ id, timestamp }` opt-arg.
104
+ - No DB backfill of legacy id-less messages; the SPA hides the
105
+ "Reply in thread" affordance on rows whose `metadata.id` is missing.
106
+ - The visible-sequence used for the anchor lookup is reconstructed as
107
+ `[...compactedHistory, ...messages.filter(notCompactionSummary)]`,
108
+ so pre-compaction anchors are supported. For pre-compaction anchors,
109
+ `_harnessMessages` is reset to `undefined` so the harness rebuilds
110
+ canonical history from `messages` on the thread's first run.
111
+ - Forking on the actively-streaming tail message of a live run returns
112
+ 409 `ANCHOR_IN_FLIGHT`; any prior, already-persisted message is
113
+ fork-able even while the parent is mid-run.
114
+ - Tool-result archive entries are filtered to only those referenced by
115
+ tool calls in the trimmed `_harnessMessages` (no whole-archive clones).
116
+ - All run-specific state is reset on the new thread:
117
+ `runtimeRunId`, `pendingApprovals`, `runStatus`,
118
+ `pendingSubagentResults`, `subagentCallbackCount`,
119
+ `runningCallbackSince`, `_continuationMessages`. `channelMeta` and
120
+ `subagentMeta` are explicitly NOT inherited so threads aren't bound
121
+ to the parent's Slack/Telegram thread and aren't subagent runs.
122
+ - Thread conversations stay out of the sidebar list (already-existing
123
+ `!c.parentConversationId` filter) and are cascade-deleted with their
124
+ parent.
125
+
126
+ ### Patch Changes
127
+
128
+ - [#100](https://github.com/cesr/poncho-ai/pull/100) [`ef4fe5d`](https://github.com/cesr/poncho-ai/commit/ef4fe5d1fd4bb31c201fd240f4524b64f01e3e6d) Thanks [@cesr](https://github.com/cesr)! - feat(logging): readable, scoped, level-aware dev server logs
129
+
130
+ `poncho dev` output is now formatted consistently across the CLI and
131
+ harness:
132
+
133
+ ```
134
+ 20:23:45 ✓ poncho dev server ready at http://localhost:3000
135
+ 20:23:45 • slack enabled at /api/messaging/slack
136
+ 20:23:45 • cron scheduled 2 jobs: hourly_check, nightly_summary
137
+ 20:24:15 → cron:hourly_check started
138
+ 20:24:17 ✓ cron:hourly_check completed in 1.2s (3 chats)
139
+ 20:25:00 ⚠ telegram approval not found: req-7f42a
140
+ 20:25:01 ✗ poncho internal error: ECONNREFUSED
141
+ ```
142
+
143
+ Format: `HH:mm:ss <symbol> <scope> <message>`. Scopes (`poncho`, `cron`,
144
+ `reminder`, `messaging`, `slack`, `telegram`, `resend`, `subagent`,
145
+ `approval`, `browser`, `csrf`, `upload`, `serverless`, `self-fetch`,
146
+ `mcp`, `telemetry`, `cost`, `model`, `harness`, `event`, `tools`)
147
+ replace the previous mix of `[poncho]`, `[poncho][cost]`, `[cron]`,
148
+ `[messaging-runner]`, `[event] ...`, etc.
149
+ - New `createLogger(scope)` exported from `@poncho-ai/sdk` with
150
+ `.debug/.info/.warn/.error/.success/.ready/.item/.child(sub)` and
151
+ helpers `formatError`, `url`, `muted`, `num`.
152
+ - Honors `NO_COLOR` / `FORCE_COLOR` and `LOG_LEVEL=debug|info|warn|error|silent`.
153
+ Verbose telemetry/cost/event lines now log at `debug` and are silent
154
+ by default.
155
+ - `poncho dev` gains `-v`/`--verbose` (debug), `-q`/`--quiet` (warn+),
156
+ and `--log-level <level>` flags.
157
+ - Each scope tag is colored with a stable pastel hue (truecolor), with
158
+ 256-color and 16-color fallbacks. Children (`cron:hourly_check`)
159
+ inherit their parent's color.
160
+ - TTY-aware: ANSI color is stripped when stdout is piped.
161
+ - Conversation-egress logging (`[poncho][egress] read: …`) is now opt-in
162
+ via `PONCHO_LOG_EGRESS=1` (matching the documented behavior; it had
163
+ been logging unconditionally).
164
+ - No behavior changes to which events are emitted — only formatting.
165
+
166
+ - [`fcf6a02`](https://github.com/cesr/poncho-ai/commit/fcf6a027880ac94ada2e3fd732b11eed9f5f15b8) Thanks [@cesr](https://github.com/cesr)! - chore: drop browser-frame noise from the dev log
167
+
168
+ Two sources of per-frame log noise during interactive browser use
169
+ are now silenced:
170
+ - `TelemetryEmitter.emit` skips `browser:frame` events alongside the
171
+ already-skipped `model:chunk`. OTLP forwarding and custom handlers
172
+ still receive every event unchanged.
173
+ - The CLI's browser SSE endpoint no longer prints the
174
+ `[poncho][browser-sse] Frame N: WxH, data bytes: ...` counter
175
+ (which fired for the first 3 frames and every 50th). Related
176
+ `frameCount` / `droppedFrames` state dropped with it.
177
+
178
+ - [#97](https://github.com/cesr/poncho-ai/pull/97) [`1eb1b1e`](https://github.com/cesr/poncho-ai/commit/1eb1b1e71641f79aa089a967811dcfe2de59be8d) Thanks [@cesr](https://github.com/cesr)! - refactor: extract subagent lifecycle into AgentOrchestrator (phase 5)
179
+
180
+ Move subagent orchestration (~1100 lines) from the CLI into the
181
+ AgentOrchestrator class in the harness package. The orchestrator now
182
+ owns all subagent state (activeSubagentRuns, pendingSubagentApprovals,
183
+ pendingCallbackNeeded), lifecycle methods (runSubagent,
184
+ processSubagentCallback, triggerParentCallback), SubagentManager
185
+ creation, approval handling, and stale recovery.
186
+
187
+ New hooks on OrchestratorHooks allow transport-specific concerns
188
+ (child harness creation, serverless dispatch, SSE stream lifecycle,
189
+ messaging notifications) to stay in the CLI while the orchestrator
190
+ handles all orchestration logic.
191
+
192
+ Also fixes subagent approval persistence (decisions now explicitly
193
+ written to the conversation store) and adds live SSE streaming for
194
+ parent callback runs in the web UI.
195
+
196
+ - [`33eaf9f`](https://github.com/cesr/poncho-ai/commit/33eaf9fcc57bab916ae8a25c942912eb5d6396cc) Thanks [@cesr](https://github.com/cesr)! - fix: stop buffering `browser:frame` events for SSE replay
197
+
198
+ Every `browser:frame` carries a base64 screenshot (~100 KB) and they
199
+ stream at 10+ fps. `broadcastEvent` was pushing them into the
200
+ per-conversation replay buffer (`ConversationEventStream.buffer`)
201
+ alongside real conversation events. In a long interactive browser
202
+ session this grew to multiple GB (observed: ~51k frames ≈ 4.4 GB of
203
+ retained base64 strings) and eventually crashed the dev server with
204
+ `FATAL ERROR: Reached heap limit - JavaScript heap out of memory`
205
+ inside V8's `JsonStringify`.
206
+
207
+ Frames are now excluded from the replay buffer — they still reach
208
+ live SSE subscribers, they just don't accumulate for late joiners,
209
+ matching the existing treatment of `browser:status`.
210
+
211
+ - [`a843130`](https://github.com/cesr/poncho-ai/commit/a8431303992381f338d6a90feeba03273734fd81) Thanks [@cesr](https://github.com/cesr)! - fix(web-ui): show assistant content alongside run errors
212
+
213
+ When a run ended with `run:error` (most visibly `MAX_STEPS_EXCEEDED`),
214
+ the web UI renderer replaced the entire assistant turn with just the
215
+ error banner. All the text and tool activity the agent had already
216
+ produced — which the server correctly persists — was hidden because
217
+ the render branch was `if (_error) { only error } else { content }`.
218
+
219
+ The renderer now renders the content first (sections, streaming tools
220
+ and text, pending approvals) and appends the error banner at the end.
221
+ The "waiting" spinner is also suppressed when an error is present.
222
+
223
+ - Updated dependencies [[`ef4fe5d`](https://github.com/cesr/poncho-ai/commit/ef4fe5d1fd4bb31c201fd240f4524b64f01e3e6d), [`fcf6a02`](https://github.com/cesr/poncho-ai/commit/fcf6a027880ac94ada2e3fd732b11eed9f5f15b8), [`1eb1b1e`](https://github.com/cesr/poncho-ai/commit/1eb1b1e71641f79aa089a967811dcfe2de59be8d), [`21ee02a`](https://github.com/cesr/poncho-ai/commit/21ee02a577cd0a85823cc3922dd0dc54c630f417), [`ef4fe5d`](https://github.com/cesr/poncho-ai/commit/ef4fe5d1fd4bb31c201fd240f4524b64f01e3e6d)]:
224
+ - @poncho-ai/sdk@1.9.0
225
+ - @poncho-ai/harness@0.39.0
226
+ - @poncho-ai/messaging@0.8.4
227
+
228
+ ## 0.37.0
229
+
230
+ ### Minor Changes
231
+
232
+ - [`620a0c8`](https://github.com/cesr/poncho-ai/commit/620a0c89efaafce28968fca5cbde2e2b19bd1595) Thanks [@cesr](https://github.com/cesr)! - feat: add recurrent reminders (daily, weekly, monthly, cron)
233
+
234
+ The `set_reminder` tool now accepts an optional `recurrence` parameter that makes reminders repeat on a schedule instead of firing once. Supports daily, weekly (with specific days-of-week), monthly, and cron expressions. Recurring reminders are rescheduled after each firing and can be bounded by `maxOccurrences` or `endsAt`. Cancel a recurring reminder to stop all future occurrences.
235
+
236
+ ### Patch Changes
237
+
238
+ - [`6486de2`](https://github.com/cesr/poncho-ai/commit/6486de2242a2976068e4bd09f7c0f2d978c35c96) Thanks [@cesr](https://github.com/cesr)! - fix: persist subagent `parentConversationId` atomically so children never appear top-level in the sidebar.
239
+
240
+ `SubagentManager.spawn` previously did a two-step write: `conversationStore.create(...)` followed by `conversationStore.update(...)` to attach `parentConversationId`, `subagentMeta`, and the initial user message. If the follow-up update was interrupted (serverless timeout, transient DB error), the child row was left in the database with `parent_conversation_id = NULL`, so it slipped past the `!c.parentConversationId` filter on `/api/conversations` and showed up as a top-level conversation. This was especially visible with cron-driven research subagents.
241
+
242
+ `ConversationStore.create` now accepts an optional `init` bag (`parentConversationId`, `subagentMeta`, `messages`, `channelMeta`) that is written in the single INSERT — both into the `data` blob and into the dedicated `parent_conversation_id` column. `spawn` passes those fields through and drops the redundant update, eliminating the orphan window. All existing `create(ownerId, title, tenantId)` callers keep working since `init` is optional.
243
+
244
+ - Updated dependencies [[`6486de2`](https://github.com/cesr/poncho-ai/commit/6486de2242a2976068e4bd09f7c0f2d978c35c96), [`0d0578f`](https://github.com/cesr/poncho-ai/commit/0d0578fbc97a3d2644c4e22cab14ff02a79f805f), [`620a0c8`](https://github.com/cesr/poncho-ai/commit/620a0c89efaafce28968fca5cbde2e2b19bd1595)]:
245
+ - @poncho-ai/harness@0.38.0
246
+
3
247
  ## 0.36.9
4
248
 
5
249
  ### Patch Changes