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