@code-yeongyu/senpi-agent-core 2026.9.29 → 2026.10.1-2

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.
Files changed (285) hide show
  1. package/README.md +49 -20
  2. package/dist/agent-loop.d.ts +27 -3
  3. package/dist/agent-loop.js +192 -56
  4. package/dist/agent.d.ts +21 -7
  5. package/dist/agent.js +38 -18
  6. package/dist/harness/execution/tools.d.ts +1 -1
  7. package/dist/harness/execution/tools.js +0 -2
  8. package/dist/harness/messages.js +1 -0
  9. package/dist/harness/pico3/bash.d.ts +10 -0
  10. package/dist/harness/pico3/bash.js +25 -0
  11. package/dist/harness/pico3/bounded.d.ts +21 -0
  12. package/dist/harness/pico3/bounded.js +95 -0
  13. package/dist/harness/pico3/chord.d.ts +41 -0
  14. package/dist/harness/pico3/chord.js +147 -0
  15. package/dist/harness/pico3/context.d.ts +16 -0
  16. package/dist/harness/pico3/context.js +88 -0
  17. package/dist/harness/pico3/harness.d.ts +198 -0
  18. package/dist/harness/pico3/harness.js +645 -0
  19. package/dist/harness/pico3/hooks.d.ts +10 -0
  20. package/dist/harness/pico3/hooks.js +33 -0
  21. package/dist/harness/pico3/index.d.ts +19 -0
  22. package/dist/harness/pico3/index.js +15 -0
  23. package/dist/harness/pico3/jsonl.d.ts +58 -0
  24. package/dist/harness/pico3/jsonl.js +322 -0
  25. package/dist/harness/pico3/kinds/collapse.d.ts +49 -0
  26. package/dist/harness/pico3/kinds/collapse.js +191 -0
  27. package/dist/harness/pico3/kinds/entries.d.ts +78 -0
  28. package/dist/harness/pico3/kinds/entries.js +13 -0
  29. package/dist/harness/pico3/kinds/frames.d.ts +9 -0
  30. package/dist/harness/pico3/kinds/frames.js +75 -0
  31. package/dist/harness/pico3/kinds/generation.d.ts +94 -0
  32. package/dist/harness/pico3/kinds/generation.js +504 -0
  33. package/dist/harness/pico3/kinds/job.d.ts +44 -0
  34. package/dist/harness/pico3/kinds/job.js +143 -0
  35. package/dist/harness/pico3/kinds/plugin.d.ts +15 -0
  36. package/dist/harness/pico3/kinds/plugin.js +35 -0
  37. package/dist/harness/pico3/kinds/post-tools.d.ts +22 -0
  38. package/dist/harness/pico3/kinds/post-tools.js +145 -0
  39. package/dist/harness/pico3/kinds/task-api.d.ts +3 -0
  40. package/dist/harness/pico3/kinds/task-api.js +45 -0
  41. package/dist/harness/pico3/kinds/tool.d.ts +43 -0
  42. package/dist/harness/pico3/kinds/tool.js +373 -0
  43. package/dist/harness/pico3/legacy-tracker.d.ts +11 -0
  44. package/dist/harness/pico3/legacy-tracker.js +39 -0
  45. package/dist/harness/pico3/membrane.d.ts +23 -0
  46. package/dist/harness/pico3/membrane.js +140 -0
  47. package/dist/harness/pico3/memory.d.ts +53 -0
  48. package/dist/harness/pico3/memory.js +265 -0
  49. package/dist/harness/pico3/scheduler.d.ts +49 -0
  50. package/dist/harness/pico3/scheduler.js +437 -0
  51. package/dist/harness/pico3/session.d.ts +264 -0
  52. package/dist/harness/pico3/session.js +1328 -0
  53. package/dist/harness/pico3/system.d.ts +126 -0
  54. package/dist/harness/pico3/system.js +244 -0
  55. package/dist/harness/pico3/types.d.ts +973 -0
  56. package/dist/harness/pico3/types.js +94 -0
  57. package/dist/harness/pico3/view.d.ts +34 -0
  58. package/dist/harness/pico3/view.js +404 -0
  59. package/dist/harness/runtime/drive/tool-placement.js +2 -27
  60. package/dist/harness/telemetry.d.ts +36 -36
  61. package/dist/harness/tools/image.js +1 -1
  62. package/dist/harness/utils/read-folders/index.d.ts +2 -2
  63. package/dist/harness/utils/read-folders/index.js +2 -2
  64. package/dist/harness/utils/read-folders/tree-sitter/grammar-assets.js +1 -1
  65. package/dist/proxy.d.ts +2 -2
  66. package/dist/types.d.ts +111 -34
  67. package/package.json +10 -5
  68. package/dist/agent-loop.d.ts.map +0 -1
  69. package/dist/agent-loop.js.map +0 -1
  70. package/dist/agent.d.ts.map +0 -1
  71. package/dist/agent.js.map +0 -1
  72. package/dist/assistant-terminal-state.d.ts.map +0 -1
  73. package/dist/assistant-terminal-state.js.map +0 -1
  74. package/dist/empty-assistant-recovery.d.ts.map +0 -1
  75. package/dist/empty-assistant-recovery.js.map +0 -1
  76. package/dist/harness/agent-harness.d.ts.map +0 -1
  77. package/dist/harness/agent-harness.js.map +0 -1
  78. package/dist/harness/compaction/branch-summarization.d.ts.map +0 -1
  79. package/dist/harness/compaction/branch-summarization.js.map +0 -1
  80. package/dist/harness/compaction/compaction.d.ts.map +0 -1
  81. package/dist/harness/compaction/compaction.js.map +0 -1
  82. package/dist/harness/compaction/utils.d.ts.map +0 -1
  83. package/dist/harness/compaction/utils.js.map +0 -1
  84. package/dist/harness/config.d.ts.map +0 -1
  85. package/dist/harness/config.js.map +0 -1
  86. package/dist/harness/context.d.ts.map +0 -1
  87. package/dist/harness/context.js.map +0 -1
  88. package/dist/harness/env/nodejs.d.ts.map +0 -1
  89. package/dist/harness/env/nodejs.js.map +0 -1
  90. package/dist/harness/events.d.ts.map +0 -1
  91. package/dist/harness/events.js.map +0 -1
  92. package/dist/harness/execution/assistant.d.ts.map +0 -1
  93. package/dist/harness/execution/assistant.js.map +0 -1
  94. package/dist/harness/execution/effect-gate.d.ts.map +0 -1
  95. package/dist/harness/execution/effect-gate.js.map +0 -1
  96. package/dist/harness/execution/tools.d.ts.map +0 -1
  97. package/dist/harness/execution/tools.js.map +0 -1
  98. package/dist/harness/hooks.d.ts.map +0 -1
  99. package/dist/harness/hooks.js.map +0 -1
  100. package/dist/harness/messages.d.ts.map +0 -1
  101. package/dist/harness/messages.js.map +0 -1
  102. package/dist/harness/prompt-templates.d.ts.map +0 -1
  103. package/dist/harness/prompt-templates.js.map +0 -1
  104. package/dist/harness/result.d.ts.map +0 -1
  105. package/dist/harness/result.js.map +0 -1
  106. package/dist/harness/runtime/drive/boundary.d.ts.map +0 -1
  107. package/dist/harness/runtime/drive/boundary.js.map +0 -1
  108. package/dist/harness/runtime/drive/checkpoint.d.ts.map +0 -1
  109. package/dist/harness/runtime/drive/checkpoint.js.map +0 -1
  110. package/dist/harness/runtime/drive/deferred.d.ts.map +0 -1
  111. package/dist/harness/runtime/drive/deferred.js.map +0 -1
  112. package/dist/harness/runtime/drive/generation.d.ts.map +0 -1
  113. package/dist/harness/runtime/drive/generation.js.map +0 -1
  114. package/dist/harness/runtime/drive/reconcile.d.ts.map +0 -1
  115. package/dist/harness/runtime/drive/reconcile.js.map +0 -1
  116. package/dist/harness/runtime/drive/recovery.d.ts.map +0 -1
  117. package/dist/harness/runtime/drive/recovery.js.map +0 -1
  118. package/dist/harness/runtime/drive/response.d.ts.map +0 -1
  119. package/dist/harness/runtime/drive/response.js.map +0 -1
  120. package/dist/harness/runtime/drive/retry.d.ts.map +0 -1
  121. package/dist/harness/runtime/drive/retry.js.map +0 -1
  122. package/dist/harness/runtime/drive/structural.d.ts.map +0 -1
  123. package/dist/harness/runtime/drive/structural.js.map +0 -1
  124. package/dist/harness/runtime/drive/terminal.d.ts.map +0 -1
  125. package/dist/harness/runtime/drive/terminal.js.map +0 -1
  126. package/dist/harness/runtime/drive/tool-placement.d.ts.map +0 -1
  127. package/dist/harness/runtime/drive/tool-placement.js.map +0 -1
  128. package/dist/harness/runtime/drive/tools.d.ts.map +0 -1
  129. package/dist/harness/runtime/drive/tools.js.map +0 -1
  130. package/dist/harness/runtime/drive.d.ts.map +0 -1
  131. package/dist/harness/runtime/drive.js.map +0 -1
  132. package/dist/harness/runtime/harness.d.ts.map +0 -1
  133. package/dist/harness/runtime/harness.js.map +0 -1
  134. package/dist/harness/runtime/index.d.ts.map +0 -1
  135. package/dist/harness/runtime/index.js.map +0 -1
  136. package/dist/harness/runtime/lane.d.ts.map +0 -1
  137. package/dist/harness/runtime/lane.js.map +0 -1
  138. package/dist/harness/runtime/progress.d.ts.map +0 -1
  139. package/dist/harness/runtime/progress.js.map +0 -1
  140. package/dist/harness/runtime/reducer.d.ts.map +0 -1
  141. package/dist/harness/runtime/reducer.js.map +0 -1
  142. package/dist/harness/runtime/restore.d.ts.map +0 -1
  143. package/dist/harness/runtime/restore.js.map +0 -1
  144. package/dist/harness/runtime/transcript.d.ts.map +0 -1
  145. package/dist/harness/runtime/transcript.js.map +0 -1
  146. package/dist/harness/runtime/types.d.ts.map +0 -1
  147. package/dist/harness/runtime/types.js.map +0 -1
  148. package/dist/harness/session/commit.d.ts.map +0 -1
  149. package/dist/harness/session/commit.js.map +0 -1
  150. package/dist/harness/session/context.d.ts.map +0 -1
  151. package/dist/harness/session/context.js.map +0 -1
  152. package/dist/harness/session/fork-policy.d.ts.map +0 -1
  153. package/dist/harness/session/fork-policy.js.map +0 -1
  154. package/dist/harness/session/fork.d.ts.map +0 -1
  155. package/dist/harness/session/fork.js.map +0 -1
  156. package/dist/harness/session/in-memory-storage-state.d.ts.map +0 -1
  157. package/dist/harness/session/in-memory-storage-state.js.map +0 -1
  158. package/dist/harness/session/index.d.ts.map +0 -1
  159. package/dist/harness/session/index.js.map +0 -1
  160. package/dist/harness/session/jsonl/codec.d.ts.map +0 -1
  161. package/dist/harness/session/jsonl/codec.js.map +0 -1
  162. package/dist/harness/session/jsonl/fork.d.ts.map +0 -1
  163. package/dist/harness/session/jsonl/fork.js.map +0 -1
  164. package/dist/harness/session/jsonl/index.d.ts.map +0 -1
  165. package/dist/harness/session/jsonl/index.js.map +0 -1
  166. package/dist/harness/session/jsonl/io.d.ts.map +0 -1
  167. package/dist/harness/session/jsonl/io.js.map +0 -1
  168. package/dist/harness/session/jsonl/legacy-v3.d.ts.map +0 -1
  169. package/dist/harness/session/jsonl/legacy-v3.js.map +0 -1
  170. package/dist/harness/session/jsonl/repo.d.ts.map +0 -1
  171. package/dist/harness/session/jsonl/repo.js.map +0 -1
  172. package/dist/harness/session/jsonl/storage.d.ts.map +0 -1
  173. package/dist/harness/session/jsonl/storage.js.map +0 -1
  174. package/dist/harness/session/jsonl/types.d.ts.map +0 -1
  175. package/dist/harness/session/jsonl/types.js.map +0 -1
  176. package/dist/harness/session/memory.d.ts.map +0 -1
  177. package/dist/harness/session/memory.js.map +0 -1
  178. package/dist/harness/session/mutation-line.d.ts.map +0 -1
  179. package/dist/harness/session/mutation-line.js.map +0 -1
  180. package/dist/harness/session/session.d.ts.map +0 -1
  181. package/dist/harness/session/session.js.map +0 -1
  182. package/dist/harness/session/testing/benchmark/datasets.d.ts.map +0 -1
  183. package/dist/harness/session/testing/benchmark/datasets.js.map +0 -1
  184. package/dist/harness/session/testing/benchmark/session-repo.d.ts.map +0 -1
  185. package/dist/harness/session/testing/benchmark/session-repo.js.map +0 -1
  186. package/dist/harness/session/testing/benchmark/storage.d.ts.map +0 -1
  187. package/dist/harness/session/testing/benchmark/storage.js.map +0 -1
  188. package/dist/harness/session/testing/conformance/session-repo.d.ts.map +0 -1
  189. package/dist/harness/session/testing/conformance/session-repo.js.map +0 -1
  190. package/dist/harness/session/testing/conformance/storage.d.ts.map +0 -1
  191. package/dist/harness/session/testing/conformance/storage.js.map +0 -1
  192. package/dist/harness/session/testing/gating-storage.d.ts.map +0 -1
  193. package/dist/harness/session/testing/gating-storage.js.map +0 -1
  194. package/dist/harness/session/testing/index.d.ts.map +0 -1
  195. package/dist/harness/session/testing/index.js.map +0 -1
  196. package/dist/harness/session/testing/instrumented-storage.d.ts.map +0 -1
  197. package/dist/harness/session/testing/instrumented-storage.js.map +0 -1
  198. package/dist/harness/session/testing/storage-decorator.d.ts.map +0 -1
  199. package/dist/harness/session/testing/storage-decorator.js.map +0 -1
  200. package/dist/harness/session/testing/types.d.ts.map +0 -1
  201. package/dist/harness/session/testing/types.js.map +0 -1
  202. package/dist/harness/session/types.d.ts.map +0 -1
  203. package/dist/harness/session/types.js.map +0 -1
  204. package/dist/harness/session/values.d.ts.map +0 -1
  205. package/dist/harness/session/values.js.map +0 -1
  206. package/dist/harness/skills.d.ts.map +0 -1
  207. package/dist/harness/skills.js.map +0 -1
  208. package/dist/harness/system-prompt.d.ts.map +0 -1
  209. package/dist/harness/system-prompt.js.map +0 -1
  210. package/dist/harness/telemetry.d.ts.map +0 -1
  211. package/dist/harness/telemetry.js.map +0 -1
  212. package/dist/harness/tools/bash.d.ts.map +0 -1
  213. package/dist/harness/tools/bash.js.map +0 -1
  214. package/dist/harness/tools/edit-diff.d.ts.map +0 -1
  215. package/dist/harness/tools/edit-diff.js.map +0 -1
  216. package/dist/harness/tools/edit.d.ts.map +0 -1
  217. package/dist/harness/tools/edit.js.map +0 -1
  218. package/dist/harness/tools/file-mutation-queue.d.ts.map +0 -1
  219. package/dist/harness/tools/file-mutation-queue.js.map +0 -1
  220. package/dist/harness/tools/image.d.ts.map +0 -1
  221. package/dist/harness/tools/image.js.map +0 -1
  222. package/dist/harness/tools/index.d.ts.map +0 -1
  223. package/dist/harness/tools/index.js.map +0 -1
  224. package/dist/harness/tools/path-utils.d.ts.map +0 -1
  225. package/dist/harness/tools/path-utils.js.map +0 -1
  226. package/dist/harness/tools/post-mutate.d.ts.map +0 -1
  227. package/dist/harness/tools/post-mutate.js.map +0 -1
  228. package/dist/harness/tools/read.d.ts.map +0 -1
  229. package/dist/harness/tools/read.js.map +0 -1
  230. package/dist/harness/tools/tool-context.d.ts.map +0 -1
  231. package/dist/harness/tools/tool-context.js.map +0 -1
  232. package/dist/harness/tools/write.d.ts.map +0 -1
  233. package/dist/harness/tools/write.js.map +0 -1
  234. package/dist/harness/types.d.ts.map +0 -1
  235. package/dist/harness/types.js.map +0 -1
  236. package/dist/harness/utils/adaptive-publisher.d.ts.map +0 -1
  237. package/dist/harness/utils/adaptive-publisher.js.map +0 -1
  238. package/dist/harness/utils/output-capture.d.ts.map +0 -1
  239. package/dist/harness/utils/output-capture.js.map +0 -1
  240. package/dist/harness/utils/read-folders/brace-scanner.d.ts.map +0 -1
  241. package/dist/harness/utils/read-folders/brace-scanner.js.map +0 -1
  242. package/dist/harness/utils/read-folders/compose.d.ts.map +0 -1
  243. package/dist/harness/utils/read-folders/compose.js.map +0 -1
  244. package/dist/harness/utils/read-folders/header-protection.d.ts.map +0 -1
  245. package/dist/harness/utils/read-folders/header-protection.js.map +0 -1
  246. package/dist/harness/utils/read-folders/index.d.ts.map +0 -1
  247. package/dist/harness/utils/read-folders/index.js.map +0 -1
  248. package/dist/harness/utils/read-folders/lexical-context.d.ts.map +0 -1
  249. package/dist/harness/utils/read-folders/lexical-context.js.map +0 -1
  250. package/dist/harness/utils/read-folders/lexical-spans.d.ts.map +0 -1
  251. package/dist/harness/utils/read-folders/lexical-spans.js.map +0 -1
  252. package/dist/harness/utils/read-folders/prepare.d.ts.map +0 -1
  253. package/dist/harness/utils/read-folders/prepare.js.map +0 -1
  254. package/dist/harness/utils/read-folders/tree-sitter/engine.d.ts.map +0 -1
  255. package/dist/harness/utils/read-folders/tree-sitter/engine.js.map +0 -1
  256. package/dist/harness/utils/read-folders/tree-sitter/grammar-assets.d.ts.map +0 -1
  257. package/dist/harness/utils/read-folders/tree-sitter/grammar-assets.js.map +0 -1
  258. package/dist/harness/utils/read-folders/tree-sitter/syntax.d.ts.map +0 -1
  259. package/dist/harness/utils/read-folders/tree-sitter/syntax.js.map +0 -1
  260. package/dist/harness/utils/read-folders/types.d.ts.map +0 -1
  261. package/dist/harness/utils/read-folders/types.js.map +0 -1
  262. package/dist/harness/utils/segmented-read-view.d.ts.map +0 -1
  263. package/dist/harness/utils/segmented-read-view.js.map +0 -1
  264. package/dist/harness/utils/shell-output.d.ts.map +0 -1
  265. package/dist/harness/utils/shell-output.js.map +0 -1
  266. package/dist/harness/utils/truncate.d.ts.map +0 -1
  267. package/dist/harness/utils/truncate.js.map +0 -1
  268. package/dist/harness/utils/usage.d.ts.map +0 -1
  269. package/dist/harness/utils/usage.js.map +0 -1
  270. package/dist/index.d.ts.map +0 -1
  271. package/dist/index.js.map +0 -1
  272. package/dist/node.d.ts.map +0 -1
  273. package/dist/node.js.map +0 -1
  274. package/dist/proxy.d.ts.map +0 -1
  275. package/dist/proxy.js.map +0 -1
  276. package/dist/search/index.d.ts.map +0 -1
  277. package/dist/search/index.js.map +0 -1
  278. package/dist/stream-fn.d.ts.map +0 -1
  279. package/dist/stream-fn.js.map +0 -1
  280. package/dist/tool-arguments.d.ts.map +0 -1
  281. package/dist/tool-arguments.js.map +0 -1
  282. package/dist/tool-name-alias.d.ts.map +0 -1
  283. package/dist/tool-name-alias.js.map +0 -1
  284. package/dist/types.d.ts.map +0 -1
  285. package/dist/types.js.map +0 -1
