@jangts/agent-core 0.3.5 → 0.3.6

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 (97) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/README.md +28 -26
  3. package/development/docs/api/README.en.md +2 -0
  4. package/development/docs/api/README.md +2 -0
  5. package/development/docs/api/observability.en.md +37 -11
  6. package/development/docs/api/observability.md +64 -11
  7. package/development/docs/api/reference.en.md +469 -348
  8. package/development/docs/api/reference.md +193 -137
  9. package/development/docs/api/types.en.md +1 -0
  10. package/development/docs/api/types.md +1 -0
  11. package/development/docs/api/workflow-views.en.md +64 -0
  12. package/development/docs/api/workflow-views.md +78 -0
  13. package/development/docs/api/workflow.en.md +6 -2
  14. package/development/docs/api/workflow.md +6 -2
  15. package/development/skills/agent-core-app/SKILL.md +12 -0
  16. package/dist/cjs/capabilities/invocation.js +21 -1
  17. package/dist/cjs/capabilities/tool-runtime.js +8 -1
  18. package/dist/cjs/capabilities/tools.js +12 -17
  19. package/dist/cjs/diagnostics/index.js +51 -3
  20. package/dist/cjs/diagnostics/native-sub-flow.js +106 -0
  21. package/dist/cjs/diagnostics/sub-flow.js +278 -32
  22. package/dist/cjs/execution/engine.js +3 -2
  23. package/dist/cjs/execution/events.js +5 -5
  24. package/dist/cjs/execution/reporting.js +18 -28
  25. package/dist/cjs/execution/workflow-chain.js +211 -0
  26. package/dist/cjs/execution/workflow-graph.js +72 -0
  27. package/dist/cjs/execution/workflow.js +34 -6
  28. package/dist/cjs/kits/aggregation.js +17 -14
  29. package/dist/cjs/kits/answering/checks.js +2 -1
  30. package/dist/cjs/kits/answering/flow.js +24 -21
  31. package/dist/cjs/kits/answering/tasks.js +25 -20
  32. package/dist/cjs/kits/delivery.js +36 -24
  33. package/dist/cjs/kits/knowledge/catalog.js +33 -30
  34. package/dist/cjs/kits/policies.js +3 -2
  35. package/dist/cjs/kits/presentation/outputs.js +2 -1
  36. package/dist/cjs/kits/retrieval.js +7 -1
  37. package/dist/cjs/kits/tools.js +1 -0
  38. package/dist/cjs/model/decision-retry.js +2 -1
  39. package/dist/cjs/model/runner.js +20 -5
  40. package/dist/cjs/structs/execution/workflow-views.js +2 -0
  41. package/dist/cjs/support/context/nodes.js +48 -45
  42. package/dist/cjs/support/context/processing.js +6 -3
  43. package/dist/cjs/utils/invocation.js +1 -0
  44. package/dist/esm/capabilities/invocation.js +21 -1
  45. package/dist/esm/capabilities/tool-runtime.js +8 -1
  46. package/dist/esm/capabilities/tools.js +12 -17
  47. package/dist/esm/diagnostics/index.d.ts +1 -0
  48. package/dist/esm/diagnostics/index.js +48 -2
  49. package/dist/esm/diagnostics/native-sub-flow.d.ts +94 -0
  50. package/dist/esm/diagnostics/native-sub-flow.js +101 -0
  51. package/dist/esm/diagnostics/sub-flow.d.ts +56 -4
  52. package/dist/esm/diagnostics/sub-flow.js +271 -32
  53. package/dist/esm/execution/engine.d.ts +1 -0
  54. package/dist/esm/execution/engine.js +3 -2
  55. package/dist/esm/execution/events.js +5 -5
  56. package/dist/esm/execution/reporting.d.ts +6 -12
  57. package/dist/esm/execution/reporting.js +19 -29
  58. package/dist/esm/execution/workflow-chain.d.ts +3 -0
  59. package/dist/esm/execution/workflow-chain.js +208 -0
  60. package/dist/esm/execution/workflow-graph.d.ts +7 -0
  61. package/dist/esm/execution/workflow-graph.js +68 -0
  62. package/dist/esm/execution/workflow.d.ts +6 -0
  63. package/dist/esm/execution/workflow.js +34 -6
  64. package/dist/esm/kits/aggregation.d.ts +1 -1
  65. package/dist/esm/kits/aggregation.js +17 -14
  66. package/dist/esm/kits/answering/checks.js +2 -1
  67. package/dist/esm/kits/answering/flow.js +24 -21
  68. package/dist/esm/kits/answering/tasks.js +25 -20
  69. package/dist/esm/kits/delivery.d.ts +0 -9
  70. package/dist/esm/kits/delivery.js +36 -24
  71. package/dist/esm/kits/knowledge/catalog.js +33 -30
  72. package/dist/esm/kits/policies.d.ts +1 -1
  73. package/dist/esm/kits/policies.js +3 -2
  74. package/dist/esm/kits/presentation/outputs.js +2 -1
  75. package/dist/esm/kits/retrieval.js +7 -1
  76. package/dist/esm/kits/tools.js +1 -0
  77. package/dist/esm/model/decision-retry.d.ts +2 -0
  78. package/dist/esm/model/decision-retry.js +2 -1
  79. package/dist/esm/model/runner.d.ts +2 -0
  80. package/dist/esm/model/runner.js +20 -5
  81. package/dist/esm/structs/capabilities/invocation.d.ts +2 -0
  82. package/dist/esm/structs/capabilities/tools.d.ts +7 -3
  83. package/dist/esm/structs/common.d.ts +2 -0
  84. package/dist/esm/structs/debug.d.ts +36 -20
  85. package/dist/esm/structs/execution/workflow-views.d.ts +123 -0
  86. package/dist/esm/structs/execution/workflow-views.js +1 -0
  87. package/dist/esm/structs/execution/workflow.d.ts +4 -3
  88. package/dist/esm/structs/index.d.ts +1 -0
  89. package/dist/esm/structs/model/runtime.d.ts +2 -0
  90. package/dist/esm/support/context/nodes.js +48 -45
  91. package/dist/esm/support/context/processing.js +6 -3
  92. package/dist/esm/utils/invocation.d.ts +1 -0
  93. package/dist/esm/utils/invocation.js +1 -0
  94. package/package.json +1 -1
  95. package/dist/cjs/utils/debug.js +0 -30
  96. package/dist/esm/utils/debug.d.ts +0 -27
  97. package/dist/esm/utils/debug.js +0 -27
package/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  本文件记录 `@jangts/agent-core` 的行为变更。接口合同与使用方式见[API 手册](development/docs/api/README.md)。
4
4
 
5
+ ## 0.3.6
6
+
7
+ - Preserve explicit recovery targets from workflow error events as execution-chain transitions linked to the original errorEventId.
8
+
9
+ - Export immutable Workflow topology with toGraph() and observed per-visit execution chains with toChain(runId); keep ordered append-only subflow records and App-owned authorized read sources.
10
+ - Snapshot routes getters exactly once during node registration for execution and graph export.
11
+
12
+ - Shorten registered subnode IDs to node-local kind/definition/ordinal identifiers; retain real call correlation in relatedInvocationId.
13
+
14
+ - Separate arbitrary business type from write/fix operation and add explicit subnodeId grouping.
15
+ - Independent full/scoped logger classes share one owning store and full readAll history. Scoped delegates bind writes, restrict fixes, cannot fork, and cannot invoke; actual invocations bind their existing execution identity.
16
+ - Rejected writes/fixes keep sentinel returns and emit safe, deduplicated developer warnings.
17
+
18
+ - Optional per-call logger for native model/tool/invocation and executable Kit boundaries; omitted loggers add no sub-logs and are never inferred or globally forwarded.
19
+ - Every accepted fix appends an independently identified record referencing the original write through targetStepId; readAll preserves the full write/fix ledger in append order.
20
+
21
+ - Bind each sub-flow logger to its execution context; write/fix commit immutable snapshots immediately to runtime and notify App observers through node.progress.
22
+ - Remove logger submission through report.subs; readAll remains a read-only local query. Terminal events use runtime-owned snapshots and detached visits return write=-1 / fix=false without throwing, while every holder retains readAll access.
23
+ - write returns the new ID on success and -1 on any failure; fix returns a success boolean for every attempt; invalid revisions and detached instances return false without throwing. Retained loggers remain readable across visits or external borrowing.
24
+ - Tool debugSteps hooks write through their bound context and no longer return a logger.
25
+
5
26
  ## 0.3.5
