@poncho-ai/harness 0.38.0 → 0.39.1

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/harness@0.38.0 build /home/runner/work/poncho-ai/poncho-ai/packages/harness
2
+ > @poncho-ai/harness@0.39.1 build /home/runner/work/poncho-ai/poncho-ai/packages/harness
3
3
  > node scripts/embed-docs.js && tsup src/index.ts --format esm --dts
4
4
 
5
5
  [embed-docs] Generated poncho-docs.ts with 4 topics
@@ -8,9 +8,9 @@
8
8
  CLI tsup v8.5.1
9
9
  CLI Target: es2022
10
10
  ESM Build start
11
- ESM dist/index.js 402.58 KB
12
11
  ESM dist/isolate-TCWTUVG4.js 47.34 KB
13
- ESM ⚡️ Build success in 197ms
12
+ ESM dist/index.js 480.10 KB
13
+ ESM ⚡️ Build success in 223ms
14
14
  DTS Build start
15
- DTS ⚡️ Build success in 7534ms
16
- DTS dist/index.d.ts 58.26 KB
15
+ DTS ⚡️ Build success in 7012ms
16
+ DTS dist/index.d.ts 73.95 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,234 @@
1
1
  # @poncho-ai/harness
2
2
 
3
+ ## 0.39.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [`244a3a3`](https://github.com/cesr/poncho-ai/commit/244a3a310c6c52f9e8535b28fb25d77829583d3f) Thanks [@cesr](https://github.com/cesr)! - fix(harness): don't archive `browser_screenshot` / `browser_snapshot` payloads
8
+
9
+ The per-conversation `_toolResultArchive` had no size cap or eviction, and
10
+ browser tool results were being archived in full — base64 JPEG screenshots
11
+ (~50-500KB each) and accessibility-tree snapshots accumulated for the lifetime
12
+ of a conversation. Heavy browser sessions OOM'd `poncho dev` after ~80 minutes.
13
+
14
+ Skip archiving for view-once tool results (`browser_screenshot`,
15
+ `browser_snapshot`). The model consumes them in-step; they're never retrieved
16
+ after-the-fact, so archiving them only burns memory.
17
+
18
+ - [`d6248c8`](https://github.com/cesr/poncho-ai/commit/d6248c8b6d22e0fd0becde9e31dff7c12c724d84) Thanks [@cesr](https://github.com/cesr)! - fix(cli, harness): unify turn-parameter assembly so `conversation_recall` works everywhere
19
+
20
+ The recall tool relies on three context parameters (`__conversationRecallCorpus`,
21
+ `__conversationListFn`, `__conversationFetchFn`) that were only injected for
22
+ user-initiated HTTP turns. Cron, reminder, messaging-adapter, chat-continuation,
23
+ subagent-callback, and tool-approval-resume runs all built their own
24
+ `runInput.parameters` object and silently omitted these — causing
25
+ `conversation_recall` to throw "not available in this environment" or return
26
+ empty results depending on the call mode.
27
+
28
+ Introduces a single `buildTurnParameters(conversation, opts)` helper in the CLI
29
+ that owns context-parameter assembly (recall functions, `__activeConversationId`,
30
+ `__ownerId`, messaging metadata, tool-result archive). HTTP, messaging, and
31
+ cron/reminder paths now go through it. The harness orchestrator's three
32
+ internal turn sites (chat continuation, subagent-callback resume, tool-approval
33
+ resume) now call the existing `hooks.buildRecallParams` so they pick up the
34
+ recall functions too.
35
+
36
+ ## 0.39.0
37
+
38
+ ### Minor Changes
39
+
40
+ - [#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)
41
+
42
+ Move subagent orchestration (~1100 lines) from the CLI into the
43
+ AgentOrchestrator class in the harness package. The orchestrator now
44
+ owns all subagent state (activeSubagentRuns, pendingSubagentApprovals,
45
+ pendingCallbackNeeded), lifecycle methods (runSubagent,
46
+ processSubagentCallback, triggerParentCallback), SubagentManager
47
+ creation, approval handling, and stale recovery.
48
+
49
+ New hooks on OrchestratorHooks allow transport-specific concerns
50
+ (child harness creation, serverless dispatch, SSE stream lifecycle,
51
+ messaging notifications) to stay in the CLI while the orchestrator
52
+ handles all orchestration logic.
53
+
54
+ Also fixes subagent approval persistence (decisions now explicitly
55
+ written to the conversation store) and adds live SSE streaming for
56
+ parent callback runs in the web UI.
57
+
58
+ - [#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
59
+
60
+ Three related fixes that together dramatically reduce database and
61
+ server→browser egress for any long-lived conversation:
62
+ - `conversationStore.get()` no longer loads the `tool_result_archive`
63
+ column. Callers that actually need to reseed the harness archive —
64
+ run entry points, cron runs, reminder firings — must now use the new
65
+ `conversationStore.getWithArchive()` method instead.
66
+ - The `GET /api/conversations/:id` response strips `_toolResultArchive`
67
+ alongside the already-stripped `_continuationMessages` and
68
+ `_harnessMessages`, so the browser never receives the archive payload.
69
+ - Adds a cheap `GET /api/conversations/:id/status` endpoint backed by a
70
+ new `getStatusSnapshot()` method that reads only summary columns (no
71
+ `data` blob). The web UI poll loops now hit this endpoint every 2s
72
+ and only refetch the full conversation when `updatedAt`,
73
+ `messageCount`, or the pending-approval counts actually change.
74
+
75
+ The SQL upsert was also updated to preserve `tool_result_archive` via
76
+ `COALESCE(excluded, conversations.tool_result_archive)` so that updates
77
+ on conversations loaded via the light `get()` do not clobber the
78
+ existing archive.
79
+
80
+ - [#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
81
+
82
+ Users can now fork any persisted message into one or more threads. Each
83
+ thread is a new conversation whose initial history is a snapshot of the
84
+ parent up to and including the anchor message; replies in the thread
85
+ evolve independently of the parent. Multiple threads per parent message
86
+ are supported.
87
+
88
+ ## Web UI
89
+ - Hover any message in the main pane to reveal a "Reply in thread" pill
90
+ positioned just below the bubble (offset varies by role). The pill is
91
+ invisible by default and only appears on hover; a delayed-hide bridges
92
+ the empty space between message and pill so the user can move the
93
+ mouse onto it without it flickering off.
94
+ - Once a thread exists on a message, the pill is replaced by an
95
+ always-visible badge (`"N replies · 5m ago"`, count bold + meta muted).
96
+ Multiple threads stack vertically under the message, each with its own
97
+ badge. Hovering a badge reveals an outside-positioned `×` delete with
98
+ the same two-step "× → sure?" confirmation as the sidebar
99
+ conversation-delete.
100
+ - Clicking a badge opens the thread in a right-side panel that mirrors
101
+ the existing browser-panel pattern: a flex sibling of `.main-chat`
102
+ with a 1px drag-resize handle. The panel has its own composer
103
+ (independent file uploads, paste-to-attach, attachment preview)
104
+ rendered alongside the main composer so users can keep typing in the
105
+ parent conversation. Vertical padding matches the main composer so
106
+ both chatboxes line up at the same baseline.
107
+ - The pinned parent message and replies inside the panel render through
108
+ the same DOM construction logic as the main pane (assistant avatar +
109
+ markdown, user bubble + file thumbnails). Reply submissions stream
110
+ token-by-token via SSE (parsed model:chunk events feed an optimistic
111
+ assistant placeholder; a thinking-indicator shows until the first
112
+ chunk lands).
113
+ - The open thread is reflected in the URL hash (`#thread=<id>`) so a
114
+ page reload restores the panel. Switching conversations or closing
115
+ the panel clears the hash and any sticky drag-resize widths.
116
+
117
+ ## DB
118
+ - New `parent_message_id TEXT` column on `conversations` (migration 6)
119
+ plus a partial index on `(parent_conversation_id, parent_message_id)
120
+ WHERE parent_message_id IS NOT NULL`.
121
+ - The existing `parent_conversation_id` plumbing is reused; subagents
122
+ and threads coexist on that column, discriminated by whether
123
+ `parent_message_id` is set (subagents leave it `NULL`).
124
+ - `threadMeta` (snapshot length + cached parent-message summary)
125
+ round-trips inside the conversation `data` blob.
126
+
127
+ ## API
128
+ - `GET /api/conversations/:id/threads` → `{ threads: ApiThreadSummary[] }`
129
+ - `POST /api/conversations/:id/threads { parentMessageId, title? }` →
130
+ 201 `{ thread, conversationId }` |
131
+ 404 `PARENT_MESSAGE_NOT_FOUND` |
132
+ 409 `MESSAGE_ID_REQUIRED` (anchor lacks a stable id) |
133
+ 409 `ANCHOR_IN_FLIGHT` (anchor is the streaming tail of a live run)
134
+ - The two `SUBAGENT_READ_ONLY` gates on `/messages` and `/continue` are
135
+ now keyed on `subagentMeta` rather than `parentConversationId` so
136
+ threads remain writable.
137
+ - New `ApiThreadSummary`, `ApiThreadListResponse`,
138
+ `ApiCreateThreadRequest`, `ApiCreateThreadResponse` types in
139
+ `@poncho-ai/sdk`. New `AgentClient.listThreads` /
140
+ `AgentClient.createThread` wrappers in `@poncho-ai/client`.
141
+
142
+ ## Storage interface
143
+ - `ConversationStore.listThreads(parentConversationId)` and the
144
+ matching `StorageEngine.conversations.listThreads(...)`. External
145
+ implementers of these interfaces will need to add the method.
146
+ - `Conversation` / `ConversationCreateInit` / `ConversationSummary`
147
+ gained optional `parentMessageId` and `threadMeta` fields.
148
+
149
+ ## Fork semantics
150
+ - Stable `metadata.id` on every persisted message: `randomUUID()` is
151
+ hoisted once per turn and reused for both the user message and the
152
+ in-flight assistant message across all persist sites (cli messaging
153
+ run, cli `/messages` handler, cron path). `buildAssistantMetadata`
154
+ takes an optional `{ id, timestamp }` opt-arg.
155
+ - No DB backfill of legacy id-less messages; the SPA hides the
156
+ "Reply in thread" affordance on rows whose `metadata.id` is missing.
157
+ - The visible-sequence used for the anchor lookup is reconstructed as
158
+ `[...compactedHistory, ...messages.filter(notCompactionSummary)]`,
159
+ so pre-compaction anchors are supported. For pre-compaction anchors,
160
+ `_harnessMessages` is reset to `undefined` so the harness rebuilds
161
+ canonical history from `messages` on the thread's first run.
162
+ - Forking on the actively-streaming tail message of a live run returns
163
+ 409 `ANCHOR_IN_FLIGHT`; any prior, already-persisted message is
164
+ fork-able even while the parent is mid-run.
165
+ - Tool-result archive entries are filtered to only those referenced by
166
+ tool calls in the trimmed `_harnessMessages` (no whole-archive clones).
167
+ - All run-specific state is reset on the new thread:
168
+ `runtimeRunId`, `pendingApprovals`, `runStatus`,
169
+ `pendingSubagentResults`, `subagentCallbackCount`,
170
+ `runningCallbackSince`, `_continuationMessages`. `channelMeta` and
171
+ `subagentMeta` are explicitly NOT inherited so threads aren't bound
172
+ to the parent's Slack/Telegram thread and aren't subagent runs.
173
+ - Thread conversations stay out of the sidebar list (already-existing
174
+ `!c.parentConversationId` filter) and are cascade-deleted with their
175
+ parent.
176
+
177
+ ### Patch Changes
178
+
179
+ - [#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
180
+
181
+ `poncho dev` output is now formatted consistently across the CLI and
182
+ harness:
183
+
184
+ ```
185
+ 20:23:45 ✓ poncho dev server ready at http://localhost:3000
186
+ 20:23:45 • slack enabled at /api/messaging/slack
187
+ 20:23:45 • cron scheduled 2 jobs: hourly_check, nightly_summary
188
+ 20:24:15 → cron:hourly_check started
189
+ 20:24:17 ✓ cron:hourly_check completed in 1.2s (3 chats)
190
+ 20:25:00 ⚠ telegram approval not found: req-7f42a
191
+ 20:25:01 ✗ poncho internal error: ECONNREFUSED
192
+ ```
193
+
194
+ Format: `HH:mm:ss <symbol> <scope> <message>`. Scopes (`poncho`, `cron`,
195
+ `reminder`, `messaging`, `slack`, `telegram`, `resend`, `subagent`,
196
+ `approval`, `browser`, `csrf`, `upload`, `serverless`, `self-fetch`,
197
+ `mcp`, `telemetry`, `cost`, `model`, `harness`, `event`, `tools`)
198
+ replace the previous mix of `[poncho]`, `[poncho][cost]`, `[cron]`,
199
+ `[messaging-runner]`, `[event] ...`, etc.
200
+ - New `createLogger(scope)` exported from `@poncho-ai/sdk` with
201
+ `.debug/.info/.warn/.error/.success/.ready/.item/.child(sub)` and
202
+ helpers `formatError`, `url`, `muted`, `num`.
203
+ - Honors `NO_COLOR` / `FORCE_COLOR` and `LOG_LEVEL=debug|info|warn|error|silent`.
204
+ Verbose telemetry/cost/event lines now log at `debug` and are silent
205
+ by default.
206
+ - `poncho dev` gains `-v`/`--verbose` (debug), `-q`/`--quiet` (warn+),
207
+ and `--log-level <level>` flags.
208
+ - Each scope tag is colored with a stable pastel hue (truecolor), with
209
+ 256-color and 16-color fallbacks. Children (`cron:hourly_check`)
210
+ inherit their parent's color.
211
+ - TTY-aware: ANSI color is stripped when stdout is piped.
212
+ - Conversation-egress logging (`[poncho][egress] read: …`) is now opt-in
213
+ via `PONCHO_LOG_EGRESS=1` (matching the documented behavior; it had
214
+ been logging unconditionally).
215
+ - No behavior changes to which events are emitted — only formatting.
216
+
217
+ - [`fcf6a02`](https://github.com/cesr/poncho-ai/commit/fcf6a027880ac94ada2e3fd732b11eed9f5f15b8) Thanks [@cesr](https://github.com/cesr)! - chore: drop browser-frame noise from the dev log
218
+
219
+ Two sources of per-frame log noise during interactive browser use
220
+ are now silenced:
221
+ - `TelemetryEmitter.emit` skips `browser:frame` events alongside the
222
+ already-skipped `model:chunk`. OTLP forwarding and custom handlers
223
+ still receive every event unchanged.
224
+ - The CLI's browser SSE endpoint no longer prints the
225
+ `[poncho][browser-sse] Frame N: WxH, data bytes: ...` counter
226
+ (which fired for the first 3 frames and every 50th). Related
227
+ `frameCount` / `droppedFrames` state dropped with it.
228
+
229
+ - Updated dependencies [[`ef4fe5d`](https://github.com/cesr/poncho-ai/commit/ef4fe5d1fd4bb31c201fd240f4524b64f01e3e6d), [`ef4fe5d`](https://github.com/cesr/poncho-ai/commit/ef4fe5d1fd4bb31c201fd240f4524b64f01e3e6d)]:
230
+ - @poncho-ai/sdk@1.9.0
231
+
3
232
  ## 0.38.0
4
233
 
5
234
  ### Minor Changes