@@ -0,0 +1,143 @@
1
+ const failed = (reason, detail) => ({
2
+ status: "failed",
3
+ failure: { reason, detail },
4
+ });
5
+ const notice = (text, now) => ({
6
+ kind: "pi.notice",
7
+ model: [{ role: "user", content: text, timestamp: now }],
8
+ });
9
+ const jobKind = {
10
+ name: "pi.job",
11
+ slot: () => ({}),
12
+ describe: (task) => ({
13
+ stage: task.checkpoint?.phase ?? "starting",
14
+ ...(task.slot ?? {}),
15
+ }),
16
+ inflight: ["spawning", "running"],
17
+ phases: {
18
+ async waiting(task, runtime, ctx) {
19
+ await runtime.sleep(task.checkpoint.untilMs, ctx);
20
+ return spawn(task, task.checkpoint.occurrence, runtime, ctx);
21
+ },
22
+ async spawning(task, runtime, ctx) {
23
+ return reconcile(task, task.checkpoint, runtime, ctx);
24
+ },
25
+ async running(task, runtime, ctx) {
26
+ return reconcile(task, task.checkpoint, runtime, ctx);
27
+ },
28
+ },
29
+ async initial(task, runtime, ctx) {
30
+ if (runtime.processHost === undefined)
31
+ return { done: () => failed("spawn", "no process host") };
32
+ const now = runtime.now();
33
+ const untilMs = task.input.notBefore ?? now;
34
+ if (untilMs > now)
35
+ return { next: { phase: "waiting", untilMs, occurrence: 1 } };
36
+ return spawn(task, 1, runtime, ctx);
37
+ },
38
+ async abort(task, runtime, ctx) {
39
+ const checkpoint = task.checkpoint;
40
+ if (checkpoint === undefined || checkpoint.phase === "waiting" || runtime.processHost === undefined)
41
+ return async () => ({ killed: false });
42
+ await runtime.processHost.kill(checkpoint.key, "SIGTERM", ctx);
43
+ await runtime.sleep(runtime.now() + 5000, ctx);
44
+ await runtime.processHost.kill(checkpoint.key, "SIGKILL", ctx);
45
+ return async () => ({ killed: true });
46
+ },
47
+ };
48
+ export const job = Object.freeze(jobKind);
49
+ async function spawn(task, occurrence, runtime, ctx) {
50
+ const key = `${task.id}:${occurrence}`;
51
+ await runtime.commit((tx) => tx.checkpoint({ phase: "spawning", key, occurrence }), ctx);
52
+ try {
53
+ await runtime.processHost.start(key, task.input, ctx);
54
+ }
55
+ catch (error) {
56
+ if (ctx.abortSignal?.aborted)
57
+ throw error;
58
+ return {
59
+ done: async (tx, current) => {
60
+ if (task.input.notify)
61
+ await tx.write(current.conversationId, notice(`job ${task.id} failed to start: ${String(error)}`, runtime.now()));
62
+ return failed("spawn", String(error));
63
+ },
64
+ };
65
+ }
66
+ await runtime.commit((tx) => tx.checkpoint({ phase: "running", key, occurrence }), ctx);
67
+ return poll(task, key, occurrence, runtime, ctx);
68
+ }
69
+ async function reconcile(task, checkpoint, runtime, ctx) {
70
+ if (runtime.processHost === undefined)
71
+ return { done: () => failed("interrupted", "no process host after restart") };
72
+ let status;
73
+ try {
74
+ status = await runtime.processHost.status(checkpoint.key, ctx);
75
+ }
76
+ catch (error) {
77
+ return { done: () => failed("interrupted", `host status failed: ${String(error)}`) };
78
+ }
79
+ if (status.status === "unknown") {
80
+ if (!task.input.rerun)
81
+ return { done: () => failed("interrupted", "process outcome unknown") };
82
+ return spawn(task, checkpoint.occurrence, runtime, ctx);
83
+ }
84
+ if (checkpoint.phase === "spawning") {
85
+ await runtime.commit((tx) => tx.checkpoint({ phase: "running", key: checkpoint.key, occurrence: checkpoint.occurrence }), ctx);
86
+ }
87
+ return poll(task, checkpoint.key, checkpoint.occurrence, runtime, ctx);
88
+ }
89
+ async function poll(task, key, occurrence, runtime, ctx) {
90
+ for (let attempt = 0;; attempt++) {
91
+ let status;
92
+ try {
93
+ status = await runtime.processHost.status(key, ctx);
94
+ }
95
+ catch (error) {
96
+ return { done: () => failed("interrupted", `host status failed: ${String(error)}`) };
97
+ }
98
+ if (status.status === "unknown") {
99
+ if (!task.input.rerun)
100
+ return { done: () => failed("interrupted", "process outcome unknown") };
101
+ return spawn(task, occurrence, runtime, ctx);
102
+ }
103
+ const snapshot = status;
104
+ await runtime.commit((tx, current) => {
105
+ const output = tx.slot({ id: current.id, kind: jobKind });
106
+ output.stdout = snapshot.stdout;
107
+ output.stderr = snapshot.stderr;
108
+ output.droppedStdout = snapshot.droppedStdout;
109
+ output.droppedStderr = snapshot.droppedStderr;
110
+ if (snapshot.status === "exited")
111
+ output.exitCode = snapshot.exitCode;
112
+ }, ctx);
113
+ if (snapshot.status === "exited") {
114
+ const { exitCode, stdout, stderr } = snapshot;
115
+ if (task.input.every === undefined) {
116
+ return {
117
+ done: async (tx, current) => {
118
+ if (task.input.notify)
119
+ await tx.write(current.conversationId, notice(`job ${task.id} exited with code ${exitCode}`, runtime.now()));
120
+ return { status: "completed", result: { exitCode, occurrences: occurrence, stdout, stderr } };
121
+ },
122
+ };
123
+ }
124
+ const untilMs = runtime.now() + task.input.every;
125
+ return {
126
+ next: async (tx, current) => {
127
+ if (task.input.notify)
128
+ await tx.write(current.conversationId, notice(`job ${task.id} occurrence ${occurrence} exited with code ${exitCode}`, runtime.now()));
129
+ const output = tx.slot({ id: current.id, kind: jobKind });
130
+ output.stdout = "";
131
+ output.stderr = "";
132
+ output.droppedStdout = 0;
133
+ output.droppedStderr = 0;
134
+ delete output.exitCode;
135
+ output.occurrence = occurrence + 1;
136
+ return { phase: "waiting", untilMs, occurrence: occurrence + 1 };
137
+ },
138
+ };
139
+ }
140
+ await runtime.sleep(runtime.now() + Math.min(1000, 100 * 2 ** Math.min(attempt, 4)), ctx);
141
+ }
142
+ }
143
+ //# sourceMappingURL=job.js.map
@@ -0,0 +1,15 @@
1
+ import { type JsonValue, type Kind } from "../types.ts";
2
+ export type PluginInput = {
3
+ handler: string;
4
+ input: JsonValue;
5
+ };
6
+ type PluginCheckpoint = {
7
+ phase: "started";
8
+ };
9
+ type PluginFailure = {
10
+ reason: "missing_handler" | "threw";
11
+ detail: string;
12
+ };
13
+ export declare const plugin: Readonly<Kind<PluginInput, PluginCheckpoint, import("@earendil-works/chord").JsonValue, PluginFailure, null, object, import("../types.ts").KindConfig<import("../types.ts").ConfigShape, import("../types.ts").ConfigShape>, import("../types.ts").JsonObject, import("../types.ts").TaskTx>>;
14
+ export {};
15
+ //# sourceMappingURL=plugin.d.ts.map
@@ -0,0 +1,35 @@
1
+ import { toStored } from "../types.js";
2
+ import { taskApi } from "./task-api.js";
3
+ const pluginKind = {
4
+ name: "pi.plugin",
5
+ inflight: ["started"],
6
+ phases: {
7
+ async started(task, runtime, ctx) {
8
+ return run(task, runtime, ctx);
9
+ },
10
+ },
11
+ async initial(task, runtime, ctx) {
12
+ await runtime.commit((tx) => tx.checkpoint({ phase: "started" }), ctx);
13
+ return run(task, runtime, ctx);
14
+ },
15
+ async abort() {
16
+ return async () => null;
17
+ },
18
+ };
19
+ export const plugin = Object.freeze(pluginKind);
20
+ async function run(task, runtime, ctx) {
21
+ const handler = runtime.plugins.get(task.input.handler);
22
+ if (handler === undefined) {
23
+ return { done: () => ({ status: "failed", failure: { reason: "missing_handler", detail: task.input.handler } }) };
24
+ }
25
+ try {
26
+ const result = toStored(await handler(task.input.input, taskApi(task, runtime), ctx));
27
+ return { done: () => ({ status: "completed", result }) };
28
+ }
29
+ catch (error) {
30
+ if (ctx.abortSignal?.aborted)
31
+ throw error;
32
+ return { done: () => ({ status: "failed", failure: { reason: "threw", detail: String(error) } }) };
33
+ }
34
+ }
35
+ //# sourceMappingURL=plugin.js.map
@@ -0,0 +1,22 @@
1
+ import type { Context } from "@earendil-works/chord";
2
+ import { type CoreKind, type HookInfo, type Id } from "../types.ts";
3
+ export type PostToolsInput = {
4
+ inputs: Id[];
5
+ assistant: Id;
6
+ tools: Id[];
7
+ };
8
+ export type PostToolsResult = {
9
+ successor?: Id;
10
+ ended?: "terminate" | "handoff";
11
+ };
12
+ export interface PostToolsHooks {
13
+ afterTools(assistant: Id, results: Id[], info: HookInfo, ctx: Context): void | Promise<void>;
14
+ }
15
+ export declare const postToolsConfig: {
16
+ readonly sticky: {
17
+ readonly steeringMode: "all" | "one-at-a-time";
18
+ readonly followUpMode: "all" | "one-at-a-time";
19
+ };
20
+ };
21
+ export declare const postTools: CoreKind<PostToolsInput, never, PostToolsResult, never, null, PostToolsHooks, typeof postToolsConfig>;
22
+ //# sourceMappingURL=post-tools.d.ts.map
@@ -0,0 +1,145 @@
1
+ import { toStored } from "../types.js";
2
+ export const postToolsConfig = {
3
+ sticky: {
4
+ steeringMode: "one-at-a-time",
5
+ followUpMode: "one-at-a-time",
6
+ },
7
+ };
8
+ export const postTools = {
9
+ name: "pi.post_tools",
10
+ turn: true,
11
+ config: postToolsConfig,
12
+ phases: {},
13
+ async initial(task, rt, ctx) {
14
+ const rows = await rt.commit(async (tx) => {
15
+ const assistant = await tx.entry(task.input.assistant);
16
+ const calls = (assistant?.model?.[0]?.content ?? []).filter((content) => content.type === "toolCall");
17
+ return Promise.all(task.input.tools.map(async (id, index) => {
18
+ const toolTask = (await tx.task(id));
19
+ const call = calls[index];
20
+ if (toolTask.outcome?.status === "completed") {
21
+ const result = toolTask.outcome.result;
22
+ return {
23
+ call,
24
+ entry: result.entry,
25
+ control: result.control,
26
+ missing: undefined,
27
+ };
28
+ }
29
+ if (toolTask.outcome?.status === "aborted") {
30
+ const aborted = toolTask.outcome.result;
31
+ return {
32
+ call,
33
+ entry: aborted.entry,
34
+ control: undefined,
35
+ missing: aborted.entry === undefined ? "aborted" : undefined,
36
+ };
37
+ }
38
+ return { call, entry: undefined, control: undefined, missing: "orphaned" };
39
+ }));
40
+ }, ctx);
41
+ const results = rows.map((row) => row.entry).filter((entry) => entry !== undefined);
42
+ await rt.hooks.each(ctx, (hook, api) => hook.afterTools?.(task.input.assistant, results, api, ctx));
43
+ return {
44
+ done: async (tx, current) => {
45
+ const conversationId = current.conversationId;
46
+ const head = await tx.newestEntry(conversationId, { withHead: true });
47
+ const state = tx.rewindable(conversationId);
48
+ const selectedTools = [...state.selectedTools];
49
+ let terminate = false;
50
+ let handoff;
51
+ for (const row of rows) {
52
+ for (const name of row.control?.addTools ?? [])
53
+ if (!selectedTools.includes(name))
54
+ selectedTools.push(name);
55
+ if (row.control?.terminate)
56
+ terminate = true;
57
+ if (row.control?.handoff !== undefined)
58
+ handoff = row.control.handoff;
59
+ }
60
+ if (selectedTools.length !== state.selectedTools.length) {
61
+ state.selectedTools = selectedTools;
62
+ tx.emit({ type: "config.changed", keys: ["selectedTools"] });
63
+ }
64
+ for (const row of rows) {
65
+ if (row.missing === undefined)
66
+ continue;
67
+ tx.appendEntry(conversationId, {
68
+ kind: "pi.tool_result",
69
+ model: [
70
+ toStored({
71
+ role: "toolResult",
72
+ toolCallId: row.call.id,
73
+ toolName: row.call.name,
74
+ content: [{ type: "text", text: `Tool result unavailable: task ${row.missing}.` }],
75
+ isError: true,
76
+ timestamp: rt.now(),
77
+ }),
78
+ ],
79
+ data: { diagnostics: [{ severity: "error", message: row.missing, code: row.missing }] },
80
+ });
81
+ tx.emit({
82
+ type: "warning",
83
+ source: "post_tools",
84
+ message: `synthesized ${row.missing} tool result for ${row.call.id}`,
85
+ });
86
+ }
87
+ let headBoundary = head?.id;
88
+ if (handoff !== undefined) {
89
+ headBoundary = tx.appendEntry(conversationId, {
90
+ kind: "pi.handoff",
91
+ head: "self",
92
+ model: [{ role: "user", content: handoff, timestamp: rt.now() }],
93
+ });
94
+ }
95
+ if (handoff !== undefined || terminate) {
96
+ tx.sticky(conversationId).turn = { tools: [] };
97
+ await tx.resolveInputs(task.input.inputs, { status: "done", answer: task.input.assistant });
98
+ tx.emit({ type: "turn.ended", inputs: task.input.inputs, status: "done", answer: task.input.assistant });
99
+ const { triggers } = await tx.boundary(conversationId, "final", headBoundary);
100
+ if (triggers.length > 0)
101
+ tx.emit({ type: "turn.started", inputs: triggers });
102
+ const ended = handoff !== undefined ? "handoff" : "terminate";
103
+ return {
104
+ status: "completed",
105
+ result: triggers.length > 0
106
+ ? { ended, successor: tx.createTask({ kind: "pi.generation", input: { inputs: triggers } }) }
107
+ : { ended },
108
+ };
109
+ }
110
+ const { triggers, terminated } = await tx.boundary(conversationId, "postTools", headBoundary);
111
+ if (terminated) {
112
+ tx.sticky(conversationId).turn = { tools: [] };
113
+ await tx.resolveInputs(task.input.inputs, { status: "unanswered", reason: "terminated" });
114
+ tx.emit({ type: "turn.ended", inputs: task.input.inputs, status: "unanswered", reason: "terminated" });
115
+ if (triggers.length > 0)
116
+ tx.emit({ type: "turn.started", inputs: triggers });
117
+ return {
118
+ status: "completed",
119
+ result: triggers.length > 0
120
+ ? { successor: tx.createTask({ kind: "pi.generation", input: { inputs: triggers } }) }
121
+ : {},
122
+ };
123
+ }
124
+ return {
125
+ status: "completed",
126
+ result: {
127
+ successor: tx.createTask({
128
+ kind: "pi.generation",
129
+ input: { inputs: [...task.input.inputs, ...triggers] },
130
+ }),
131
+ },
132
+ };
133
+ },
134
+ };
135
+ },
136
+ async abort(task) {
137
+ return async (tx, current) => {
138
+ tx.sticky(current.conversationId).turn = { tools: [] };
139
+ await tx.resolveInputs(task.input.inputs, { status: "unanswered", reason: "aborted" });
140
+ tx.emit({ type: "turn.ended", inputs: task.input.inputs, status: "unanswered", reason: "aborted" });
141
+ return null;
142
+ };
143
+ },
144
+ };
145
+ //# sourceMappingURL=post-tools.js.map
@@ -0,0 +1,3 @@
1
+ import type { Runtime, Task, ToolApi } from "../types.ts";
2
+ export declare function taskApi(task: Task, runtime: Runtime): ToolApi;
3
+ //# sourceMappingURL=task-api.d.ts.map
@@ -0,0 +1,45 @@
1
+ export function taskApi(task, runtime) {
2
+ const isKind = (value) => typeof value === "object" && value !== null && "name" in value && "initial" in value;
3
+ return {
4
+ taskId: task.id,
5
+ conversationId: task.conversationId,
6
+ callId: "",
7
+ stream: () => {
8
+ throw new Error("stream is only available to tools");
9
+ },
10
+ progress: () => {
11
+ throw new Error("progress is only available to tools");
12
+ },
13
+ memo: (() => Promise.reject(new Error("memo is only available to tools"))),
14
+ async conversation(spec, ctx) {
15
+ const id = await runtime.createOwnedConversation(spec, ctx);
16
+ return {
17
+ id,
18
+ send: async (input, childContext) => {
19
+ const inputId = await runtime.sendOwned(id, input, childContext);
20
+ return {
21
+ id: inputId,
22
+ wait: (waitContext) => runtime.waitForInput(inputId, waitContext),
23
+ result: (resultContext) => runtime.commit((tx) => tx.input(inputId), resultContext),
24
+ };
25
+ },
26
+ abort: (childContext) => runtime.abortConversation(id, childContext),
27
+ };
28
+ },
29
+ task: ((kind, input, opts, ctx) => {
30
+ if (!isKind(kind))
31
+ throw new Error("task(): pass a kind token");
32
+ return runtime.commit((tx) => tx.createTask(kind, input, opts), ctx);
33
+ }),
34
+ getTask: async (ref, ctx) => (await runtime.commit((tx) => tx.task(ref.id), ctx)),
35
+ waitForTask: (ref, ctx) => runtime.waitForTask(ref.id, ctx),
36
+ slot: (ref, ctx) => runtime.commit(async (tx) => {
37
+ const storedTask = await tx.task(ref.id);
38
+ if (storedTask === undefined)
39
+ return undefined;
40
+ return (tx.snapshot({ doc: "sticky", conversationId: storedTask.conversationId }).tasks[ref.id] ??
41
+ undefined);
42
+ }, ctx),
43
+ };
44
+ }
45
+ //# sourceMappingURL=task-api.js.map
@@ -0,0 +1,43 @@
1
+ import type { Context } from "@earendil-works/chord";
2
+ import type { ToolCall } from "@earendil-works/pi-ai";
3
+ import { type AnyToolDeclaration, type BeforeToolApi, type CoreKind, type HookInfo, type HookResult, type Id, type Step, type Stored, type ToolControl, type ToolResult } from "../types.ts";
4
+ export type StoredToolCall = Stored<ToolCall>;
5
+ export type ToolInput = {
6
+ assistant: Id;
7
+ call: StoredToolCall;
8
+ offered: string[];
9
+ index: number;
10
+ };
11
+ export type ToolCheckpoint = {
12
+ phase: "started";
13
+ replay: "safe" | "unsafe";
14
+ call: StoredToolCall;
15
+ };
16
+ export type ToolTaskResult = {
17
+ entry: Id;
18
+ control?: ToolControl;
19
+ };
20
+ /** Hook points this kind calls. Register with `h.hooks(namespace, kinds.tool, { … })`. */
21
+ export interface ToolHooks {
22
+ /** Before invocation, before `started`. Chain on `call`; `{ block }` stops it. A throw blocks. */
23
+ beforeTool(call: StoredToolCall, api: BeforeToolApi, ctx: Context): HookResult<{
24
+ call?: StoredToolCall;
25
+ block?: string;
26
+ }>;
27
+ /** After the tool returns; may replace the result. Chain. */
28
+ afterTool(call: StoredToolCall, result: ToolResult, api: HookInfo & {
29
+ readonly callId: string;
30
+ }, ctx: Context): HookResult<ToolResult>;
31
+ }
32
+ /** Validate arguments with the tool's real schema (TypeBox 1.x). */
33
+ export declare function invalid(declaration: AnyToolDeclaration, call: StoredToolCall): string | undefined;
34
+ export declare const tool: CoreKind<ToolInput, ToolCheckpoint, ToolTaskResult, never, {
35
+ entry: Id;
36
+ }, ToolHooks>;
37
+ export declare const DEFAULT_BOUNDS: {
38
+ maxBytes: number;
39
+ maxLines: number;
40
+ retain: "head";
41
+ };
42
+ export type { Step };
43
+ //# sourceMappingURL=tool.d.ts.map