6
27
 
7
28
  - Add decorators and typescript-decorators keywords for npm discovery; preserve the English-first getting-started README.
package/README.md CHANGED
@@ -46,7 +46,7 @@ console.log(await agent.run({ question: 'Hello' }));
46
46
 
47
47
  A node returns a state patch. After commit, routes read the updated state: `route.to('next')` continues to another node; `route.deliver('answer')` returns the final result. The first node is the default entry, and routes match in declaration order.
48
48
 
49
- The Provider above returns fixed text. Replace it with a real Provider without changing the workflow. The [complete offline example](https://agent-core-docs.pages.jangts.cafe/en/manual/examples/offline-agent) adds tools, multiple nodes and progress observation.
49
+ The Provider above returns fixed text. Replace it with a real Provider without changing the workflow. The [complete offline example](https://agent-core-docs.pages.jangts.cafe/en/manual/examples/offline-agent.html) adds tools, multiple nodes and progress observation.
50
50
 
51
51
  ## Connect a real model
52
52
 
@@ -89,7 +89,7 @@ export AI_MODEL="your-model-id"
89
89
  node model.mjs
90
90
  ```
91
91
 
92
- To connect the first workflow, replace its offline provider declaration with `import { provider } from './provider.mjs'`. Model `invoke` returns `{ value, invocation }`; `value` contains the complete result and `invocation` records the call. Failures throw. Configure Runner `sink.output` to consume live chunks while retaining the complete `value`. See [Core model calls](https://agent-core-docs.pages.jangts.cafe/en/manual/api/core).
92
+ To connect the first workflow, replace its offline provider declaration with `import { provider } from './provider.mjs'`. Model `invoke` returns `{ value, invocation }`; `value` contains the complete result and `invocation` records the call. Failures throw. Configure Runner `sink.output` to consume live chunks while retaining the complete `value`. See [Core model calls](https://agent-core-docs.pages.jangts.cafe/en/manual/api/core.html).
93
93
 
94
94
  ## Define and execute a tool
95
95
 
@@ -146,7 +146,7 @@ const executed = await tools.invoke({
146
146
  console.log(executed.value); // 42
147
147
  ```
148
148
 
149
- The model proposes an id and arguments. `tools.invoke` performs parsing, authorization and business execution. For multi-step behavior, put selection, execution and reply into Workflow nodes using `context.model.invoke` and `context.tools.invoke`. See [model and tool integration](https://agent-core-docs.pages.jangts.cafe/en/manual/basic-usage).
149
+ The model proposes an id and arguments. `tools.invoke` performs parsing, authorization and business execution. For multi-step behavior, put selection, execution and reply into Workflow nodes using `context.model.invoke` and `context.tools.invoke`. See [model and tool integration](https://agent-core-docs.pages.jangts.cafe/en/manual/basic-usage.html).
150
150
 
151
151
  ## Organize handlers as classes
152
152
 
@@ -183,7 +183,7 @@ Install `npm install -D tsx typescript`, then run `npx tsx greeting.mts`. Existi
183
183
  - `@tool` and `@fragment` support classes and existing instance methods; method decorators retain the original name and bind the real host. `@workflow`, `@agent` and `@model` define original options without creating Engines or Runners.
184
184
  - Getters can organize routes and private helpers. The route table is fixed during assembly; `when/complete` callbacks receive the latest execution state.
185
185
 
186
- The [decorator guide](https://agent-core-docs.pages.jangts.cafe/en/manual/api/decorators) covers host binding, namespace reads, multi-namespace registration and instance scope. Object definitions and decorator outputs use the same Core contracts.
186
+ The [decorator guide](https://agent-core-docs.pages.jangts.cafe/en/manual/api/decorators.html) covers host binding, namespace reads, multi-namespace registration and instance scope. Object definitions and decorator outputs use the same Core contracts.
187
187
 
188
188
  ## Add knowledge, context and caching
189
189
 
@@ -199,21 +199,22 @@ const snapshot = knowledge.read({ documentId: 'manual', selection: { mode: 'docu
199
199
  console.log(snapshot);
200
200
  ```
201
201
 
202
- App supplies the material; knowledge catalogs handle identity, versions and selection without automatically crawling websites or creating databases. The [knowledge-answering example](https://agent-core-docs.pages.jangts.cafe/en/manual/api/knowledge-answering) connects retrieval, evidence checking, generation, repair and delivery.
202
+ App supplies the material; knowledge catalogs handle identity, versions and selection without automatically crawling websites or creating databases. The [knowledge-answering example](https://agent-core-docs.pages.jangts.cafe/en/manual/api/knowledge-answering.html) connects retrieval, evidence checking, generation, repair and delivery.
203
203
 
204
- Workflow `context.cache` provides synchronous Engine-lifetime memory partitioned by node, using `get/has/set/delete/clear`. App-owned asynchronous `context.agentCache` connects longer-lived storage; workflow state remains in state. Ordinary nodes and Support policies handle history selection, trimming and summaries. See [context processing](https://agent-core-docs.pages.jangts.cafe/en/manual/api/context-processing) and [cache contracts](https://agent-core-docs.pages.jangts.cafe/en/manual/api/workflow).
204
+ Workflow `context.cache` provides synchronous Engine-lifetime memory partitioned by node, using `get/has/set/delete/clear`. App-owned asynchronous `context.agentCache` connects longer-lived storage; workflow state remains in state. Ordinary nodes and Support policies handle history selection, trimming and summaries. See [context processing](https://agent-core-docs.pages.jangts.cafe/en/manual/api/context-processing.html) and [cache contracts](https://agent-core-docs.pages.jangts.cafe/en/manual/api/workflow.html).
205
205
 
206
206
  ## Continue by task
207
207
 
208
208
  | Task | Documentation |
209
209
  | --- | --- |
210
- | Create an app or integrate with a project | [Developer guide](https://agent-core-docs.pages.jangts.cafe/en/manual/) · [Installation](https://agent-core-docs.pages.jangts.cafe/en/manual/getting-started) |
211
- | Routes, models, budgets, cancellation and branches | [Workflow](https://agent-core-docs.pages.jangts.cafe/en/manual/api/workflow) · [Core](https://agent-core-docs.pages.jangts.cafe/en/manual/api/core) |
212
- | Tools, schemas, context and integration policies | [Support](https://agent-core-docs.pages.jangts.cafe/en/manual/api/support) · [Context nodes](https://agent-core-docs.pages.jangts.cafe/en/manual/api/context-processing) |
213
- | Knowledge, intents, retrieval, artifacts and persistent tasks | [Kits](https://agent-core-docs.pages.jangts.cafe/en/manual/api/kits) · [Recipes](https://agent-core-docs.pages.jangts.cafe/en/recipes/) |
214
- | Mock model replies, tool proposals, streams and failures | [MockGPT Kit](https://agent-core-docs.pages.jangts.cafe/en/manual/api/mock) |
215
- | Execution facts, call chains and Journal | [Observability](https://agent-core-docs.pages.jangts.cafe/en/manual/api/observability) |
216
- | Integrate with a development agent | [Agent-assisted development and Skill](https://agent-core-docs.pages.jangts.cafe/en/manual/agent-development) |
210
+ | Create an app or integrate with a project | [Developer guide](https://agent-core-docs.pages.jangts.cafe/en/manual/) · [Installation](https://agent-core-docs.pages.jangts.cafe/en/manual/getting-started.html) |
211
+ | Routes, models, budgets, cancellation and branches | [Workflow](https://agent-core-docs.pages.jangts.cafe/en/manual/api/workflow.html) · [Core](https://agent-core-docs.pages.jangts.cafe/en/manual/api/core.html) |
212
+ | Tools, schemas, context and integration policies | [Support](https://agent-core-docs.pages.jangts.cafe/en/manual/api/support.html) · [Context nodes](https://agent-core-docs.pages.jangts.cafe/en/manual/api/context-processing.html) |
213
+ | Knowledge, intents, retrieval, artifacts and persistent tasks | [Kits](https://agent-core-docs.pages.jangts.cafe/en/manual/api/kits.html) · [Recipes](https://agent-core-docs.pages.jangts.cafe/en/recipes/) |
214
+ | Mock model replies, tool proposals, streams and failures | [MockGPT Kit](https://agent-core-docs.pages.jangts.cafe/en/manual/api/mock.html) |
215
+ | Execution facts, call chains and Journal | [Observability](https://agent-core-docs.pages.jangts.cafe/en/manual/api/observability.html) |
216
+ | Export workflow graphs and execution chains for developer views | [Graph and chain API](https://agent-core-docs.pages.jangts.cafe/en/manual/api/workflow-views.html) · [Further reading](https://agent-core-docs.pages.jangts.cafe/en/guide/extended/workflow-views.html) |
217
+ | Integrate with a development agent | [Agent-assisted development and Skill](https://agent-core-docs.pages.jangts.cafe/en/manual/agent-development.html) |
217
218
  | Exact signatures, overloads and result types | [API directory](https://agent-core-docs.pages.jangts.cafe/en/api/) · [Local API handbook](development/docs/api/README.en.md) |
218
219
 
219
220
  Import Core and Support from the package root, Kits from `/kits/<name>`, and decorators from `/support/decorators`. App owns identity, business permissions, external effects and storage; Core provides generic runtime guarantees. Support and Kits remain optional.
@@ -270,7 +271,7 @@ console.log(await agent.run({ question: 'Hello' }));
270
271
 
271
272
  节点的 `run` 返回状态补丁;Engine 提交后,路由读取更新后的状态。`route.to('next')` 跳到下一节点,`route.deliver('answer')` 交付结果并结束。入口默认是首节点。有多个分支时,`routes` 按声明顺序匹配。
272
273
 
273
- 这份 Provider 只返回固定文本;接入真实模型只需替换 provider,工作流不变。[完整离线示例](https://agent-core-docs.pages.jangts.cafe/zh/manual/examples/offline-agent)进一步展示工具查询、多个节点和过程监听。
274
+ 这份 Provider 只返回固定文本;接入真实模型只需替换 provider,工作流不变。[完整离线示例](https://agent-core-docs.pages.jangts.cafe/zh/manual/examples/offline-agent.html)进一步展示工具查询、多个节点和过程监听。
274
275
 
275
276
  ## 接入真实模型
276
277
 
@@ -313,7 +314,7 @@ export AI_MODEL="your-model-id"
313
314
  node model.mjs
314
315
  ```
315
316
 
316
- 接入首个工作流时,用 `import { provider } from './provider.mjs'` 替换其中的离线 provider 声明即可。模型 `invoke` 返回 `{ value, invocation }`:`value` 是完整结果,`invocation` 是调用记录;失败抛错。需要实时文本时配置 Runner 的 `sink.output`,完整结果仍从 `value` 读取。详见[模型调用](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/core)。
317
+ 接入首个工作流时,用 `import { provider } from './provider.mjs'` 替换其中的离线 provider 声明即可。模型 `invoke` 返回 `{ value, invocation }`:`value` 是完整结果,`invocation` 是调用记录;失败抛错。需要实时文本时配置 Runner 的 `sink.output`,完整结果仍从 `value` 读取。详见[模型调用](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/core.html)。
317
318
 
318
319
  ## 定义工具并实际执行
319
320
 
@@ -370,7 +371,7 @@ const executed = await tools.invoke({
370
371
  console.log(executed.value); // 42
371
372
  ```
372
373
 
373
- 模型只提出工具 ID 和参数,`tools.invoke` 才会执行解析、授权与业务操作。需要多步调用时,把选择、执行、回答组织成上面学过的 Workflow 节点,继续使用 `context.model.invoke` 与 `context.tools.invoke`。详见[模型与工具接入](https://agent-core-docs.pages.jangts.cafe/zh/manual/basic-usage)。
374
+ 模型只提出工具 ID 和参数,`tools.invoke` 才会执行解析、授权与业务操作。需要多步调用时,把选择、执行、回答组织成上面学过的 Workflow 节点,继续使用 `context.model.invoke` 与 `context.tools.invoke`。详见[模型与工具接入](https://agent-core-docs.pages.jangts.cafe/zh/manual/basic-usage.html)。
374
375
 
375
376
  ## 用类组织节点与内部方法
376
377
 
@@ -407,7 +408,7 @@ console.log(await new AgentCoreEngine({ workflow }).run({ name: 'Ivan' }));
407
408
  - `@tool`、`@fragment` 同时支持类和已有实例方法;方法装饰保留原方法名并绑定真实宿主。`@workflow`、`@agent`、`@model` 定义原配置,不创建 Engine 或 Runner。
408
409
  - getter 可组织路由及私有辅助方法。路由表在装配时固定,`when/complete` 回调读取运行中的最新 state。
409
410
 
410
- [装饰器完整合同与示例](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/decorators)说明方法绑定、命名空间、多空间登记和实例作用域。对象写法与装饰器产物使用相同的 Core 接口。
411
+ [装饰器完整合同与示例](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/decorators.html)说明方法绑定、命名空间、多空间登记和实例作用域。对象写法与装饰器产物使用相同的 Core 接口。
411
412
 
412
413
  ## 加入资料、上下文与缓存
413
414
 
@@ -423,21 +424,22 @@ const snapshot = knowledge.read({ documentId: 'manual', selection: { mode: 'docu
423
424
  console.log(snapshot);
424
425
  ```
425
426
 
426
- 资料由 App 提供;知识目录负责标识、版本和选择,不自动抓取网站或建立数据库。需要检索、证据检查、生成、修正与交付时,按[知识回答完整示例](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/knowledge-answering)组合。
427
+ 资料由 App 提供;知识目录负责标识、版本和选择,不自动抓取网站或建立数据库。需要检索、证据检查、生成、修正与交付时,按[知识回答完整示例](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/knowledge-answering.html)组合。
427
428
 
428
- 工作流节点的 `context.cache` 提供 Engine 生命周期内、按节点分区的同步缓存,可用 `get/has/set/delete/clear`。长期存储通过 App 提供的异步 `context.agentCache` 接入;工作流状态仍放在 state。历史消息的选择、裁切与摘要通过普通节点和 Support 策略组织,见[上下文处理](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/context-processing)与[缓存合同](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/workflow)。
429
+ 工作流节点的 `context.cache` 提供 Engine 生命周期内、按节点分区的同步缓存,可用 `get/has/set/delete/clear`。长期存储通过 App 提供的异步 `context.agentCache` 接入;工作流状态仍放在 state。历史消息的选择、裁切与摘要通过普通节点和 Support 策略组织,见[上下文处理](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/context-processing.html)与[缓存合同](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/workflow.html)。
429
430
 
430
431
  ## 按任务继续阅读
431
432
 
432
433
  | 要做什么 | 入口 |
433
434
  | --- | --- |
434
- | 从空项目开始或接入现有应用 | [开发指南](https://agent-core-docs.pages.jangts.cafe/zh/manual/) · [安装与配置](https://agent-core-docs.pages.jangts.cafe/zh/manual/getting-started) |
435
- | 编排条件路由、多模型、预算、取消和分支 | [Workflow](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/workflow) · [Core](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/core) |
436
- | 管理工具、schema、上下文与接入策略 | [Support](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/support) · [上下文节点](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/context-processing) |
437
- | 使用知识、意图、检索、产物和持久任务 | [Kit 手册](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/kits) · [场景示例](https://agent-core-docs.pages.jangts.cafe/zh/recipes/) |
438
- | 模拟模型、工具提议、流式回复与故障 | [MockGPT Kit](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/mock) |
439
- | 接收执行事实、记录调用链和 Journal | [观察与日志](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/observability) |
440
- | 让开发 Agent 辅助接入 SDK | [Agent 辅助开发与 Skill](https://agent-core-docs.pages.jangts.cafe/zh/manual/agent-development) |
435
+ | 从空项目开始或接入现有应用 | [开发指南](https://agent-core-docs.pages.jangts.cafe/zh/manual/) · [安装与配置](https://agent-core-docs.pages.jangts.cafe/zh/manual/getting-started.html) |
436
+ | 编排条件路由、多模型、预算、取消和分支 | [Workflow](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/workflow.html) · [Core](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/core.html) |
437
+ | 管理工具、schema、上下文与接入策略 | [Support](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/support.html) · [上下文节点](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/context-processing.html) |
438
+ | 使用知识、意图、检索、产物和持久任务 | [Kit 手册](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/kits.html) · [场景示例](https://agent-core-docs.pages.jangts.cafe/zh/recipes/) |
439
+ | 模拟模型、工具提议、流式回复与故障 | [MockGPT Kit](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/mock.html) |
440
+ | 接收执行事实、记录调用链和 Journal | [观察与日志](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/observability.html) |
441
+ | 导出工作流图、执行链并构建开发观测界面 | [图与执行链 API](https://agent-core-docs.pages.jangts.cafe/zh/manual/api/workflow-views.html) · [延伸阅读](https://agent-core-docs.pages.jangts.cafe/zh/guide/extended/workflow-views.html) |
442
+ | 让开发 Agent 辅助接入 SDK | [Agent 辅助开发与 Skill](https://agent-core-docs.pages.jangts.cafe/zh/manual/agent-development.html) |
441
443
  | 查精确参数、重载和返回值 | [API 目录](https://agent-core-docs.pages.jangts.cafe/zh/api/) · [本地 API 手册](development/docs/api/README.md) |
442
444
 
443
445
  Core 与 Support 从包根导入,Kit 从 `/kits/<name>` 导入,装饰器从 `/support/decorators` 导入。App 拥有身份、业务权限、外部副作用和存储;Core 提供通用运行保证,Support 与 Kit 按需使用。
@@ -62,3 +62,5 @@ Synchronous algorithms remain synchronous. Source schema, permissions, budget, c
62
62
  The [MockGPT Kit](mock.md) describes `@jangts/agent-core/mock` and its `/node` and `/web` entries: rules and generators, direct return values, HTTP/SSE, tool proposals, web sources, errors, cancellation, and budget.
63
63
 
64
64
  - [Decorators and definition pools](decorators.en.md)
65
+
66
+ For developer-side static topology and observed run chains, which do not participate in task execution, see [Workflow graphs and execution chains](workflow-views.en.md).
@@ -62,3 +62,5 @@ Core 服务及共同合同从根入口,接入辅助从 `Support`,Kit 从各
62
62
  [MockGPT Kit](mock.md) 说明 `@jangts/agent-core/mock` 及其 `/node`、`/web` 入口:规则与生成器、直接返回值、HTTP/SSE、工具提议、网页来源、错误、取消与预算。
63
63
 
64
64
  - [装饰器与定义池](decorators.md)
65
+
66
+ 开发辅助接口不参与任务执行;工作流的静态拓扑与按 run 查询的执行链见[工作流图与执行链](workflow-views.md)。
@@ -83,13 +83,13 @@ await agent.run(state);
83
83
  | execution.observe.event | Loop/Workflow, model.start/end, tool start/end and permitted dynamic reports | Side channel; a synchronous throw, async rejection or hang does not change execution; still effective when persistent logging is closed |
84
84
  | execution.diagnostics → CoreLogOutput.write | Optional persistent projection of the same fact | The App decides fields, body, storage and retention; it gains no content authorization from other listeners |
85
85
  | ModelRunner.sink.output | model.start/output/parsed of the same outer layer, plus model.end on success, failure or cancellation | Body waits in order, propagates failures and preserves backpressure; the end notification is limited to 250 milliseconds independently, and its failure does not override the result or the original exception |
86
- | context.report({ usedModel, payload, subs }) | Immediate report during the current node's run | usedModel is optional boolean metadata, payload/subs are read only when content is permitted; Core fills in identity, time and sequence, and reports after the node ends or is cancelled are dropped |
87
- | node report(update, context) | usedModel/payload/subs on completion/transition | Evaluated only when content is permitted; does not replace immediate reports during the run |
86
+ | context.report({ usedModel, payload }) | Immediate report during the current node's run | usedModel is optional boolean metadata, payload are read only when content is permitted; Core fills in identity, time and sequence, and reports after the node ends or is cancelled are dropped |
87
+ | node report(update, context) | usedModel/payload on completion/transition | Evaluated only when content is permitted; does not replace immediate reports during the run |
88
88
  | context.createSubFlowLogger() | Sub-log instance bound to this execution | write records first, fix completes later, readAll obtains a fixed-format snapshot; reuses the existing node.progress outlet |
89
89
 
90
90
  Listeners can filter by metadata such as event, nodeId and workflowNodeId. workflowNodeId keeps the owning Workflow node, while model/tool boundaries still have their own nodeId and invocationId. Repeated visits to the same node have different spans, and concurrent runs do not correlate through lastCall or a shared "current request". `withObserver` can be called on an existing request scope to add a listener, inherited along sub-scopes; this is immutable wiring and leaves the original scope unaffected. Canonical methods are bound to their original receivers at assembly time. When a reusable Engine has no request scope configured, each run is assigned an independent identity.
91
91
 
92
- Listeners without accepts receive metadata only. Content events, payload and subs are collected only after the corresponding consumer explicitly accepts them; other metadata consumers do not gain the body as a side effect. Each consumer receives an independent copy. The result snapshot is isolated from the actual return value, so preview edits do not rewrite the final value; model results must still satisfy the existing Journal snapshot contract.
92
+ Listeners without accepts receive metadata only. Content events, payload and sub-log content are collected only after the corresponding consumer explicitly accepts them; other metadata consumers do not gain the body as a side effect. Each consumer receives an independent copy. The result snapshot is isolated from the actual return value, so preview edits do not rewrite the final value; model results must still satisfy the existing Journal snapshot contract.
93
93
 
94
94
  ModelPart does not provide separate reasoning content chunks. State, process notes explicitly provided by the model, tool facts, transient previews and the final answer each keep their own meaning; internal hidden reasoning or the raw protocol must not be treated as a user reply. Selection, compression and assembly can be registered as ordinary nodes separately and use real lifecycle facts; algorithmic reports are delivered as permitted node.progress.
95
95
 
@@ -97,7 +97,7 @@ Adding a listener only changes assembly configuration; the original Workflow, ru
97
97
 
98
98
  ## Sub-log instances and record-first-then-complete
99
99
 
100
- Workflow nodes, simple run(step), ToolRegistry/Support tools and the execution context of executeInvocation all provide `createSubFlowLogger()` and `report()`. Each node visit or call has one instance, and repeated create returns the same instance; no global logger is shared. subs accepts only SubFlowLogger instances belonging to that execution; plain objects, objects imitating readAll, hand-written arrays and readAll() snapshots are rejected; invalid material does not become a main execution fact. The normalized stored field subSteps is still an array, so reading historical data does not require re-creating a logger.
100
+ Workflow nodes, simple run(step), ToolRegistry/Support tools and the execution context of executeInvocation all provide `createSubFlowLogger()` and `report()`. Each node visit or call has one instance, and repeated create returns the same instance; no global logger is shared. The factory is already bound to the execution context; no context argument is required. Identity inherits the App diagnostic scope and identifies the Engine definition, run and node visit without retaining App service objects. The Loop owns the lifecycle: each accepted write/fix immediately commits an immutable snapshot to runtime before publishing node.progress to observers and the log outlet. Nodes never submit a logger or readAll() result. Terminal events use the committed runtime snapshot without reading the logger. Node completion detaches writes and releases the runtime reference; failure and cancellation preserve prior records. A later visit gets a new instance. readAll() remains readable by any holder and emits nothing. Nodes, Apps and external code may retain or lend the instance; Core does not prescribe its use. A later visit receives a new logger and may consult the previous flow through a retained old instance. Apps apply each appended fix to the original write view using operation/targetStepId and order revisions with revision. Stored subSteps remain fixed-format arrays.
101
101
 
102
102
  ```ts
103
103
  async run(state, context) {
@@ -116,23 +116,49 @@ async run(state, context) {
116
116
  if (!context.signal.aborted) subs.fix(id, { status: 'error' });
117
117
  throw error;
118
118
  }
119
- context.report({ usedModel: false, subs });
119
+ context.report({ usedModel: false });
120
120
  }
121
121
  ```
122
122
 
123
123
  | Method | Fixed contract |
124
124
  | --- | --- |
125
- | write(input): string | name and kind are required, status defaults to planned; stepId, sequence, createdAtMs and initial revision=1 are allocated automatically. Optional parentStepId, relatedDefinitionId, caseId, nextStepIds, status, time, summary, payload and usedModel. startedAtMs is recorded automatically only when running is reported explicitly, so planned time does not pass for an actual start. |
126
- | fix(stepId, patch): void | Completes status, model usage, pending times, summary, successors or payload fields for a record in the same instance; a terminal state cannot be reopened, but missing result fields can still be filled while execution is active. Keeps the ID, first order and original times, incrementing revision each time. payload merges missing keys recursively and existing facts cannot be overwritten; a given summary, time or successor cannot be rewritten. |
127
- | readAll(): readonly RecordedSubStep[] | Returns an immutable snapshot in first-write order; later fix calls do not change an earlier snapshot. With no steps it is [], and the snapshot remains readable after the execution is closed. |
125
+ | write(input): string \| -1 | name and kind are required, status defaults to planned; stepId, sequence, createdAtMs and initial revision=1 are allocated automatically. Optional parentStepId, relatedDefinitionId, caseId, nextStepIds, status, time, summary, payload and usedModel. startedAtMs is recorded automatically only when running is reported explicitly, so planned time does not pass for an actual start. |
126
+ | fix(stepId: string \| -1, patch): boolean | Completes status, model usage, pending times, summary, successors or payload fields for a record in the same instance; a terminal state cannot be reopened, but missing result fields can still be filled while execution is active. Every successful fix appends an independent record with operation=fix, a new stepId, sequence and createdAtMs. targetStepId references the original write and revision increases for that original. Each fix carries the resulting state without changing any earlier row. payload merges missing keys recursively and existing facts cannot be overwritten; a given summary, time or successor cannot be rewritten. |
127
+ | readAll(): readonly RecordedSubStep[] | Returns all write/fix records in append order; repeated fixes create separate rows and never mutate earlier rows or snapshots. With no steps it is [], and the snapshot remains readable after the execution is closed. |
128
128
 
129
- The fixed record fields are origin=reported, stepId, sequence, name, kind, status, createdAtMs and revision, plus the optional fields above. planned/unknown can advance to an actual status, while running cannot go back to planned or skipped; success/error/cancelled/skipped are terminal, the status and established facts cannot be rewritten, but pending result fields can still be filled while the owning node is active. Statuses and legal transitions come from the same reportedStepStatusCatalog. A retry writes another record and does not reopen a terminal state. The parent and successors must belong to the same logger; when the successor ID is not yet available, nextStepIds can be completed in one later fix. Pending payload fields are omitted first and are not represented by null or an empty array as an overwritable placeholder. By default at most 256 records, 65536 JSON characters for the full snapshot and 1024 write/fix calls; payload accepts only bounded-depth JSON data and does not accept functions, service instances, circular references or internal getters.
129
+ Records have origin=reported, operation=write/fix, unique stepId, append sequence, name, kind, status, createdAtMs and revision. Fix records reference the original write with targetStepId; fixing a fix ID is rejected. Historical projected snapshots may omit operation. planned/unknown can advance to an actual status, while running cannot go back to planned or skipped; success/error/cancelled/skipped are terminal, the status and established facts cannot be rewritten, but pending result fields can still be filled while the owning node is active. Statuses and legal transitions come from the same reportedStepStatusCatalog. A retry writes another record and does not reopen a terminal state. The parent and successors must belong to the same logger; when the successor ID is not yet available, nextStepIds can be completed in one later fix. Pending payload fields are omitted first and are not represented by null or an empty array as an overwritable placeholder. By default at most 256 original writes, 1024 total write/fix records and 65536 JSON characters for the complete ledger; payload accepts only bounded-depth JSON data and does not accept functions, service instances, circular references or internal getters.
130
130
 
131
- write and fix emit the initial/completion event through the existing node.progress at that moment, with payload.subStep holding operation, stepId, sequence, revision, createdAtMs, status and optional usedModel metadata. When content is permitted, the event carries the fixed-format subSteps snapshot at that point; node end/failure events also carry the last snapshot. The log appends revisions, and events already emitted are not updated in place. Results returning out of order do not change the initial order, and replay can distinguish "only a plan at the time" from "a result later". When only a plan or start was received without a result, the original status is kept; success, failure or an actual model call cannot be inferred.
131
+ write and fix emit the initial/completion event through the existing node.progress at that moment, with payload.subStep holding operation, current record stepId, targetStepId for fixes, sequence, revision, createdAtMs, status and optional usedModel metadata. When content is permitted, the event carries the fixed-format subSteps snapshot at that point; node end/failure events also carry the last snapshot. The log appends revisions, and events already emitted are not updated in place. Results returning out of order do not change the initial order, and replay can distinguish "only a plan at the time" from "a result later". When only a plan or start was received without a result, the original status is kept; success, failure or an actual model call cannot be inferred.
132
132
 
133
133
  The main node reports through context.report({ usedModel: true | false }) whether it used the model this time, and the outer usedModel in the log is kept as metadata; sub-steps report their own usedModel through write/fix. Unreported stays unknown and does not default to false; a reported true cannot change back to false. A child's true is not automatically aggregated into the main node's original marker. This is a node report: a field of true does not fabricate model.start/end or call counts, and model internal hidden reasoning is not collected. The end report(update, context) is still evaluated only when content collection is permitted; markers that must be kept in metadata mode should be submitted during the run with context.report.
134
134
 
135
- Content permission continues to be decided per event and per consumer. Without content authorization, payload/summary getters are not read, nor are the private payload/subs getters in reports; only permitted status, revision and boolean metadata are kept. The instance closes when execution ends or is cancelled, and write/fix reject late modifications. Log shutdown, outlet failure or a process crash still follow the original failure isolation and incomplete mechanism; recording intent first does not constitute a transactional audit guarantee.
135
+ Content permission continues to be decided per event and per consumer. Without content authorization, payload/summary getters are not read, nor are the private payload getters in reports; only permitted status, revision and boolean metadata are kept. The instance closes when execution ends or is cancelled, and write returns numeric -1 and fix returns false without throwing, inspecting arguments, recording or emitting. readAll remains readable. fix returns true on success; invalid IDs, invalid input, forbidden revisions and detachment all return false without throwing, changing the record or emitting a revision. write returns the new ID on success and -1 on any failure, including invalid input, limits and detachment, without throwing, recording or emitting. Log shutdown, outlet failure or a process crash still follow the original failure isolation and incomplete mechanism; recording intent first does not constitute a transactional audit guarantee.
136
+
137
+ ## Subnode grouping and restricted delegation
138
+
139
+ subnodeId groups multiple records within one node visit. It is independent of stepId, which identifies a log record. A group can contain multiple writes and multiple fixes per write; ungrouped logs belong to the parent node. Grouping does not imply dispatch, contiguous phases, scheduling or dependencies.
140
+
141
+ SubFlowLogger and ScopedSubFlowLogger are independent, non-inheriting classes implementing SubFlowLog. The full class owns storage/lifecycle, accepts subnodeId directly on write, and may fork(subnodeId). A scoped instance holds only the original logger and bound ID: write adds the ID, fix checks original-record ownership and delegates. It cannot override its group, fork or be supplied to native invoke. Both readAll methods return the same complete immutable ledger, including other groups.
142
+
143
+ Business type is an arbitrary string; operation is the separate write/fix enum. type and the compatible kind classification fill each other's omitted default. Fix uses the explicit SubFlowStepFix whitelist (status, usedModel, times, summary, nextStepIds, payload), not Partial of the write input. Identity, group, business type and label cannot be revised. A rejected fix returns false; rejected writes return -1. Safe console warnings explain fixed reasons, deduplicated per logger, without payloads or arbitrary error text; console failures do not change results.
144
+
145
+ Registered subnode IDs are local to one node visit: kind:encodedDefinitionId:ordinal, for example tool:product.references:1. Definition IDs are URL-encoded. The owning logger allocates ordinals per kind/definition at call start; failure and cancellation never reuse them, and a new node visit starts from 1. Parent identity stays in its existing fields. relatedInvocationId separately retains the real call identity for correlation with model/tool events; a short ordinal never replaces invocationId. App-owned custom groups need no business enum. Direct write({subnodeId, type, name}) and fork(subnodeId).write({type, name}) are equivalent grouping choices. fork validates its ID and native invoke rejects scoped/forged logger inputs at the boundary.
146
+
147
+ ## Optional native call records
148
+
149
+ logger is a per-call choice. Omission creates no native sub-log; passing it produces a fixed write followed by a separate fix on success, error or cancellation. Components do not create owning logger storage or implicitly forward full logging authority. Tools expose a scoped delegate bound by Core to the actual invocation. It may be lent to business helpers but cannot fork or be passed to another invoke. Business steps remain App-owned.
150
+
151
+ | Entry | Explicit logger location |
152
+ | --- | --- |
153
+ | ModelRunner / Workflow model.invoke; ToolRegistry / Support tool invocation | request.logger |
154
+ | executeInvocation / Tools lifecycle | ports.logger(context) |
155
+ | Retrieval.run; Answering task.read/readAsync, checks.check, flow.run; output.compose | context.logger |
156
+ | Knowledge.read; recovery chain tryRecover | Optional second context argument |
157
+ | Support.processContext / context node run | ports.logger / explicitly supplied context.logger |
158
+ | retryMultipleModelCalls | request.logger; records only an actual fallback attempt |
159
+ | Delivery.deliver; Aggregation.collect | execution.logger; optional third execution argument respectively |
160
+
161
+ Fixed records contain producer/definition identity and execution status, never automatic copies of prompts, results, tool arguments or customer material. A checker returning a rejection or a recovery returning unhandled still completed normally; callers choose whether to record the business result. Existing Core events and receipts remain unchanged. Pure configuration, lookup and formatting functions do not record.
136
162
 
137
163
  ## File adaptation and relational table mapping
138
164
 
@@ -83,13 +83,13 @@ await agent.run(state);
83
83
  | execution.observe.event | Loop/Workflow、model.start/end、工具开始/结束及获准的动态报告 | 旁路;同步抛错、异步拒绝或悬挂不改变执行;关闭持久日志仍有效 |
84
84
  | execution.diagnostics → CoreLogOutput.write | 同一事实的可选持久投影 | App 决定字段、正文、存储和保留期;不获得其他监听器的内容授权 |
85
85
  | ModelRunner.sink.output | 同一外层的 model.start/output/parsed,以及成功、失败或取消时 model.end | 正文按序等待、传播失败、保留背压;结束通知独立限时250毫秒,其失败不覆盖结果或原始异常 |
86
- | context.report({ usedModel, payload, subs }) | 当前节点运行中的即时报告 | usedModel 为可选布尔元数据,payload/subs 仅内容获准才读取;Core 补齐身份、时间和序号,节点结束或取消后的报告丢弃 |
87
- | 节点 report(update, context) | 完成/跳转时的 usedModel/payload/subs | 内容获准才求值,不替代运行中的即时报告 |
86
+ | context.report({ usedModel, payload }) | 当前节点运行中的即时报告 | usedModel 为可选布尔元数据,payload 仅内容获准才读取;Core 补齐身份、时间和序号,节点结束或取消后的报告丢弃 |
87
+ | 节点 report(update, context) | 完成/跳转时的 usedModel/payload | 内容获准才求值,不替代运行中的即时报告 |
88
88
  | context.createSubFlowLogger() | 绑定本次执行的子日志实例 | write 先留记录,fix 随后补全,readAll 取得固定格式快照;复用既有 node.progress 出口 |
89
89
 
90
90
  监听器可用 event、nodeId、workflowNodeId 等元数据过滤。workflowNodeId 保留所属 Workflow 节点,模型/工具边界自身仍有 nodeId 和 invocationId。重复访问同一节点有不同 span,并发运行不借助 lastCall 或共享“当前请求”关联。可在已有请求作用域上调用 `withObserver` 增加监听,沿子作用域继承;这是不可变的接线,原作用域不受影响。规范方法在装配时绑定原接收者。可复用 Engine 未配置请求作用域时,每次 run 分配独立身份。
91
91
 
92
- 无 accepts 的监听器仅接元数据。内容事件、payload 和 subs 只在对应消费者明确接纳后采集;其他元数据消费者不会连带获得正文。消费者拿到独立副本。结果快照与实际返回值隔离,不因预览修改而改写最终值;模型结果仍须符合既有 Journal 快照合同。
92
+ 无 accepts 的监听器仅接元数据。内容事件、payload 和子日志正文 只在对应消费者明确接纳后采集;其他元数据消费者不会连带获得正文。消费者拿到独立副本。结果快照与实际返回值隔离,不因预览修改而改写最终值;模型结果仍须符合既有 Journal 快照合同。
93
93
 
94
94
  ModelPart 不提供独立推理内容分片。状态、模型明确提供的过程说明、工具事实、暂态预览和最终答案各自保持含义,不能把内部隐藏推理或原始协议当用户回复。选择、压缩与装配可分别注册普通节点,使用真实生命周期事实;算法报告按获准的 node.progress 交付。
95
95
 
@@ -97,7 +97,7 @@ ModelPart 不提供独立推理内容分片。状态、模型明确提供的过
97
97
 
98
98
  ## 子日志实例与先记后补
99
99
 
100
- Workflow 节点、简易 run(step)、ToolRegistry/Support 工具及 executeInvocation 的执行 context 均提供 `createSubFlowLogger()` 和 `report()`。每次节点访问或调用各有一个实例,多次 create 返回同一实例;不共用全局 logger。subs 只接受所属执行的 SubFlowLogger 实例,普通对象、仿造 readAll 的对象、手写数组和 readAll() 快照均会拒收;非法材料不成为主执行事实。规范化后的存储字段 subSteps 仍为数组,读取历史数据不需要重新创建 logger。
100
+ Workflow 节点、简易 run(step)、ToolRegistry/Support 工具及 executeInvocation 的执行 context 均提供 `createSubFlowLogger()` 和 `report()`。每次节点访问或调用各有一个实例,多次 create 返回同一实例;不共用全局 logger。创建入口已绑定执行 context,无需再次传参;身份沿 App 装配的诊断作用域继承,自动关联当前 Engine 定义、run 与 node 访问,不保存 App 服务对象。Loop 接管生命周期,write/fix 接受后立即把不可变快照交给 runtime,再通过 node.progress 通知 App 与日志出口。节点不提交 logger 或 readAll() 的结果;终态事件使用 runtime 已接收的快照,不回读 logger。节点结束时解绑写入并释放 runtime 的实例引用,失败与取消保留此前记录;再次访问同一节点创建独立实例。readAll() 向任何持有者提供持续只读查询,不产生事件或提交。实例可由节点、App 或外部代码保留并借用,Core 不限制用途;后续节点访问获得新实例,旧实例可用于读取上次 flow。App 按 operation 与 targetStepId 将追加的 fix 应用到原 write 对应的界面视图,按 revision 判断修订顺序。存储字段 subSteps 为固定格式数组。
101
101
 
102
102
  ```ts
103
103
  async run(state, context) {
@@ -116,23 +116,76 @@ async run(state, context) {
116
116
  if (!context.signal.aborted) subs.fix(id, { status: 'error' });
117
117
  throw error;
118
118
  }
119
- context.report({ usedModel: false, subs });
119
+ context.report({ usedModel: false });
120
120
  }
121
121
  ```
122
122
 
123
123
  | 方法 | 固定合同 |
124
124
  | --- | --- |
125
- | write(input): string | name、kind 必填,status 默认 planned;自动分配 stepId、sequence、createdAtMs 和初始 revision=1。可选 parentStepId、relatedDefinitionId、caseId、nextStepIds、状态、时间、摘要、payload 和 usedModel。只有明确报告 running 才自动记 startedAtMs,计划时间不冒充实际开始。 |
126
- | fix(stepId, patch): void | 给同一实例内的记录补状态、模型使用、待定时间、摘要、后继或 payload 字段;终态不能重开,但执行仍活跃时可补缺失的结果字段。保留 ID、首次顺序和原时间,每次增加 revision。payload 递归补缺失键,已有事实不能覆盖;已给定的摘要、时间和后继不能改写。 |
127
- | readAll(): readonly RecordedSubStep[] | 按首次 write 顺序返回不可变快照;之后的 fix 不改变先前快照。没有步骤为 [],执行关闭后仍可读快照。 |
125
+ | write(input): string \| -1 | name 必填,type 为自定义业务类型;兼容的 kind 分类与 type 至少提供一项,缺省时互为补足,status 默认 planned;自动分配 stepId、sequence、createdAtMs 和初始 revision=1。可选 parentStepId、relatedDefinitionId、caseId、nextStepIds、状态、时间、摘要、payload 和 usedModel。只有明确报告 running 才自动记 startedAtMs,计划时间不冒充实际开始。 |
126
+ | fix(stepId: string \| -1, patch): boolean | 给同一实例内的记录补状态、模型使用、待定时间、摘要、后继或 payload 字段;终态不能重开,但执行仍活跃时可补缺失的结果字段。每次成功均追加独立记录,operation=fix,分配新 stepId、sequence、createdAtMs;targetStepId 指向原 write 的 ID,revision 按该原记录递增。记录携带本次修订后的完整状态,不修改原 write 或先前 fix。payload 递归补缺失键,已有事实不能覆盖;已给定的摘要、时间和后继不能改写。 |
127
+ | readAll(): readonly RecordedSubStep[] | 按实际追加顺序返回全部 write/fix 记录;多次 fix 对应多条记录,旧行和旧快照保持不变。没有步骤为 [],执行关闭后仍可读快照。 |
128
128
 
129
- 记录的固定字段为 origin=reported、stepId、sequence、name、kind、status、createdAtMs、revision,及上述可选字段。planned/unknown 可推进到实际状态,running 不能退回计划或 skipped;success/error/cancelled/skipped 为终态,状态和已确定的事实不能改写,但所属节点仍活跃时可以继续填入等待中的结果字段。状态及合法推进关系来自同一 reportedStepStatusCatalog。重试另 write 一条,不重开终态。父、后继必须属于同一 logger;尚未取得后继 ID 时可在后续 fix 中一次补齐 nextStepIds。待填 payload 字段先省略,不以 null 或空数组冒充可覆盖的占位。默认最多256条、全部快照65536个JSON字符、1024次 write/fix;payload 只收有限深度的 JSON 数据,不接受函数、服务实例、循环引用或内部 getter。
129
+ 记录的固定字段为 origin=reported、operation=write/fix、唯一 stepId、追加序号 sequence、name、kind、status、createdAtMs、revision;fix 另有 targetStepId,始终关联原 write,不能以 fix 记录的 ID 再修订。历史投影快照可缺省 operation。planned/unknown 可推进到实际状态,running 不能退回计划或 skipped;success/error/cancelled/skipped 为终态,状态和已确定的事实不能改写,但所属节点仍活跃时可以继续填入等待中的结果字段。状态及合法推进关系来自同一 reportedStepStatusCatalog。重试另 write 一条,不重开终态。父、后继必须属于同一 logger;尚未取得后继 ID 时可在后续 fix 中一次补齐 nextStepIds。待填 payload 字段先省略,不以 null 或空数组冒充可覆盖的占位。默认最多256条原始 write、总计1024条 write/fix 记录、全部序列65536个JSON字符;payload 只收有限深度的 JSON 数据,不接受函数、服务实例、循环引用或内部 getter。
130
130
 
131
- write 和 fix 当时就经既有 node.progress 发射初始/补全事件,payload.subStep 保存 operation、stepId、sequence、revision、createdAtMs、status 和可选 usedModel 元数据。内容获准时,事件附带该时点的固定格式 subSteps 快照;节点结束/失败事件也附带最后快照。日志追加修订,已经输出的事件不原地更新。结果乱序返回不改变初始顺序,回放可区分“当时只有计划”和“后来有了结果”。只收到计划或开始而没有结果时保持原状态;不能推断已经成功、失败或实际调用了模型。
131
+ write 和 fix 当时就经既有 node.progress 发射初始/补全事件,payload.subStep 保存 operation、当前记录 stepId、fix 的 targetStepId、sequence、revision、createdAtMs、status 和可选 usedModel 元数据。内容获准时,事件附带该时点的固定格式 subSteps 快照;节点结束/失败事件也附带最后快照。日志追加修订,已经输出的事件不原地更新。原始 write 不因乱序结果而重新排序;fix 按实际接收顺序追加,回放可区分“当时只有计划”和“后来有了结果”。只收到计划或开始而没有结果时保持原状态;不能推断已经成功、失败或实际调用了模型。
132
132
 
133
133
  主节点通过 context.report({ usedModel: true | false }) 上报本次自身是否使用模型,日志外层 usedModel 作为元数据保留;子步骤通过 write/fix 上报自身的 usedModel。未上报保持未知,不默认 false;已报告 true 不能改回 false。子节点的 true 不自动汇总进主节点原始标记。此为节点报告,不因字段为 true 而补造 model.start/end 或调用次数,也不采集模型内部隐藏推理。结束 report(update, context) 仍仅在内容采集获准时求值,需在元数据模式保留的标记应在运行中用 context.report 提交。
134
134
 
135
- 内容权限继续按事件和消费者分别判断。未获内容授权时不读取 payload/summary getter,也不读取报告中的私有 payload/subs getter;只保留已获准的状态、修订和布尔元数据。执行结束或取消后实例关闭,write/fix 拒绝迟到修改。日志关闭、出口失败或进程崩溃仍遵守原失败隔离及 incomplete 机制,先记意图不构成事务审计保证。
135
+ 内容权限继续按事件和消费者分别判断。未获内容授权时不读取 payload/summary getter,也不读取报告中的私有 payload getter;只保留已获准的状态、修订和布尔元数据。执行结束或取消后实例关闭,write 固定返回数字 -1,fix 返回 false,不报错、不校验或读取入参、不入账或发事件;readAll 持续可读。fix 成功返回 true;无效 ID、非法输入、禁止的修订及解绑等失败统一返回 false,不抛错、不改变原记录或产生修订事件。write 成功返回新 ID,非法输入、容量限制、解绑等任何失败统一返回 -1,不抛错、不入账或发事件。日志关闭、出口失败或进程崩溃仍遵守原失败隔离及 incomplete 机制,先记意图不构成事务审计保证。
136
+
137
+ ## 子节点归集与受限委托
138
+
139
+ `subnodeId` 是同次 node 执行内的逻辑归集身份,不是某条日志的 ID。一个子节点可以拥有多条 write,以及每条 write 的多次 fix;未指定 subnodeId 的记录直接归父 node。它不规定分发、连续分段、执行顺序或依赖关系。App 按实际职责组织自定义子节点,无需为了日志增加调度节点。
140
+
141
+ - `SubFlowLogger` 是完整类,独占记录存储与生命周期。write 可直接填写任意非空字符串 subnodeId,无业务枚举;也可通过 fork(subnodeId) 创建另一个实例。
142
+ - `ScopedSubFlowLogger` 是独立且不继承完整类的委托类,只持有原 logger 与绑定 ID,不保存记录。write 自动补归属并拒绝覆盖;fix 只能修订该子节点的原记录,越界返回 false。没有 fork,不能作为原生 invoke 的 logger。
143
+ - 两类实现共同读写接口 `SubFlowLog`;它们的 readAll 返回同一份全量不可变记录,包括其他分组。读权限不会扩大受限实例的写权限。
144
+ - fix 使用独立 `SubFlowStepFix`,不是 Partial<write参数>。只接受 status、usedModel、startedAtMs、endedAtMs、summary、nextStepIds、payload,仍受状态推进和已有事实保护。不能改变 subnodeId、type、kind、name、stepId 或其他身份字段。
145
+ - type 是可自定义的业务日志类型,operation 才是 write/fix。fix 继承原记录的业务类型和归属;每次成功都追加独立记录。
146
+
147
+ ```ts
148
+ const logger = context.createSubFlowLogger();
149
+ // 可直接指定分组,fork 不是必需步骤。
150
+ logger.write({ subnodeId: 'prepare', type: 'source.read', name: '读取资料' });
151
+ const logs: SubFlowLog = logger.fork('prepare');
152
+ prepareMaterials(logs); // 子函数只需要公共读写接口。
153
+ await context.tools.invoke({ toolId: 'read', input: {}, logger });
154
+ // Core 传给真实工具的 execution.logger 是 ScopedSubFlowLogger。
155
+ ```
156
+
157
+ 注册子节点 ID 只在本次 node 执行内唯一,格式为 kind:encodedDefinitionId:ordinal,例如 tool:product.references:1。定义 ID 使用 URL 编码,计数按能力种类与定义 ID 分开,在调用开始时分配;失败、取消不复用,下一次 node 访问从1开始。父级访问身份已有独立字段,不重复拼入子节点 ID。真实调用身份单独保存在 relatedInvocationId,用于对应模型/工具主事件,不以短序号代替 invocationId。重复/并发调用分别归集,同次调用的多条日志保持相同 subnodeId。自定义子节点由 node 自行命名,两种归集都没有业务枚举约束。
158
+
159
+ fix 的失败统一返回 false,write 的失败统一返回 -1;调试控制台使用固定原因输出 warn,同一 logger 同类原因去重,不包含入参、正文或任意错误文本。控制台自身异常不改变返回值。fork 对无效 ID 的参数检查与 invoke 对非完整 logger 的边界检查仍保留。
160
+
161
+ ## 原生调用的可选记录
162
+
163
+ logger 是调用级参数,不是全局开关。未传入时不产生原生子日志,开发者可以自行组织全部记录;显式传入时原生组件统一 write 一条运行记录,并在成功、失败或取消时 fix,形成两条独立记录。不自动创建完整 logger 存储或向所有下游传播完整 logger 权限,不改变它所属的 App、Engine、node 或生命周期。Tool handler 取得 Core 为本次调用绑定的 execution.logger,可把该受限委托交给内部业务函数;不能继续 fork 或传给另一次 invoke。
164
+
165
+ | 原生入口 | 显式传入位置 | 固定记录 |
166
+ | --- | --- | --- |
167
+ | ModelRunner.invoke/Workflow model.invoke | request.logger | Model call,关联阶段 ID |
168
+ | ToolRegistry.invoke/invokeAsync、Support 工具 | request.logger | Tool call,关联工具 ID |
169
+ | executeInvocation/Tools Kit 生命周期 | ports.logger(context) | Invocation,关联 handler ID |
170
+ | Retrieval.run | context.logger | Retrieval |
171
+ | Answering task.read/readAsync、checks.check、flow.run | context.logger | 证据读取、每个实际 checker、完整答复流程 |
172
+ | Knowledge.read | 可选第二参数的 logger | Read knowledge |
173
+ | Presentation outputs.compose | context.logger | Compose output |
174
+ | Support.processContext、上下文节点 run | ports.logger/显式提供的 context.logger | Process context |
175
+ | Support.retryMultipleModelCalls | request.logger | 只在实际降级重试时记录 Retry model proposal |
176
+ | Policies 恢复链 tryRecover | 可选第二参数的 logger | 每个实际尝试的恢复策略 |
177
+ | Delivery.deliver | execution.logger | Deliver result |
178
+ | Aggregation.collect | 可选第三参数的 logger | Aggregate queries |
179
+
180
+ 固定记录只描述执行边界,不自动复制模型输入输出、工具参数或客户材料。检查正常返回不通过、恢复正常返回未处理,都属于函数成功返回;业务结果由开发者按需补充。已有 Core 主事件继续提供原有调用事实;可选子日志用于节点内部编排展示,不替代主事件、回执或权限检查。纯配置、清单查询和格式化函数不追加日志。
181
+
182
+ ```ts
183
+ const logger = context.createSubFlowLogger();
184
+ await context.model.invoke({ input: '简要说明', logger });
185
+ await context.tools.invoke({ toolId: 'read', input: {}, logger });
186
+ // 此次调用未传 logger,不追加原生子日志。
187
+ await context.tools.invoke({ toolId: 'read', input: {} });
188
+ ```
136
189
 
137
190
  ## 文件适配与关系表映射
138
191