@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,67 @@
1
+ import { Context, Service, type ScopeKey } from '@leuduan/cordis';
2
+ import type { PromptBlock } from '../llm/index.js';
3
+ import type { ToolEntry } from '../loop/index.js';
4
+ import type { AgentDefinition, ThreadSummary } from '../models/index.js';
5
+ import { type AgentSelector } from '../kit/scope.js';
6
+ export type PromptSlot = 'base' | 'instruction' | 'context';
7
+ /**
8
+ * What a contribution is rendered against: the agent, where the thread works, and the tools it
9
+ * reaches.
10
+ *
11
+ * Deliberately not the thread's id or metadata. A recorded prompt is the head of every request a
12
+ * provider caches, so it must not depend on which thread it is: threads of one agent in one
13
+ * workspace then render the same prompt. Anything thread-specific belongs in the conversation, as
14
+ * a step contribution (see `workspaceContext`).
15
+ */
16
+ export type PromptRenderInput = {
17
+ readonly agent: AgentDefinition;
18
+ readonly thread: {
19
+ readonly environment: ThreadSummary['environment'];
20
+ };
21
+ /** What the agent may call from the rendering scope, as the registries stand at render time. */
22
+ readonly tools: readonly ToolEntry[];
23
+ };
24
+ /**
25
+ * One section a plugin adds to an agent's prompt.
26
+ *
27
+ * `render` is synchronous and pure in its inputs: anything needing IO reads it when the plugin
28
+ * mounts, and returns the cached value here. Returning `null` contributes nothing — or, for a tag
29
+ * that already exists, removes it.
30
+ */
31
+ export type PromptContribution = {
32
+ readonly tag: string;
33
+ readonly slot: PromptSlot;
34
+ /** Which agents get it; see `AgentSelector`. */
35
+ readonly agents: AgentSelector;
36
+ /** Render order within the slot; ties break on `tag`. Default 0. */
37
+ readonly order?: number;
38
+ render(input: PromptRenderInput): string | null;
39
+ };
40
+ /**
41
+ * Prompt contributions, live like the other registries and layered by Cordis scope like tools:
42
+ * an untagged contribution is global, a contribution registered through a thread's context belongs
43
+ * to that thread's layer. The prompt itself is rendered once, when a thread first runs and every
44
+ * activation plugin is ready, and recorded on it; this service only says what that render
45
+ * would be right now.
46
+ */
47
+ export declare class PromptsService extends Service {
48
+ static inject: string[];
49
+ private readonly layers;
50
+ constructor(ctx: Context);
51
+ /** Adds a contribution to one layer; returns the function that removes it. */
52
+ contribute(scope: ScopeKey | undefined, contribution: PromptContribution): () => void;
53
+ /**
54
+ * The prompt `agentName` would send on a thread rendered now from `scope`: the agent's base
55
+ * prompt, then the global layer's contributions, then each closer layer outward-in, each in
56
+ * declared order, never mount order. A contribution whose tag is already present replaces that
57
+ * section in place — so the closest layer wins a tag — and `null` removes it.
58
+ *
59
+ * The base prompt is seeded at the layer that defines the agent, so only that layer and closer
60
+ * ones can replace or remove it with a `base` contribution: for a global agent every layer can,
61
+ * while a scoped agent's own base prompt outranks every layer farther out. Instruction and context
62
+ * contributions apply from every layer. Throws for an agent unknown from `scope`.
63
+ */
64
+ render(scope: ScopeKey | undefined, agentName: string, thread: PromptRenderInput['thread']): PromptBlock[];
65
+ }
66
+ /** Registers a contribution in the calling plugin's layer for the lifetime of its fiber. */
67
+ export declare const contributePrompt: (ctx: Context, contribution: PromptContribution) => (() => void | Promise<void>);
@@ -0,0 +1,79 @@
1
+ import type { RunOutcomeKind, RunSettledReason } from '../models/index.js';
2
+ import type { DurableRunState, Hold, HoldBasis } from '../loop/index.js';
3
+ /**
4
+ * Where one run request stands, as its waiters see it: waiting to be admitted (`requested`), with
5
+ * an execution serving it (`running`, finalization included), held with the request still pending,
6
+ * or settled. A held run carries its structured `hold` and the `basis` it was read on, an immutable
7
+ * observation at publication, not a snapshot of the thread. `{ reason: 'shutdown' }` is what a
8
+ * waiter is told when the application closes under it.
9
+ */
10
+ export type RunState = {
11
+ readonly state: 'requested';
12
+ } | {
13
+ readonly state: 'running';
14
+ } | {
15
+ readonly state: 'held';
16
+ readonly hold: Hold;
17
+ readonly basis: HoldBasis;
18
+ } | {
19
+ readonly state: 'settled';
20
+ readonly outcome: RunOutcomeKind;
21
+ readonly reason: RunSettledReason;
22
+ readonly errorText: string | null;
23
+ };
24
+ /**
25
+ * One change of a run's state, published as it happens: `requested` once its cause is durable,
26
+ * `running` at admission, and `held` or `settled` only after the execution's finalization and its
27
+ * release of the thread, so nothing that reads it can still find the execution running.
28
+ */
29
+ export type RunEvent = {
30
+ readonly threadId: string;
31
+ readonly runId: string;
32
+ } & RunState;
33
+ /**
34
+ * The read rule, the same as the events': a run an execution serves is `running` until that
35
+ * execution releases the thread, even when its settlement row is already durable; a settled run
36
+ * with no live execution is its settlement; a pending one is what the owner's current decision for
37
+ * it says, `held` with its hold or `requested`, since holds have no rows to read. `null` for a
38
+ * run the reader does not know: one the thread never had, or, on a thread out of memory, one older
39
+ * than its pending run and its latest settlement, which its catalog entry does not keep.
40
+ */
41
+ export declare function readRunState(facts: {
42
+ readonly durable: DurableRunState;
43
+ /** Whether an execution serving this run holds the thread now. */
44
+ readonly executing: boolean;
45
+ /** The hold the owner currently reads on the thread's pending request, `null` when it has none to say. */
46
+ readonly held: {
47
+ readonly hold: Hold;
48
+ readonly basis: HoldBasis;
49
+ } | null;
50
+ }): RunState | null;
51
+ /** Where a waiter reads runs from: the event stream, and the read that follows the same rule. */
52
+ export type RunSource = {
53
+ onRunEvent(listener: (event: RunEvent) => void): () => void;
54
+ runState(threadId: string, runId: string): RunState | null;
55
+ };
56
+ /**
57
+ * A run a waiter named is unknown to the catalog: the thread never had it, or the thread is out of
58
+ * memory and the run is older than its pending run and its latest settlement. A read or a hold
59
+ * loads the thread, which knows its every run.
60
+ */
61
+ export declare class UnknownRunError extends Error {
62
+ readonly threadId: string;
63
+ readonly runId: string;
64
+ constructor(threadId: string, runId: string);
65
+ }
66
+ /**
67
+ * Waits until run `runId` on `threadId` reaches a state `until` accepts, and resolves with it, where
68
+ * `source` is `ctx.threads`. The wait is for that run: not for the input that asked for it to be
69
+ * answered, nor for the thread to go quiet, since a cause that lands while an execution finishes is
70
+ * carried to a successor request. `queued.runId` of a `send` names the run to wait for. It
71
+ * subscribes first and reads the state after, so a change that happened before the call is read,
72
+ * not missed; on each event of the run it reads again rather than trust the event, which may be
73
+ * stale by the time it is delivered. Rejects with the signal's reason when aborted (the run goes on),
74
+ * with {@link UnknownRunError} for a run unknown to the catalog, and with whatever the read or
75
+ * `until` threw; unsubscribes however it ends.
76
+ */
77
+ export declare function waitForRun(source: RunSource, threadId: string, runId: string, until: (state: RunState) => boolean, signal?: AbortSignal): Promise<RunState>;
78
+ /** What a caller waiting for a run's work to stop waits for: the run held or settled, as `waitForRun`'s `until`. */
79
+ export declare const heldOrSettled: (state: RunState) => boolean;
@@ -0,0 +1,267 @@
1
+ import type { Context } from '@leuduan/cordis';
2
+ import type { AppendEntry, Journal } from '../journal/index.js';
3
+ import type { PromptBlock } from '../llm/index.js';
4
+ import type { CompactOptions, RouteStatement, RowRef, SendOptions, SendOutcome, StreamedChunk, SurfacePrepareOutcome, WithdrawOptions, WithdrawOutcome } from '../loop/index.js';
5
+ import type { CancelIntent, JournalEvent, ThreadInput, ThreadOrigin, ThreadSummary, TurnEndReason } from '../models/index.js';
6
+ import type { DeepReadonly } from '../util/json.js';
7
+ import type { AdmissionView } from './admission.js';
8
+ import type { ForkOptions } from './birth.js';
9
+ import type { ConfigurationChange, ConfigurationResult, ThreadsService } from './threads.js';
10
+ import type { ThreadView } from './threadView.js';
11
+ /** One answer to a parked confirmation. */
12
+ export type ConfirmationAnswer = {
13
+ request_id: string;
14
+ approved: boolean;
15
+ rejection_message?: string | null;
16
+ };
17
+ /**
18
+ * How `cancel()` cancels: a person's stop (`user`), which holds the thread until a releasing cause,
19
+ * or a feature's `cleanup`, which holds nothing; `rows`, extension rows built inside the cancel's
20
+ * write for the same group, or a refusal of it by throwing; and `until`, the milestone the call
21
+ * settles at: `released` (the default) once the write has landed and what the cancel captured has
22
+ * released the thread, `recorded` once the write alone has landed.
23
+ */
24
+ export type CancelOptions = {
25
+ readonly intent: CancelIntent;
26
+ readonly rows?: (threadId: string) => readonly AppendEntry<'ext'>[];
27
+ readonly until?: 'recorded' | 'released';
28
+ };
29
+ /**
30
+ * One conversation in the journal. Threads are independent: their own transcript, their own
31
+ * exclusive admission while the owner runs them, their own confirmations. Two may run at once. A
32
+ * thread runs for a recorded request: `send` or `answer` with `wake`, or `resume`.
33
+ *
34
+ * Durable accessors read the journal; execution status and ctx belong to the current activation.
35
+ * The handle never owns plugin lifetime and survives replacement of that activation.
36
+ */
37
+ export declare class Thread {
38
+ private readonly inbox;
39
+ private readonly service;
40
+ private readonly admission;
41
+ readonly id: string;
42
+ private readonly journal;
43
+ constructor(service: ThreadsService,
44
+ /** The admission owner's reads and cancel, given by the service that owns it. */
45
+ admission: AdmissionView, id: string,
46
+ /** The journal with core's writes, which only the thread owner hands out. */
47
+ journal: Journal);
48
+ /**
49
+ * Reads what this thread's folds say through `reader`, which is synchronous: the thread is loaded
50
+ * and held for the call (a `keep` retention), so nothing drops it meanwhile: how a caller that
51
+ * holds nothing reads a thread's conversation, where one that holds it already reads
52
+ * `ctx.threads.view`. The catalog reads (`summary`, `status`, `lastOutcome`) need neither.
53
+ */
54
+ read<T>(reader: (view: ThreadView) => T): Promise<T>;
55
+ /** Lazily activates this thread. Its plugins are fixed once ready: mount them from activate listeners or presets. */
56
+ get ctx(): Context;
57
+ /**
58
+ * The current activation's signal, the one its `lagent/thread/activate` listeners receive: it
59
+ * aborts when the activation is released or stopped, not when one turn is cancelled. Activates
60
+ * the thread, as `ctx` does, and like `ctx` throws `ThreadBusyError` while the activation is being
61
+ * released, since a getter cannot wait; a read after the release starts a new activation; and once
62
+ * `ctx.threads` has shut down it throws.
63
+ */
64
+ get signal(): AbortSignal;
65
+ /**
66
+ * Activates this thread if it is not live, after any release in progress, and resolves once its
67
+ * plugins are ready: the barrier a run waits at, so a plugin that cannot mount, such as a recorded
68
+ * preset installation that no longer restores, rejects here with its error and nothing runs. A
69
+ * host that changes a thread's installations and wants the failure now awaits this.
70
+ */
71
+ whenReady(): Promise<void>;
72
+ /**
73
+ * Changes this thread's preset installations as one operation: validates the whole change,
74
+ * releases the live activation, records every installation applied or removed in one write, and
75
+ * restores a thread that was live from the record, rebuilding its recorded prompt when asked
76
+ * (which restores a thread at rest too); a thread at rest otherwise stays at rest, and its next run
77
+ * or `whenReady()` restores it. Removals go first, then
78
+ * applications, which are restored in that order. A given `installationId` makes a retry a no-op,
79
+ * and a removed id is never accepted again; removing an id not installed is no change, and a
80
+ * defining installation is never removed. Refused busy while an operation holds the thread, and
81
+ * refused with `ThreadActivatingError` while its activation is still getting ready, with
82
+ * `ThreadUnsettledError` for an unfinished confirmation (open, or approved and not yet run), and
83
+ * once lagent is closing. The record is the boundary: a cancel before it records nothing, a cancel
84
+ * after it ends only the restoration, and a setup that fails after it rejects with
85
+ * `RestoreFailedError`, the change standing, so a change that removes a broken installation
86
+ * always goes through.
87
+ */
88
+ configure(change: ConfigurationChange): Promise<ConfigurationResult>;
89
+ /**
90
+ * Takes this thread out of the working set: releases an idle activation and drops the rows and
91
+ * folds, under one admission; the catalog entry stays. Refused busy while an operation holds it.
92
+ */
93
+ close(): Promise<void>;
94
+ /**
95
+ * This thread's catalog entry: its identity and lineage, how its last turn ended, whether it has
96
+ * work, what it waits on, and what plugins and hosts contributed — everything a listing shows,
97
+ * read without a row of the thread in memory, exact as of the thread's last group.
98
+ */
99
+ get summary(): ThreadSummary;
100
+ get agentName(): string;
101
+ /** App-owned annotations the engine never reads. */
102
+ get metadata(): ThreadSummary['metadata'];
103
+ /** Where this thread came from: its caller, the caller's row and the cause; `null` for a root thread. */
104
+ get origin(): ThreadOrigin | null;
105
+ /**
106
+ * How many delegation hops separate this thread from its origin root: one for each thread
107
+ * of its caller chain that has a caller, a caller the catalog does not hold included.
108
+ */
109
+ get depth(): number;
110
+ /**
111
+ * The thread at the top of this one's origin tree, the caller chain's thread with no caller:
112
+ * itself for a thread created without an `origin`. `null` when the chain does not reach one, at a
113
+ * caller the catalog does not hold or a cycle, which only a journal that broke its rules has; a
114
+ * reader that decides by the root then decides nothing, rather than take a thread part-way up for
115
+ * it. From the catalog, loading nothing; fork lineage is {@link lineageRoot}'s.
116
+ */
117
+ get originRoot(): string | null;
118
+ get environment(): ThreadSummary['environment'];
119
+ /** The thread and row this one was forked at, or `null` unless it is a fork. */
120
+ get forkedFrom(): RowRef | null;
121
+ /**
122
+ * The thread at the start of this one's fork lineage: itself unless it is a fork. Forks of one
123
+ * root share its history, and so the provider cache that holds it.
124
+ */
125
+ get lineageRoot(): string;
126
+ /** How this thread's own last turn ended, from the catalog; `null` before its first ends, or while one is open. */
127
+ lastOutcome(): DeepReadonly<TurnEndReason> | null;
128
+ /** Forks this thread at a row, or at the turn holding one; see `ctx.threads.fork`. */
129
+ fork(options: ForkOptions): Promise<Thread>;
130
+ /**
131
+ * Re-renders the prompt from the registries as they stand — the thread's own plugins included,
132
+ * which is why it activates the thread and waits for them — and records it; later turns send the
133
+ * new one. The deliberate exception to a prompt being frozen at first run.
134
+ */
135
+ rebuildPrompt(): Promise<PromptBlock[]>;
136
+ /**
137
+ * This thread's events as they are appended: `ctx.journal.subscribe` filtered to the thread, so a
138
+ * promise the listener returns is reported if it rejects, as any subscriber's is. Returns the
139
+ * unsubscribe function.
140
+ */
141
+ on(listener: (event: JournalEvent) => void): () => void;
142
+ /** The model's output as it streams on this thread. Returns the unsubscribe function. */
143
+ onChunk(listener: (chunk: StreamedChunk) => void): () => void;
144
+ /**
145
+ * Queues durable input without driving, and resolves once it is durable with what the write did:
146
+ * `queued`, with the row that recorded it; `known`, when this thread was already handed `id`, which
147
+ * queues nothing and names the original row; or `refused`, with the reason `rows` vetoed it for.
148
+ *
149
+ * `rows` runs inside the write once the input's target is decided, and adds a plugin's rows to the
150
+ * same group or vetoes the input by returning `{ refuse }` (see `WriteRows`); a callback that
151
+ * throws fails the send with that error instead. A known id never calls it.
152
+ * `source` attributes the input to a plugin, as on a step contribution, and needs the `id` the
153
+ * plugin derived: the claimed `input/message` keeps both, and input waiting for a turn is claimed
154
+ * as one unsourced input or every consecutive sourced input at the head of the queue.
155
+ *
156
+ * Text is the common case and stays a string; `{ role: 'developer', content }` queues a message
157
+ * that speaks as the harness rather than as the person, and content parts carry what text cannot.
158
+ *
159
+ * Where input waits is the sender's `target` when it names one, and admission's choice otherwise.
160
+ * Admission joins a running turn at its next step; the caller that started the turn owns its
161
+ * result. On an idle thread it waits for a turn of its own, behind input sent before it, and is
162
+ * claimed only by that turn's first step: a turn that opens by answering calls an earlier turn
163
+ * left leaves it for the next turn, which the same run opens once that work completed.
164
+ * `target: 'next-turn'` asks for a turn of its own even while a run holds the thread, as a new
165
+ * assignment does; `target: 'next-step'` joins the next model step of whichever turn takes it,
166
+ * including a turn that resumes parked calls, as a report on work already set going does.
167
+ * Sending never interrupts: an in-flight model call or tool is never cut off. Interruption is
168
+ * `cancel()`, then `send()` with a wake, deliberately two visible steps.
169
+ *
170
+ * A wake may state the route it runs on (`RouteStatement`), checked inside the write: an `expect`
171
+ * that no longer matches the thread's route is refused with `RouteConflictError`, one whose route
172
+ * cannot run with `RouteUnavailableError`; a `select` changes the route, which reauthorizes all the
173
+ * thread's unfinished work on it, only while no request is pending or the route cannot run, and no
174
+ * run serving the pending request holds the thread. A refusal writes nothing.
175
+ */
176
+ send(input: ThreadInput, options?: SendOptions): Promise<SendOutcome>;
177
+ /**
178
+ * Takes back one queued input that no step has claimed yet, by the id it was sent with, and
179
+ * resolves with what the write did: `withdrawn`, `not-queued` (claimed, discarded or unknown), or
180
+ * `refused` by a `rows` veto, which adds a plugin's rows to the same write either way and is told whether
181
+ * the input was withdrawn. The id stays known, so `send` with it queues nothing again.
182
+ */
183
+ withdraw(inputId: string, options?: WithdrawOptions): Promise<WithdrawOutcome>;
184
+ /**
185
+ * Records answers to confirmations parked on this thread, all of them or none. Does not drive: the
186
+ * run the answer's cause asks for re-dispatches them, through authorization again. A request that
187
+ * already has a decision — answered before, or approved and then revoked — is refused with
188
+ * `ConfirmationAnsweredError`, carrying the decision on record; a batch naming one request twice
189
+ * is refused outright.
190
+ */
191
+ answer(decisions: readonly ConfirmationAnswer[], options?: {
192
+ readonly wake?: boolean;
193
+ }): Promise<void>;
194
+ /**
195
+ * Asks the thread to run again, as a person or a host does: a cause that releases the failure,
196
+ * cancellation and startup holds, recorded in one write and resolving once durable. A `route`
197
+ * statement is checked as `send` checks a wake's. Resolves with the run the cause joined or opened.
198
+ */
199
+ resume(options?: {
200
+ readonly route?: RouteStatement;
201
+ }): Promise<string>;
202
+ /**
203
+ * A cancel's answer to each call the thread suspended, read inside its write: an error result in
204
+ * the declaration's turn and step, citing the call and the declaration.
205
+ */
206
+ private closeWaitRows;
207
+ /** The thread's pending run request, read inside a write. */
208
+ private pendingRun;
209
+ /**
210
+ * Takes back approvals of calls without a result. Each becomes a rejection, so the call does not run
211
+ * again: its next dispatch ends it with an error. A call that already started, and then waits or
212
+ * was cut off, keeps what it did, and a child thread it started keeps running. Refused while a run
213
+ * holds the thread, since that run may be executing one. A batch with any id that does not qualify
214
+ * records nothing. Writes only to the journal, so it also works on a thread that cannot activate,
215
+ * which is how a host gets such a thread out of an approval it cannot run.
216
+ */
217
+ revokeApprovals(requestIds: readonly string[], rejectionMessage?: string | null): Promise<void>;
218
+ /**
219
+ * Asks the thread's strategy to prepare its surface now, between turns, with the `request`
220
+ * trigger and `options`, which the engine passes on and never reads. This is how a host offers a `/compact` command.
221
+ *
222
+ * Holds the thread's admission, as a run does, but accepts no input: `send()` meanwhile queues for the
223
+ * next turn unless its sender names `next-step`, a run waits for it, and `activity` names the compaction. Requires a
224
+ * settled thread — no tool call without a result, no open confirmation, no answer its stop checks
225
+ * still owe — and rejects with `ThreadUnsettledError` otherwise; an interrupted open turn is closed
226
+ * first, as a run closes it. The route is resolved as a turn's would be. Opens no turn, runs no
227
+ * step hook and claims no queued input. Aborts on `signal`, on `cancel()` and on shutdown, and then
228
+ * resolves `cancelled` rather than rejects, with whatever the dispatch committed; cancelled before
229
+ * it began, it resolves `cancelled` with nothing dispatched. A strategy that failed on its own while
230
+ * the signal aborted resolves `failed`.
231
+ *
232
+ * Resolves with the one outcome record: the replacement rows committed and how the dispatch ended;
233
+ * `skipped` with a reason when no strategy answered.
234
+ */
235
+ compact(options?: CompactOptions): Promise<SurfacePrepareOutcome>;
236
+ /**
237
+ * Cancels the thread, whatever its state: captures the operation admitted now, if any, and aborts
238
+ * only it, then records one write: the `thread/cancel` row, the clear of everything queued, an
239
+ * error result answering each call the thread suspended on a wait, resolved or not, the rows
240
+ * `options.rows` adds, and the settlement, by the cancel's intent, of a pending run no execution is
241
+ * still to settle. So a cancelled thread never holds a waiting call, and a feature watching the
242
+ * call learns of the cancel from its result. The run the captured execution serves settles in that execution's
243
+ * finalization, unless the finalization built its settlement before this write and left it pending. A `user` cancel (a person's stop) holds the thread until a releasing cause; a
244
+ * `cleanup` one holds nothing. From the call until its write has landed and what it captured has
245
+ * released the thread, the cancel holds the thread, so a run meanwhile is refused busy; a cancel
246
+ * made meanwhile joins it. With `until: 'released'`, the default, resolves then, or rejects with its
247
+ * own write's failure, which records nothing — so a `send` after `cancel()` never races the
248
+ * cancelled operation. With `until: 'recorded'` it settles with that write alone, resolving once
249
+ * it has landed and rejecting with its failure, without waiting for what was captured to wind down:
250
+ * a run's drain and finalization are the engine's, and a failure of theirs goes to `reportError`,
251
+ * so a caller that needs the thread free awaits `released`. Each joined call gets its own write's
252
+ * outcome.
253
+ */
254
+ cancel(reason: string, options: CancelOptions): Promise<void>;
255
+ }
256
+ /** The answers as journal rows on the thread that asked, appended as one group. */
257
+ export declare const confirmationRows: (threadId: string, decisions: readonly ConfirmationAnswer[]) => {
258
+ type: "confirm/resolved";
259
+ data: {
260
+ request_id: string;
261
+ approved: boolean;
262
+ rejection_message: string | null;
263
+ };
264
+ options: {
265
+ threadId: string;
266
+ };
267
+ }[];
@@ -0,0 +1,100 @@
1
+ import { type Context, type Scope, type Scoped, type ScopeKey } from '@leuduan/cordis';
2
+ import { type CompactOptions, type Lease, type LoopServices, type SurfacePrepareOutcome } from '../loop/index.js';
3
+ import type { ServedRun } from '../loop/index.js';
4
+ import type { Thread } from './thread.js';
5
+ import type { AdmissionView } from './admission.js';
6
+ import type { ThreadsService } from './threads.js';
7
+ /**
8
+ * One process-local activation: the thread's Cordis scope, the plugins mounted in it, their
9
+ * readiness, and the loop that runs in it. It owns resources, never admission: which operation
10
+ * holds the thread, and its cancellation, are the admission owner's, which the threads service
11
+ * keeps and which hands each run or compaction its signal and lease.
12
+ */
13
+ export declare class ThreadActivation {
14
+ readonly scope: Scope;
15
+ readonly target: Scoped;
16
+ private readonly runtime;
17
+ private readonly loop;
18
+ private readiness;
19
+ private readonly controller;
20
+ private failed;
21
+ private prepared;
22
+ /** The plugin tree as it was when the activation became ready, which is what it runs with. */
23
+ private readyTree;
24
+ private staleBecause;
25
+ private draining;
26
+ private closingDone;
27
+ private readonly service;
28
+ private readonly admission;
29
+ readonly thread: Thread;
30
+ private readonly released;
31
+ constructor(service: ThreadsService,
32
+ /** The admission owner's reads, given by the service that owns it. */
33
+ admission: AdmissionView, owner: Context, thread: Thread, loopServices: (scope: ScopeKey) => LoopServices, released: () => void);
34
+ /**
35
+ * From readiness on, the plugin tree is what the activation runs with. A guard on each of its
36
+ * plugins marks the activation stale before that plugin's disposers run, whatever unloads it: a
37
+ * dependency gone, a root mount disposed, a reload. Its own release marks it too, harmlessly.
38
+ */
39
+ private watchTree;
40
+ private markStale;
41
+ /**
42
+ * Whether the plugins changed since readiness: one unloaded or reloaded, or one added through
43
+ * `thread.ctx`, which is reported once. A stale activation dispatches nothing new, and the owner
44
+ * replaces it once the operation holding the thread settles.
45
+ */
46
+ isStale(): boolean;
47
+ /**
48
+ * Whether a setup in this activation is still running: its listeners and installations have not
49
+ * settled, or a plugin of its tree is in transition, one mounted later through `thread.ctx` or one
50
+ * reloading included. A change that waits for this activation to go, made from one of those
51
+ * setups, would wait on itself, so it is refused meanwhile. Not a readiness check: readiness is
52
+ * settled once.
53
+ */
54
+ get activating(): boolean;
55
+ private observe;
56
+ /** Aborts on release and on stop; what the activate listeners receive. */
57
+ get signal(): AbortSignal;
58
+ /** Whether readiness failed: the owner releases such an activation once its operation settles. */
59
+ get hasFailed(): boolean;
60
+ /** Set once `release()` has begun: resolves when the scope is disposed. The owner waits for it before activating again. */
61
+ get closed(): Promise<void> | undefined;
62
+ private settle;
63
+ /** One execution of the run `served`, under the admitted operation's signal and lease. */
64
+ run(options: {
65
+ signal: AbortSignal;
66
+ lease: Lease;
67
+ served: ServedRun;
68
+ }): Promise<void>;
69
+ /**
70
+ * One request to prepare the surface, under the admitted operation's signal and lease; see
71
+ * `Thread.compact`. Resolves with the outcome, `cancelled` when the signal aborts first.
72
+ */
73
+ compact(options: CompactOptions & {
74
+ signal: AbortSignal;
75
+ lease: Lease;
76
+ }): Promise<SurfacePrepareOutcome>;
77
+ /**
78
+ * Waits for readiness, settled once when the activation began, then checks the agent and records
79
+ * the prompt if the thread has none. Only then is the scope complete: the thread's plugins may
80
+ * define its agent, and an unknown one fails here, before a prompt is recorded or a turn opens,
81
+ * so input waits for a retry. A stale activation never gets here: the owner replaces it first.
82
+ */
83
+ private ready;
84
+ /**
85
+ * Resolves once the activation is ready: its listeners and installations settled, every plugin of
86
+ * its tree active. The same barrier a run uses: a settled but PENDING plugin is not ready, so a
87
+ * caller never reads a half-configured scope.
88
+ */
89
+ whenReady(): Promise<void>;
90
+ /** The owner releases scopes only after every thread has drained, including failed setup. */
91
+ stop(reason: Error): void;
92
+ /** Resolves once setup has ended, however, and every plugin mounted since is settled. */
93
+ whenIdle(): Promise<void>;
94
+ /**
95
+ * Disposes the scope once setup has ended. The owner calls this with no executing operation on
96
+ * the thread, or from the operation that is settling; the scope's own unload guard is what waits
97
+ * for a loop when something else disposes the scope.
98
+ */
99
+ release(): Promise<void>;
100
+ }
@@ -0,0 +1,38 @@
1
+ import { Service, type Context } from '@leuduan/cordis';
2
+ export type ThreadDirsConfig = {
3
+ /**
4
+ * Absolute application data directory; thread directories live under `<dataDir>/threads`. `null`
5
+ * turns thread directories off, for a host without a filesystem of its own. Required either way.
6
+ */
7
+ dataDir: string | null;
8
+ };
9
+ /**
10
+ * Where each thread keeps files of its own: `<dataDir>/threads/<thread-id>/`, a scratch space its
11
+ * file tools may read and write as part of the application's shared data directory. Harness-written
12
+ * files go in named subdirectories such as `tool-outputs/`.
13
+ *
14
+ * The path is derived from the data directory and thread id, but absolute paths are also recorded
15
+ * in prompts and tool results. Keep the data directory at the same location when reopening a
16
+ * durable journal. Plugins can use the id supplied by their activation hook to find the directory.
17
+ *
18
+ * File tools may read and write the entire data directory, including other threads' scratch files.
19
+ *
20
+ * With `dataDir: null` there are no directories: `dataDir` and `root` are `null`, activation creates
21
+ * nothing, and `dirFor` and `ensure` throw. The service stays mounted either way, because the threads
22
+ * service injects it. A plugin that needs directories calls {@link ThreadDirsService.require} where it
23
+ * mounts, so a composition without them fails there.
24
+ */
25
+ export declare class ThreadDirsService extends Service<ThreadDirsConfig> {
26
+ readonly dataDir: string | null;
27
+ readonly root: string | null;
28
+ constructor(ctx: Context, config: ThreadDirsConfig);
29
+ /**
30
+ * The data directory, for the plugin `user` that cannot work without thread directories. Call it
31
+ * first where the plugin mounts, so a root mounted with `dataDir: null` refuses there.
32
+ */
33
+ require(user: string): string;
34
+ /** The directory of `threadId`, without touching the filesystem. */
35
+ dirFor(threadId: string): string;
36
+ /** The directory of `threadId`, created if missing. */
37
+ ensure(threadId: string): string;
38
+ }
@@ -0,0 +1,92 @@
1
+ import type { ConversationMessage, PromptBlock, ToolSpec } from '../llm/index.js';
2
+ import type { ConfirmationState, ForkPoint, InputFate, InstallationRecord, RowRef, RunOutcome, Target, WaitEntry } from '../loop/index.js';
3
+ import type { JournalEvent, QueuedInput, Seq } from '../models/index.js';
4
+ import type { DeepReadonly } from '../util/json.js';
5
+ import type { Journal } from '../journal/index.js';
6
+ import type { ReadonlyState } from '../util/foldState.js';
7
+ /**
8
+ * What one thread's folds say, read synchronously (`ctx.threads.view`, `thread.read`): valid while
9
+ * something holds the thread in memory — a journal write or a contributor running for it, a run, a
10
+ * retention. Reading a thread nothing holds may find it unloaded and throws `ThreadNotLoadedError`.
11
+ */
12
+ export declare class ThreadView {
13
+ private readonly inbox;
14
+ private readonly journal;
15
+ readonly threadId: string;
16
+ private readonly targetOf;
17
+ constructor(journal: Journal, threadId: string, targetOf: (threadId: string) => Target);
18
+ /**
19
+ * The thread's route, why it cannot run here (`blocked`), and whether a route change is accepted
20
+ * now (`selectable`): what a route statement is checked against (`Thread.send`). Never throws.
21
+ */
22
+ target(): Target;
23
+ /**
24
+ * The conversation as the model sees it, a fork's inherited history included. After a
25
+ * replacement that is the replaced view, stand-ins included; `replayLineage()` is the record.
26
+ */
27
+ transcript(): readonly ConversationMessage[];
28
+ /**
29
+ * The row behind each {@link transcript} message, index for index — what a fork anchors on. A
30
+ * stand-in's is the `surface/replaced` row that put it there.
31
+ */
32
+ messageSeqs(): readonly RowRef[];
33
+ /**
34
+ * The `llm/request` that produced the reply at `row`, on the thread that owns it; `null` for a
35
+ * row that is not a reply. Forking there regenerates the reply.
36
+ */
37
+ requestBehind(row: RowRef): RowRef | null;
38
+ /**
39
+ * The original rows a {@link messageSeqs} row stands for, in transcript order: the row itself
40
+ * when it is an original, and for a `surface/replaced` row, the originals behind every row it
41
+ * cites, followed through replacements of replacements — what a stand-in summarizes, on whichever
42
+ * thread holds `row`.
43
+ */
44
+ originalsBehind(row: RowRef): RowRef[];
45
+ /**
46
+ * Every turn ending along the thread's lineage, and every replacement recorded between turns,
47
+ * oldest first: where "fork from here" cuts.
48
+ */
49
+ forkPoints(): ForkPoint[];
50
+ /** The last thing the model said on the thread, if anything; see {@link lastAssistantMessage}. */
51
+ finalMessage(): ReadonlyState<ConversationMessage> | null;
52
+ /**
53
+ * How the run that began after `fromSeq` ended, and what it answered: a run's outcome, which an
54
+ * `aborted` turn ends. A delegation task is not a run and keeps its own settlement rule.
55
+ */
56
+ outcomeSince(fromSeq: Seq): RunOutcome;
57
+ /** The system prompt the thread sends; empty until its first turn records it. */
58
+ prompt(): readonly PromptBlock[];
59
+ /**
60
+ * The tool specifications `request` sent, as recorded then: thread-local tools and middleware's
61
+ * changes included, whatever is registered now. The request may be the thread's own or one it
62
+ * inherits; it is read on the thread that made it.
63
+ */
64
+ requestTools(request: JournalEvent<'llm/request'> | JournalEvent<'auxiliary/request'>): readonly ToolSpec[];
65
+ /** Requests waiting on the user, as owned frozen snapshots that survive later answers. */
66
+ pendingConfirmations(): DeepReadonly<ConfirmationState[]>;
67
+ /**
68
+ * The waits the thread declared, in declaration order, answered ones included, as owned frozen
69
+ * snapshots that survive later resolutions; with `owner`, only the waits declared under it. The
70
+ * registration named by an owner resolves its waits; a read never does.
71
+ */
72
+ waits(options?: {
73
+ readonly owner?: string;
74
+ }): readonly Readonly<WaitEntry>[];
75
+ /** The thread's own rows so far: what `thread.on` would have delivered. */
76
+ replay(): readonly JournalEvent[];
77
+ /**
78
+ * A fork's inherited rows, then its own, each with its original thread id and seq — what a
79
+ * frontend replays to show a fork's whole history. The same as `replay()` for a thread that is
80
+ * not a fork.
81
+ */
82
+ replayLineage(): readonly JournalEvent[];
83
+ /** Input waiting for a step to claim it, in the order it was sent. */
84
+ queued(): readonly QueuedInput[];
85
+ /**
86
+ * What became of the input `inputId`: never handed to this thread, queued, claimed by a step, or
87
+ * discarded unclaimed; see {@link InputFate}.
88
+ */
89
+ input(inputId: string): InputFate;
90
+ /** The thread's preset installations in recorded order, as readonly snapshots. */
91
+ installations(): readonly InstallationRecord[];
92
+ }