@jangts/agent-core 0.3.5 → 0.5.0

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 (288) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +33 -31
  3. package/development/docs/README.en.md +2 -2
  4. package/development/docs/acceptance.en.md +2 -2
  5. package/development/docs/agent-development.en.md +1 -1
  6. package/development/docs/api/README.en.md +6 -2
  7. package/development/docs/api/README.md +4 -0
  8. package/development/docs/api/configuration-in-workflow.en.md +403 -0
  9. package/development/docs/api/configuration-in-workflow.md +403 -0
  10. package/development/docs/api/core.en.md +7 -7
  11. package/development/docs/api/core.md +6 -6
  12. package/development/docs/api/decorators.en.md +20 -0
  13. package/development/docs/api/decorators.md +20 -0
  14. package/development/docs/api/examples.en.md +1 -1
  15. package/development/docs/api/examples.md +1 -1
  16. package/development/docs/api/kits.en.md +22 -4
  17. package/development/docs/api/kits.md +22 -4
  18. package/development/docs/api/knowledge-answering.en.md +4 -1
  19. package/development/docs/api/knowledge-answering.md +4 -1
  20. package/development/docs/api/mock.en.md +2 -0
  21. package/development/docs/api/mock.md +2 -0
  22. package/development/docs/api/observability.en.md +37 -11
  23. package/development/docs/api/observability.md +64 -11
  24. package/development/docs/api/reference.en.md +876 -657
  25. package/development/docs/api/reference.md +662 -508
  26. package/development/docs/api/support.en.md +55 -9
  27. package/development/docs/api/support.md +53 -7
  28. package/development/docs/api/types.en.md +36 -1
  29. package/development/docs/api/types.md +44 -0
  30. package/development/docs/api/workflow-views.en.md +64 -0
  31. package/development/docs/api/workflow-views.md +78 -0
  32. package/development/docs/api/workflow.en.md +6 -2
  33. package/development/docs/api/workflow.md +6 -2
  34. package/development/docs/basic-usage.en.md +1 -1
  35. package/development/docs/basic-usage.md +1 -1
  36. package/development/docs/create-app.en.md +1 -1
  37. package/development/docs/examples/registration/associated.mjs +8 -0
  38. package/development/docs/examples/registration/independent.mjs +20 -0
  39. package/development/docs/examples/registration/protocol.mjs +48 -0
  40. package/development/docs/examples/registration/run.mjs +47 -0
  41. package/development/docs/examples/registration/tools.mjs +75 -0
  42. package/development/docs/examples/registration/workflow.mjs +109 -0
  43. package/development/docs/flows/knowledge-maintenance.en.md +1 -1
  44. package/development/docs/materials.en.md +1 -1
  45. package/development/docs/mechanisms.en.md +2 -2
  46. package/development/docs/mechanisms.md +1 -1
  47. package/development/docs/operations.en.md +1 -1
  48. package/development/docs/records.en.md +1 -1
  49. package/development/docs/registration.en.md +4 -4
  50. package/development/docs/registration.md +2 -2
  51. package/development/skills/agent-core-app/SKILL.md +16 -4
  52. package/development/skills/agent-core-app/templates/node-ts/README.md.tpl +1 -1
  53. package/development/skills/agent-core-app/templates/node-ts/src/catalog.ts.tpl +2 -2
  54. package/development/skills/agent-core-app/templates/node-ts/test/app.test.mjs.tpl +1 -1
  55. package/dist/cjs/capabilities/index.js +5 -12
  56. package/dist/cjs/capabilities/invocation.js +21 -1
  57. package/dist/cjs/capabilities/model.js +56 -12
  58. package/dist/cjs/capabilities/tool-conditions.js +65 -0
  59. package/dist/cjs/capabilities/tool-runtime.js +18 -4
  60. package/dist/cjs/capabilities/tools.js +12 -17
  61. package/dist/cjs/context/audit.js +5 -8
  62. package/dist/cjs/context/index.js +3 -4
  63. package/dist/cjs/diagnostics/index.js +51 -3
  64. package/dist/cjs/diagnostics/native-sub-flow.js +106 -0
  65. package/dist/cjs/diagnostics/sub-flow.js +278 -32
  66. package/dist/cjs/execution/engine.js +3 -2
  67. package/dist/cjs/execution/events.js +5 -5
  68. package/dist/cjs/execution/reporting.js +18 -28
  69. package/dist/cjs/execution/workflow-chain.js +211 -0
  70. package/dist/cjs/execution/workflow-graph.js +72 -0
  71. package/dist/cjs/execution/workflow.js +34 -6
  72. package/dist/cjs/index.js +21 -17
  73. package/dist/cjs/kits/aggregation.js +17 -14
  74. package/dist/cjs/kits/answering/checks.js +2 -1
  75. package/dist/cjs/kits/answering/flow.js +24 -21
  76. package/dist/cjs/kits/answering/tasks.js +30 -25
  77. package/dist/cjs/kits/delivery.js +36 -24
  78. package/dist/cjs/kits/domains/catalog.js +113 -0
  79. package/dist/cjs/kits/domains/index.js +20 -0
  80. package/dist/cjs/kits/{intents → domains}/registry.js +77 -31
  81. package/dist/cjs/kits/{intents → domains}/scopes.js +21 -21
  82. package/dist/cjs/kits/index.js +14 -13
  83. package/dist/cjs/kits/knowledge/catalog.js +33 -30
  84. package/dist/cjs/kits/policies.js +3 -2
  85. package/dist/cjs/kits/presentation/formats.js +110 -0
  86. package/dist/cjs/kits/presentation/index.js +10 -5
  87. package/dist/cjs/kits/presentation/outputs.js +2 -1
  88. package/dist/cjs/kits/reflection.js +2 -2
  89. package/dist/cjs/kits/retrieval.js +7 -1
  90. package/dist/cjs/kits/text-blocks.js +101 -0
  91. package/dist/cjs/kits/tools.js +247 -158
  92. package/dist/cjs/model/decision-retry.js +2 -1
  93. package/dist/cjs/model/index.js +2 -6
  94. package/dist/cjs/model/interactions/calls.js +61 -0
  95. package/dist/cjs/model/interactions/json-object.js +11 -11
  96. package/dist/cjs/model/interactions/native-functions.js +17 -23
  97. package/dist/cjs/model/message-diagnostics.js +13 -3
  98. package/dist/cjs/model/options.js +2 -0
  99. package/dist/cjs/model/preparation.js +39 -6
  100. package/dist/cjs/model/runner.js +34 -5
  101. package/dist/cjs/model/selection-transport.js +4 -4
  102. package/dist/cjs/model/token-budget.js +3 -0
  103. package/dist/cjs/model/transports.js +3 -2
  104. package/dist/cjs/structs/index.js +7 -6
  105. package/dist/cjs/structs/kits/domains/scopes.js +2 -0
  106. package/dist/cjs/structs/kits/presentation/formats.js +2 -0
  107. package/dist/cjs/structs/kits/text-blocks.js +11 -0
  108. package/dist/cjs/structs/model/session.js +11 -0
  109. package/dist/cjs/structs/support/associations.js +2 -0
  110. package/dist/cjs/support/associations.js +79 -0
  111. package/dist/cjs/support/context/nodes.js +48 -45
  112. package/dist/cjs/support/context/processing.js +6 -3
  113. package/dist/cjs/support/context/snapshot.js +11 -1
  114. package/dist/cjs/support/decorators/index.js +45 -3
  115. package/dist/cjs/support/index.js +1 -0
  116. package/dist/cjs/support/model/capabilities.js +35 -5
  117. package/dist/cjs/support/model/chat-completions.js +11 -2
  118. package/dist/cjs/support/model/completion/calls.js +10 -56
  119. package/dist/cjs/support/model/preview-rules.js +11 -11
  120. package/dist/cjs/support/model/reply-preview.js +3 -3
  121. package/dist/cjs/support/model/session.js +152 -0
  122. package/dist/cjs/support/model/stage-transport.js +8 -8
  123. package/dist/cjs/support/model/transports.js +5 -2
  124. package/dist/cjs/support/tools.js +42 -17
  125. package/dist/cjs/utils/invocation.js +1 -0
  126. package/dist/esm/capabilities/index.d.ts +5 -10
  127. package/dist/esm/capabilities/index.js +5 -9
  128. package/dist/esm/capabilities/invocation.js +21 -1
  129. package/dist/esm/capabilities/model.d.ts +17 -13
  130. package/dist/esm/capabilities/model.js +54 -10
  131. package/dist/esm/capabilities/tool-conditions.d.ts +9 -0
  132. package/dist/esm/capabilities/tool-conditions.js +59 -0
  133. package/dist/esm/capabilities/tool-runtime.js +18 -4
  134. package/dist/esm/capabilities/tools.d.ts +3 -3
  135. package/dist/esm/capabilities/tools.js +12 -17
  136. package/dist/esm/context/audit.js +5 -8
  137. package/dist/esm/context/index.d.ts +3 -4
  138. package/dist/esm/context/index.js +3 -4
  139. package/dist/esm/diagnostics/index.d.ts +1 -0
  140. package/dist/esm/diagnostics/index.js +48 -2
  141. package/dist/esm/diagnostics/native-sub-flow.d.ts +94 -0
  142. package/dist/esm/diagnostics/native-sub-flow.js +101 -0
  143. package/dist/esm/diagnostics/sub-flow.d.ts +56 -4
  144. package/dist/esm/diagnostics/sub-flow.js +271 -32
  145. package/dist/esm/execution/engine.d.ts +1 -0
  146. package/dist/esm/execution/engine.js +3 -2
  147. package/dist/esm/execution/events.js +5 -5
  148. package/dist/esm/execution/reporting.d.ts +6 -12
  149. package/dist/esm/execution/reporting.js +19 -29
  150. package/dist/esm/execution/workflow-chain.d.ts +3 -0
  151. package/dist/esm/execution/workflow-chain.js +208 -0
  152. package/dist/esm/execution/workflow-graph.d.ts +7 -0
  153. package/dist/esm/execution/workflow-graph.js +68 -0
  154. package/dist/esm/execution/workflow.d.ts +6 -0
  155. package/dist/esm/execution/workflow.js +34 -6
  156. package/dist/esm/index.d.ts +19 -13
  157. package/dist/esm/index.js +18 -15
  158. package/dist/esm/kits/aggregation.d.ts +1 -1
  159. package/dist/esm/kits/aggregation.js +17 -14
  160. package/dist/esm/kits/answering/checks.js +2 -1
  161. package/dist/esm/kits/answering/flow.js +24 -21
  162. package/dist/esm/kits/answering/tasks.d.ts +6 -6
  163. package/dist/esm/kits/answering/tasks.js +30 -25
  164. package/dist/esm/kits/delivery.d.ts +0 -9
  165. package/dist/esm/kits/delivery.js +36 -24
  166. package/dist/esm/kits/domains/catalog.d.ts +42 -0
  167. package/dist/esm/kits/domains/catalog.js +110 -0
  168. package/dist/esm/kits/domains/index.d.ts +4 -0
  169. package/dist/esm/kits/domains/index.js +4 -0
  170. package/dist/esm/kits/domains/registry.d.ts +100 -0
  171. package/dist/esm/kits/{intents → domains}/registry.js +77 -31
  172. package/dist/esm/kits/{intents → domains}/scopes.d.ts +18 -18
  173. package/dist/esm/kits/{intents → domains}/scopes.js +21 -21
  174. package/dist/esm/kits/index.d.ts +6 -5
  175. package/dist/esm/kits/index.js +6 -5
  176. package/dist/esm/kits/knowledge/catalog.js +33 -30
  177. package/dist/esm/kits/policies.d.ts +1 -1
  178. package/dist/esm/kits/policies.js +3 -2
  179. package/dist/esm/kits/presentation/formats.d.ts +42 -0
  180. package/dist/esm/kits/presentation/formats.js +105 -0
  181. package/dist/esm/kits/presentation/index.d.ts +14 -5
  182. package/dist/esm/kits/presentation/index.js +10 -5
  183. package/dist/esm/kits/presentation/outputs.js +2 -1
  184. package/dist/esm/kits/reflection.js +3 -3
  185. package/dist/esm/kits/retrieval.js +7 -1
  186. package/dist/esm/kits/text-blocks.d.ts +24 -0
  187. package/dist/esm/kits/text-blocks.js +97 -0
  188. package/dist/esm/kits/tools.d.ts +69 -52
  189. package/dist/esm/kits/tools.js +247 -158
  190. package/dist/esm/model/decision-retry.d.ts +2 -0
  191. package/dist/esm/model/decision-retry.js +2 -1
  192. package/dist/esm/model/index.d.ts +2 -6
  193. package/dist/esm/model/index.js +2 -6
  194. package/dist/esm/model/interactions/calls.d.ts +40 -0
  195. package/dist/esm/model/interactions/calls.js +58 -0
  196. package/dist/esm/model/interactions/json-object.js +11 -11
  197. package/dist/esm/model/interactions/native-functions.js +17 -23
  198. package/dist/esm/model/message-diagnostics.d.ts +6 -5
  199. package/dist/esm/model/message-diagnostics.js +13 -3
  200. package/dist/esm/model/options.js +2 -0
  201. package/dist/esm/model/preparation.js +39 -6
  202. package/dist/esm/model/runner.d.ts +2 -0
  203. package/dist/esm/model/runner.js +34 -5
  204. package/dist/esm/model/selection-transport.js +4 -4
  205. package/dist/esm/model/token-budget.js +3 -0
  206. package/dist/esm/model/transports.d.ts +2 -1
  207. package/dist/esm/model/transports.js +3 -2
  208. package/dist/esm/structs/capabilities/invocation.d.ts +3 -1
  209. package/dist/esm/structs/capabilities/model.d.ts +42 -11
  210. package/dist/esm/structs/capabilities/tools.d.ts +16 -7
  211. package/dist/esm/structs/common.d.ts +3 -1
  212. package/dist/esm/structs/debug.d.ts +36 -20
  213. package/dist/esm/structs/execution/workflow-views.d.ts +123 -0
  214. package/dist/esm/structs/execution/workflow.d.ts +4 -3
  215. package/dist/esm/structs/index.d.ts +8 -6
  216. package/dist/esm/structs/index.js +7 -6
  217. package/dist/esm/structs/kits/answering/tasks.d.ts +2 -2
  218. package/dist/esm/structs/kits/{intents → domains}/catalog.d.ts +20 -20
  219. package/dist/esm/structs/kits/{intents → domains}/registry.d.ts +24 -21
  220. package/dist/esm/structs/kits/{intents → domains}/scopes.d.ts +9 -9
  221. package/dist/esm/structs/kits/domains/scopes.js +1 -0
  222. package/dist/esm/structs/kits/presentation/formats.d.ts +42 -0
  223. package/dist/esm/structs/kits/presentation/formats.js +1 -0
  224. package/dist/esm/structs/kits/text-blocks.d.ts +25 -0
  225. package/dist/esm/structs/kits/text-blocks.js +10 -0
  226. package/dist/esm/structs/kits/tools.d.ts +82 -83
  227. package/dist/esm/structs/model/interactions.d.ts +18 -11
  228. package/dist/esm/structs/model/messages.d.ts +34 -2
  229. package/dist/esm/structs/model/runtime.d.ts +9 -0
  230. package/dist/esm/structs/model/session.d.ts +29 -0
  231. package/dist/esm/structs/model/session.js +10 -0
  232. package/dist/esm/structs/support/associations.d.ts +22 -0
  233. package/dist/esm/structs/support/associations.js +1 -0
  234. package/dist/esm/structs/support/model/interactions.d.ts +2 -2
  235. package/dist/esm/structs/support/model/messages.d.ts +6 -13
  236. package/dist/esm/structs/support/tools.d.ts +23 -23
  237. package/dist/esm/support/associations.d.ts +26 -0
  238. package/dist/esm/support/associations.js +76 -0
  239. package/dist/esm/support/context/nodes.js +48 -45
  240. package/dist/esm/support/context/processing.js +6 -3
  241. package/dist/esm/support/context/snapshot.js +11 -1
  242. package/dist/esm/support/decorators/index.d.ts +13 -2
  243. package/dist/esm/support/decorators/index.js +40 -3
  244. package/dist/esm/support/decorators/pool.d.ts +6 -5
  245. package/dist/esm/support/decorators/types.d.ts +3 -1
  246. package/dist/esm/support/index.d.ts +1 -0
  247. package/dist/esm/support/index.js +1 -0
  248. package/dist/esm/support/model/capabilities.d.ts +8 -3
  249. package/dist/esm/support/model/capabilities.js +35 -5
  250. package/dist/esm/support/model/chat-completions.js +11 -2
  251. package/dist/esm/support/model/completion/calls.d.ts +6 -34
  252. package/dist/esm/support/model/completion/calls.js +8 -55
  253. package/dist/esm/support/model/index.d.ts +1 -1
  254. package/dist/esm/support/model/preview-rules.d.ts +13 -8
  255. package/dist/esm/support/model/preview-rules.js +11 -11
  256. package/dist/esm/support/model/reply-preview.d.ts +2 -2
  257. package/dist/esm/support/model/reply-preview.js +3 -3
  258. package/dist/esm/support/model/session.d.ts +61 -0
  259. package/dist/esm/support/model/session.js +148 -0
  260. package/dist/esm/support/model/stage-transport.d.ts +1 -1
  261. package/dist/esm/support/model/stage-transport.js +9 -9
  262. package/dist/esm/support/model/transports.d.ts +2 -0
  263. package/dist/esm/support/model/transports.js +2 -1
  264. package/dist/esm/support/tools.d.ts +11 -3
  265. package/dist/esm/support/tools.js +43 -18
  266. package/dist/esm/utils/catalog.d.ts +1 -1
  267. package/dist/esm/utils/invocation.d.ts +1 -0
  268. package/dist/esm/utils/invocation.js +1 -0
  269. package/package.json +20 -6
  270. package/dist/cjs/execution/index.js +0 -30
  271. package/dist/cjs/kits/intents/catalog.js +0 -82
  272. package/dist/cjs/kits/intents/index.js +0 -35
  273. package/dist/cjs/utils/debug.js +0 -30
  274. package/dist/esm/execution/index.d.ts +0 -11
  275. package/dist/esm/execution/index.js +0 -11
  276. package/dist/esm/kits/intents/catalog.d.ts +0 -39
  277. package/dist/esm/kits/intents/catalog.js +0 -79
  278. package/dist/esm/kits/intents/index.d.ts +0 -22
  279. package/dist/esm/kits/intents/index.js +0 -18
  280. package/dist/esm/kits/intents/registry.d.ts +0 -88
  281. package/dist/esm/utils/debug.d.ts +0 -27
  282. package/dist/esm/utils/debug.js +0 -27
  283. /package/dist/cjs/structs/{kits/intents/catalog.js → execution/workflow-views.js} +0 -0
  284. /package/dist/cjs/structs/kits/{intents/registry.js → domains/catalog.js} +0 -0
  285. /package/dist/cjs/structs/kits/{intents/scopes.js → domains/registry.js} +0 -0
  286. /package/dist/esm/structs/{kits/intents/catalog.js → execution/workflow-views.js} +0 -0
  287. /package/dist/esm/structs/kits/{intents/registry.js → domains/catalog.js} +0 -0
  288. /package/dist/esm/structs/kits/{intents/scopes.js → domains/registry.js} +0 -0
