pi-durable-subagents 1.0.2 → 1.0.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/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.0.3
4
+
5
+ - Recovery delivers a call's task when an earlier execution ended before its
6
+ subagent received it (for example, an orchestrator restart while the call
7
+ waited for a provider slot). It used to send only "Continue the task", and
8
+ the fresh subagent had to guess what the task was.
9
+
3
10
  ## 1.0.2
4
11
 
5
12
  The first published release (1.0.0 and 1.0.1 were prepared but never
@@ -625,12 +625,21 @@ export default function createExecutor(ledgers, options = {}) {
625
625
  const receipt = unresolved && entries.some(e => receiptId(e) === unresolved.rid2);
626
626
  const openingRid = t.opening && contentHash([t.opening.rid, "dispatch"]);
627
627
  const openingReceived = openingRid && entries.some(e => receiptId(e) === openingRid);
628
+ // The task has one identity: the dispatch of the call's first execution. A later execution continues only once
629
+ // the session holds that task; an execution interrupted before its child received it (still waiting for a
630
+ // provider slot, say) leaves a session without a task, and "continue" would ask a fresh model to guess.
631
+ const taskRid = contentHash([`${t.callId}#1.1`, "dispatch"]);
632
+ const taskReceived = !openingRid && entries.some(e => receiptId(e) === taskRid);
628
633
  if (openingRid && !openingReceived)
629
634
  await sender.send(t.callId, "task", { message: t.opening.message }, undefined, { rid: openingRid });
635
+ else if (!openingRid && !taskReceived)
636
+ await sender.send(t.callId, "task", { message: t.spec.task }, undefined, { rid: taskRid });
630
637
  else if (unresolved && !receipt)
631
638
  await sender.send(t.callId, "continue", { message: String(unresolved.message) }, { qid: String(unresolved.qid), rev: Number(unresolved.rev) }, { rid: String(unresolved.rid2) });
639
+ else if (previous)
640
+ await sender.send(t.callId, "continue", { message: `Continue the task. Tool calls whose outcomes are unknown: ${dangling.join(", ") || "none"}.` }, undefined, { rid: contentHash([exec, "dispatch"]) });
632
641
  else
633
- await sender.send(t.callId, previous ? "continue" : "task", { message: previous ? `Continue the task. Tool calls whose outcomes are unknown: ${dangling.join(", ") || "none"}.` : t.opening?.message ?? t.spec.task }, undefined, { rid: contentHash([exec, "dispatch"]) });
642
+ await sender.send(t.callId, "task", { message: t.opening?.message ?? t.spec.task }, undefined, { rid: contentHash([exec, "dispatch"]) });
634
643
  if (interrupted(a)) {
635
644
  await fence(journal, exec, { park: a });
636
645
  return finish(journal, t.callId, exec, makeResult("stopped"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-durable-subagents",
3
- "version": "1.0.2",
3
+ "version": "1.0.3",
4
4
  "description": "Subagents for pi that never lose work and never do it twice. Crash-safe workflows, automatic recovery, and a live view just like the main agent.",
5
5
  "type": "module",
6
6
  "license": "MIT",