@poncho-ai/harness 0.59.5 → 0.59.6
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 +4 -4
- package/CHANGELOG.md +15 -0
- package/dist/index.js +18 -1
- package/package.json +1 -1
- package/src/orchestrator/run-conversation-turn.ts +33 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @poncho-ai/harness@0.59.
|
|
2
|
+
> @poncho-ai/harness@0.59.6 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[32m557.00 KB[39m
|
|
12
11
|
[32mESM[39m [1mdist/isolate-F2PPSUL6.js [22m[32m53.82 KB[39m
|
|
13
|
-
[32mESM[39m
|
|
12
|
+
[32mESM[39m [1mdist/index.js [22m[32m557.73 KB[39m
|
|
13
|
+
[32mESM[39m ⚡️ Build success in 256ms
|
|
14
14
|
[34mDTS[39m Build start
|
|
15
|
-
[32mDTS[39m ⚡️ Build success in
|
|
15
|
+
[32mDTS[39m ⚡️ Build success in 8276ms
|
|
16
16
|
[32mDTS[39m [1mdist/index.d.ts [22m[32m101.66 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# @poncho-ai/harness
|
|
2
2
|
|
|
3
|
+
## 0.59.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [`e573f72`](https://github.com/cesr/poncho-ai/commit/e573f72ca31627e48dbdbf296946a72c59a488db) Thanks [@cesr](https://github.com/cesr)! - Preserve the LLM transcript when a turn dies. The errored branch of
|
|
8
|
+
runConversationTurn persisted only the display draft — `_harnessMessages`
|
|
9
|
+
was never updated, so the model's next turn had no memory of the entire
|
|
10
|
+
failed interaction (its user message included), even though the user could
|
|
11
|
+
see it on screen. Both the errored branch and the cancelled-without-
|
|
12
|
+
`run:cancelled.messages` fallback now append a faithful plain-text
|
|
13
|
+
reconstruction (user message + assistant text-so-far + tool activity + an
|
|
14
|
+
interruption note) to the transcript. Plain text on purpose: replaying real
|
|
15
|
+
tool_use blocks would need paired results or the next API call rejects the
|
|
16
|
+
dangling pair.
|
|
17
|
+
|
|
3
18
|
## 0.59.5
|
|
4
19
|
|
|
5
20
|
### Patch Changes
|
package/dist/index.js
CHANGED
|
@@ -14498,6 +14498,20 @@ var runConversationTurn = async (opts) => {
|
|
|
14498
14498
|
};
|
|
14499
14499
|
} catch (error) {
|
|
14500
14500
|
flushTurnDraft(draft);
|
|
14501
|
+
const reconstructTranscriptTail = (reason) => {
|
|
14502
|
+
const parts = [];
|
|
14503
|
+
if (draft.assistantResponse.length > 0) parts.push(draft.assistantResponse);
|
|
14504
|
+
if (draft.toolTimeline.length > 0) {
|
|
14505
|
+
parts.push(`Tool activity before interruption:
|
|
14506
|
+
${draft.toolTimeline.join("\n")}`);
|
|
14507
|
+
}
|
|
14508
|
+
parts.push(`[This turn was interrupted: ${reason}. The work above may be incomplete.]`);
|
|
14509
|
+
return [
|
|
14510
|
+
...conversation._harnessMessages ?? [],
|
|
14511
|
+
userMessage,
|
|
14512
|
+
{ role: "assistant", content: parts.join("\n\n") }
|
|
14513
|
+
];
|
|
14514
|
+
};
|
|
14501
14515
|
const aborted = opts.abortSignal?.aborted === true;
|
|
14502
14516
|
if (aborted || runCancelled) {
|
|
14503
14517
|
if (draft.assistantResponse.length > 0 || draft.toolTimeline.length > 0 || draft.sections.length > 0) {
|
|
@@ -14508,7 +14522,7 @@ var runConversationTurn = async (opts) => {
|
|
|
14508
14522
|
latestRunId,
|
|
14509
14523
|
contextTokens: 0,
|
|
14510
14524
|
contextWindow: 0,
|
|
14511
|
-
harnessMessages: cancelHarnessMessages,
|
|
14525
|
+
harnessMessages: cancelHarnessMessages ?? reconstructTranscriptTail("cancelled"),
|
|
14512
14526
|
toolResultArchive: opts.harness.getToolResultArchive(opts.conversationId)
|
|
14513
14527
|
},
|
|
14514
14528
|
{ shouldRebuildCanonical: true }
|
|
@@ -14551,6 +14565,9 @@ var runConversationTurn = async (opts) => {
|
|
|
14551
14565
|
}
|
|
14552
14566
|
if (draft.assistantResponse.length > 0 || draft.toolTimeline.length > 0 || draft.sections.length > 0) {
|
|
14553
14567
|
conversation.messages = buildMessages(false);
|
|
14568
|
+
conversation._harnessMessages = reconstructTranscriptTail(
|
|
14569
|
+
error instanceof Error ? `error \u2014 ${error.message}` : "error"
|
|
14570
|
+
);
|
|
14554
14571
|
conversation.updatedAt = Date.now();
|
|
14555
14572
|
await opts.conversationStore.update(conversation);
|
|
14556
14573
|
}
|
package/package.json
CHANGED
|
@@ -420,6 +420,31 @@ export const runConversationTurn = async (
|
|
|
420
420
|
};
|
|
421
421
|
} catch (error) {
|
|
422
422
|
flushTurnDraft(draft);
|
|
423
|
+
|
|
424
|
+
// The LLM transcript (`_harnessMessages`) is normally only written at a
|
|
425
|
+
// clean finalize / a cancel that delivered `run:cancelled.messages`. A
|
|
426
|
+
// turn that dies any other way (in-process error, abort that never
|
|
427
|
+
// surfaced the cancel event) would leave the transcript WITHOUT this
|
|
428
|
+
// turn at all — the display shows the partial work but the model has
|
|
429
|
+
// amnesia about the whole interaction on the next turn. Reconstruct a
|
|
430
|
+
// faithful plain-text record from the draft instead: the user message
|
|
431
|
+
// plus an assistant message carrying the text-so-far + tool activity.
|
|
432
|
+
// Plain text on purpose — replaying real tool_use blocks would need
|
|
433
|
+
// paired results or the next API call 400s on the dangling pair.
|
|
434
|
+
const reconstructTranscriptTail = (reason: string): Message[] => {
|
|
435
|
+
const parts: string[] = [];
|
|
436
|
+
if (draft.assistantResponse.length > 0) parts.push(draft.assistantResponse);
|
|
437
|
+
if (draft.toolTimeline.length > 0) {
|
|
438
|
+
parts.push(`Tool activity before interruption:\n${draft.toolTimeline.join("\n")}`);
|
|
439
|
+
}
|
|
440
|
+
parts.push(`[This turn was interrupted: ${reason}. The work above may be incomplete.]`);
|
|
441
|
+
return [
|
|
442
|
+
...(conversation._harnessMessages ?? []),
|
|
443
|
+
userMessage,
|
|
444
|
+
{ role: "assistant" as const, content: parts.join("\n\n") },
|
|
445
|
+
];
|
|
446
|
+
};
|
|
447
|
+
|
|
423
448
|
const aborted = opts.abortSignal?.aborted === true;
|
|
424
449
|
if (aborted || runCancelled) {
|
|
425
450
|
if (
|
|
@@ -434,7 +459,8 @@ export const runConversationTurn = async (
|
|
|
434
459
|
latestRunId,
|
|
435
460
|
contextTokens: 0,
|
|
436
461
|
contextWindow: 0,
|
|
437
|
-
harnessMessages:
|
|
462
|
+
harnessMessages:
|
|
463
|
+
cancelHarnessMessages ?? reconstructTranscriptTail("cancelled"),
|
|
438
464
|
toolResultArchive: opts.harness.getToolResultArchive(opts.conversationId),
|
|
439
465
|
},
|
|
440
466
|
{ shouldRebuildCanonical: true },
|
|
@@ -484,6 +510,12 @@ export const runConversationTurn = async (
|
|
|
484
510
|
draft.sections.length > 0
|
|
485
511
|
) {
|
|
486
512
|
conversation.messages = buildMessages(false); // terminal: errored
|
|
513
|
+
// Keep the LLM transcript faithful too (see reconstructTranscriptTail
|
|
514
|
+
// above) — without this, the next turn's model context skipped the
|
|
515
|
+
// whole errored interaction.
|
|
516
|
+
conversation._harnessMessages = reconstructTranscriptTail(
|
|
517
|
+
error instanceof Error ? `error — ${error.message}` : "error",
|
|
518
|
+
);
|
|
487
519
|
conversation.updatedAt = Date.now();
|
|
488
520
|
await opts.conversationStore.update(conversation);
|
|
489
521
|
}
|