@@ -3,13 +3,14 @@
3
3
  *
4
4
  * A `ToolDefinition` is the App-facing declaration: a schema adapter plus authorize, execute
5
5
  * and parseOutput handlers. This module pins those handlers to their definition and adapts
6
- * them to the lower-level `ExecutableTool` contract, while keeping the synchronous and
6
+ * them to the lower-level `ErasedTool` contract, while keeping the synchronous and
7
7
  * asynchronous boundaries explicit: `invokeAsync` awaits authorization and execution,
8
8
  * `invoke` rejects a promise from either.
9
9
  *
10
10
  * Exports: `createToolRegistry`.
11
11
  */
12
12
  import { assertion, synchronous, isPromiseLike } from '../utils/synchronous.js';
13
+ import { toolActive } from './tool-conditions.js';
13
14
  import { ToolRegistry } from './tools.js';
14
15
  /**
15
16
  * Run authorization and execution for one call, in that order.
@@ -18,16 +19,25 @@ import { ToolRegistry } from './tools.js';
18
19
  * violation instead of being silently ignored. Cancellation is checked before and after each
19
20
  * phase so an aborted request never produces a successful value.
20
21
  */
21
- function execute(definition, input, context, execution) {
22
+ function execute(definition, input, context, execution, unavailable) {
22
23
  const { signal, mode, diagnostics, report, createSubFlowLogger } = execution;
23
24
  signal.throwIfAborted();
25
+ if (!toolActive(definition.active, context))
26
+ throw unavailable?.(definition.id) ?? new Error(`Tool is inactive: ${definition.id}`);
24
27
  // Re-check after the handler returned: work that completed during cancellation must not be
25
28
  // reported as a success.
26
29
  const complete = (value) => {
27
30
  signal.throwIfAborted();
28
31
  return value;
29
32
  };
30
- const operation = { app: context, signal, diagnostics, report, createSubFlowLogger };
33
+ const operation = {
34
+ app: context,
35
+ signal,
36
+ diagnostics,
37
+ logger: execution.logger,
38
+ report,
39
+ createSubFlowLogger,
40
+ };
31
41
  const authorized = (result) => {
32
42
  assertion(result, 'Tool authorization must return void');
33
43
  signal.throwIfAborted();
@@ -58,6 +68,7 @@ function execute(definition, input, context, execution) {
58
68
  */
59
69
  export function createToolRegistry(definitions, context, options) {
60
70
  const registry = new ToolRegistry(options);
71
+ const unavailable = options.errors?.unavailable?.bind(options.errors);
61
72
  registry.registerAll(definitions.map((definition) => {
62
73
  // Every entry point pins the same canonical handlers, including callers
63
74
  // that use this creator directly rather than defineToolCatalog.
@@ -67,6 +78,9 @@ export function createToolRegistry(definitions, context, options) {
67
78
  kind,
68
79
  description,
69
80
  inputSchema,
81
+ active: typeof definition.active === 'function'
82
+ ? definition.active.bind(definition)
83
+ : definition.active,
70
84
  authorize: authorize.bind(definition),
71
85
  execute: handle.bind(definition),
72
86
  parseOutput: parseOutput.bind(definition),
@@ -80,7 +94,7 @@ export function createToolRegistry(definitions, context, options) {
80
94
  // definition cannot change what this registry validates.
81
95
  parseInput: inputSchema.parse.bind(inputSchema),
82
96
  parseOutput: bound.parseOutput,
83
- execute: (input, execution) => execute(bound, input, context, execution),
97
+ execute: (input, execution) => execute(bound, input, context, execution, unavailable),
84
98
  };
85
99
  }));
86
100
  registry.seal();
@@ -1,10 +1,10 @@
1
1
  import type { ToolResult } from '../structs/invocation.js';
2
- import type { ExecutableTool, RegisteredTool, ToolExecutionEvent, ToolRegistryPorts, ToolRegistryOptions, ToolInvocationRequest } from '../structs/capabilities/tools.js';
2
+ import type { ErasedTool, RegisteredTool, ToolExecutionEvent, ToolRegistryPorts, ToolRegistryOptions, ToolInvocationRequest } from '../structs/capabilities/tools.js';
3
3
  /**
4
4
  * Registry mechanism only: visibility, authorization policy, schemas and semantic metadata
5
5
  * are host registrations. A registry is mutable until sealed and keeps its own call log.
6
6
  */
7
- export declare class ToolRegistry<Tool extends ExecutableTool = ExecutableTool> {
7
+ export declare class ToolRegistry<Tool extends ErasedTool = ErasedTool> {
8
8
  /** Insertion order is the declaration order and is preserved by every enumeration below. */
9
9
  private readonly tools;
10
10
  /** Sealing is one-way: a running stage must not add tools to the registry it executes. */
@@ -117,6 +117,6 @@ export declare class ToolRegistry<Tool extends ExecutableTool = ExecutableTool>
117
117
  */
118
118
  seal(): this;
119
119
  }
120
- export type { ToolDefinition, ToolExecutionContext, ExecutableTool, RegisteredTool, ToolExecutionEvent, ToolRegistryPorts, ToolRegistryOptions, ToolInvocationRequest, } from '../structs/capabilities/tools.js';
120
+ export type { ToolDefinition, ToolExecutionContext, ErasedTool, RegisteredTool, ToolExecutionEvent, ToolRegistryPorts, ToolRegistryOptions, ToolInvocationRequest, } from '../structs/capabilities/tools.js';
121
121
  export { executeInvocation } from './invocation.js';
122
122
  export type { InvocationHandler, ToolInvocationPorts, ToolJournal, } from '../structs/capabilities/invocation.js';
@@ -11,6 +11,7 @@
11
11
  *
12
12
  * Exports: `ToolRegistry`, `executeInvocation`, and the tool/invocation contracts.
13
13
  */
14
+ import { nativeSubFlowSync, nativeSubFlowAsync } from '../diagnostics/native-sub-flow.js';
14
15
  import { executionEvents } from '../execution/events.js';
15
16
  import { invocationId as nextInvocationId, invocationResult, toolInvocation, } from '../utils/invocation.js';
16
17
  import { synchronous } from '../utils/synchronous.js';
@@ -116,7 +117,8 @@ export class ToolRegistry {
116
117
  */
117
118
  invoke(request) {
118
119
  const call = toolInvocation(request, arguments.length);
119
- return this.execute(call.toolId, call.input, false, call.diagnostics, call.signal);
120
+ const callId = nextInvocationId();
121
+ return nativeSubFlowSync({ ...call, signal: combineSignals(this.ports.signal, call.signal), invocationId: callId }, 'tool', call.toolId, (scopedLogger) => this.execute(call.toolId, call.input, false, call.diagnostics, call.signal, scopedLogger, callId));
120
122
  }
121
123
  /**
122
124
  * Invoke a registered tool and await its result.
@@ -128,7 +130,8 @@ export class ToolRegistry {
128
130
  */
129
131
  async invokeAsync(request) {
130
132
  const call = toolInvocation(request, arguments.length);
131
- return (await this.execute(call.toolId, call.input, true, call.diagnostics, call.signal));
133
+ const callId = nextInvocationId();
134
+ return nativeSubFlowAsync({ ...call, signal: combineSignals(this.ports.signal, call.signal), invocationId: callId }, 'tool', call.toolId, (scopedLogger) => this.execute(call.toolId, call.input, true, call.diagnostics, call.signal, scopedLogger, callId));
132
135
  }
133
136
  /**
134
137
  * Run one call: validate, parse input, execute, parse output, then record the outcome.
@@ -140,7 +143,7 @@ export class ToolRegistry {
140
143
  * @param requestSignal Per-call signal, combined with the request-lifetime signal.
141
144
  * @returns The frozen result on success; every failure path throws.
142
145
  */
143
- execute(name, input, asynchronous, parentDiagnostics = this.diagnostics, requestSignal) {
146
+ execute(name, input, asynchronous, parentDiagnostics = this.diagnostics, requestSignal, logger, callId = nextInvocationId()) {
144
147
  // A tool call stays inside the run that invoked it: mixing two diagnostic trees would
145
148
  // produce records with two parents and break run-scoped correlation.
146
149
  if (this.diagnostics?.identity?.runId &&
@@ -152,7 +155,7 @@ export class ToolRegistry {
152
155
  throw this.ports.unavailable?.(name) ?? new Error(`Tool is not registered: ${name}`);
153
156
  // Either signal may cancel the call; combining them keeps both lifetimes effective.
154
157
  const signal = combineSignals(this.ports.signal, requestSignal);
155
- const invocationId = nextInvocationId();
158
+ const invocationId = callId;
156
159
  const diagnostics = parentDiagnostics?.child(invocationId, {
157
160
  invocationId,
158
161
  nodeRole: 'invocation',
@@ -190,24 +193,15 @@ export class ToolRegistry {
190
193
  };
191
194
  const succeed = (result) => {
192
195
  signal.throwIfAborted();
193
- let debug = reports.debug();
194
196
  if (tool.debugSteps && diagnostics?.enabled('tool.result', 'content')) {
195
197
  try {
196
- debug = reports.debug({
197
- subs: synchronous(tool.debugSteps(result, reporting), 'Tool debug reports must be synchronous'),
198
- });
198
+ synchronous(tool.debugSteps(result, reporting), 'Tool debug reports must be synchronous');
199
199
  }
200
- catch (error) {
201
- // Debug material is optional evidence: it must not turn a successful tool call into
202
- // a failure. Defer the error until a consumer actually asks for the sub-steps.
203
- debug = {
204
- usedModel: reports.debug().usedModel,
205
- subSteps: () => {
206
- throw error;
207
- },
208
- };
200
+ catch {
201
+ diagnostics?.emit('node.progress', () => ({ reportError: 'INVALID_NODE_REPORT' }));
209
202
  }
210
203
  }
204
+ const debug = reports.debug();
211
205
  signal.throwIfAborted();
212
206
  reports.close();
213
207
  diagnostics?.emit('tool.result', () => ({
@@ -277,6 +271,7 @@ export class ToolRegistry {
277
271
  signal.throwIfAborted();
278
272
  phase = 'execute';
279
273
  const value = tool.execute(parsed, {
274
+ logger,
280
275
  mode: asynchronous ? 'async' : 'sync',
281
276
  invocationId,
282
277
  signal,
@@ -32,13 +32,10 @@ export function auditContextChange(original, current, mutable) {
32
32
  const changed = JSON.stringify(before.value) !== JSON.stringify(after.value);
33
33
  breakWhile(changed &&
34
34
  (!mutable.has(before.id) || before.role === 'system' || before.trust === 'instruction'), fail(`Protected context changed: ${before.id}`));
35
- if (changed &&
36
- before.value !== null &&
37
- after.value !== null &&
38
- typeof before.value === 'object' &&
39
- typeof after.value === 'object')
40
- // Only the field set is compared here; field order is not meaningful for context data.
41
- breakWhile(JSON.stringify(Object.keys(before.value).sort()) !==
42
- JSON.stringify(Object.keys(after.value).sort()), fail('Context fields must be preserved'));
35
+ if (changed && typeof before.value === 'object' && typeof after.value === 'object')
36
+ // A null value carries no fields. Treat it as an empty field set so turning it into an
37
+ // object, or dropping an object back to null, is still rejected as a structural change.
38
+ breakWhile(JSON.stringify(Object.keys(before.value ?? {}).sort()) !==
39
+ JSON.stringify(Object.keys(after.value ?? {}).sort()), fail('Context fields must be preserved'));
43
40
  }
44
41
  }
@@ -5,14 +5,13 @@
5
5
  * Core owns the guarantees here. A fragment declares its trust, lifetime and character
6
6
  * budget in one place; assembly validates those declarations and refuses to truncate;
7
7
  * auditing rejects structural change to protected fragments. Selection, ordering, compression
8
- * and model choice remain App-side nodes that run before this boundary.
8
+ * and model choice remain App-side nodes that run before this boundary. Optional Kit helpers
9
+ * such as evidence checks are imported from their own `/kits/*` entries, not from here.
9
10
  *
10
- * Exports: `assembleFragments`, `assembleContextPlan`, `ContextJournal`, the fragment helpers,
11
- * and the evidence Kit helpers consumed alongside assembled context.
11
+ * Exports: `assembleFragments`, `assembleContextPlan`, `ContextJournal` and the fragment helpers.
12
12
  */
13
13
  export * from './fragments.js';
14
14
  export { assembleFragments } from './assembly.js';
15
15
  export * from './journal.js';
16
- export * from '../kits/evidence.js';
17
16
  export type { ContextPlan } from '../structs/context/processing.js';
18
17
  export { assembleContextPlan } from './plan.js';
@@ -5,13 +5,12 @@
5
5
  * Core owns the guarantees here. A fragment declares its trust, lifetime and character
6
6
  * budget in one place; assembly validates those declarations and refuses to truncate;
7
7
  * auditing rejects structural change to protected fragments. Selection, ordering, compression
8
- * and model choice remain App-side nodes that run before this boundary.
8
+ * and model choice remain App-side nodes that run before this boundary. Optional Kit helpers
9
+ * such as evidence checks are imported from their own `/kits/*` entries, not from here.
9
10
  *
10
- * Exports: `assembleFragments`, `assembleContextPlan`, `ContextJournal`, the fragment helpers,
11
- * and the evidence Kit helpers consumed alongside assembled context.
11
+ * Exports: `assembleFragments`, `assembleContextPlan`, `ContextJournal` and the fragment helpers.
12
12
  */
13
13
  export * from './fragments.js';
14
14
  export { assembleFragments } from './assembly.js';
15
15
  export * from './journal.js';
16
- export * from '../kits/evidence.js';
17
16
  export { assembleContextPlan } from './plan.js';
@@ -1,6 +1,7 @@
1
1
  import type { DiagnosticContext, CreateDiagnosticsOptions } from '../structs/diagnostics.js';
2
2
  export * from '../structs/diagnostics.js';
3
3
  export * from './catalog.js';
4
+ export { SubFlowLogger, ScopedSubFlowLogger } from './sub-flow.js';
4
5
  export type * from '../structs/debug.js';
5
6
  export { reportedStepStatusCatalog, reportedStepStatuses } from '../structs/debug.js';
6
7
  /**
@@ -17,6 +17,7 @@ import { payloadSnapshot } from './sub-flow.js';
17
17
  import { breakWhile } from '../utils/rules.js';
18
18
  export * from '../structs/diagnostics.js';
19
19
  export * from './catalog.js';
20
+ export { SubFlowLogger, ScopedSubFlowLogger } from './sub-flow.js';
20
21
  export { reportedStepStatusCatalog, reportedStepStatuses } from '../structs/debug.js';
21
22
  /**
22
23
  * Configure the optional log consumer of the shared execution fact source.
@@ -107,7 +108,7 @@ export function normalizeDiagnosticEvent(input) {
107
108
  // The count and size bounds match what the sub-flow logger enforces, so a record produced by
108
109
  // Core can never be rejected here; only hand-edited or foreign records can.
109
110
  if (!Array.isArray(steps) ||
110
- steps.length > 256 ||
111
+ steps.length > 1024 ||
111
112
  new Set(steps.map((step) => step?.stepId)).size !== steps.length ||
112
113
  steps.some((step) => !step ||
113
114
  step.origin !== 'reported' ||
@@ -118,7 +119,15 @@ export function normalizeDiagnosticEvent(input) {
118
119
  !Number.isSafeInteger(step.sequence) ||
119
120
  step.sequence < 1 ||
120
121
  (step.status !== undefined && !reportedStepStatuses.includes(step.status)) ||
121
- ['parentStepId', 'relatedDefinitionId', 'caseId', 'summary'].some((key) => step[key] !== undefined && typeof step[key] !== 'string') ||
122
+ [
123
+ 'type',
124
+ 'subnodeId',
125
+ 'parentStepId',
126
+ 'relatedDefinitionId',
127
+ 'relatedInvocationId',
128
+ 'caseId',
129
+ 'summary',
130
+ ].some((key) => step[key] !== undefined && typeof step[key] !== 'string') ||
122
131
  (step.usedModel !== undefined && typeof step.usedModel !== 'boolean') ||
123
132
  (step.revision !== undefined &&
124
133
  (!Number.isSafeInteger(step.revision) ||
@@ -133,6 +142,37 @@ export function normalizeDiagnosticEvent(input) {
133
142
  (!Number.isSafeInteger(raw.subStepsDropped) || Number(raw.subStepsDropped) < 0)) ||
134
143
  (raw.subStepsTruncated !== undefined && typeof raw.subStepsTruncated !== 'boolean'))
135
144
  throw new TypeError('Invalid reported diagnostic steps');
145
+ const originals = new Map();
146
+ let lastSequence = 0;
147
+ for (const step of steps) {
148
+ if (step.operation === undefined)
149
+ continue; // Historical projected snapshots remain readable.
150
+ breakWhile(!['write', 'fix'].includes(step.operation) || step.sequence <= lastSequence, () => new TypeError('Invalid sub-flow record order'));
151
+ lastSequence = step.sequence;
152
+ if (step.operation === 'write') {
153
+ breakWhile(step.targetStepId !== undefined || step.revision !== 1, () => new TypeError('Invalid sub-flow write record'));
154
+ originals.set(step.stepId, {
155
+ revision: 1,
156
+ subnodeId: step.subnodeId,
157
+ type: step.type,
158
+ relatedInvocationId: step.relatedInvocationId,
159
+ });
160
+ }
161
+ else {
162
+ const previous = originals.get(step.targetStepId);
163
+ breakWhile(previous === undefined ||
164
+ step.revision !== previous.revision + 1 ||
165
+ step.subnodeId !== previous.subnodeId ||
166
+ step.type !== previous.type ||
167
+ step.relatedInvocationId !== previous.relatedInvocationId, () => new TypeError('Invalid sub-flow fix reference'));
168
+ originals.set(step.targetStepId, {
169
+ revision: step.revision,
170
+ subnodeId: step.subnodeId,
171
+ type: step.type,
172
+ relatedInvocationId: step.relatedInvocationId,
173
+ });
174
+ }
175
+ }
136
176
  // Structural check only: the returned snapshot is discarded because the clone below already
137
177
  // produces the detached copy kept by the normalized record.
138
178
  for (const step of steps)
@@ -145,8 +185,14 @@ export function normalizeDiagnosticEvent(input) {
145
185
  breakWhile(progress !== undefined &&
146
186
  (!progress ||
147
187
  !['write', 'fix'].includes(progress.operation) ||
188
+ ['type', 'subnodeId', 'relatedInvocationId'].some((key) => progress[key] !== undefined &&
189
+ typeof progress[key] !== 'string') ||
148
190
  typeof progress.stepId !== 'string' ||
149
191
  !progress.stepId ||
192
+ (progress.targetStepId !== undefined &&
193
+ (progress.operation !== 'fix' ||
194
+ typeof progress.targetStepId !== 'string' ||
195
+ !progress.targetStepId)) ||
150
196
  !Number.isSafeInteger(progress.sequence) ||
151
197
  progress.sequence < 1 ||
152
198
  !Number.isSafeInteger(progress.revision) ||
@@ -0,0 +1,94 @@
1
+ /**
2
+ * Optional fixed sub-flow records for native execution boundaries.
3
+ *
4
+ * Callers choose the logger explicitly. A full logger issues a scoped delegate for this call; already-scoped Kit contexts reuse
5
+ * their delegate. Neither path creates storage or changes execution and cancellation.
6
+ * Logging failures are isolated from the wrapped operation.
7
+ *
8
+ * Exports: nativeSubFlowCatalog, nativeSubFlowSync, nativeSubFlowAsync.
9
+ */
10
+ import type { SubFlowLog, ScopedSubFlowLogger } from '../structs/debug.js';
11
+ /** Fixed metadata shared by native producers; pure getters and formatters are not producers. */
12
+ export declare const nativeSubFlowCatalog: {
13
+ readonly model: {
14
+ readonly name: "Model call";
15
+ readonly kind: "model";
16
+ readonly type: "model.call";
17
+ };
18
+ readonly tool: {
19
+ readonly name: "Tool call";
20
+ readonly kind: "tool";
21
+ readonly type: "tool.call";
22
+ };
23
+ readonly invocation: {
24
+ readonly name: "Invocation";
25
+ readonly kind: "invocation";
26
+ readonly type: "handler.call";
27
+ };
28
+ readonly retrieval: {
29
+ readonly name: "Retrieval";
30
+ readonly kind: "retrieval";
31
+ readonly type: "retrieval.run";
32
+ };
33
+ readonly task: {
34
+ readonly name: "Read answer evidence";
35
+ readonly kind: "retrieval";
36
+ readonly type: "evidence.read";
37
+ };
38
+ readonly check: {
39
+ readonly name: "Check answer";
40
+ readonly kind: "validation";
41
+ readonly type: "answer.check";
42
+ };
43
+ readonly output: {
44
+ readonly name: "Compose output";
45
+ readonly kind: "presentation";
46
+ readonly type: "output.compose";
47
+ };
48
+ readonly answer: {
49
+ readonly name: "Answer flow";
50
+ readonly kind: "answering";
51
+ readonly type: "answer.run";
52
+ };
53
+ readonly retry: {
54
+ readonly name: "Retry model proposal";
55
+ readonly kind: "recovery";
56
+ readonly type: "model.retry";
57
+ };
58
+ readonly context: {
59
+ readonly name: "Process context";
60
+ readonly kind: "context";
61
+ readonly type: "context.process";
62
+ };
63
+ readonly recovery: {
64
+ readonly name: "Recovery attempt";
65
+ readonly kind: "recovery";
66
+ readonly type: "recovery.try";
67
+ };
68
+ readonly delivery: {
69
+ readonly name: "Deliver result";
70
+ readonly kind: "delivery";
71
+ readonly type: "delivery.run";
72
+ };
73
+ readonly aggregation: {
74
+ readonly name: "Aggregate queries";
75
+ readonly kind: "retrieval";
76
+ readonly type: "queries.collect";
77
+ };
78
+ readonly knowledge: {
79
+ readonly name: "Read knowledge";
80
+ readonly kind: "retrieval";
81
+ readonly type: "knowledge.read";
82
+ };
83
+ };
84
+ type Producer = keyof typeof nativeSubFlowCatalog;
85
+ type Context = {
86
+ readonly logger?: SubFlowLog;
87
+ readonly signal?: AbortSignal;
88
+ readonly invocationId?: string;
89
+ };
90
+ /** Preserve a synchronous boundary while pairing an optional write with one result revision. */
91
+ export declare function nativeSubFlowSync<Value>(context: Context, producer: Producer, id: string, invoke: (logger?: ScopedSubFlowLogger) => Value): Value;
92
+ /** Await the original operation without introducing another timeout or cancellation race. */
93
+ export declare function nativeSubFlowAsync<Value>(context: Context, producer: Producer, id: string, invoke: (logger?: ScopedSubFlowLogger) => Value | PromiseLike<Value>): Promise<Value>;
94
+ export {};
@@ -0,0 +1,101 @@
1
+ import { SubFlowLogger, requireSubFlowLogger, bindNativeSubFlowLogger } from './sub-flow.js';
2
+ /** Fixed metadata shared by native producers; pure getters and formatters are not producers. */
3
+ export const nativeSubFlowCatalog = {
4
+ model: { name: 'Model call', kind: 'model', type: 'model.call' },
5
+ tool: { name: 'Tool call', kind: 'tool', type: 'tool.call' },
6
+ invocation: { name: 'Invocation', kind: 'invocation', type: 'handler.call' },
7
+ retrieval: { name: 'Retrieval', kind: 'retrieval', type: 'retrieval.run' },
8
+ task: { name: 'Read answer evidence', kind: 'retrieval', type: 'evidence.read' },
9
+ check: { name: 'Check answer', kind: 'validation', type: 'answer.check' },
10
+ output: { name: 'Compose output', kind: 'presentation', type: 'output.compose' },
11
+ answer: { name: 'Answer flow', kind: 'answering', type: 'answer.run' },
12
+ retry: { name: 'Retry model proposal', kind: 'recovery', type: 'model.retry' },
13
+ context: { name: 'Process context', kind: 'context', type: 'context.process' },
14
+ recovery: { name: 'Recovery attempt', kind: 'recovery', type: 'recovery.try' },
15
+ delivery: { name: 'Deliver result', kind: 'delivery', type: 'delivery.run' },
16
+ aggregation: { name: 'Aggregate queries', kind: 'retrieval', type: 'queries.collect' },
17
+ knowledge: { name: 'Read knowledge', kind: 'retrieval', type: 'knowledge.read' },
18
+ };
19
+ /** Start one fixed record; its revision is best-effort and never controls the operation. */
20
+ function begin(context, producer, id) {
21
+ let logger;
22
+ try {
23
+ logger =
24
+ context.logger instanceof SubFlowLogger
25
+ ? bindNativeSubFlowLogger(context.logger, producer, id)
26
+ : context.logger;
27
+ }
28
+ catch {
29
+ /* A recording limit must not turn a valid operation into a failure. */
30
+ }
31
+ let step = -1;
32
+ try {
33
+ if (logger)
34
+ step = logger.write({
35
+ ...nativeSubFlowCatalog[producer],
36
+ relatedDefinitionId: id,
37
+ ...(context.invocationId === undefined
38
+ ? {}
39
+ : { relatedInvocationId: context.invocationId }),
40
+ status: 'running',
41
+ });
42
+ }
43
+ catch {
44
+ /* Optional recording must not change execution. */
45
+ }
46
+ return {
47
+ logger,
48
+ finish: (status) => {
49
+ try {
50
+ if (logger && step !== -1)
51
+ logger.fix(step, { status });
52
+ }
53
+ catch {
54
+ /* A broken or detached logger cannot replace the operation result. */
55
+ }
56
+ },
57
+ };
58
+ }
59
+ /** Signal access is diagnostic metadata and cannot replace an operation failure. */
60
+ function failureStatus(context) {
61
+ try {
62
+ return context.signal?.aborted ? 'cancelled' : 'error';
63
+ }
64
+ catch {
65
+ return 'error';
66
+ }
67
+ }
68
+ /** Preserve a synchronous boundary while pairing an optional write with one result revision. */
69
+ export function nativeSubFlowSync(context, producer, id, invoke) {
70
+ if (producer === 'model' || producer === 'tool' || producer === 'invocation')
71
+ requireSubFlowLogger(context.logger);
72
+ if (!context.logger)
73
+ return invoke();
74
+ const { logger, finish } = begin(context, producer, id);
75
+ try {
76
+ const value = invoke(logger);
77
+ finish('success');
78
+ return value;
79
+ }
80
+ catch (error) {
81
+ finish(failureStatus(context));
82
+ throw error;
83
+ }
84
+ }
85
+ /** Await the original operation without introducing another timeout or cancellation race. */
86
+ export async function nativeSubFlowAsync(context, producer, id, invoke) {
87
+ if (producer === 'model' || producer === 'tool' || producer === 'invocation')
88
+ requireSubFlowLogger(context.logger);
89
+ if (!context.logger)
90
+ return invoke();
91
+ const { logger, finish } = begin(context, producer, id);
92
+ try {
93
+ const value = await invoke(logger);
94
+ finish('success');
95
+ return value;
96
+ }
97
+ catch (error) {
98
+ finish(failureStatus(context));
99
+ throw error;
100
+ }
101
+ }
@@ -1,5 +1,12 @@
1
- import type { RecordedSubStep, SubFlowLogger, SubStepProgress, SubFlowValue } from '../structs/debug.js';
1
+ import type { RecordedSubStep, SubFlowLog, SubFlowStepInput, SubFlowStepFix, SubStepProgress, SubFlowValue } from '../structs/debug.js';
2
2
  import type { DiagnosticIdentity } from '../structs/diagnostics.js';
3
+ type Step = RecordedSubStep & Required<Pick<RecordedSubStep, 'createdAtMs' | 'revision' | 'status'>>;
4
+ /** Validate a committed snapshot without consulting its logger or invoking App code. */
5
+ export declare function captureSubFlowSnapshot(steps: readonly Readonly<RecordedSubStep>[] | undefined, identity?: Readonly<DiagnosticIdentity>): {
6
+ subSteps: readonly Readonly<RecordedSubStep>[];
7
+ subStepsDropped: number;
8
+ subStepsTruncated: boolean;
9
+ };
3
10
  /**
4
11
  * Validate and deep-copy a reported payload.
5
12
  *
@@ -14,6 +21,48 @@ import type { DiagnosticIdentity } from '../structs/diagnostics.js';
14
21
  * limits below.
15
22
  */
16
23
  export declare function payloadSnapshot(input: unknown): Readonly<Record<string, SubFlowValue>>;
24
+ /** Stable diagnostic reasons; untrusted error text and caller payloads never reach the console. */
25
+ declare const rejectionReasons: {
26
+ readonly inactive: "logger is detached or execution is cancelled";
27
+ readonly scope: "target does not belong to this subnode";
28
+ readonly target: "original write record was not found";
29
+ readonly fields: "input contains a forbidden field";
30
+ readonly transition: "status transition is not allowed";
31
+ readonly sealed: "an established fact cannot be overwritten";
32
+ readonly limit: "recording limit exceeded";
33
+ readonly input: "invalid input or result patch";
34
+ };
35
+ type RejectionReason = keyof typeof rejectionReasons;
36
+ /** Unexported issuance token prevents constructing counterfeit full or scoped loggers. */
37
+ declare const loggerToken: unique symbol;
38
+ type Store = SubFlowLog & {
39
+ owns(stepId: string | -1, subnodeId: string): boolean;
40
+ isActive(): boolean;
41
+ nextNativeSubnodeId(kind: string, definitionId: string): string;
42
+ warn(operation: 'write' | 'fix', reason: RejectionReason): void;
43
+ };
44
+ /** Full execution-owned recorder. Owns its store and may issue restricted delegates. */
45
+ export declare class SubFlowLogger implements SubFlowLog {
46
+ #private;
47
+ constructor(token: typeof loggerToken, store: Store);
48
+ write(input: SubFlowStepInput): string | -1;
49
+ fix(stepId: string | -1, patch: SubFlowStepFix): boolean;
50
+ readAll(): readonly Readonly<RecordedSubStep>[];
51
+ /** Issue a delegate for an App-owned logical group; no execution or scheduling is implied. */
52
+ fork(subnodeId: string): ScopedSubFlowLogger;
53
+ }
54
+ /** Non-inheriting delegate. Stores only the original logger and its bound subnode identity. */
55
+ export declare class ScopedSubFlowLogger implements SubFlowLog {
56
+ #private;
57
+ constructor(token: typeof loggerToken, logger: SubFlowLogger, subnodeId: string);
58
+ write(input: Omit<SubFlowStepInput, 'subnodeId'>): string | -1;
59
+ fix(stepId: string | -1, patch: SubFlowStepFix): boolean;
60
+ readAll(): readonly Readonly<RecordedSubStep>[];
61
+ }
62
+ /** Runtime check complements nominal invocation types; scoped or forged inputs cannot invoke. */
63
+ export declare function requireSubFlowLogger(logger: unknown): asserts logger is SubFlowLogger | undefined;
64
+ /** Allocate a short node-local group; the owning node visit already supplies the namespace. */
65
+ export declare function bindNativeSubFlowLogger(logger: SubFlowLogger, kind: string, definitionId: string): ScopedSubFlowLogger;
17
66
  /**
18
67
  * Create a logger bound to one active execution visit.
19
68
  *
@@ -22,14 +71,14 @@ export declare function payloadSnapshot(input: unknown): Readonly<Record<string,
22
71
  *
23
72
  * @param owner Object that owns the visit. `readSubFlowLogger` compares this identity before
24
73
  * returning any step.
25
- * @param active Reports whether the visit is still open; a closed logger rejects writes.
74
+ * @param active Reports whether the visit is still open; a detached logger returns write=-1 and fix=false.
26
75
  * @param content Reports whether content-level detail is enabled. When false, summaries and
27
76
  * payloads are dropped before anything is stored.
28
- * @param changed Called after each accepted write or fix with the progress delta to publish.
77
+ * @param changed Runtime receiver called after each accepted write/fix with its delta and immutable snapshot.
29
78
  * @param identity Diagnostic run and span the logger belongs to; used to reject cross-scope reads.
30
79
  * @returns A frozen logger instance.
31
80
  */
32
- export declare function createSubFlowLogger(owner: object, active: () => boolean, content: () => boolean, changed: (logger: SubFlowLogger, progress: SubStepProgress) => void, identity?: Readonly<DiagnosticIdentity>): SubFlowLogger;
81
+ export declare function createSubFlowLogger(owner: object, active: () => boolean, content: () => boolean, changed: (logger: SubFlowLogger, progress: SubStepProgress, steps: readonly Step[]) => void, identity?: Readonly<DiagnosticIdentity>): SubFlowLogger;
33
82
  /**
34
83
  * Read the steps recorded by a logger issued by this module.
35
84
  *
@@ -44,3 +93,6 @@ export declare function createSubFlowLogger(owner: object, active: () => boolean
44
93
  * belongs to another diagnostic scope.
45
94
  */
46
95
  export declare function readSubFlowLogger(input: unknown, owner?: object, identity?: Readonly<DiagnosticIdentity>): readonly Readonly<RecordedSubStep>[];
96
+ /** Release execution callbacks while preserving the instance's immutable query history. */
97
+ export declare function detachSubFlowLogger(logger: SubFlowLogger): void;
98
+ export {};