@leuduan/lagent 0.0.0-stage → 0.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 (327) hide show
  1. package/LICENSE +16 -0
  2. package/README.md +144 -2
  3. package/dist/chunks/2O7ZGEIT.js +1 -0
  4. package/dist/chunks/2OSESBIL.js +1 -0
  5. package/dist/chunks/34KW6VNQ.js +1 -0
  6. package/dist/chunks/37YOGDGY.js +1 -0
  7. package/dist/chunks/3LQHQRIU.js +6 -0
  8. package/dist/chunks/3QCW4WDJ.js +1 -0
  9. package/dist/chunks/4XVRUSCQ.js +1 -0
  10. package/dist/chunks/6ECI2GGV.js +1 -0
  11. package/dist/chunks/74HKUGRR.js +1 -0
  12. package/dist/chunks/ADHERZLW.js +2 -0
  13. package/dist/chunks/AP6Q4EPT.js +36 -0
  14. package/dist/chunks/BM3S37EZ.js +1 -0
  15. package/dist/chunks/C5LYCXJG.js +1 -0
  16. package/dist/chunks/CDQG7RKA.js +1 -0
  17. package/dist/chunks/D7E6EWIE.js +3 -0
  18. package/dist/chunks/DDANMY45.js +3 -0
  19. package/dist/chunks/DRYAN665.js +1 -0
  20. package/dist/chunks/DXFXAYDN.js +17 -0
  21. package/dist/chunks/EGZI4XQX.js +24 -0
  22. package/dist/chunks/ENWFSU27.js +41 -0
  23. package/dist/chunks/G6RXC3AL.js +1 -0
  24. package/dist/chunks/G74AGRAJ.js +15 -0
  25. package/dist/chunks/GQGNVSKB.js +1 -0
  26. package/dist/chunks/IJ2WNMD5.js +7 -0
  27. package/dist/chunks/J5S4URAW.js +1 -0
  28. package/dist/chunks/JPZFKSWT.js +1 -0
  29. package/dist/chunks/KESCTXGO.js +5 -0
  30. package/dist/chunks/L3N4FIEN.js +1 -0
  31. package/dist/chunks/NAOUTU7A.js +4 -0
  32. package/dist/chunks/NDIM7MEW.js +1 -0
  33. package/dist/chunks/O4PPOM5Z.js +2 -0
  34. package/dist/chunks/OVZFGILJ.js +1 -0
  35. package/dist/chunks/P5ZHHOOM.js +6 -0
  36. package/dist/chunks/PUSUPTAT.js +1 -0
  37. package/dist/chunks/QMMLQJBS.js +1 -0
  38. package/dist/chunks/RK3VP2Q4.js +3 -0
  39. package/dist/chunks/SGGMBSBA.js +1 -0
  40. package/dist/chunks/SL2YLB2F.js +1 -0
  41. package/dist/chunks/TOOIB6J2.js +1 -0
  42. package/dist/chunks/TYTQRLTX.js +1 -0
  43. package/dist/chunks/UC3FVVJ2.js +5 -0
  44. package/dist/chunks/UCTEU62F.js +1 -0
  45. package/dist/chunks/UD3VJER6.js +1 -0
  46. package/dist/chunks/UKXMCHHT.js +1 -0
  47. package/dist/chunks/WUUKTSRT.js +7 -0
  48. package/dist/chunks/X65X4KP5.js +7 -0
  49. package/dist/chunks/YIR5MYGU.js +1 -0
  50. package/dist/chunks/YLNJXQ3Z.js +1 -0
  51. package/dist/context.d.ts +101 -0
  52. package/dist/index.d.ts +47 -0
  53. package/dist/index.js +77 -0
  54. package/dist/journal/catalog.d.ts +112 -0
  55. package/dist/journal/forkChain.d.ts +16 -0
  56. package/dist/journal/index.d.ts +15 -0
  57. package/dist/journal/journal.d.ts +475 -0
  58. package/dist/journal/projection.d.ts +87 -0
  59. package/dist/journal/store.d.ts +181 -0
  60. package/dist/kit/claim.d.ts +13 -0
  61. package/dist/kit/drain.d.ts +10 -0
  62. package/dist/kit/extension.d.ts +180 -0
  63. package/dist/kit/grants.d.ts +9 -0
  64. package/dist/kit/modes.d.ts +65 -0
  65. package/dist/kit/retries.d.ts +25 -0
  66. package/dist/kit/scope.d.ts +32 -0
  67. package/dist/kit/service.d.ts +7 -0
  68. package/dist/kit/strategy.d.ts +10 -0
  69. package/dist/kit/timers.d.ts +43 -0
  70. package/dist/kit/tool.d.ts +72 -0
  71. package/dist/llm/client.d.ts +135 -0
  72. package/dist/llm/content.d.ts +52 -0
  73. package/dist/llm/door.d.ts +21 -0
  74. package/dist/llm/door.js +1 -0
  75. package/dist/llm/failure.d.ts +82 -0
  76. package/dist/llm/index.d.ts +16 -0
  77. package/dist/llm/primitives.d.ts +286 -0
  78. package/dist/llm/prompt.d.ts +21 -0
  79. package/dist/llm/provider.d.ts +63 -0
  80. package/dist/llm/readLedger.d.ts +24 -0
  81. package/dist/llm/request.d.ts +58 -0
  82. package/dist/loop/agent.d.ts +134 -0
  83. package/dist/loop/auxiliary.d.ts +54 -0
  84. package/dist/loop/chain.d.ts +46 -0
  85. package/dist/loop/chunks.d.ts +27 -0
  86. package/dist/loop/continuation.d.ts +166 -0
  87. package/dist/loop/decide.d.ts +64 -0
  88. package/dist/loop/errors.d.ts +162 -0
  89. package/dist/loop/forks.d.ts +61 -0
  90. package/dist/loop/holds.d.ts +104 -0
  91. package/dist/loop/hooks.d.ts +241 -0
  92. package/dist/loop/inbox.d.ts +188 -0
  93. package/dist/loop/index.d.ts +37 -0
  94. package/dist/loop/limits.d.ts +14 -0
  95. package/dist/loop/opening.d.ts +42 -0
  96. package/dist/loop/prepare.d.ts +30 -0
  97. package/dist/loop/projections.d.ts +307 -0
  98. package/dist/loop/replace.d.ts +33 -0
  99. package/dist/loop/requests.d.ts +129 -0
  100. package/dist/loop/route.d.ts +53 -0
  101. package/dist/loop/runtime.d.ts +85 -0
  102. package/dist/loop/state.d.ts +70 -0
  103. package/dist/loop/strategy.d.ts +71 -0
  104. package/dist/loop/summary.d.ts +3 -0
  105. package/dist/loop/surface.d.ts +153 -0
  106. package/dist/loop/threadState.d.ts +72 -0
  107. package/dist/loop/tool.d.ts +101 -0
  108. package/dist/loop/toolCalls.d.ts +42 -0
  109. package/dist/loop/wake.d.ts +32 -0
  110. package/dist/models/config/agent.d.ts +18 -0
  111. package/dist/models/config/prompt.d.ts +18 -0
  112. package/dist/models/door.d.ts +12 -0
  113. package/dist/models/door.js +1 -0
  114. package/dist/models/index.d.ts +7 -0
  115. package/dist/models/jsonSchema.d.ts +7 -0
  116. package/dist/models/wire/journal.d.ts +2772 -0
  117. package/dist/models/wire/primitives.d.ts +65 -0
  118. package/dist/plugin.d.ts +53 -0
  119. package/dist/plugin.js +1 -0
  120. package/dist/plugins/agentsMd.d.ts +76 -0
  121. package/dist/plugins/agentsMd.js +1 -0
  122. package/dist/plugins/ask/askQuestion.d.ts +9 -0
  123. package/dist/plugins/ask/index.d.ts +26 -0
  124. package/dist/plugins/ask/index.js +1 -0
  125. package/dist/plugins/ask/service.d.ts +125 -0
  126. package/dist/plugins/commands/background.d.ts +8 -0
  127. package/dist/plugins/commands/foreground.d.ts +4 -0
  128. package/dist/plugins/commands/index.d.ts +40 -0
  129. package/dist/plugins/commands/index.js +1 -0
  130. package/dist/plugins/commands/output.d.ts +115 -0
  131. package/dist/plugins/commands/record.d.ts +549 -0
  132. package/dist/plugins/commands/service.d.ts +314 -0
  133. package/dist/plugins/commands/shell.d.ts +25 -0
  134. package/dist/plugins/compaction/checkpoint.d.ts +91 -0
  135. package/dist/plugins/compaction/config.d.ts +133 -0
  136. package/dist/plugins/compaction/estimate.d.ts +29 -0
  137. package/dist/plugins/compaction/index.d.ts +2 -0
  138. package/dist/plugins/compaction/index.js +7 -0
  139. package/dist/plugins/compaction/log.d.ts +61 -0
  140. package/dist/plugins/compaction/planner.d.ts +207 -0
  141. package/dist/plugins/compaction/preset.d.ts +86 -0
  142. package/dist/plugins/compaction/prune.d.ts +9 -0
  143. package/dist/plugins/compaction/records.d.ts +227 -0
  144. package/dist/plugins/compaction/segments.d.ts +23 -0
  145. package/dist/plugins/compaction/shared.d.ts +14 -0
  146. package/dist/plugins/compaction/summarize.d.ts +13 -0
  147. package/dist/plugins/dateAndBranch.d.ts +47 -0
  148. package/dist/plugins/dateAndBranch.js +1 -0
  149. package/dist/plugins/delegations/answers.d.ts +39 -0
  150. package/dist/plugins/delegations/assignmentKey.d.ts +22 -0
  151. package/dist/plugins/delegations/cleanup.d.ts +161 -0
  152. package/dist/plugins/delegations/constraint.d.ts +76 -0
  153. package/dist/plugins/delegations/index.d.ts +39 -0
  154. package/dist/plugins/delegations/index.js +1 -0
  155. package/dist/plugins/delegations/notices.d.ts +261 -0
  156. package/dist/plugins/delegations/obligations.d.ts +210 -0
  157. package/dist/plugins/delegations/record.d.ts +632 -0
  158. package/dist/plugins/delegations/request.d.ts +381 -0
  159. package/dist/plugins/delegations/role.d.ts +30 -0
  160. package/dist/plugins/delegations/service.d.ts +562 -0
  161. package/dist/plugins/delegations/standing.d.ts +19 -0
  162. package/dist/plugins/delegations/stopCheck.d.ts +21 -0
  163. package/dist/plugins/delegations/testing.d.ts +16 -0
  164. package/dist/plugins/delegations/tools.d.ts +71 -0
  165. package/dist/plugins/delegations/waitBook.d.ts +116 -0
  166. package/dist/plugins/delegations/waits.d.ts +118 -0
  167. package/dist/plugins/diagnostics/digest.d.ts +14 -0
  168. package/dist/plugins/diagnostics/index.d.ts +68 -0
  169. package/dist/plugins/diagnostics/index.js +1 -0
  170. package/dist/plugins/historyRecall/history.d.ts +9 -0
  171. package/dist/plugins/historyRecall/index.d.ts +31 -0
  172. package/dist/plugins/historyRecall/index.js +1 -0
  173. package/dist/plugins/historyRecall/render.d.ts +34 -0
  174. package/dist/plugins/historyRecall/tools.d.ts +4 -0
  175. package/dist/plugins/mcp/catalog.d.ts +36 -0
  176. package/dist/plugins/mcp/config.d.ts +63 -0
  177. package/dist/plugins/mcp/connection.d.ts +53 -0
  178. package/dist/plugins/mcp/errors.d.ts +32 -0
  179. package/dist/plugins/mcp/index.d.ts +33 -0
  180. package/dist/plugins/mcp/index.js +5 -0
  181. package/dist/plugins/mcp/mount.d.ts +98 -0
  182. package/dist/plugins/mcp/names.d.ts +25 -0
  183. package/dist/plugins/mcp/render.d.ts +29 -0
  184. package/dist/plugins/mcp/slots.d.ts +15 -0
  185. package/dist/plugins/mcp/stdio.d.ts +49 -0
  186. package/dist/plugins/mcp/tool.d.ts +41 -0
  187. package/dist/plugins/providers/anthropic.d.ts +175 -0
  188. package/dist/plugins/providers/anthropicMessages.d.ts +65 -0
  189. package/dist/plugins/providers/codex.d.ts +60 -0
  190. package/dist/plugins/providers/codexAuth.d.ts +116 -0
  191. package/dist/plugins/providers/deepseek.d.ts +55 -0
  192. package/dist/plugins/providers/door.d.ts +61 -0
  193. package/dist/plugins/providers/door.js +1 -0
  194. package/dist/plugins/providers/failure.d.ts +23 -0
  195. package/dist/plugins/providers/gateway.d.ts +23 -0
  196. package/dist/plugins/providers/index.d.ts +6 -0
  197. package/dist/plugins/providers/openaiChat.d.ts +62 -0
  198. package/dist/plugins/providers/openaiResponses.d.ts +100 -0
  199. package/dist/plugins/providers/opencodeCopilot.d.ts +23 -0
  200. package/dist/plugins/providers/opencodeGo.d.ts +98 -0
  201. package/dist/plugins/providers/shared.d.ts +104 -0
  202. package/dist/plugins/providers/stream.d.ts +154 -0
  203. package/dist/plugins/routeContext.d.ts +22 -0
  204. package/dist/plugins/routeContext.js +1 -0
  205. package/dist/plugins/schedules/index.d.ts +21 -0
  206. package/dist/plugins/schedules/index.js +5 -0
  207. package/dist/plugins/schedules/record.d.ts +396 -0
  208. package/dist/plugins/schedules/service.d.ts +120 -0
  209. package/dist/plugins/schedules/time.d.ts +26 -0
  210. package/dist/plugins/schedules/tools.d.ts +6 -0
  211. package/dist/plugins/skills/discovery.d.ts +54 -0
  212. package/dist/plugins/skills/index.d.ts +31 -0
  213. package/dist/plugins/skills/index.js +1 -0
  214. package/dist/plugins/skills/tool.d.ts +11 -0
  215. package/dist/plugins/store/durableObject.d.ts +23 -0
  216. package/dist/plugins/store/durableObject.js +1 -0
  217. package/dist/plugins/store/durableObjectConnection.d.ts +27 -0
  218. package/dist/plugins/store/memory.d.ts +29 -0
  219. package/dist/plugins/store/sql.d.ts +59 -0
  220. package/dist/plugins/store/sqlite.d.ts +31 -0
  221. package/dist/plugins/store/sqlite.js +1 -0
  222. package/dist/plugins/subAgents/availableRoutes.d.ts +53 -0
  223. package/dist/plugins/subAgents/fork.d.ts +32 -0
  224. package/dist/plugins/subAgents/index.d.ts +67 -0
  225. package/dist/plugins/subAgents/index.js +1 -0
  226. package/dist/plugins/subAgents/tool.d.ts +38 -0
  227. package/dist/plugins/toolPolicy/index.d.ts +61 -0
  228. package/dist/plugins/toolPolicy/index.js +1 -0
  229. package/dist/plugins/tools/editFiles.d.ts +128 -0
  230. package/dist/plugins/tools/fsRead.d.ts +17 -0
  231. package/dist/plugins/tools/html.d.ts +23 -0
  232. package/dist/plugins/tools/index.d.ts +59 -0
  233. package/dist/plugins/tools/index.js +1 -0
  234. package/dist/plugins/tools/network.d.ts +23 -0
  235. package/dist/plugins/tools/ripgrep.d.ts +20 -0
  236. package/dist/plugins/tools/textEdit.d.ts +67 -0
  237. package/dist/plugins/tools/web.d.ts +32 -0
  238. package/dist/plugins/truncateToolOutput.d.ts +26 -0
  239. package/dist/plugins/truncateToolOutput.js +1 -0
  240. package/dist/plugins/usage/index.d.ts +24 -0
  241. package/dist/plugins/usage/index.js +1 -0
  242. package/dist/plugins/usage/tracker.d.ts +34 -0
  243. package/dist/plugins/verify/facts.d.ts +356 -0
  244. package/dist/plugins/verify/index.d.ts +75 -0
  245. package/dist/plugins/verify/index.js +1 -0
  246. package/dist/plugins/verify/service.d.ts +90 -0
  247. package/dist/plugins/workflows/assignment.d.ts +16 -0
  248. package/dist/plugins/workflows/bindings.d.ts +95 -0
  249. package/dist/plugins/workflows/cleanup.d.ts +38 -0
  250. package/dist/plugins/workflows/definition.d.ts +184 -0
  251. package/dist/plugins/workflows/fold.d.ts +373 -0
  252. package/dist/plugins/workflows/index.d.ts +28 -0
  253. package/dist/plugins/workflows/index.js +6 -0
  254. package/dist/plugins/workflows/observations.d.ts +81 -0
  255. package/dist/plugins/workflows/participants.d.ts +143 -0
  256. package/dist/plugins/workflows/policy.d.ts +112 -0
  257. package/dist/plugins/workflows/providers.d.ts +146 -0
  258. package/dist/plugins/workflows/record.d.ts +2863 -0
  259. package/dist/plugins/workflows/routing.d.ts +116 -0
  260. package/dist/plugins/workflows/schema.d.ts +26 -0
  261. package/dist/plugins/workflows/service.d.ts +477 -0
  262. package/dist/plugins/workflows/submit.d.ts +8 -0
  263. package/dist/plugins/workflows/view.d.ts +103 -0
  264. package/dist/plugins/workflows/work.d.ts +21 -0
  265. package/dist/plugins/workspaceContext.d.ts +38 -0
  266. package/dist/plugins/workspaceContext.js +1 -0
  267. package/dist/presets/agents.d.ts +7 -0
  268. package/dist/presets/base.d.ts +10 -0
  269. package/dist/presets/codex.d.ts +60 -0
  270. package/dist/presets/index.d.ts +4 -0
  271. package/dist/presets/prompts.d.ts +56 -0
  272. package/dist/sandbox/absent.d.ts +32 -0
  273. package/dist/sandbox/client.d.ts +39 -0
  274. package/dist/sandbox/files.d.ts +28 -0
  275. package/dist/sandbox/index.d.ts +49 -0
  276. package/dist/sandbox/index.js +4 -0
  277. package/dist/sandbox/mode.d.ts +57 -0
  278. package/dist/sandbox/policy.d.ts +86 -0
  279. package/dist/sandbox/protocol.d.ts +107 -0
  280. package/dist/sandbox/service.d.ts +143 -0
  281. package/dist/sandbox/worker.d.ts +12 -0
  282. package/dist/sandbox/worker.js +1 -0
  283. package/dist/services/admission.d.ts +174 -0
  284. package/dist/services/agents.d.ts +37 -0
  285. package/dist/services/birth.d.ts +220 -0
  286. package/dist/services/contributions.d.ts +73 -0
  287. package/dist/services/core.d.ts +34 -0
  288. package/dist/services/journal.d.ts +26 -0
  289. package/dist/services/launches.d.ts +104 -0
  290. package/dist/services/llm.d.ts +80 -0
  291. package/dist/services/owner.d.ts +367 -0
  292. package/dist/services/preset.d.ts +154 -0
  293. package/dist/services/presets.d.ts +139 -0
  294. package/dist/services/prompts.d.ts +67 -0
  295. package/dist/services/runEvents.d.ts +79 -0
  296. package/dist/services/thread.d.ts +267 -0
  297. package/dist/services/threadActivation.d.ts +100 -0
  298. package/dist/services/threadDirs.d.ts +38 -0
  299. package/dist/services/threadView.d.ts +92 -0
  300. package/dist/services/threads.d.ts +449 -0
  301. package/dist/services/tools.d.ts +41 -0
  302. package/dist/sys/environment.d.ts +47 -0
  303. package/dist/sys/git.d.ts +60 -0
  304. package/dist/sys/paths.d.ts +56 -0
  305. package/dist/sys/spawn.d.ts +176 -0
  306. package/dist/testing/clock.d.ts +17 -0
  307. package/dist/testing/fakeLlm.d.ts +74 -0
  308. package/dist/testing/fedLlm.d.ts +32 -0
  309. package/dist/testing/helpers.d.ts +344 -0
  310. package/dist/testing/index.d.ts +13 -0
  311. package/dist/testing/index.js +1 -0
  312. package/dist/testing/processes.d.ts +13 -0
  313. package/dist/testing/sandbox.d.ts +71 -0
  314. package/dist/testing/settlement.d.ts +6 -0
  315. package/dist/testing/tmpDirs.d.ts +17 -0
  316. package/dist/util/async.d.ts +8 -0
  317. package/dist/util/diff.d.ts +25 -0
  318. package/dist/util/dispatch.d.ts +8 -0
  319. package/dist/util/errors.d.ts +28 -0
  320. package/dist/util/foldState.d.ts +17 -0
  321. package/dist/util/freeze.d.ts +2 -0
  322. package/dist/util/ids.d.ts +2 -0
  323. package/dist/util/json.d.ts +37 -0
  324. package/dist/util/log.d.ts +6 -0
  325. package/dist/util/text.d.ts +21 -0
  326. package/dist/util/version.d.ts +2 -0
  327. package/package.json +175 -3
