@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,307 @@
1
+ import type { InboxTarget, InstallationLifetime, InterruptionPolicy, JournalEvent, QueuedInput, Seq, ThreadEnvironment, ThreadFork, ThreadOrigin, TurnEndReason } from '../models/index.js';
2
+ import type { ReadonlyState } from '../util/foldState.js';
3
+ import type { DeepReadonly, JsonValue, ReadonlyJsonValue } from '../util/json.js';
4
+ import type { ConversationMessage, ModelRoute, ParsedToolCall, PromptBlock, ResponseFinish, ToolCall, ToolSpec } from '../llm/index.js';
5
+ import type { Journal } from '../journal/index.js';
6
+ import type { Reducer } from './threadState.js';
7
+ /**
8
+ * Where a thread is in its turns: the highest one opened, how many steps it has taken, how it ended,
9
+ * and whether a tool asked it to stop.
10
+ *
11
+ * `step` counts `step/start` since the last `turn/start`, so it is only meaningful while that turn
12
+ * is in flight — a finished turn's count says nothing about the next one. It is folded rather than
13
+ * counted in memory so the loop's decision stays a function of the journal across a restart.
14
+ * `turnOpen` holds while a turn is in flight — including one whose process died, which the thread
15
+ * closes as `interrupted` before it opens another.
16
+ *
17
+ * A fork continues the turn numbering and inherits `concludedTurn`, so a fork taken after a
18
+ * concluding result is not owed a reply either. Everything else here describes the source's
19
+ * execution and resets: a fork has no turn in flight and no outcome of its own, even when it was cut
20
+ * inside one of its source's turns.
21
+ */
22
+ export declare const turnBoundary: Reducer<{
23
+ lastTurn: number;
24
+ step: number;
25
+ /** How this thread's own last turn ended; `null` before its first ends, or while one is open. */
26
+ lastReason: TurnEndReason | null;
27
+ turnOpen: boolean;
28
+ /**
29
+ * The turn in which a tool result asked for the turn to end, until input arrives. Holds across
30
+ * the turn boundary: the concluding result is not a reply the model owes, so nothing happens until
31
+ * someone sends something new — but only the turn it landed in is cut short by it.
32
+ */
33
+ concludedTurn: number | null;
34
+ }>;
35
+ /** Whether a thread's latest answer has been judged by its stop checks. */
36
+ export type AnswerCheck = {
37
+ status: 'none';
38
+ } | ({
39
+ status: 'pending' | 'accepted' | 'rejected';
40
+ seq: Seq;
41
+ text: string;
42
+ } & ({
43
+ kind: 'reply';
44
+ finish: ResponseFinish;
45
+ } | {
46
+ kind: 'concluded';
47
+ }));
48
+ /**
49
+ * The conversation's latest answer — a reply with no tool calls, or a result that concluded the
50
+ * turn — and whether a stop check has judged it.
51
+ *
52
+ * An answer is `pending` from the moment it is recorded until its turn ends `completed` (accepted)
53
+ * or `rejected`. Every other ending leaves it pending, so a check a crash, an abort or a failing
54
+ * listener cut short is still owed; new input supersedes the answer altogether. Folded from rows
55
+ * the loop writes anyway, so there is no marker for a crash to fall in front of.
56
+ *
57
+ * A fork resets it (see `threadState`'s fork table); a fork is never cut where a check is still owed,
58
+ * so nothing is lost.
59
+ */
60
+ export declare const answerCheck: Reducer<AnswerCheck>;
61
+ /**
62
+ * Calls dispatched and not yet answered, and the row that recorded the dispatch.
63
+ *
64
+ * Bookkeeping, not truth: what a turn still owes answers for is {@link unansweredToolCalls}, read
65
+ * off the conversation. This exists so a re-dispatched call can cite its original `tool/call` rather
66
+ * than recording a second one.
67
+ */
68
+ export declare const dispatchedCalls: Reducer<Map<string, Seq>>;
69
+ /** One dispatch attempt of a call: its `tool/authorization` row, and what became of it. */
70
+ export type DispatchAttempt = {
71
+ /** The `tool/authorization` row: the attempt itself. */
72
+ seq: Seq;
73
+ /** The `tool/call` row the attempt dispatched. */
74
+ call_seq: Seq;
75
+ turn: number;
76
+ decision: JournalEvent<'tool/authorization'>['data']['decision'];
77
+ /** What the tool declared, at this attempt, a re-dispatch may do if the attempt is interrupted. */
78
+ policy: InterruptionPolicy;
79
+ };
80
+ /**
81
+ * The latest dispatch attempt of every call that has no result yet, by call id.
82
+ *
83
+ * An attempt is written immediately before the tool is invoked, so an allowed attempt with no
84
+ * result, from a turn that has since closed, of a call that did not suspend, is a call the process
85
+ * was cut off in: the tool may have begun. {@link abandonedAttempt} reads that; the policy recorded with the attempt
86
+ * decides what a re-dispatch may do. A new `tool/call` under a reused provider id starts a new call
87
+ * with no attempt; a result clears the call's attempt.
88
+ */
89
+ export declare const dispatchAttempts: Reducer<Map<string, DispatchAttempt>>;
90
+ /**
91
+ * The attempt of `callId` that was abandoned, if any: allowed, so the tool may have begun;
92
+ * unanswered; of the `tool/call` row being dispatched now, not of an earlier call that reused the
93
+ * provider's id; of a call that is not suspended (`waits`), since a waiting call returned on purpose
94
+ * and one whose wait resolved is dispatched again from its recorded value, however often a crash
95
+ * cuts that dispatch off; and from a turn before `currentTurn`, so the process that made it is gone —
96
+ * every earlier turn is closed before a new one opens. Read before a new attempt is recorded, so the
97
+ * judgment is about the attempt that was cut off.
98
+ */
99
+ export declare function abandonedAttempt(state: ReadonlyMap<string, DispatchAttempt>, waits: ReadonlyMap<Seq, WaitEntry>, callId: string, callSeq: Seq, currentTurn: number): DispatchAttempt | undefined;
100
+ /** A call's `wait/declared` row, as the waits fold keeps it. */
101
+ export type WaitDeclaration = {
102
+ /** The `wait/declared` row. */
103
+ readonly seq: Seq;
104
+ readonly turn: number;
105
+ readonly step: number;
106
+ readonly call_id: string;
107
+ readonly call_seq: Seq;
108
+ readonly owner: string;
109
+ readonly dependency: {
110
+ readonly [key: string]: ReadonlyJsonValue;
111
+ };
112
+ readonly deadline_at: number | null;
113
+ readonly reason: string;
114
+ };
115
+ /** One declared wait: its declaration, the value it resolved with, and whether its call was answered. */
116
+ export type WaitEntry = {
117
+ readonly declaration: WaitDeclaration;
118
+ value: {
119
+ readonly [key: string]: ReadonlyJsonValue;
120
+ } | null;
121
+ /** The call's `tool/result` landed: by its dispatch from the value, or by a cancel. */
122
+ answered: boolean;
123
+ };
124
+ /**
125
+ * Every wait the thread declared, by `call_seq`, kept after its call is answered, so answer-once can
126
+ * report a value recorded before. A fork starts with none: it is never cut with a call unanswered.
127
+ */
128
+ export declare const waits: Reducer<Map<Seq, WaitEntry>>;
129
+ /** Declared, with no value and no answer: what holds the thread, and what its owner still resolves. */
130
+ export declare const isUnresolved: (entry: WaitEntry | undefined) => boolean;
131
+ /** Declared and unanswered, resolved or not: the waiting call's authority, which a cancel answers. */
132
+ export declare const isSuspended: (entry: WaitEntry | undefined) => boolean;
133
+ /** The thread's suspended waits, in declaration order. */
134
+ export declare const suspendedWaits: (state: ReadonlyMap<Seq, WaitEntry>) => WaitEntry[];
135
+ /**
136
+ * Tool calls on the last assistant message that have no result yet.
137
+ *
138
+ * Derived from the conversation, not from `tool/call` rows, because the conversation is what a
139
+ * provider validates: a message holding calls must be followed by a result for each one. Calls are
140
+ * recorded one row at a time, so a hard kill part-way through that burst leaves a thread with fewer
141
+ * `tool/call` rows than the model asked for — nothing "pending", and a conversation nothing could
142
+ * answer. Reading the assistant message instead makes the two agree by construction.
143
+ */
144
+ export declare function unansweredToolCalls(messages: readonly DeepReadonly<ConversationMessage>[]): DeepReadonly<ToolCall>[];
145
+ export type ConfirmationState = {
146
+ request_id: string;
147
+ thread_id: string;
148
+ /** The `tool/call` row this request was raised for — the dispatch it belongs to. */
149
+ call_seq: Seq | null;
150
+ tool_call: ParsedToolCall;
151
+ reason: string;
152
+ resolution: {
153
+ approved: boolean;
154
+ rejection_message: string | null;
155
+ } | null;
156
+ };
157
+ /**
158
+ * A thread's confirmation requests and their answers, keyed by request id. Thread-scoped: an answer
159
+ * is written on the thread that asked, so a thread's confirmations are a function of its own rows.
160
+ * A fork starts with none: a fork is never cut with a request still open, and an inherited answer
161
+ * belongs to a call the source already finished.
162
+ */
163
+ export declare const confirmations: Reducer<Map<string, ConfirmationState>>;
164
+ /** Requests still waiting on the user on one thread. */
165
+ export declare const outstandingConfirmations: (state: ReadonlyMap<string, ReadonlyState<ConfirmationState>>, threadId: string) => ReadonlyState<ConfirmationState>[];
166
+ /**
167
+ * Calls one thread must not dispatch now, by call id: those waiting on a user's answer, and those
168
+ * whose wait has not resolved. Neither is turn-bound: dispatching again before the answer or the
169
+ * value would only raise a second request, or declare the wait twice.
170
+ */
171
+ export declare const parkedCallIds: (confirmationState: ReadonlyMap<string, ReadonlyState<ConfirmationState>>, waitState: ReadonlyMap<Seq, WaitEntry>, threadId: string) => Set<string>;
172
+ /**
173
+ * How a dispatch was answered, if it was ever asked about. `undefined` means nobody has been asked —
174
+ * which is what tells a re-dispatched call to go through authorization again rather than assume.
175
+ *
176
+ * Matched on the `tool/call` row rather than the provider's call id: two threads, or two turns of
177
+ * one thread, may legitimately see the same id, and an approval must not carry across.
178
+ */
179
+ export declare const approvalFor: (state: Map<string, ConfirmationState>, dispatch: {
180
+ threadId: string;
181
+ callId: string;
182
+ callSeq: Seq | null;
183
+ }) => {
184
+ approved: boolean;
185
+ rejection_message: string | null;
186
+ } | undefined;
187
+ export type ThreadRecord = {
188
+ thread_id: string;
189
+ agent_name: string;
190
+ metadata: JournalEvent<'thread/spawned'>['data']['metadata'];
191
+ /** The source thread and row this thread was forked at; `null` unless it is a fork. */
192
+ fork: ThreadFork | null;
193
+ origin: ThreadOrigin | null;
194
+ environment: ThreadEnvironment;
195
+ /** The constraint owners the thread's runs are under. */
196
+ requires: readonly string[];
197
+ /** The `thread/spawned` row. */
198
+ seq: Seq;
199
+ };
200
+ /**
201
+ * A thread's identity, lineage and environment, from its spawn row. A fork's lineage replays its
202
+ * source's spawn row first and its own after it, so the fork's record is its own. The set of all
203
+ * threads is the journal's catalog, not a fold.
204
+ */
205
+ export declare const threadRecord: Reducer<ThreadRecord | null>;
206
+ /** The thread's latest `confirm/resolved` row, or `null`: what tells a parked caller an answer landed under it. */
207
+ export declare const lastAnswer: Reducer<Seq | null>;
208
+ /**
209
+ * The thread's route: the one its spawn row was born with, replaced by each cause that changed it.
210
+ * A lineage fold: a fork, born with none of its own, goes on with the route its inherited rows fold
211
+ * to at the cut, which keeps it on the model whose cache holds its history. Nothing else changes it:
212
+ * not turns, settlements, cancels or compaction. `null` only before a spawn row, which no thread lacks.
213
+ */
214
+ export declare const threadRoute: Reducer<ModelRoute | null>;
215
+ /**
216
+ * The system prompt a thread sends: the latest `thread/prompt` row, or none yet. A fork inherits
217
+ * it and never renders its own, so it sends its source's exact prompt.
218
+ */
219
+ export declare const threadPrompt: Reducer<PromptBlock[] | null>;
220
+ /**
221
+ * The tool specifications a thread's requests send: the latest `thread/tools` row, or none before
222
+ * its first request. Read at a request's seq, what that request sent. A fork inherits it.
223
+ */
224
+ export declare const threadTools: Reducer<readonly ToolSpec[] | null>;
225
+ /**
226
+ * Whether a fork has yet to claim the task it was created with. A fork cut at a request inherits a
227
+ * conversation that ends on input its source is answering. Created to regenerate that answer, the
228
+ * fork owes it; created with a task, it owes only the task. So a task discarded before it was
229
+ * claimed — by `cancel()` — leaves the fork with nothing to do, rather than answering its source's
230
+ * request. Any input the fork records settles it.
231
+ */
232
+ export declare const forkTask: Reducer<{
233
+ spawnSeq: Seq | null;
234
+ unclaimed: boolean;
235
+ }>;
236
+ export type InboxState = Record<InboxTarget, QueuedInput[]>;
237
+ /**
238
+ * Input waiting for a turn or a step boundary. Durable, so a crash does not lose a queued message.
239
+ * A fork starts with nothing queued: its source's queued input is not the fork's.
240
+ */
241
+ export declare const inbox: Reducer<InboxState>;
242
+ /** Where one input id's life is recorded: the row that queued it, and the step's row that claimed it. */
243
+ export type InputRows = {
244
+ readonly queuedAt: Seq;
245
+ readonly claimedAt: Seq | null;
246
+ };
247
+ /**
248
+ * Every input id this thread was ever handed: the row that queued it and, once a step took it, the
249
+ * `input/message` that claimed it. Never forgets: this is what makes `send` with an explicit id
250
+ * idempotent across a re-dispatch or a restart, and why a withdrawn or cancelled id stays
251
+ * spent. A fork starts over: the ids its source was handed are the source's.
252
+ */
253
+ export declare const inputs: Reducer<Map<string, InputRows>>;
254
+ /**
255
+ * How the run that began after a row ended, and what it answered, read from the thread's events
256
+ * after that row. A run's outcome, not a delegation task's: an `aborted` turn ends a run, while a
257
+ * task stays open across it (the delegations plugin's own fold).
258
+ */
259
+ export type RunOutcome = {
260
+ /** The last turn ending seen for this run, if any. */
261
+ reason: TurnEndReason | null;
262
+ /**
263
+ * The accepted answer: the reply, or the output of the tool result that concluded the turn. Empty
264
+ * until the run has answered — a provisional or rejected answer is not one.
265
+ */
266
+ output: string;
267
+ /** Whether the conversation has reached an answer: a complete reply, or a result that concluded the turn. */
268
+ answered: boolean;
269
+ };
270
+ /**
271
+ * How the run that began after `fromSeq` ended, and what it answered.
272
+ *
273
+ * The `answerCheck` reducer folded over the rows after `fromSeq`: the same rule the loop and its stop
274
+ * checks read, so an answer is a complete reply with nothing left to call, or a tool result that
275
+ * concluded the turn, and it becomes the run's answer only at the `turn/end(completed)` that
276
+ * accepted it. A process that died before that ending leaves it unaccepted, and the scan goes on to
277
+ * the turn that checks it. Scanning stops at the first turn ending that settles the run, answered or
278
+ * failed outright, so a later turn of the same thread is never mistaken for this run's.
279
+ */
280
+ export declare function outcomeSince(journal: Journal, threadId: string, fromSeq: Seq): RunOutcome;
281
+ /** A turn ending after which the run will not produce an answer without new input. */
282
+ export declare const isRunFailure: (reason: TurnEndReason | null) => boolean;
283
+ /** One installation a thread holds, as its folds read it. */
284
+ export type InstallationRecord = {
285
+ readonly installationId: string;
286
+ readonly presetId: string;
287
+ /** The validated configuration, defaults included: exactly what `setup` receives. */
288
+ readonly config: JsonValue;
289
+ /**
290
+ * `defining` for one recorded as such in its thread's spawn row, on this thread or on the one a
291
+ * fork inherited it from, which cannot be removed; `configurable` for any other, one applied
292
+ * later included.
293
+ */
294
+ readonly lifetime: InstallationLifetime;
295
+ };
296
+ /** A thread's installations: the current ones in application order, and every id it ever used. */
297
+ export type InstallationsState = {
298
+ readonly current: Map<string, InstallationRecord>;
299
+ readonly used: Set<string>;
300
+ };
301
+ /**
302
+ * The preset installations that define a thread's plugins. A fork inherits its source's
303
+ * installations and reserved ids at the cut: its own spawn row carries none, and the source's spawn
304
+ * row, which it folds through lineage, keeps a defining installation defining on every fork.
305
+ * Installations never move, so application order is also the order they are restored in.
306
+ */
307
+ export declare const installations: Reducer<InstallationsState>;
@@ -0,0 +1,33 @@
1
+ import type { Journal } from '../journal/index.js';
2
+ import type { JournalEventInput, ReplacementTrigger, Seq } from '../models/index.js';
3
+ import type { RowRef } from './surface.js';
4
+ type ReplacedData = JournalEventInput['surface/replaced'];
5
+ type DistributiveOmit<T, K extends PropertyKey> = T extends unknown ? Omit<T, K> : never;
6
+ /**
7
+ * One replacement as a strategy offers it: what a `surface/replaced` row records that the strategy
8
+ * decides — its kind, stand-in and `source` — and the rows it replaces, in surface order. The
9
+ * engine fills in the rest.
10
+ */
11
+ export type ReplacementInput = DistributiveOmit<ReplacedData, 'trigger' | 'turn' | 'step' | 'auxiliary_request_seq'> & {
12
+ /** The rows replaced: a contiguous run of the current surface for a `span`, one row for a `rewrite`. */
13
+ readonly source_seqs: readonly Seq[];
14
+ /** The `auxiliary/request` row the stand-in was made from, when a model call made it. */
15
+ readonly auxiliary_request_seq?: Seq | null;
16
+ };
17
+ /** Where a replacement is recorded: what caused it, and the turn and step, both `null` between turns. */
18
+ export type ReplacementContext = {
19
+ readonly trigger: ReplacementTrigger;
20
+ readonly turn: number | null;
21
+ readonly step: number | null;
22
+ };
23
+ /**
24
+ * The one way a replacement reaches the journal: appends `replacements` as one atomic group on
25
+ * `threadId`, each with the context filled in. The group is judged inside the write, against the
26
+ * durable surface, each row against the surface the previous one left, and refused whole with a
27
+ * {@link ReplacementRefusedError} when one breaks a rule; nothing of it is written then. Counts
28
+ * nothing and judges nothing of its own: the rules are the surface's (`judgeGroup`).
29
+ *
30
+ * The caller holds the thread's lease; `runSurfacePrepare` checks it before recording.
31
+ */
32
+ export declare function replaceSurface(journal: Journal, threadId: string, context: ReplacementContext, replacements: readonly ReplacementInput[]): Promise<RowRef[]>;
33
+ export {};
@@ -0,0 +1,129 @@
1
+ import type { CancelIntent, RunChain, RunOutcomeKind, RunSettledReason, Seq } from '../models/index.js';
2
+ import type { InputFate } from './state.js';
3
+ import type { Reducer } from './threadState.js';
4
+ /** One `run/cause` row as the request fold keeps it. */
5
+ export type RunCause = {
6
+ readonly seq: Seq;
7
+ /** The row's timestamp: how old the cause is, which the startup policy judges. */
8
+ readonly at: string;
9
+ readonly inputId: string | null;
10
+ readonly releases: boolean;
11
+ readonly chain: RunChain;
12
+ };
13
+ /** The request a thread is authorized to run, with every cause it holds, residual ones first. */
14
+ export type PendingRun = {
15
+ readonly runId: string;
16
+ /** The `run/requested` row. */
17
+ readonly requestedAt: Seq;
18
+ readonly causes: readonly RunCause[];
19
+ };
20
+ /** One `run/settled` row as the request fold keeps it. */
21
+ export type RunSettlement = {
22
+ readonly runId: string;
23
+ readonly seq: Seq;
24
+ readonly outcome: RunOutcomeKind;
25
+ readonly reason: RunSettledReason;
26
+ readonly errorText: string | null;
27
+ readonly through: Seq;
28
+ readonly residual: readonly Seq[];
29
+ };
30
+ /** One `thread/cancel` row as the request fold keeps it. */
31
+ export type CancelRecord = {
32
+ readonly seq: Seq;
33
+ readonly cancelId: string;
34
+ readonly intent: CancelIntent;
35
+ readonly runId: string | null;
36
+ readonly reason: string;
37
+ };
38
+ /**
39
+ * A thread's run requests, folded from its `run/*` and `thread/cancel` rows: the pending request,
40
+ * the first cancel that captured it, the latest settlement and user cancel, the latest releasing
41
+ * cause, and every request it ever
42
+ * opened with its settlement, so a waiter can read any run by id. A row that breaks the request
43
+ * rules (a cause or settlement for a run that is not pending, a request opened over a pending one)
44
+ * is kept in `inconsistencies` rather than thrown: core's fold is fatal, and a bad row must not
45
+ * stop the thread from being read.
46
+ */
47
+ export type RequestsState = {
48
+ pending: PendingRun | null;
49
+ /**
50
+ * The first cancel row naming the pending request's execution, whichever its intent: what a
51
+ * recovery settles that request by when the process died before its execution's finalization did.
52
+ * The first capture fixes the intent; a later cancel joining it changes nothing here.
53
+ */
54
+ pendingCancel: CancelRecord | null;
55
+ latestSettlement: RunSettlement | null;
56
+ latestUserCancel: CancelRecord | null;
57
+ /** The seq of the latest cause that releases holds, on any request. */
58
+ latestReleasing: Seq | null;
59
+ /** Every request by id: its `run/requested` row, and its settlement once it has one. */
60
+ readonly runs: Map<string, {
61
+ readonly requestedAt: Seq;
62
+ settlement: RunSettlement | null;
63
+ }>;
64
+ /**
65
+ * The latest `turn/start`: the run it served and the attempt cutoff of the execution that opened
66
+ * it, which a recovery settles a failure recorded before a crash with.
67
+ */
68
+ latestTurn: {
69
+ readonly seq: Seq;
70
+ readonly runId: string;
71
+ readonly attemptCutoff: Seq;
72
+ } | null;
73
+ /**
74
+ * The turns of the pending request in a row, since its latest releasing cause, that ended
75
+ * `interrupted` with the activation or the judgment as the cause; an abandonment by recovery leaves
76
+ * the count as it was. What an
77
+ * entry decision spends its repairs against: a request held on an interrupted turn that was
78
+ * already repaired is not repaired again until a releasing cause releases it.
79
+ */
80
+ interruptions: number;
81
+ /** The causes a settlement carried over, until the successor request it opened takes them. */
82
+ carried: readonly RunCause[];
83
+ readonly inconsistencies: string[];
84
+ };
85
+ /**
86
+ * The request fold: core's {@link RequestsState} concern of `threadState`. A fork starts with none
87
+ * of its source's requests.
88
+ */
89
+ export declare const requests: Reducer<RequestsState>;
90
+ /** Where a run stands from its rows alone: pending, settled with its settlement, or unknown on this thread. */
91
+ export type DurableRunState = {
92
+ readonly state: 'pending';
93
+ } | {
94
+ readonly state: 'settled';
95
+ readonly settlement: RunSettlement;
96
+ } | {
97
+ readonly state: 'unknown';
98
+ };
99
+ export declare function durableRunState(state: RequestsState, runId: string): DurableRunState;
100
+ /**
101
+ * What a settlement decided, and where its execution's cutoffs fall, for {@link residualOf}: the
102
+ * attempt cutoff, the position the execution was admitted at, and the cancel's write, when a cancel
103
+ * settled the request and its write landed.
104
+ */
105
+ export type ResidualRule = {
106
+ readonly outcome: RunOutcomeKind;
107
+ readonly reason: RunSettledReason;
108
+ readonly attemptCutoff: Seq;
109
+ readonly cancelSeq: Seq | null;
110
+ };
111
+ /**
112
+ * The causes of `pending` a settlement carries over to a successor request, by seq. A cause whose
113
+ * input a step claimed, or that left the queue unclaimed, carries nothing whatever its position;
114
+ * of the rest:
115
+ *
116
+ * - `completed` carries the causes recorded after the attempt cutoff: a wake that landed while the
117
+ * execution was finishing runs once more;
118
+ * - `failed` carries only the releasing ones recorded after the cutoff: a person's message that
119
+ * arrived during the attempt runs, while the cause that started it, and a notice or a fire, does
120
+ * not retry a failure;
121
+ * - a cancel's carries those recorded after its write, which it did not clear, or, when that write
122
+ * failed and cleared nothing, those after the attempt cutoff;
123
+ * - an `obsolete` request carries nothing: its authority is gone, and a successor comes with causes
124
+ * of its own.
125
+ *
126
+ * `fate` reads an input's fate on the thread (`inputFate`). Input left queued with no cause runs
127
+ * again only when a new cause arrives.
128
+ */
129
+ export declare function residualOf(pending: PendingRun, rule: ResidualRule, fate: (inputId: string) => InputFate['state']): Seq[];
@@ -0,0 +1,53 @@
1
+ import type { ModelRoute } from '../llm/index.js';
2
+ import type { ModelSelection } from './runtime.js';
3
+ /**
4
+ * What a wake says about the route it runs on, checked by core inside the write that records it:
5
+ * `expect`, the route the caller was shown and did not change; `select`, the route to run on,
6
+ * folded over the thread's route as a creation's fields are, so a complete one is itself. A wake
7
+ * that states none runs on the thread's route as it is, unchecked.
8
+ */
9
+ export type RouteStatement = {
10
+ readonly expect: ModelRoute;
11
+ } | {
12
+ readonly select: ModelSelection;
13
+ };
14
+ /**
15
+ * The thread's route as a statement is checked against: the route, why it cannot run here
16
+ * (its provider is not registered), and whether a route change is accepted now — no run serving the
17
+ * pending request holds the thread, and no request is pending, the route cannot run, or the
18
+ * request is held by a failure or a cancellation.
19
+ */
20
+ export type Target = {
21
+ readonly route: ModelRoute;
22
+ readonly blocked: string | null;
23
+ readonly selectable: boolean;
24
+ };
25
+ /** What checks a route statement inside its write: the thread owner, which knows admission and the registry. */
26
+ export interface RouteAuthority {
27
+ /** The thread's target as its rows and the process stand now. */
28
+ target(threadId: string): Target;
29
+ /** `selection` folded over `base`; throws `RouteUnavailableError` when the provider is not registered. */
30
+ resolve(selection: ModelSelection, base: ModelRoute): ModelRoute;
31
+ }
32
+ /** A route statement does not match the thread's route as it stands, or would change it when it may not. */
33
+ export declare class RouteConflictError extends Error {
34
+ readonly threadId: string;
35
+ readonly route: ModelRoute;
36
+ constructor(threadId: string,
37
+ /** The thread's route when the statement was refused. */
38
+ route: ModelRoute, reason: string);
39
+ }
40
+ /** A route cannot run here: its provider is not registered. Nothing was written, or no turn opened. */
41
+ export declare class RouteUnavailableError extends Error {
42
+ readonly route: Pick<ModelRoute, 'provider'> & Partial<ModelRoute>;
43
+ constructor(route: Pick<ModelRoute, 'provider'> & Partial<ModelRoute>);
44
+ }
45
+ /** Whether two routes are the same tuple; a `null` effort (the provider's own default) is a value like any other. */
46
+ export declare const sameRoute: (a: ModelRoute, b: ModelRoute) => boolean;
47
+ /**
48
+ * The route a cause records for `statement`, read inside its write: `null` when the cause leaves
49
+ * the thread's route as it is. `expect` needs the route runnable, then matching; `select` resolves
50
+ * over it, and a different route is written only while the target is selectable. Refusals throw,
51
+ * which refuses the whole write.
52
+ */
53
+ export declare function statedRoute(threadId: string, statement: RouteStatement, routes: RouteAuthority): ModelRoute | null;
@@ -0,0 +1,85 @@
1
+ import type { Context, Scoped } from '@leuduan/cordis';
2
+ import type { ModelCallClient, ModelRoute, ThinkingEffort, ToolSpec } from '../llm/index.js';
3
+ import type { DeepReadonly } from '../util/json.js';
4
+ import type { Journal } from '../journal/index.js';
5
+ import type { AgentDefinition } from '../models/index.js';
6
+ import type { ChunkChannel } from './chunks.js';
7
+ import type { TurnLimits } from './limits.js';
8
+ import type { SurfaceStrategy } from './strategy.js';
9
+ import type { Tool } from './tool.js';
10
+ /** Anything advertised to the model — a builtin tool or a sub-agent. */
11
+ export type ToolEntry = {
12
+ readonly name: string;
13
+ readonly tool: Tool;
14
+ /**
15
+ * `tool.buildSpec()` with `name` forced to the registered name: the registry's own deep copy,
16
+ * frozen, shared by every request that advertises the tool.
17
+ */
18
+ readonly spec: DeepReadonly<ToolSpec>;
19
+ };
20
+ /**
21
+ * Route fields to fold over a route (`LlmService.resolveRoute`): absent fields keep the route's own;
22
+ * naming a different provider resets what is left unnamed to that provider's defaults. A `null`
23
+ * effort names the provider's own default, as a route records it, so a complete route resolves to
24
+ * itself.
25
+ */
26
+ export type ModelSelection = {
27
+ readonly provider?: string;
28
+ readonly model?: string;
29
+ readonly thinkingEffort?: ThinkingEffort | null;
30
+ };
31
+ /**
32
+ * What the loop runs against.
33
+ *
34
+ * The journal says what happened; the registries say what a thread can do right now. Every lookup
35
+ * here is live — resolved when the loop asks, never captured at start — which is the whole of how a
36
+ * registry change reaches a running conversation. There is no turn signal: it is carried by
37
+ * value on each turn, so two concurrent turns cannot see each other's.
38
+ */
39
+ export interface LoopServices {
40
+ readonly journal: Journal;
41
+ /** The model's output as it streams. Ephemeral — see {@link ChunkChannel}. */
42
+ readonly chunks: ChunkChannel;
43
+ readonly limits: TurnLimits;
44
+ /** The registered definition, or a thrown `UnknownAgentError`. */
45
+ agent(name: string): AgentDefinition;
46
+ /** What `agentName` may call, in grant order, as the registries stand right now. */
47
+ toolsFor(agentName: string): ToolEntry[];
48
+ /** One tool `agentName` may call, or `undefined` when it is unknown or not granted. */
49
+ tool(agentName: string, toolName: string): ToolEntry | undefined;
50
+ /** Why `route` cannot run now, its provider not registered, or `null`. Registry lookup only. */
51
+ unavailable(route: ModelRoute): string | null;
52
+ /** `selection` folded over `base`; throws `RouteUnavailableError` when its provider is not registered. */
53
+ resolveRoute(selection: ModelSelection, base: ModelRoute): ModelRoute;
54
+ /** A client for a resolved route; throws when its provider is gone or the client cannot be built. */
55
+ client(route: ModelRoute): ModelCallClient;
56
+ /** Whether a constraint registration under `owner` is live now: what a call's wait may name. */
57
+ waitOwner(owner: string): boolean;
58
+ /**
59
+ * The constraint registrations `threadId`'s run needs, its own `requires` and every thread's above
60
+ * it by origin, as a token equal only for the same registrations, all ready; `null` while one is
61
+ * missing. A judgment is fenced on it: a required owner may be a checker of the answer.
62
+ */
63
+ requiredRegistrations(threadId: string): string | null;
64
+ }
65
+ /** Only a live activation can supply an execution runtime. There is no passive/no-op runtime. */
66
+ export interface LoopRuntime extends LoopServices {
67
+ readonly ctx: Context;
68
+ readonly target: Scoped;
69
+ readonly signal: AbortSignal;
70
+ /**
71
+ * Whether the activation's plugins have changed since it was ready: the loop dispatches nothing
72
+ * new once they have, and ends the turn as `interrupted` at its next boundary.
73
+ */
74
+ stale(): boolean;
75
+ /** The strategy that prepares the thread's surface, if one is provided (`provideStrategy`). */
76
+ strategy(): SurfaceStrategy | undefined;
77
+ }
78
+ /**
79
+ * A thread's exclusive execution lease, as one holder holds it: a run, or a request to prepare the
80
+ * surface. `held` is read on every use of something the holder handed out, so a callback that
81
+ * escapes its holder does nothing under a later one's lease.
82
+ */
83
+ export interface Lease {
84
+ readonly held: boolean;
85
+ }