@poncho-ai/harness 0.59.1 → 0.59.3
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 +28 -0
- package/dist/index.d.ts +39 -118
- package/dist/index.js +37 -327
- package/package.json +1 -1
- package/src/index.ts +3 -11
- package/src/orchestrator/entries-dual-write.ts +20 -209
- package/src/orchestrator/index.ts +1 -6
- package/src/orchestrator/orchestrator.ts +22 -115
- package/src/orchestrator/run-conversation-turn.ts +0 -108
- package/src/state.ts +3 -1
- package/src/storage/entries.ts +47 -182
- package/src/storage/memory-engine.ts +2 -2
- package/src/storage/sql-dialect.ts +27 -7
- package/test/entries-dual-write.test.ts +21 -144
- package/test/entries-store.test.ts +43 -53
- package/test/entries.test.ts +37 -105
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @poncho-ai/harness@0.59.
|
|
2
|
+
> @poncho-ai/harness@0.59.3 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[32m556.92 KB[39m
|
|
11
12
|
[32mESM[39m [1mdist/isolate-F2PPSUL6.js [22m[32m53.82 KB[39m
|
|
12
|
-
[32mESM[39m
|
|
13
|
-
[32mESM[39m ⚡️ Build success in 233ms
|
|
13
|
+
[32mESM[39m ⚡️ Build success in 268ms
|
|
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 8081ms
|
|
16
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m101.11 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# @poncho-ai/harness
|
|
2
2
|
|
|
3
|
+
## 0.59.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`c9f7331`](https://github.com/cesr/poncho-ai/commit/c9f733190103bcb1ec1b0173c6760a8ef4bea2f3) Thanks [@cesr](https://github.com/cesr)! - Reframe `conversation_entries` as the subagent delivery queue and delete the
|
|
8
|
+
abandoned transcript dual-write. The entry log now carries exactly two types
|
|
9
|
+
— `subagent_result` (race-free delivery of a finished subagent's result) and
|
|
10
|
+
`callback_started` (consumption marker) — which is the one conversation
|
|
11
|
+
field with concurrent writers. The unread transcript entry types
|
|
12
|
+
(user/assistant/harness messages, compaction overlays), their dual-write
|
|
13
|
+
call sites, and the parity checker were groundwork for a full blob
|
|
14
|
+
replacement that was deliberately abandoned after the 0.58.0 cutover
|
|
15
|
+
incident; they were already unfaithful for callback turns and are deleted
|
|
16
|
+
rather than maintained as drift-prone dead weight. Read paths now filter the
|
|
17
|
+
queue types explicitly, so legacy transcript rows are ignored. Also fixes
|
|
18
|
+
`conversations.rename` to update the title inside the `data` blob (via an
|
|
19
|
+
atomic in-database JSON set) — the 0.59.2 column-only update didn't surface
|
|
20
|
+
on reads, which parse the blob.
|
|
21
|
+
|
|
22
|
+
## 0.59.2
|
|
23
|
+
|
|
24
|
+
### Patch Changes
|
|
25
|
+
|
|
26
|
+
- [`ac0faae`](https://github.com/cesr/poncho-ai/commit/ac0faae54365afda5ef518b0a306a8cde5978ca8) Thanks [@cesr](https://github.com/cesr)! - conversations.rename now does a targeted title-column UPDATE instead of a
|
|
27
|
+
whole-row get→mutate→update. The read-modify-write raced a streaming turn's
|
|
28
|
+
per-step draft persist: a rename landing mid-run wrote the stale blob back
|
|
29
|
+
and silently reverted the turn's persisted progress.
|
|
30
|
+
|
|
3
31
|
## 0.59.1
|
|
4
32
|
|
|
5
33
|
### Patch Changes
|
package/dist/index.d.ts
CHANGED
|
@@ -127,24 +127,39 @@ interface CompactResult {
|
|
|
127
127
|
declare const compactMessages: (model: LanguageModel, messages: Message[], config: CompactionConfig, options?: CompactMessagesOptions) => Promise<CompactResult>;
|
|
128
128
|
|
|
129
129
|
/**
|
|
130
|
-
*
|
|
130
|
+
* The subagent delivery queue: append-only `conversation_entries` rows that
|
|
131
|
+
* carry a finished subagent's result to its parent conversation.
|
|
131
132
|
*
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
*
|
|
135
|
-
*
|
|
136
|
-
*
|
|
133
|
+
* Why this exists: subagent results are the ONE conversation field with
|
|
134
|
+
* concurrent writers. A subagent finishes whenever it finishes — possibly
|
|
135
|
+
* while the parent turn is mid-stream doing whole-blob writes — so a
|
|
136
|
+
* read-modify-write on the mutable conversation row could serialize a stale
|
|
137
|
+
* snapshot over the result (the historical "lost subagent result" clobber).
|
|
138
|
+
* An append-only INSERT can't express that race. Everything single-writer
|
|
139
|
+
* (message history, metadata) stays on the conversation row, where the
|
|
140
|
+
* orchestrator's per-conversation turn serialization already makes mutation
|
|
141
|
+
* safe.
|
|
137
142
|
*
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
*
|
|
141
|
-
*
|
|
142
|
-
*
|
|
143
|
-
*
|
|
144
|
-
* once this rebuild logic is proven.
|
|
143
|
+
* Two entry types:
|
|
144
|
+
* - `subagent_result`: a finished subagent's result, appended by the
|
|
145
|
+
* orchestrator's result-delivery path.
|
|
146
|
+
* - `callback_started`: marks which result entries a callback turn
|
|
147
|
+
* consumed (by seq). Consumption is an append, never a delete — a
|
|
148
|
+
* result is "pending" until a later callback_started lists its seq.
|
|
145
149
|
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
150
|
+
* Historical note: this module once defined a full transcript's worth of
|
|
151
|
+
* entry types (user/assistant/harness messages, compaction overlays) as
|
|
152
|
+
* groundwork for replacing the conversation blob entirely. The full read
|
|
153
|
+
* cutover shipped briefly (harness 0.58.0), proved unfaithful for callback
|
|
154
|
+
* turns, and was reverted; the unread types + dual-writes were then deleted
|
|
155
|
+
* rather than maintained as drift-prone dead weight. If a future feature
|
|
156
|
+
* needs real history semantics (editing, branching, audit), design that
|
|
157
|
+
* migration fresh — and remember the 0.58.0 lesson: an append-only log is
|
|
158
|
+
* only as good as the completeness of its writers.
|
|
159
|
+
*
|
|
160
|
+
* Ordering: every entry carries a monotonic per-conversation `seq`,
|
|
161
|
+
* assigned by the engine at append time. Entries are sorted by `seq`
|
|
162
|
+
* ascending when passed to the rebuild fn.
|
|
148
163
|
*/
|
|
149
164
|
interface BaseEntry {
|
|
150
165
|
/** Stable cross-reference id (uuid). */
|
|
@@ -153,48 +168,6 @@ interface BaseEntry {
|
|
|
153
168
|
seq: number;
|
|
154
169
|
createdAt: number;
|
|
155
170
|
}
|
|
156
|
-
/** A user-role display message (incl. typed subagent-callback messages). */
|
|
157
|
-
interface UserMessageEntry extends BaseEntry {
|
|
158
|
-
type: "user_message";
|
|
159
|
-
message: Message;
|
|
160
|
-
turnId: string;
|
|
161
|
-
/** Hidden from the display transcript (e.g. a framed job prompt, an
|
|
162
|
-
* onboarding seed, or an injected subagent-result message). Still part
|
|
163
|
-
* of the record; just not rendered as a chat bubble. */
|
|
164
|
-
hidden?: boolean;
|
|
165
|
-
}
|
|
166
|
-
/** The final assistant bubble for a completed/cancelled/errored turn. */
|
|
167
|
-
interface AssistantMessageEntry extends BaseEntry {
|
|
168
|
-
type: "assistant_message";
|
|
169
|
-
message: Message;
|
|
170
|
-
turnId: string;
|
|
171
|
-
runId: string;
|
|
172
|
-
}
|
|
173
|
-
/** A post-hoc edit to an already-emitted assistant message — replaces the
|
|
174
|
-
* orchestrator/resume "mutate the last assistant message in place" writes
|
|
175
|
-
* with an append. Applied at rebuild time. */
|
|
176
|
-
interface AssistantAmendmentEntry extends BaseEntry {
|
|
177
|
-
type: "assistant_amendment";
|
|
178
|
-
targetEntryId: string;
|
|
179
|
-
appendText?: string;
|
|
180
|
-
}
|
|
181
|
-
/** One LLM-transcript message (the model-visible form). Appended from the
|
|
182
|
-
* run loop per step — never diffed from an array. */
|
|
183
|
-
interface HarnessMessageEntry extends BaseEntry {
|
|
184
|
-
type: "harness_message";
|
|
185
|
-
message: Message;
|
|
186
|
-
turnId: string;
|
|
187
|
-
}
|
|
188
|
-
/** Compaction overlay: nothing is deleted. At rebuild, the LLM context is
|
|
189
|
-
* the latest compaction's `summaryMessage` followed by the harness
|
|
190
|
-
* messages from `firstKeptSeq` onward. */
|
|
191
|
-
interface CompactionEntry extends BaseEntry {
|
|
192
|
-
type: "compaction";
|
|
193
|
-
summaryMessage: Message;
|
|
194
|
-
firstKeptSeq: number;
|
|
195
|
-
tokensBefore?: number;
|
|
196
|
-
tokensAfter?: number;
|
|
197
|
-
}
|
|
198
171
|
/** A finished subagent's result arriving for the parent. Pending = a
|
|
199
172
|
* subagent_result whose seq is not listed in any later callback_started. */
|
|
200
173
|
interface SubagentResultEntry extends BaseEntry {
|
|
@@ -207,38 +180,15 @@ interface CallbackStartedEntry extends BaseEntry {
|
|
|
207
180
|
type: "callback_started";
|
|
208
181
|
consumedSeqs: number[];
|
|
209
182
|
}
|
|
210
|
-
type ConversationEntry =
|
|
183
|
+
type ConversationEntry = SubagentResultEntry | CallbackStartedEntry;
|
|
211
184
|
/**
|
|
212
185
|
* An entry to append, before the engine assigns `seq` and `createdAt`. This
|
|
213
186
|
* is a DISTRIBUTIVE omit — `Omit<ConversationEntry, K>` over a union would
|
|
214
|
-
* collapse to only the keys common to every member
|
|
215
|
-
*
|
|
216
|
-
*
|
|
187
|
+
* collapse to only the keys common to every member, so we distribute over
|
|
188
|
+
* the union with a conditional type to omit those fields from each member
|
|
189
|
+
* individually.
|
|
217
190
|
*/
|
|
218
191
|
type NewConversationEntry = ConversationEntry extends infer T ? T extends ConversationEntry ? Omit<T, "seq" | "createdAt"> : never : never;
|
|
219
|
-
/**
|
|
220
|
-
* Rebuild the LLM-visible message context from the entry log.
|
|
221
|
-
*
|
|
222
|
-
* If a compaction overlay exists, the context is its summary message
|
|
223
|
-
* followed by every harness message with seq >= firstKeptSeq (a later
|
|
224
|
-
* compaction's firstKeptSeq can point at an earlier summary that was
|
|
225
|
-
* itself appended as a harness message, so layered compactions just work).
|
|
226
|
-
* With no compaction, it's every harness message in order.
|
|
227
|
-
*/
|
|
228
|
-
declare function buildLlmContext(entries: ConversationEntry[]): Message[];
|
|
229
|
-
interface DisplaySnapshot {
|
|
230
|
-
messages: Message[];
|
|
231
|
-
/** Total display messages available (for pagination UIs). */
|
|
232
|
-
totalMessages: number;
|
|
233
|
-
/** seq of the first message returned (a `beforeSeq` pagination cursor). */
|
|
234
|
-
headSeq: number | null;
|
|
235
|
-
}
|
|
236
|
-
/**
|
|
237
|
-
* Rebuild the display transcript (the user-visible chat) from the entry
|
|
238
|
-
* log, returning the trailing `tailN` messages. Amendments are folded into
|
|
239
|
-
* their target assistant message; hidden user messages are dropped.
|
|
240
|
-
*/
|
|
241
|
-
declare function buildDisplaySnapshot(entries: ConversationEntry[], tailN: number): DisplaySnapshot;
|
|
242
192
|
/**
|
|
243
193
|
* Subagent results that have arrived but not yet been consumed by a
|
|
244
194
|
* callback turn — the append-only replacement for the mutable
|
|
@@ -2403,45 +2353,16 @@ interface RunConversationTurnResult {
|
|
|
2403
2353
|
}
|
|
2404
2354
|
declare const runConversationTurn: (opts: RunConversationTurnOpts) => Promise<RunConversationTurnResult>;
|
|
2405
2355
|
|
|
2406
|
-
/** True when dual-write parity verification is opted in via env. */
|
|
2407
|
-
declare const entriesParityEnabled: () => boolean;
|
|
2408
2356
|
type NewEntryNoId = NewConversationEntry extends infer T ? T extends NewConversationEntry ? Omit<T, "id"> : never : never;
|
|
2409
2357
|
/**
|
|
2410
|
-
* Append entries to the conversation's
|
|
2411
|
-
* blob write. Best-effort and non-blocking by contract:
|
|
2358
|
+
* Append entries to the conversation's queue. Best-effort by contract:
|
|
2412
2359
|
* - stamps a fresh uuid `id` on each entry (required input column),
|
|
2413
2360
|
* - never throws (logs and returns [] on failure),
|
|
2414
|
-
* -
|
|
2361
|
+
* - safe to `void` when the caller doesn't need the stored rows.
|
|
2415
2362
|
*
|
|
2416
|
-
* Returns the stored entries (with seq/createdAt)
|
|
2417
|
-
*
|
|
2418
|
-
* empty input / failure.
|
|
2363
|
+
* Returns the stored entries (with seq/createdAt) — the callback path needs
|
|
2364
|
+
* the seqs to record consumption.
|
|
2419
2365
|
*/
|
|
2420
2366
|
declare const appendEntriesSafe: (store: ConversationStore, conversation: Pick<Conversation, "conversationId" | "ownerId" | "tenantId">, entries: NewEntryNoId[], log: Logger) => Promise<ConversationEntry[]>;
|
|
2421
|
-
/**
|
|
2422
|
-
* The harness messages added during the just-finished turn — i.e. the suffix
|
|
2423
|
-
* of the new `_harnessMessages` array beyond what was there before the turn.
|
|
2424
|
-
*
|
|
2425
|
-
* BEST-EFFORT: the blob replaces `_harnessMessages` wholesale (it's not an
|
|
2426
|
-
* append log), so we recover "what's new" by length-diffing prev vs next.
|
|
2427
|
-
* When a compaction collapsed history this turn, `next` can be SHORTER than
|
|
2428
|
-
* `prev`; in that case there's no clean suffix and we return the whole `next`
|
|
2429
|
-
* so the entry log still ends up with the model-visible context (parity will
|
|
2430
|
-
* flag the over-count for review). The compaction entry (appended separately)
|
|
2431
|
-
* is what makes rebuild correct in that case.
|
|
2432
|
-
*/
|
|
2433
|
-
declare const newHarnessMessagesThisTurn: (prev: Message[] | undefined, next: Message[] | undefined) => {
|
|
2434
|
-
messages: Message[];
|
|
2435
|
-
approximate: boolean;
|
|
2436
|
-
};
|
|
2437
|
-
/**
|
|
2438
|
-
* Rebuild LLM context + display snapshot from the entry log and diff against
|
|
2439
|
-
* the blob. Logs under `[entries-parity]` with the conversationId. Never
|
|
2440
|
-
* throws. No-op unless PONCHO_VERIFY_ENTRIES === "1".
|
|
2441
|
-
*/
|
|
2442
|
-
declare const verifyEntriesParity: (store: ConversationStore, conversationId: string, blob: {
|
|
2443
|
-
harnessMessages?: Message[];
|
|
2444
|
-
displayMessages?: Message[];
|
|
2445
|
-
}, log: Logger) => Promise<void>;
|
|
2446
2367
|
|
|
2447
|
-
export { type ActiveConversationRun, type ActiveSubagentRun, type AgentFrontmatter, AgentHarness, type AgentIdentity, type AgentLimitsConfig, type AgentModelConfig, AgentOrchestrator, type ApprovalEventItem, type ArchivedToolResult$1 as ArchivedToolResult, type
|
|
2368
|
+
export { type ActiveConversationRun, type ActiveSubagentRun, type AgentFrontmatter, AgentHarness, type AgentIdentity, type AgentLimitsConfig, type AgentModelConfig, AgentOrchestrator, type ApprovalEventItem, type ArchivedToolResult$1 as ArchivedToolResult, type BashConfig, BashEnvironmentManager, type BashExecutionLimits, type BuiltInToolToggles, CALLBACK_LOCK_STALE_MS, type CallbackStartedEntry, type CompactMessagesOptions, type CompactResult, type CompactionConfig, type ContinuationHooks, type Conversation, type ConversationCreateInit, type ConversationEntry, type ConversationState, type ConversationStatusSnapshot, type ConversationStore, type ConversationSummary, type CreateSkillToolsOptions, type CronJobConfig, DEFAULT_AGENT_DESCRIPTION, DEFAULT_AGENT_NAME, DEFAULT_MAX_STEPS, DEFAULT_MODEL_NAME, DEFAULT_MODEL_PROVIDER, DEFAULT_TEMPERATURE, DEFAULT_TIMEOUT, type DefaultAgentDefinitionOptions, type EventSink, type ExecuteTurnResult, type HarnessOptions, type HarnessRunOutput, type HistorySource, InMemoryConversationStore, InMemoryEngine, InMemoryStateStore, type IsolateBinding, type IsolateConfig, LocalMcpBridge, LocalUploadStore, MAX_CONCURRENT_SUBAGENTS, MAX_CONTINUATION_COUNT, MAX_SUBAGENT_CALLBACK_COUNT, MAX_SUBAGENT_NESTING, type MainMemory, type McpConfig, type MemoryConfig, type MemoryStore, type MessagingChannelConfig, type ModelProviderFactory, type MountProvider, type NetworkConfig, type NewConversationEntry, OPENAI_CODEX_CLIENT_ID, type OpenAICodexAuthConfig, type OpenAICodexDeviceAuthRequest, type OpenAICodexSession, type OrchestratorHooks, type OrchestratorOptions, type OtlpConfig, type OtlpOption, PONCHO_UPLOAD_SCHEME, type ParsedAgent, type PendingSubagentApproval, type PendingSubagentResult, type PendingToolCall, type PonchoConfig, PonchoFsAdapter, PostgresEngine, type ProviderConfig, type Recurrence, type RecurrenceType, type Reminder, type ReminderCreateInput, type ReminderStatus, type ReminderStore, type RemoteMcpServerConfig, type RunConversationTurnOpts, type RunConversationTurnResult, type RunOutcome, type RunRequest, type RuntimeRenderContext, S3UploadStore, STALE_SUBAGENT_THRESHOLD_MS, STORAGE_SCHEMA_VERSION, type SecretsStore, type SkillContextEntry, type SkillMetadata, type SkillSource, SqliteEngine, type StateConfig, type StateProviderName, type StateStore, type StorageConfig, type StorageEngine, type StorageFactoryOptions, type StorageProvider, type StoredApproval, type SubagentManager, type SubagentResult, type SubagentResultEntry, type SubagentSpawnResult, type SubagentSummary, type SubagentTranscript, type SubagentTranscriptMode, TOOL_RESULT_ARCHIVE_PARAM, type TelemetryConfig, TelemetryEmitter, type TenantTokenPayload, type ToolAccess, type ToolCall, ToolDispatcher, type ToolExecutionResult, type TurnDraftState, type TurnResultMetadata, type TurnSection, type UploadStore, type UploadsConfig, VFS_SCHEME, VercelBlobUploadStore, type VfsDirEntry, type VfsStat, type VirtualMount, abnormalEndResponse, appendEntriesSafe, applyTurnMetadata, buildAgentDirectoryName, buildApprovalCheckpoints, buildAssistantMetadata, buildSkillContextWindow, buildToolCompletedText, cloneSections, compactMessages, completeOpenAICodexDeviceAuth, computeNextOccurrence, createBashTool, createConversationStore, createConversationStoreFromEngine, createDefaultTools, createDeleteDirectoryTool, createDeleteTool, createEditTool, createMemoryStore, createMemoryStoreFromEngine, createMemoryTools, createModelProvider, createReminderStore, createReminderStoreFromEngine, createReminderTools, createSearchTools, createSecretsStore, createSkillTools, createStateStore, createStorageEngine, createSubagentTools, createTodoStoreFromEngine, createTurnDraftState, createUploadStore, createWriteTool, decodeFileInputData, defaultAgentDefinition, deleteOpenAICodexSession, deriveUploadKey, ensureAgentIdentity, estimateTokens, estimateTotalTokens, executeConversationTurn, findSafeSplitPoint, flushTurnDraft, generateAgentId, getAgentStoreDirectory, getModelContextWindow, getOpenAICodexAccessToken, getOpenAICodexAuthFilePath, getOpenAICodexRequiredScopes, getPendingSubagentResults, getPonchoStoreRoot, isMessageArray, jsonSchemaToZod, lastAssistantText, loadCanonicalHistory, loadPonchoConfig, loadRunHistory, loadSkillContext, loadSkillInstructions, loadSkillMetadata, loadSkillMetadataFromDirs, loadVfsSkillMetadata, mergeSkills, normalizeApprovalCheckpoint, normalizeOtlp, normalizeScriptPolicyPath, normalizeToolAccess, parseAgentFile, parseAgentMarkdown, parseSkillFrontmatter, ponchoDocsTool, readOpenAICodexSession, readSkillResource, realResponseText, recordStandardTurnEvent, renderAgentPrompt, resolveAgentIdentity, resolveCompactionConfig, resolveEnv, resolveMemoryConfig, resolveRunRequest, resolveSkillDirs, resolveStateConfig, runConversationTurn, slugifyStorageComponent, startOpenAICodexDeviceAuth, verifyTenantToken, withToolResultArchiveParam, writeOpenAICodexSession };
|