@@ -0,0 +1,75 @@
1
+ import type { Plugin } from '@leuduan/cordis';
2
+ import { z } from 'zod';
3
+ export declare const VerifyConfigSchema: z.ZodObject<{
4
+ command: z.ZodString;
5
+ cwd: z.ZodString;
6
+ }, z.core.$strict>;
7
+ export type VerifyConfig = z.input<typeof VerifyConfigSchema>;
8
+ /**
9
+ * A gate that holds a thread's answer while it has an unverified change: an `edit_files`
10
+ * result, a `run_command` other than the verification, or a background command's start or end,
11
+ * with no passing verification since. The verification is a `run_command` whose command text and
12
+ * working directory are the configured ones, run by the model like any other command, through the
13
+ * conversation's confirmation; the gate runs nothing itself.
14
+ *
15
+ * A verification counts only if its allowed attempt — the `tool/authorization` row written just
16
+ * before it starts — comes after the result row of the last other change, and its result says it
17
+ * ran to completion with exit code 0. Commands and edits are exclusive, so within one response a
18
+ * verification starts after the changes before it settled; the attempt still decides, as results
19
+ * land in model order and a change from elsewhere — a background command, a tool by another plugin
20
+ * under the same name — need not be. Until its outcome is known it is a possible change itself, since a
21
+ * formatter in the check rewrites files: one that passes proves its own changes and everything
22
+ * settled before it started; one that fails, is cancelled, times out, is interrupted or leaves
23
+ * processes behind leaves verification outstanding. A background command that ends after it
24
+ * started makes it stale; one still running at the stop is not held against the gate. A call that
25
+ * was never allowed to run, denied or rejected, changed nothing and is not counted.
26
+ *
27
+ * With an unverified change it sends the model back to run the command, at most
28
+ * {@link VERIFY_REMINDERS} times since the last change other than a verification run, or since the
29
+ * person last wrote, and then rejects the answer, so the turn ends `rejected`. When policy denied
30
+ * the latest verification attempt since the person last wrote, a read-only conversation say, it
31
+ * rejects at once, wherever that attempt's result landed among the changes' results.
32
+ *
33
+ * The {@link verify} service is the judge: the preset puts its verification in force on the thread
34
+ * it serves for as long as it is mounted (`ctx.verify.gate`), and tells the model of it. A
35
+ * requirement recorded for the assignment the thread serves on the same verification is judged
36
+ * with the gate, once: a barrier at its arming, with or without a change, counting its reminders
37
+ * and denials from it.
38
+ *
39
+ * So that the model need not learn the command from an objection, the thread is also told it up
40
+ * front, as a notice at the next model step whenever no notice it can still see says the same: on
41
+ * its first step, and again after a replacement took it away. The notice is neither a change nor a
42
+ * reminder.
43
+ *
44
+ * A pure fold over each thread's rows, not the current turn's, so a crash or an approval pause
45
+ * cannot hide an earlier turn's unverified work, and judging an answer again after a crash repeats
46
+ * nothing. The fold records what happened whatever the verification is, so it is one for every
47
+ * gate, and each verification is judged from it at the stop.
48
+ *
49
+ * The thread's delegated work is its own: a change made by any thread its calls started, at any
50
+ * depth, counts as the thread's, at its row, so a verification must have started after it. Every
51
+ * command a child ran counts, a passing run of the same verification included: a check may rewrite
52
+ * files, and a child's proof is not its caller's. Rows are numbered in one journal order across threads, so the two
53
+ * compare directly; a child's change also starts the count of reminders over. A child that is not
54
+ * loaded is read from the catalog, so this holds across a restart, and a child whose changes cannot
55
+ * be read rejects the answer at once rather than pass it. A thread an owner assigned, such as a
56
+ * workflow's isolated participant, is that owner's work, not its caller's. The preset is not handed
57
+ * down: a child is not gated itself.
58
+ *
59
+ * Installed per thread, with `cwd` resolved against the thread's cwd by the host; or mounted
60
+ * (`mountPreset`) from the setup of a preset placed on a thread, which gates that thread. Refuses
61
+ * to mount without the {@link verify} service.
62
+ */
63
+ export declare const verifyPreset: import("../../services/preset.js").Preset<z.ZodObject<{
64
+ command: z.ZodString;
65
+ cwd: z.ZodString;
66
+ }, z.core.$strict>>;
67
+ /**
68
+ * The `ctx.verify` service ({@link VerifyService}), the one judge of verification on every thread:
69
+ * the gates {@link verifyPreset} mounts, and the requirements an owner records for an assignment
70
+ * with `owed(...)`, whose threads require {@link VERIFY_OWNER}. Root-only, mounted once by the
71
+ * application, before anything mounts the preset.
72
+ */
73
+ export declare const verify: Plugin.Object<undefined>;
74
+ export { VERIFY_PRESET, VERIFY_REMINDERS } from './facts.js';
75
+ export { VERIFY_OWNER, type OwedVerification, type VerifyService } from './service.js';
@@ -0,0 +1 @@
1
+ import{o as T}from"../../chunks/EGZI4XQX.js";import"../../chunks/UD3VJER6.js";import"../../chunks/SGGMBSBA.js";import"../../chunks/3QCW4WDJ.js";import"../../chunks/C5LYCXJG.js";import"../../chunks/J5S4URAW.js";import{a as N}from"../../chunks/G74AGRAJ.js";import{a as C}from"../../chunks/SL2YLB2F.js";import"../../chunks/JPZFKSWT.js";import"../../chunks/RK3VP2Q4.js";import"../../chunks/74HKUGRR.js";import{a as V}from"../../chunks/QMMLQJBS.js";import"../../chunks/YIR5MYGU.js";import{a as F}from"../../chunks/L3N4FIEN.js";import"../../chunks/NAOUTU7A.js";import"../../chunks/UKXMCHHT.js";import"../../chunks/GQGNVSKB.js";import"../../chunks/DXFXAYDN.js";import{b as g,e as M}from"../../chunks/DRYAN665.js";import{d as O}from"../../chunks/2OSESBIL.js";import{o as w}from"../../chunks/YLNJXQ3Z.js";import"../../chunks/DDANMY45.js";import{h as S}from"../../chunks/37YOGDGY.js";import{a as R}from"../../chunks/KESCTXGO.js";import"../../chunks/TYTQRLTX.js";import"../../chunks/D7E6EWIE.js";import{isAbsolute as se,resolve as oe}from"node:path";import{z as E}from"zod";import{isAbsolute as H,resolve as y}from"node:path";import{z as d}from"zod";var p="verify",Y=2,Q="edit_files",X="run_command",q=d.strictObject({command:d.string(),cwd:d.string()}),z=g({plugin:"lagent:verify",kind:"notice",version:1,schema:q}),J=g({plugin:"lagent:verify",kind:"reminder",version:1,schema:q}),k=g({plugin:"lagent:verify",kind:"rejected",version:1,schema:d.strictObject({...q.shape,cause:d.enum(["denied","unverified"])})}),m=(n,e)=>JSON.stringify([n,e]);function Z(n,e){let{metadata:t}=n;return!n.is_error&&t.exit_code===0&&t.timed_out===!1&&t.aborted===!1&&t.stop_failed===!1&&typeof t.cwd=="string"&&y(t.cwd)===e}var P=(n,e)=>{let t=n.commands.get(e);return t===void 0&&(t={resultAt:null,failedAt:null,provenAt:null,decision:null},n.commands.set(e,t)),t},A=(n,e)=>{for(let t of[...n.reminders.keys()])t!==e&&n.reminders.delete(t)},h=S({key:"lagent:verify:facts",init:()=>({threadCwd:null,calls:new Map,changedAt:null,commands:new Map,personAt:null,reminders:new Map}),apply(n,e){switch(e.type){case"thread/spawned":n.threadCwd=y(e.data.environment.cwd);break;case"assistant/message":for(let t of e.data.response.message.tool_calls)t.arguments===null?n.calls.delete(t.call_id):t.name===Q?n.calls.set(t.call_id,{run:null,allowedAt:null}):t.name===X?n.calls.set(t.call_id,{run:ee(n,t.arguments),allowedAt:null}):n.calls.delete(t.call_id);break;case"tool/authorization":{let t=n.calls.get(e.data.call_id);if(t===void 0)break;e.data.decision==="allow"&&(t.allowedAt=e.seq),t.run!==null&&(P(n,t.run.key).decision={seq:e.seq,denied:e.data.decision==="deny"});break}case"tool/result":{let{result:t}=e.data,r=n.calls.get(t.call_id);if(n.calls.delete(t.call_id),r===void 0||r.allowedAt===null)break;if(r.run===null){n.changedAt=e.seq,A(n,null);break}let i=P(n,r.run.key);i.resultAt=e.seq,Z(t,r.run.cwd)?i.provenAt=Math.max(i.provenAt??0,r.allowedAt):i.failedAt=e.seq,A(n,r.run.key);break}case"ext":N.read(e)!==void 0&&(n.changedAt=e.seq,A(n,null));break;case"input/message":if(e.data.source===null)n.personAt=e.seq,n.reminders.clear();else{let t=J.readContribution(e);if(t!==void 0){let r=m(t.command,t.cwd);n.reminders.set(r,[...n.reminders.get(r)??[],e.seq])}}break;default:break}return n}});function ee(n,e){let t=e.command;if(typeof t!="string"||n.threadCwd===null)return{key:m(JSON.stringify(t??null),null),cwd:null};let r=e.workdir,i=typeof r=="string"&&r!==""?y(n.threadCwd,r):n.threadCwd;return{key:m(t,i),cwd:i}}var f=(n,e)=>n===null?e:e===null?n:Math.max(n,e);function ne(n){let e=n.changedAt;for(let t of n.commands.values())e=f(e,t.resultAt);return e}var j=C({key:"verify",version:1,schema:d.strictObject({changed_at:d.number().int().positive().nullable()}),applies:()=>!0,compute:(n,e)=>({changed_at:ne(n.state(h,e))})});function D(n,e){let t=new Set([e]),r=null;for(let i of n.origins.subtree(e,{self:!0})){let{origin:s,thread_id:o}=i;if(s===null||s.cause.kind==="assignment"||!t.has(s.caller_thread_id))continue;t.add(o);let a=j.read(n,o);if(a.status!=="available")return{unreadable:`agent ${o}: ${a.status==="unavailable"?a.reason:"its changes are not recorded"}`};r=f(r,a.value.changed_at)}return{at:r}}function _(n,e,t,r){let i=m(e.command,e.cwd),s=r;for(let[u,$]of n.commands)s=f(s,u===i?$.failedAt:$.resultAt);s=f(s,n.changedAt);let o=n.commands.get(i),a=o?.decision??null,c=f(n.personAt,t),l=f(t,r);return{mutatedAt:s,provenAt:o?.provenAt??null,denied:a!==null&&a.denied&&(c===null||a.seq>c),reminders:(n.reminders.get(i)??[]).filter(u=>l===null||u>l).length}}var te=d.strictObject({owner:d.string().min(1),assignment:d.string().min(1),generation:d.number().int().nonnegative(),input:d.string().min(1),command:d.string().trim().min(1),cwd:d.string().refine(H,"An absolute path")}),x=g({plugin:"lagent:verify",kind:"requirement",version:1,schema:te});function I(n){let e=x.parse(n);return{...e,cwd:y(e.cwd)}}var K=n=>JSON.stringify([n.owner,n.assignment,n.generation]),U=x.projection({key:"requirements",init:()=>new Map,onFork:"reset",apply(n,e,t){let r=K(e);return n.has(r)||n.set(r,{value:e,seq:t.seq}),n}});function W(n,e,t,r){let i=t?void 0:n.state(U,e).get(K(r));return i===void 0?[x.entry(r,{threadId:e})]:JSON.stringify(i.value)===JSON.stringify(r)?[]:{refuse:{message:`Verification for assignment ${r.assignment} is already owed on ${e}, differently`}}}function B(n,e){let t=n.state(U,e);if(t.size===0)return null;let{inputs:r}=n.state(w,e),i=T(n,e),s=null;for(let{value:o,seq:a}of t.values()){let c=r.get(o.input)?.claimedAt??null;if(c===null)continue;let l=Math.max(a,c);i!==null&&i>l||(s===null||s.at<l)&&(s={verification:{command:o.command,cwd:o.cwd},at:l})}return s}function L(n,e,t,r){let i=`\`${e.command}\` (in ${e.cwd})`;if("unreadable"in r)return k.rejection(`The changes of the work this conversation delegated cannot be read (${r.unreadable}), so ${i} cannot be shown to cover them.`,{...e,cause:"unverified"});let{mutatedAt:s,provenAt:o,denied:a,reminders:c}=_(n,e,t,r.at),l=f(s,t);if(l===null||o!==null&&o>l)return;let u=t!==null&&t===l;return a?k.rejection(`Verification is not allowed in this mode: ${i} was denied, so ${u?"the assignment is":"the changes since it last passed are"} unverified.`,{...e,cause:"denied"}):c>=Y?k.rejection(`${i} has not passed since ${u?"the assignment began":"the last change"}, after ${c} reminder${c===1?"":"s"} to run it.`,{...e,cause:"unverified"}):{decision:"continue",message:J.contribution({content:`Before finishing, run ${i} and fix what fails.`},e)}}import{resolve as G}from"node:path";import{Service as re}from"@leuduan/cordis";function ie(n){if(n.kind==="send")return null;if(n.kind==="create"){let{origin:i,spec:s}=n.opening;return{origin:i,requires:s.requires,installations:s.installations}}let{origin:e,requires:t,inherits:r}=n.opening;return{origin:e,requires:t,installations:r.installations}}var v="lagent:verify",b=class extends re{static inject=["threads","journal"];gates=new Map;constructor(e){super(e,"verify"),e.effect(()=>e.threads.registerOwner({owner:v}).dispose),e.effect(()=>e.journal.register(h)),j.register(e),e.on("lagent/turn/stop",t=>this.judge(t))}gate(e,t){let r=Symbol("verify gate"),i=this.gates.get(e);return i===void 0&&this.gates.set(e,i=new Map),i.set(r,{command:t.command,cwd:G(t.cwd)}),()=>{i.delete(r),i.size===0&&this.gates.get(e)===i&&this.gates.delete(e)}}owed(e){let{inputId:t,...r}=e,i=I({...r,input:t}),s=m(i.command,i.cwd);return o=>{let{threadId:a}=o,c=ie(o);if(!this.required(a,c))return{refuse:{message:`Thread ${a} owes verification, so it must require ${v}`}};let l=this.inPlace(a,c).find(u=>m(u.command,u.cwd)!==s);return l!==void 0?{refuse:{message:`Thread ${a} verifies with \`${l.command}\` (in ${l.cwd}), not the \`${i.command}\` (in ${i.cwd}) this assignment pins`}}:W(this.ctx.journal,a,c!==null,i)}}judge({threadId:e,observe:t}){t(()=>this.observed(e));let{judged:r,delegated:i}=this.reading(e);if(r.size===0)return;let s=this.ctx.journal.state(h,e),o;for(let{verification:a,armedAt:c}of r.values()){let l=L(s,a,c,i);if(l?.decision==="reject")return l;o??=l}return o}observed(e){let{judged:t,delegated:r}=this.reading(e),i=this.ctx.journal.state(h,e);return JSON.stringify([[...t].map(([s,{verification:o,armedAt:a}])=>[s,a,"unreadable"in r?null:_(i,o,a,r.at)]),r])}reading(e){let t=new Map,r=B(this.ctx.journal,e);for(let i of this.gates.get(e)?.values()??[])t.set(m(i.command,i.cwd),{verification:i,armedAt:null});return r!==null&&t.set(m(r.verification.command,r.verification.cwd),{verification:r.verification,armedAt:r.at}),{judged:t,delegated:t.size===0?{at:null}:D(this.ctx.journal,e)}}inPlace(e,t){return[...(t===null?[...this.ctx.journal.state(w,e).installations.current.values()].map(({presetId:s,config:o})=>({presetId:s,config:o})):t.installations.map(({preset_id:s,config:o})=>({presetId:s,config:o}))).flatMap(({presetId:s,config:o})=>{if(s!==p)return[];let{command:a,cwd:c}=o;return[{command:a,cwd:G(c)}]}),...this.gates.get(e)?.values()??[]]}required(e,t){let{owners:r}=this.ctx.journal.origins.requiredOwners(t??e);return r.some(({owner:i})=>i===v)}};var ae=E.strictObject({command:E.string().trim().min(1),cwd:E.string().refine(se,"An absolute path: resolve it against the thread's cwd before installing")}),Oe=F({id:p,placement:"thread",schema:ae,inject:["journal","verify"],setup(n,e,t){let r=V(n,"verify","verifyPreset"),i={command:e.command,cwd:oe(e.cwd)},s=`\`${i.command}\` (in ${i.cwd})`;M(n,{event:z,rank:1,current:()=>i,render:()=>R("verification",`This conversation verifies its work with ${s}: after changing files, run it and fix what fails before you finish.`)}),n.effect(()=>r.gate(t.thread.id,i))}}),Fe={name:"lagent:verify",inject:["threads","journal"],async apply(n){O(n,"verify"),await n.plugin(b)}};export{v as VERIFY_OWNER,p as VERIFY_PRESET,Y as VERIFY_REMINDERS,ae as VerifyConfigSchema,Fe as verify,Oe as verifyPreset};
@@ -0,0 +1,90 @@
1
+ import { Service, type Context } from '@leuduan/cordis';
2
+ import { type WriteRows } from '../../loop/index.js';
3
+ import { type Verification } from './facts.js';
4
+ declare module '@leuduan/cordis' {
5
+ interface Context {
6
+ /** Verification: the gates and assignment requirements of every thread (optional plugin). */
7
+ verify: VerifyService;
8
+ }
9
+ }
10
+ /**
11
+ * The constraint owner a thread owing verification requires (`requires` in its creation, its own
12
+ * or a thread's above it by origin): while the `verify` service is not mounted, the thread is held
13
+ * `missing`, and a judgment made without this registration does not end its turn (core's fence on
14
+ * required registrations).
15
+ */
16
+ export declare const VERIFY_OWNER = "lagent:verify";
17
+ /** The verification one assignment owes, as its owner records it with {@link VerifyService.owed}. */
18
+ export type OwedVerification = {
19
+ /** The owner that schedules the assignment, as an assignment origin names it. */
20
+ readonly owner: string;
21
+ /** The assignment's id. */
22
+ readonly assignment: string;
23
+ /** The participant generation serving it. */
24
+ readonly generation: number;
25
+ /** The input whose claim activates the assignment, which arms the requirement. */
26
+ readonly inputId: string;
27
+ /** The pinned verification: the command text `run_command` must be given. */
28
+ readonly command: string;
29
+ /** The absolute directory it must run in. */
30
+ readonly cwd: string;
31
+ };
32
+ /**
33
+ * Verification, the one judge of every thread's answers on it. Two things put a verification in
34
+ * force on a thread: a gate the verify preset mounts there ({@link gate}), which demands a pass
35
+ * after the last change; and the requirement an owner recorded for the assignment the thread
36
+ * serves ({@link owed}), armed when the assignment's input is claimed, which demands a pass after
37
+ * both its arming and the last change, whether or not the thread changed anything. A gate and a
38
+ * requirement on one verification are judged once, together; a later requirement supersedes an
39
+ * earlier one, as does a delegation task opened on the thread after it armed, and replaying one
40
+ * renews no reminder or denial.
41
+ *
42
+ * Each verification covers the thread's delegated work too: a change any thread its calls started
43
+ * made, at any depth, its passing runs of the same verification included, needs a pass after it, read from that thread's facts when it is loaded and
44
+ * otherwise from the catalog, which the service contributes every thread's changes to.
45
+ *
46
+ * It registers {@link VERIFY_OWNER}: a thread owing verification requires it, so while the service
47
+ * is not mounted the thread is held rather than its answer accepted unchecked.
48
+ */
49
+ export declare class VerifyService extends Service {
50
+ static inject: string[];
51
+ /** The gates mounted now, by thread: each mount's verification. */
52
+ private readonly gates;
53
+ constructor(ctx: Context);
54
+ /**
55
+ * Puts `verification` in force on `threadId` until the returned function is called: what the
56
+ * verify preset's setup does for the thread it serves, for as long as it is mounted.
57
+ */
58
+ gate(threadId: string, verification: Verification): () => void;
59
+ /**
60
+ * The rows recording `requirement` on the thread a write schedules its assignment on, for that
61
+ * write's `rows`. Decided inside the write, refused: unless the thread requires
62
+ * {@link VERIFY_OWNER}, by its own creation or a thread's above it by origin, so its run is held
63
+ * while this service is missing; when a verify preset installed on the thread, or a gate mounted
64
+ * there now, names another verification, which the two would demand in turn and never both pass;
65
+ * and for one recorded under the same assignment and generation differently. None for one
66
+ * recorded already exactly so: a replay renews nothing.
67
+ */
68
+ owed(requirement: OwedVerification): WriteRows;
69
+ /**
70
+ * The thread's say on its answer: every verification in force on it, each judged once, a gate's
71
+ * on the same verification as the requirement judged with the requirement's arming. Any rejection
72
+ * wins, then the first continuation. It declares what the say rests on (`observed`) whichever it
73
+ * is, an abstention too, so a change while another check awaited sends the answer to be judged again.
74
+ */
75
+ private judge;
76
+ /**
77
+ * What a verdict on the thread rests on, as one token: each verification in force with its arming
78
+ * and what its judgment reads of the thread's facts, and the last change of its delegated work.
79
+ */
80
+ private observed;
81
+ /**
82
+ * The verifications in force on the thread, by {@link commandKey}, each with the moment its
83
+ * requirement armed (`null` for a gate alone), and its delegated work's last change.
84
+ */
85
+ private reading;
86
+ /** The verifications the thread is configured with: its installed verify presets, and the gates mounted on it now. */
87
+ private inPlace;
88
+ /** Whether the thread, or one above it by origin, requires {@link VERIFY_OWNER}; its opening when the write opens it. */
89
+ private required;
90
+ }
@@ -0,0 +1,16 @@
1
+ import type { Context } from '@leuduan/cordis';
2
+ import { type Governance } from './policy.js';
3
+ /**
4
+ * Presents each instance to the threads working it at the model steps they take (§6 of the design),
5
+ * at rank 2, after the rank-1 notices of what is in force (sandbox, verification, permission mode):
6
+ * to its root, its assignment, with everything needed to work it, or the decision, block or cleanup
7
+ * it waits on; to an isolated participant's child, its own assignment. Contributed only when no
8
+ * notice the thread can still see says the same: at the step that claims the assignment's activation
9
+ * input, and again after compaction or a replacement took it away; a contribution never wakes the
10
+ * thread. An instance that ended is told so to its root once, and only while an earlier presentation
11
+ * that restricted it is still visible. Notice visibility decides what is told, never authority,
12
+ * which the activation's claim alone gives.
13
+ */
14
+ export declare function presentAssignments(ctx: Context, governance: Governance): void;
15
+ /** A host decision's verdict as the model is told it: what was decided, never who decided it. */
16
+ export declare function verdictOf(verdict: 'approve' | 'revise'): string;
@@ -0,0 +1,95 @@
1
+ import type { ReadonlyJsonValue } from '../../util/json.js';
2
+ import type { CanonicalDefinition } from './definition.js';
3
+ import type { InstanceState, ResultDecision } from './fold.js';
4
+ import type { Acquired } from './providers.js';
5
+ import type { ReadonlyState } from '../../util/foldState.js';
6
+ import { type Entered, type InstanceRowInput, type TransitionCause } from './record.js';
7
+ /**
8
+ * The results no longer current: each retired by its own step's re-entry (and `retiring`, retired
9
+ * by an entry being planned), and transitively each result whose attempt bound a stale one as a
10
+ * `current` input. Historical bindings need no freshness. A result binds only results accepted
11
+ * before it, so one pass in acceptance order settles every chain.
12
+ */
13
+ export declare const staleResults: (state: ReadonlyState<InstanceState>, retiring?: ReadonlySet<string>) => Set<string>;
14
+ /**
15
+ * The results that were no longer current when row `seq` was recorded: retired by the entries
16
+ * recorded up to it, and what was bound to those. What went stale after it is the difference from
17
+ * {@link staleResults}.
18
+ */
19
+ export declare function staleAsOf(state: ReadonlyState<InstanceState>, seq: number): Set<string>;
20
+ /** A recorded decision as the routing envelope carries it. */
21
+ export declare function resultDecision(state: ReadonlyState<InstanceState>, decision: string | null): ResultDecision | null;
22
+ /**
23
+ * The value input `name` of an attempt was bound to, as recorded: immutable results make a result's
24
+ * citation exact, and evidence is read from the entry that recorded it, never acquired again.
25
+ */
26
+ export declare function boundValue(state: ReadonlyState<InstanceState>, entered: ReadonlyState<Entered>, name: string): ReadonlyJsonValue;
27
+ /**
28
+ * A decision being planned in the same write as the entry: what it records on `result` (`null` for
29
+ * a recovery's), and the persistent participants it restarts, whose new generation the entry pins.
30
+ */
31
+ export type Deciding = {
32
+ readonly result: string | null;
33
+ readonly id: string;
34
+ readonly decision: ResultDecision;
35
+ readonly restart: readonly string[];
36
+ };
37
+ /** An entry refused: the input that could not be bound, and why. Nothing is retired or consumed. */
38
+ export type EntryRefusal = {
39
+ readonly refused: string;
40
+ };
41
+ /** The evidence an entry needs before it can be planned: what to acquire, for exactly this attempt. */
42
+ export type EvidenceNeeds = {
43
+ readonly transition: string;
44
+ readonly attempt: string;
45
+ readonly step: string;
46
+ readonly inputs: readonly {
47
+ readonly input: string;
48
+ readonly provider: string;
49
+ }[];
50
+ };
51
+ /** Evidence acquired outside the write, for one transition into one attempt, by input. */
52
+ export type EntryEvidence = {
53
+ readonly transition: string;
54
+ readonly attempt: string;
55
+ readonly inputs: ReadonlyMap<string, Acquired>;
56
+ };
57
+ /**
58
+ * Plans entering `step`, atomically: re-entry retires the step's current result, then every input
59
+ * binds against what remains, then the attempt opens with its assignments. The plan is one
60
+ * `entered` row, so its write retires, binds, opens and consumes the step's allowance together, or,
61
+ * refused, does none of it. Each assignment records where it runs and what activates it: the
62
+ * conversation participant's runs on the root, activated by `activation`, the host's first input at
63
+ * opening and the transition's scheduling input after; an isolated participant's runs as the task
64
+ * of its assignment on the child of its generation (the one a restart being decided gives it), its
65
+ * task's input activating it.
66
+ *
67
+ * - A `current` binding needs the producer's current result, approved if the step is gated; an
68
+ * optional one binds `null` only when the producer has accepted nothing (for that participant).
69
+ * A stale or unapproved result is not absence. The step's own current result is always retired
70
+ * by its entry, so an optional current self-binding binds `null`.
71
+ * - A `historical` binding takes the producer's latest accepted result, retired or stale included,
72
+ * such as the one this entry retires; optional when there is none yet.
73
+ * - An isolated participant the opening did not pin (one the definition registered now added, or
74
+ * moved off the conversation) cannot run: the entry is refused.
75
+ * - An evidence binding takes what its provider acquired for this very attempt (`evidence`), with
76
+ * the provider's citation, the value recorded in the row; once every other input binds, what is
77
+ * not acquired yet is returned as `needs`. Absence binds `null` when the binding is optional and
78
+ * refuses the entry otherwise; an unavailable answer refuses it either way.
79
+ */
80
+ export declare function planEntry(state: ReadonlyState<InstanceState>, definition: CanonicalDefinition, request: {
81
+ readonly instance: string;
82
+ readonly step: string;
83
+ readonly cause: TransitionCause;
84
+ readonly activation: string;
85
+ /** The decision this entry's write records, which bindings already see. */
86
+ readonly deciding?: Deciding;
87
+ /** Evidence acquired for the entry; used only when it is for this very transition and attempt. */
88
+ readonly evidence?: EntryEvidence;
89
+ }): {
90
+ readonly row: Extract<InstanceRowInput, {
91
+ op: 'entered';
92
+ }>;
93
+ } | EntryRefusal | {
94
+ readonly needs: EvidenceNeeds;
95
+ };
@@ -0,0 +1,38 @@
1
+ import type { Context } from '@leuduan/cordis';
2
+ import type { AppendEntry } from '../../journal/index.js';
3
+ import { type InstanceState } from './fold.js';
4
+ import type { InstanceRowInput } from './record.js';
5
+ import type { Barrier } from './routing.js';
6
+ import type { ReadonlyState } from '../../util/foldState.js';
7
+ /**
8
+ * The one evidence barrier an instance's cancellation, its pending recovery's decision, the restarts
9
+ * that decision names and the successor it opens all wait on (decision 18 of the slice-2 plan). The
10
+ * lifetime owners answer for their own work, from durable evidence ({@link workUnder}): commands for
11
+ * whether each command ended, delegations for each task's settlement, cleanup and stop
12
+ * acknowledgement, and for whether a conversation can take another task (`continuation`). This
13
+ * combines them over what the instance owns:
14
+ *
15
+ * - an admitted cancellation: everything under the root;
16
+ * - a pending recovery: its attempt's isolated participants' children and everything under them,
17
+ * with the root's stops of them; on a mixed step, whose root assignment it superseded too, also
18
+ * the root's own work: its commands, the threads it started and the run that was under way at
19
+ * the recovery's boundary; and each persistent participant's conversation, which is
20
+ * draining while delegations says to wait, unknown while it cannot be asked (delegations not
21
+ * mounted, the child not loaded), unresolved while its task state cannot be read, and
22
+ * uncontinuable, so a decision must restart it, once delegations refuses it more work.
23
+ *
24
+ * Either way, a participant's start still in flight (`starting`, its assignments) is work still
25
+ * ending: it may yet open a task, or find its assignment superseded and open none. Anything else
26
+ * waits on nothing. Read synchronously, inside a write or while the threads it reads are held loaded.
27
+ */
28
+ export declare function barrierOf(ctx: Context, state: ReadonlyState<InstanceState>, starting: readonly string[]): Barrier;
29
+ /**
30
+ * The stop obligation, for the root write that records `row`, over the tasks a recovery it opens
31
+ * leaves running: when one of its observations ends a task without acceptance, the attempt recovers,
32
+ * and every other open isolated assignment's task that delegations' records show open or still
33
+ * draining is stopped for good, so nothing of the attempt keeps working while a person decides.
34
+ * Delegations carries it out from that write, or at its next repair. None otherwise.
35
+ */
36
+ export declare function siblingStops(ctx: Context, state: ReadonlyState<InstanceState>, row: Extract<InstanceRowInput, {
37
+ op: 'observed';
38
+ }>): AppendEntry<'ext'>[];
@@ -0,0 +1,184 @@
1
+ import { z } from 'zod';
2
+ import { type ThinkingEffort } from '../../llm/index.js';
3
+ import { type ReadonlyJsonValue } from '../../util/json.js';
4
+ import type { ResultDecision } from './fold.js';
5
+ /** The edge target that completes an instance. */
6
+ export declare const COMPLETE = "$complete";
7
+ /** A value an edge predicate compares a field with. */
8
+ export type JsonScalar = string | number | boolean | null;
9
+ /** An isolated participant's model: a default, and whether the instance's starter may change it. */
10
+ export type ParticipantModel = {
11
+ readonly provider: string;
12
+ readonly model: string;
13
+ readonly thinkingEffort?: ThinkingEffort;
14
+ readonly configurable: boolean;
15
+ };
16
+ export type Participant =
17
+ /** The root's own agent. */
18
+ {
19
+ readonly context: 'conversation';
20
+ }
21
+ /** A delegated agent the workflow starts itself, under a host-bound role. */
22
+ | {
23
+ readonly context: 'isolated';
24
+ readonly lifetime: 'instance' | 'attempt';
25
+ readonly role: string;
26
+ readonly model: ParticipantModel;
27
+ };
28
+ export type Binding = {
29
+ /** The instance's input, a step's whole result, or one participant's output in it. */
30
+ readonly source: '$input' | {
31
+ readonly step: string;
32
+ readonly participant?: string;
33
+ };
34
+ readonly mode: 'current' | 'historical';
35
+ readonly optional: boolean;
36
+ }
37
+ /** A host-bound evidence provider, resolved at attempt entry. */
38
+ | {
39
+ readonly evidence: string;
40
+ readonly optional: boolean;
41
+ };
42
+ export type Assignment = {
43
+ readonly participant: string;
44
+ /** The step inputs this assignment receives. */
45
+ readonly reads: readonly string[];
46
+ readonly prompt: string;
47
+ readonly output: z.ZodType;
48
+ /** Host-bound check providers judging an isolated participant's answer; omitted = []. */
49
+ readonly checks?: readonly string[];
50
+ };
51
+ /** A choice a person may attach to a `revise`, with the decision reasons it may accompany. */
52
+ export type StepOption = {
53
+ readonly name: string;
54
+ readonly on: readonly ('gate' | 'recovery')[];
55
+ };
56
+ /** One condition of an edge: the JSON Pointer `field` of the routing envelope equals `equals`. */
57
+ export type Condition = {
58
+ readonly field: string;
59
+ readonly equals: JsonScalar;
60
+ };
61
+ export type Edge = {
62
+ readonly when: readonly Condition[] | 'otherwise';
63
+ readonly to: string;
64
+ };
65
+ export type Step = {
66
+ readonly inputs: Readonly<Record<string, Binding>>;
67
+ readonly assignments: readonly Assignment[];
68
+ /** A person's decision after every assignment is accepted. */
69
+ readonly gate: boolean;
70
+ /** Omitted = []. */
71
+ readonly options?: readonly StepOption[];
72
+ /** A host-bound allowlist policy name; `null` adds no step restriction. */
73
+ readonly restriction: string | null;
74
+ readonly maxAttempts: number;
75
+ /** Evaluated in order over the step's result; the first match is taken. The last is `otherwise`. */
76
+ readonly edges: readonly Edge[];
77
+ };
78
+ /**
79
+ * A workflow as its author writes it, handed to {@link defineWorkflow}. Its `id` is its whole
80
+ * identity: an edit that keeps the procedure's meaning (a prompt, a schema, an allowance) keeps the
81
+ * id and applies to running instances from their next action; a breaking one gets a new id.
82
+ */
83
+ export type Definition = {
84
+ readonly id: string;
85
+ /** The instance's input. */
86
+ readonly input: z.ZodType;
87
+ readonly entry: string;
88
+ /** Host-bound checks on the conversation participant's agent; omitted = []. */
89
+ readonly prerequisites?: readonly string[];
90
+ readonly participants: Readonly<Record<string, Participant>>;
91
+ readonly steps: Readonly<Record<string, Step>>;
92
+ };
93
+ /** A definition's data with every omitted list filled in: what is validated. */
94
+ export type DefinitionData = Omit<Definition, 'prerequisites' | 'steps'> & {
95
+ readonly prerequisites: readonly string[];
96
+ readonly steps: Readonly<Record<string, Omit<Step, 'options' | 'assignments'> & {
97
+ readonly options: readonly StepOption[];
98
+ readonly assignments: readonly (Assignment & {
99
+ readonly checks: readonly string[];
100
+ })[];
101
+ }>>;
102
+ };
103
+ /** A schema as its JSON Schema rendering: what the model is shown and an instance records. */
104
+ export type JsonSchema = {
105
+ readonly [key: string]: ReadonlyJsonValue;
106
+ };
107
+ /**
108
+ * A definition as plain JSON: its data, omitted lists filled in, with every schema replaced by its
109
+ * rendering. It is the readable copy an instance records for audit and display, never executed.
110
+ */
111
+ export type CanonicalDefinition = Omit<DefinitionData, 'input' | 'steps'> & {
112
+ readonly input: JsonSchema;
113
+ readonly steps: Readonly<Record<string, Omit<DefinitionData['steps'][string], 'assignments'> & {
114
+ readonly assignments: readonly (Omit<DefinitionData['steps'][string]['assignments'][number], 'output'> & {
115
+ readonly output: JsonSchema;
116
+ })[];
117
+ }>>;
118
+ };
119
+ /**
120
+ * A defined workflow: a frozen, canonical copy of the author's definition, admitted. Only
121
+ * {@link defineWorkflow} makes one, and registration takes nothing else. Its validators are rebuilt
122
+ * from the admitted schemas and held apart ({@link schemaOf}), so nothing the host holds, and
123
+ * nothing reachable from the definition, can change what it validates.
124
+ */
125
+ export type WorkflowDefinition = CanonicalDefinition;
126
+ /** A definition refused, with every problem found. */
127
+ export declare class WorkflowDefinitionError extends Error {
128
+ readonly workflow: string;
129
+ readonly problems: readonly string[];
130
+ constructor(workflow: string, problems: readonly string[]);
131
+ }
132
+ export declare const isWorkflowDefinition: (value: unknown) => value is WorkflowDefinition;
133
+ /** The schema `definition` validates its input, or one assignment's output, with; for this plugin only. */
134
+ export declare function schemaOf(definition: WorkflowDefinition, target: '$input' | {
135
+ readonly step: string;
136
+ readonly participant: string;
137
+ }): z.ZodType;
138
+ /**
139
+ * Admits a workflow definition (§5 of the design): checks its shape, schemas and graph, then copies
140
+ * and freezes it. Every problem is reported at once in a {@link WorkflowDefinitionError}.
141
+ * Later changes to the object passed in change nothing about the definition returned. Names the host
142
+ * binds (restrictions, prerequisites, roles, providers) are checked when the definition is registered.
143
+ */
144
+ export declare function defineWorkflow(definition: Definition): WorkflowDefinition;
145
+ /** Splits a JSON Pointer into unescaped tokens, or `undefined` when it is not one. */
146
+ export declare function pointerTokens(pointer: string): string[] | undefined;
147
+ /** What a step's edges test: its accepted outputs by participant, and the decision on them. */
148
+ export type Envelope = {
149
+ readonly outputs: Readonly<Record<string, ReadonlyJsonValue>>;
150
+ readonly decision: ResultDecision | null;
151
+ };
152
+ /**
153
+ * The edge routing takes: the first, in declaration order, whose every condition holds over
154
+ * `envelope`; a missing field holds no condition. Registration makes the last edge `otherwise`, so
155
+ * one always matches.
156
+ */
157
+ export declare function selectEdge(edges: readonly Edge[], envelope: Envelope): Edge;
158
+ /** What a recovery's revise with `option` routes over: no outputs, and the decision. */
159
+ export declare const recoveryEnvelope: (option: string, feedback: string | null) => Envelope;
160
+ /**
161
+ * Why `edge`, selected for a recovery's revise with `option`, cannot take it, or `null`: it must
162
+ * guard both `/decision/reason = recovery` and `/decision/option = option`, so an `otherwise` or a
163
+ * match that happens to hold never routes a recovery, and it must enter a step, not complete the
164
+ * instance, which a recovery has no result to complete with.
165
+ */
166
+ export declare function recoveryEdgeProblem(edge: Edge, option: string): string | null;
167
+ /** What a host binds by name for its definitions: what registration checks they name. */
168
+ export type DefinitionBindings = {
169
+ /** Restriction policies, by name. */
170
+ readonly restrictions: ReadonlySet<string>;
171
+ /** Prerequisites the host checks, by name. */
172
+ readonly prerequisites: ReadonlySet<string>;
173
+ /** Roles isolated participants run under, by name. */
174
+ readonly roles: ReadonlySet<string>;
175
+ /** Check providers, by name. */
176
+ readonly checks: ReadonlySet<string>;
177
+ /** Evidence providers, by name. */
178
+ readonly evidence: ReadonlySet<string>;
179
+ };
180
+ /**
181
+ * Why `definition` cannot be registered against `bindings`: names it uses that the host does not
182
+ * bind. Whether a bound provider is available is asked at each opening, never here.
183
+ */
184
+ export declare function bindingProblems(definition: WorkflowDefinition, bindings: DefinitionBindings): string[];