@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
@@ -0,0 +1,403 @@
1
+ # 从完整代码看懂独立配置与关联配置
2
+
3
+ Tool 是供模型选择和提交参数的接口。ExecutableTool 增加授权、执行和输出校验,Tool 增加一个 lifecycle 生命周期块。Intent 只是 Tool 的用途标记和专门描述,没有独立 ID 或注册表。下面使用公开的内存笔记与离线 Provider 展示完整流程。
4
+
5
+ ```text
6
+ Tool declaration → node selects tools → model proposes name and arguments
7
+ → schema / activation / authorization → execute → validated result
8
+ ```
9
+
10
+ ## 1. 执行 Tool:参数、授权、处理与结果校验
11
+
12
+ [tools.mjs](../examples/registration/tools.mjs)
13
+
14
+ ```js
15
+ /** Tutorial tools: public in-memory notes only; no application database or network access. */
16
+ import { Support } from '@jangts/agent-core';
17
+
18
+ // The two business inputs differ; the model must use the selected tool's schema.
19
+ export function textInput(field) {
20
+ return Support.defineSchema({
21
+ jsonSchema: {
22
+ type: 'object',
23
+ properties: { [field]: { type: 'string', minLength: 1 } },
24
+ required: [field],
25
+ additionalProperties: false,
26
+ },
27
+ parse(value) {
28
+ if (
29
+ !value ||
30
+ typeof value !== 'object' ||
31
+ Array.isArray(value) ||
32
+ Object.keys(value).length !== 1 ||
33
+ typeof value[field] !== 'string' ||
34
+ !value[field].trim()
35
+ ) {
36
+ throw new TypeError(`Expected one nonempty string: ${field}`);
37
+ }
38
+ return { [field]: value[field].trim() };
39
+ },
40
+ });
41
+ }
42
+
43
+ const notes = [{ id: 'n1', title: '咖啡烘焙', body: '烘焙程度可结合豆色和风味判断。' }];
44
+
45
+ /** Build fresh declarations so manual and associated examples share no mutable request state. */
46
+ export function toolDefinitions() {
47
+ return [
48
+ {
49
+ id: 'search_notes',
50
+ asIntent: '用户希望查找笔记',
51
+ kind: 'read',
52
+ description: '按主题检索公开笔记',
53
+ inputSchema: textInput('query'),
54
+ authorize() {}, // This tutorial uses public constants, with no private account data.
55
+ execute({ query }) {
56
+ return notes
57
+ .filter((note) => note.title.includes(query))
58
+ .map(({ id, title }) => ({ id, title }));
59
+ },
60
+ parseOutput(value) {
61
+ if (
62
+ !Array.isArray(value) ||
63
+ value.some((note) => typeof note?.id !== 'string' || typeof note.title !== 'string')
64
+ ) {
65
+ throw new TypeError('Invalid search result');
66
+ }
67
+ return value;
68
+ },
69
+ },
70
+ {
71
+ id: 'read_note',
72
+ kind: 'read',
73
+ description: '读取已定位笔记的正文',
74
+ inputSchema: textInput('noteId'),
75
+ authorize() {},
76
+ execute({ noteId }) {
77
+ const note = notes.find((note) => note.id === noteId);
78
+ if (!note) throw new Error('Note not found');
79
+ return { ...note };
80
+ },
81
+ parseOutput(value) {
82
+ if (!value || typeof value.body !== 'string') {
83
+ throw new TypeError('Invalid note body');
84
+ }
85
+ return value;
86
+ },
87
+ },
88
+ ];
89
+ }
90
+ ```
91
+
92
+ ## 2. 独立配置:分别声明模型接口和执行合同
93
+
94
+ [independent.mjs](../examples/registration/independent.mjs)
95
+
96
+ 模型声明只生成 `{ toolId, input }` 提议,不直接执行业务。执行目录另行绑定本次请求的应用上下文。
97
+
98
+ ```js
99
+ /** Independent model and execution declarations, connected through checked Tool IDs. */
100
+ import { Support } from '@jangts/agent-core';
101
+ import { toolDefinitions, textInput } from './tools.mjs';
102
+
103
+ export function independentConfiguration() {
104
+ const execution = Support.defineToolCatalog(toolDefinitions());
105
+ const tools = Support.defineModelTools([
106
+ {
107
+ id: 'search_notes', description: '按主题检索公开笔记', asIntent: '用户希望查找笔记',
108
+ inputSchema: { jsonSchema: textInput('query').jsonSchema, parse: value => value },
109
+ resolve: input => ({ toolId: 'search_notes', input }),
110
+ },
111
+ {
112
+ id: 'read_note', description: '读取已定位笔记的正文',
113
+ inputSchema: { jsonSchema: textInput('noteId').jsonSchema, parse: value => value },
114
+ resolve: input => ({ toolId: 'read_note', input }),
115
+ },
116
+ ]);
117
+ return { execution, tools };
118
+ }
119
+ ```
120
+
121
+ ## 3. 关联配置:一份声明提供模型视图与执行入口
122
+
123
+ [associated.mjs](../examples/registration/associated.mjs)
124
+
125
+ 目录从同一 Tool 推导名称、描述、Schema 和调用映射,省掉独立写法中的重复声明;授权与执行校验仍走原通道。
126
+
127
+ ```js
128
+ /** One executable Tool declaration supplies both model and execution contracts. */
129
+ import { Support } from '@jangts/agent-core';
130
+ import { toolDefinitions } from './tools.mjs';
131
+
132
+ export function associatedConfiguration() {
133
+ const execution = Support.defineToolCatalog(toolDefinitions());
134
+ return { execution, tools: execution.tools };
135
+ }
136
+ ```
137
+
138
+ ## 4. 工作流:节点如何装配上下文、调用模型和执行提议
139
+
140
+ [workflow.mjs](../examples/registration/workflow.mjs)
141
+
142
+ ```js
143
+ /** One runtime for both configuration styles; its Provider is a fixed offline fixture. */
144
+ import { AgentCoreEngine, Support, defineWorkflow, route } from '@jangts/agent-core';
145
+
146
+ const context = Support.defineContextFragments(
147
+ [
148
+ {
149
+ id: 'task-policy',
150
+ sourceId: 'tutorial',
151
+ trust: 'instruction',
152
+ lifetime: 'configuration',
153
+ role: 'system',
154
+ maxChars: 500,
155
+ format: () => '按用户需求选择一个已提供的能力并提交参数。操作结果由程序返回。',
156
+ },
157
+ {
158
+ id: 'tool-catalog',
159
+ sourceId: 'tool-registry',
160
+ trust: 'server',
161
+ lifetime: 'step',
162
+ role: 'user',
163
+ maxChars: 6000,
164
+ format: ({ tools }) => ({ tools: [...tools.values()].map(({id, description}) => ({id, description})) }),
165
+ },
166
+ {
167
+ id: 'question',
168
+ sourceId: 'user-message',
169
+ trust: 'user',
170
+ lifetime: 'turn',
171
+ role: 'user',
172
+ maxChars: 1000,
173
+ format: ({ question }) => ({ question }),
174
+ },
175
+ ],
176
+ { maxInputChars: 8000 },
177
+ );
178
+
179
+ /** Stage policy selects candidates; association does not automatically submit every registration. */
180
+ export function taskTransport(tools, toolIds = ['search_notes', 'read_note']) {
181
+ return Support.createStageModelTransport({
182
+ id: 'task',
183
+ tools,
184
+ stages: [{ id: 'choose-operation', toolIds }],
185
+ });
186
+ }
187
+
188
+ const workflow = defineWorkflow({
189
+ id: 'notes-request',
190
+ nodes: [
191
+ {
192
+ id: 'decide',
193
+ description: '组织上下文,让模型提出一次操作',
194
+ async run(state, { model, app }) {
195
+ const input = context.build({
196
+ input: {
197
+ question: state.question,
198
+ tools: app.tools,
199
+ },
200
+ });
201
+ const { value: proposal } = await model.invoke({
202
+ stageId: 'choose-operation',
203
+ transport: 'task',
204
+ input,
205
+ });
206
+ return { proposal };
207
+ },
208
+ routes: [route.to('execute')],
209
+ },
210
+ {
211
+ id: 'execute',
212
+ description: '经过工具合同执行提议,取得真实结果',
213
+ async run(state, { tools }) {
214
+ const { value: result } = await tools.invoke(state.proposal);
215
+ return { result };
216
+ },
217
+ routes: [route.deliver('result')],
218
+ },
219
+ ],
220
+ });
221
+
222
+ /** The chosen reply is fixture input, not a language-understanding implementation. */
223
+ export async function runCase(configuration, question, proposedName, proposedInput) {
224
+ const submitted = [];
225
+ const provider = {
226
+ async *stream(messages, { options }) {
227
+ submitted.push({ messages, functions: options.functions });
228
+ if (!options.functions.some((fn) => fn.name === proposedName)) {
229
+ throw new Error('Fixture attempted an unavailable capability');
230
+ }
231
+ yield {
232
+ type: 'function-call-delta',
233
+ index: 0,
234
+ id: 'offline-call',
235
+ name: proposedName,
236
+ arguments: JSON.stringify(proposedInput),
237
+ };
238
+ },
239
+ };
240
+ const agent = new AgentCoreEngine({
241
+ workflow,
242
+ app: { tools: configuration.tools },
243
+ tools: configuration.execution.bind({ app: {} }),
244
+ model: {
245
+ provider,
246
+ transports: [taskTransport(configuration.tools, configuration.candidateIds)],
247
+ maxCalls: 1,
248
+ },
249
+ });
250
+ return { result: await agent.run({ question }), submitted };
251
+ }
252
+ ```
253
+
254
+ ## 5. 另一种模型协议:name/input 包装复用同一执行合同
255
+
256
+ [protocol.mjs](../examples/registration/protocol.mjs)
257
+
258
+ ```js
259
+ /** A name/input envelope changes model output format while preserving the same tool proposal. */
260
+ import { Support } from '@jangts/agent-core';
261
+
262
+ export function wrappedConfiguration(configuration) {
263
+ const capability = {
264
+ id: 'tool_request',
265
+ description: '提交工具名称和参数,由程序执行',
266
+ inputSchema: Support.defineSchema({
267
+ jsonSchema: {
268
+ type: 'object',
269
+ required: ['name', 'input'],
270
+ additionalProperties: false,
271
+ properties: {
272
+ name: { type: 'string', enum: configuration.tools.ids() },
273
+ input: { type: 'object' },
274
+ },
275
+ anyOf: configuration.tools.definitions.map((tool) => ({
276
+ properties: {
277
+ name: { const: tool.id },
278
+ input: tool.inputSchema.jsonSchema,
279
+ },
280
+ })),
281
+ },
282
+ parse(value) {
283
+ if (
284
+ !value ||
285
+ typeof value !== 'object' ||
286
+ Array.isArray(value) ||
287
+ Object.keys(value).some((key) => key !== 'name' && key !== 'input') ||
288
+ typeof value.name !== 'string' ||
289
+ !value.input ||
290
+ typeof value.input !== 'object' ||
291
+ Array.isArray(value.input)
292
+ ) {
293
+ throw new TypeError('Expected { name, input }');
294
+ }
295
+ configuration.tools.require(value.name);
296
+ return value;
297
+ },
298
+ }),
299
+ resolve: ({ name, input }) => ({ toolId: name, input }),
300
+ };
301
+ return {
302
+ ...configuration,
303
+ tools: Support.defineModelTools([capability]),
304
+ candidateIds: ['tool_request'],
305
+ };
306
+ }
307
+ ```
308
+
309
+ ## 6. 离线验证:两种配置的模型请求与执行结果相同
310
+
311
+ [run.mjs](../examples/registration/run.mjs)
312
+
313
+ ```js
314
+ /** Run the tutorial offline and check that both configuration styles produce equivalent contracts. */
315
+ import assert from 'node:assert/strict';
316
+ import { independentConfiguration } from './independent.mjs';
317
+ import { associatedConfiguration } from './associated.mjs';
318
+ import { runCase, taskTransport } from './workflow.mjs';
319
+ import { wrappedConfiguration } from './protocol.mjs';
320
+
321
+ const separate = independentConfiguration();
322
+ const linked = associatedConfiguration();
323
+ assert.deepEqual(linked.tools.withIntent({}).ids(), separate.tools.withIntent({}).ids());
324
+ const rawFunctions = (configuration) =>
325
+ taskTransport(configuration.tools).prepare('choose-operation').options.functions;
326
+ assert.deepEqual(rawFunctions(linked), rawFunctions(separate));
327
+ assert.deepEqual(
328
+ linked.tools.resolve(
329
+ { toolId: 'search_notes', input: { query: ' 咖啡 ' } },
330
+ { stageId: 'choose-operation' },
331
+ ),
332
+ separate.tools.resolve(
333
+ { toolId: 'search_notes', input: { query: ' 咖啡 ' } },
334
+ { stageId: 'choose-operation' },
335
+ ),
336
+ );
337
+ for (const [question, name, input] of [
338
+ ['帮我找咖啡相关的笔记', 'search_notes', { query: '咖啡' }],
339
+ ['读一下n1这篇笔记', 'read_note', { noteId: 'n1' }],
340
+ ]) {
341
+ const a = await runCase(separate, question, name, input);
342
+ const b = await runCase(linked, question, name, input);
343
+ assert.deepEqual(a.submitted, b.submitted);
344
+ assert.deepEqual(a.result, b.result);
345
+ console.log(JSON.stringify({ question, result: b.result }));
346
+ }
347
+ const a = await runCase(wrappedConfiguration(separate), '帮我找咖啡相关的笔记', 'tool_request', {
348
+ name: 'search_notes',
349
+ input: { query: '咖啡' },
350
+ });
351
+ const b = await runCase(wrappedConfiguration(linked), '帮我找咖啡相关的笔记', 'tool_request', {
352
+ name: 'search_notes',
353
+ input: { query: '咖啡' },
354
+ });
355
+ assert.deepEqual(a.submitted, b.submitted);
356
+ assert.deepEqual(a.result, b.result);
357
+ console.log(
358
+ 'PASS: discovery, model functions, messages and execution results match.',
359
+ );
360
+ console.log('PASS: name/input envelope uses the same workflow and execution contract.');
361
+ ```
362
+
363
+ ## 需求识别用途与激活条件
364
+
365
+ ```ts
366
+ const tools = Support.defineModelTools([{
367
+ id: "manage_memo",
368
+ description: "Process a memo draft and check conflicts",
369
+ inputSchema: memoSchema,
370
+ asIntent: {
371
+ description: "The user wants to remember something or set a reminder",
372
+ when: context => context.features.memos,
373
+ },
374
+ active: context => context.services.memos != null,
375
+ resolve: input => input,
376
+ }]);
377
+ const candidates = tools.withIntent(context);
378
+ const known = tools.select(["manage_memo"], context);
379
+ ```
380
+
381
+ `asIntent` 接受 `true`、描述、布尔判断函数或 `{ description?, when?, delegates? }`。省略不参与需求识别;`active` 省略表示激活。两种选取方式均检查激活条件,专门描述只作用于当前视图。delegates 可选,表示允许集合而不是顺序,由领域注册器校验词汇;不会产生 Intent ID 或跨 Tool 描述聚合。
382
+
383
+ ## 装饰器配置
384
+
385
+ ```ts
386
+ @Intent({ description: "Accept memo requests", delegates: ["read", "final"] })
387
+ @WorkflowTool("manage_memo", { ns: "assistant" })
388
+ class MemoTool {
389
+ description = "Process a memo request";
390
+ inputSchema = memoSchema;
391
+ resolve(input) { return input; }
392
+ }
393
+ ```
394
+
395
+ 装饰器从 `@jangts/agent-core/support/decorators` 导入。`@WorkflowTool` 与 `@WorkflowNode` 一样支持类和公开实例方法。`@Intent` 单独挂在同一目标上,单用不注册;Tool 装饰器及其定义不接收 asIntent。关联不依赖装饰器顺序。
396
+
397
+ ## 运行示例
398
+
399
+ ```sh
400
+ node packages/agent-core/development/docs/examples/registration/run.mjs
401
+ ```
402
+
403
+ 离线 fixture 验证接线和合同等价,不证明自然语言识别或真实供应商表现。Cafe 保留目标和下一步一次提交的分组协议,goal 指向 GoalTool;Banker 将本轮 Tool 候选投影到 name/input 协议。两端复用相同 Tool 合同,不强求同一种业务工作流。
@@ -44,14 +44,14 @@ Budgets default to the current modelRunnerDefaults: maxCalls=8, callTimeoutMs=30
44
44
  Input messages contain fields such as role/content/images, and images in read-only input are retained with the message. remainingCalls, signal, and journal can be read directly; call counts use callCount/totalCallCount. lastCall is a read-only snapshot of the previous completed record and is not a basis for concurrent correlation. Selection and compression nodes share counts through the same model port. A single runner executes one call at a time; concurrent tasks each use a child runner, and each returned value is correlated by its own invocation.
45
45
 
46
46
  ```ts
47
- interface ModelCapability<Input, Output = Input> {
47
+ interface BaseTool<Input, Output = Input> {
48
48
  readonly id: string;
49
49
  readonly description: string;
50
50
  readonly inputSchema: SchemaAdapter<Input>;
51
51
  resolve(input: Input, context: Readonly<{ stageId: string }>): Output;
52
52
  }
53
53
  interface ModelSelection {
54
- readonly capabilityId: string;
54
+ readonly toolId: string;
55
55
  readonly input: unknown;
56
56
  }
57
57
  interface ModelTransportDefinition<Output> {
@@ -62,11 +62,11 @@ interface ModelTransportDefinition<Output> {
62
62
 
63
63
  PreparedModelTransport<Output> is the unified transport preparation contract: options, schemaChars, optional instruction, and createResponse(). The returned collector has outputChars, push(part), and finish(): Output; the text collector accumulates and rejects function-call parts, and the structured collector returns a result only after full parsing. A collector is a new instance per call and does not reuse state across requests. PreparedModelInteraction is used for structured adapter composition, while text transports implement the generic collection contract directly.
64
64
 
65
- ModelCapability uses inputSchema.parse to parse capability parameters and resolve(input, { stageId }) to produce a typed stage result. resolve runs synchronously; a mistakenly returned thenable is rejected, and it neither executes tools nor authorizes. ModelCapabilitySource.resolve(selection, context) first verifies the IDs available in this stage, then parses, converts, and runs the declared refine checks.
65
+ BaseTool uses inputSchema.parse to parse capability parameters and resolve(input, { stageId }) to produce a typed stage result. resolve runs synchronously; a mistakenly returned thenable is rejected, and it neither executes tools nor authorizes. ModelToolSource.resolve(selection, context) first verifies the IDs available in this stage, then parses, converts, and runs the declared refine checks.
66
66
 
67
67
  Core reads outputChars after the collector factory returns, after each push, and after finish: the value must be a non-negative safe integer, and NaN, Infinity, negative numbers, and fractions are rejected as protocol errors. maxOutputChars may be explicitly set to Infinity, but that does not relax the collector counting contract. Diagnostics keep the peak of each valid observation, and finish may release or normalize internal buffers; buffers are not required to grow indefinitely.
68
68
 
69
- Native interaction accepts a string or a valid function-call-delta. A function part must be a non-array object with index 0; id, when provided, must be a non-empty string, and name and arguments, when provided, must be strings. Conflicting IDs, multiple calls, unregistered capabilities, mixed body text, or incomplete arguments are rejected, and no tool is executed.
69
+ Native interaction accepts a string or a valid function-call-delta. A function part must be a non-array object with index 0; id, when provided, must be a non-empty string, and name and arguments, when provided, must be strings. Conflicting IDs, multiple calls, unregistered tools, mixed body text, or incomplete arguments are rejected, and no tool is executed.
70
70
 
71
71
  Optional call metadata on the collector is read only once on a best-effort basis; a throwing getter does not overwrite an obtained business result, the original error, or cancellation, nor does it block the model.end wrap-up. outputChars is an execution-validated field and is exempt from this tolerance rule.
72
72
 
@@ -89,7 +89,7 @@ Preparation fixes the instruction, Schema, options, and collector factory receiv
89
89
 
90
90
  Measurement returns `ModelInputMeasurement` with body messageChars, added instructionChars, out-of-message declaration schemaChars, transport budget usage transportChars, the actual total inputChars, the effective limit, and withinBudget. It is not a budget reservation or a pass: the final input is still measured and validated again before the Provider. A handle belongs only to the Runner/Workflow request that prepared it, can be consumed once, and cannot replace stageId, transport, or the output reservation. Cancellation, expiry, foreign handles, and reuse are rejected; a pre-check rejection still consumes no model calls.
91
91
 
92
- The final call fixes a snapshot of message role, content, and images before the first asynchronous wait, and budgeting, token counting, and Provider sending share that snapshot; the caller modifying the original object afterwards does not rewrite the request. prepare fixes the set of capability IDs for this preparation, and capabilities registered later are available only to new preparations.
92
+ The final call fixes a snapshot of message role, content, and images before the first asynchronous wait, and budgeting, token counting, and Provider sending share that snapshot; the caller modifying the original object afterwards does not rewrite the request. prepare fixes the set of capability IDs for this preparation, and tools registered later are available only to new preparations.
93
93
 
94
94
  Character budgets accept only non-negative safe integers or Infinity; a budget carried by BuiltContext must pass the same validation and can only narrow the Runner upper limit. NaN, missing budgets, fractions, and other invalid values are rejected before billing and Provider calls, and measurement and actual execution use the same judgment.
95
95
 
@@ -221,10 +221,10 @@ isResult only answers with a boolean; if a resumable business check is needed, t
221
221
 
222
222
  ## ToolRegistry and ToolRuntime
223
223
 
224
- The low-level ToolRegistry in Core can take hand-written ExecutableTool implementations; Support's ToolRuntime comes from typed tool catalogs. Both reuse the same real invocation mechanism.
224
+ The low-level ToolRegistry in Core can take hand-written ErasedTool implementations; Support's ToolRuntime comes from typed tool catalogs. Both reuse the same real invocation mechanism.
225
225
 
226
226
  ```ts
227
- interface ExecutableTool {
227
+ interface ErasedTool {
228
228
  readonly id: string;
229
229
  readonly kind: string;
230
230
  parseInput(input: unknown): unknown;
@@ -44,14 +44,14 @@ const b = await runner.invoke({ input: '你好' });
44
44
  输入消息包含 role/content/images 等字段,只读输入中的图片会随消息保留。remainingCalls、signal、journal 可直接读取;调用计数使用 callCount/totalCallCount。lastCall 是上一条完成记录的只读快照,不作为并发关联依据。选择/压缩节点通过同一模型端口共享计数。同一个 runner 同时执行一次调用;并发任务分别使用子 runner,各返回值以自己的 invocation 关联。
45
45
 
46
46
  ```ts
47
- interface ModelCapability<Input, Output = Input> {
47
+ interface BaseTool<Input, Output = Input> {
48
48
  readonly id: string;
49
49
  readonly description: string;
50
50
  readonly inputSchema: SchemaAdapter<Input>;
51
51
  resolve(input: Input, context: Readonly<{ stageId: string }>): Output;
52
52
  }
53
53
  interface ModelSelection {
54
- readonly capabilityId: string;
54
+ readonly toolId: string;
55
55
  readonly input: unknown;
56
56
  }
57
57
  interface ModelTransportDefinition<Output> {
@@ -62,11 +62,11 @@ interface ModelTransportDefinition<Output> {
62
62
 
63
63
  PreparedModelTransport<Output>为统一的传输准备合同:options、schemaChars、可选instruction、createResponse()。返回的collector具有outputChars、push(part)及finish(): Output;文本collector累积并拒绝函数调用分片,结构化collector完整解析后才返回结果。collector是每次调用新建的实例,不复用跨请求状态。PreparedModelInteraction 供结构化适配组合使用,文本传输直接实现通用收集合同。
64
64
 
65
- ModelCapability 使用 inputSchema.parse 解析能力参数,使用 resolve(input, { stageId }) 生成类型化阶段结果。resolve 同步执行,误返 thenable 时拒绝,不执行工具或授权。ModelCapabilitySource.resolve(selection, context) 先核对本阶段可用 ID,再解析、转换并执行已声明的 refine 检查。
65
+ BaseTool 使用 inputSchema.parse 解析能力参数,使用 resolve(input, { stageId }) 生成类型化阶段结果。resolve 同步执行,误返 thenable 时拒绝,不执行工具或授权。ModelToolSource.resolve(selection, context) 先核对本阶段可用 ID,再解析、转换并执行已声明的 refine 检查。
66
66
 
67
67
  Core 在 collector 工厂返回后、每次 push 后和 finish 后读取 outputChars:值必须是非负安全整数,NaN、Infinity、负数和小数均按协议错误拒绝。maxOutputChars 可以显式设为 Infinity,但不放宽 collector 计数合同。诊断保留各次有效观测的峰值,finish 可释放或规范化内部缓冲,不要求缓冲一直增长。
68
68
 
69
- 原生交互接收字符串或合法的 function-call-delta。函数分片必须是非数组对象,index 为 0;id 提供时必须是非空字符串,name 和 arguments 提供时必须是字符串。冲突 ID、多个调用、未登记能力、混合正文或不完整参数被拒绝,不执行工具。
69
+ 原生交互接收字符串或合法的 function-call-delta。函数分片必须是非数组对象,index 为 0;id 提供时必须是非空字符串,name 和 arguments 提供时必须是字符串。冲突 ID、多个调用、未登记能力、混合正文或不完整参数被拒绝,不执行工具。需要正文 + 多调用时使用 `Support.createSessionModelTransport`;它复用同一聚合 collector,但不改变原生交互的单提案合同。
70
70
 
71
71
  collector 可选 call 元数据只尽力读取一次;getter 抛错不覆盖已取得的业务结果、原始错误或取消,也不阻止 model.end 收尾。outputChars 是执行校验字段,不适用这个容错规则。
72
72
 
@@ -221,10 +221,10 @@ isResult只回答boolean;若需可恢复业务检查,App在流程节点中
221
221
 
222
222
  ## ToolRegistry 和 ToolRuntime
223
223
 
224
- Core低层ToolRegistry可以接手写ExecutableTool;Support的ToolRuntime来自类型化工具目录。两者复用同一个真实调用机制。
224
+ Core低层ToolRegistry可以接手写ErasedTool;Support的ToolRuntime来自类型化工具目录。两者复用同一个真实调用机制。
225
225
 
226
226
  ```ts
227
- interface ExecutableTool {
227
+ interface ErasedTool {
228
228
  readonly id: string;
229
229
  readonly kind: string;
230
230
  parseInput(input: unknown): unknown;
@@ -81,3 +81,23 @@ agent/model ids are registration keys, not Core branch, model or transport ident
81
81
  A routes getter may return `when: state => this._ready(state)` and `complete: state => this._reply(state)`. Workflow assembly reads and snapshots the table, potentially reading the getter multiple times. Keep getters pure and independent of request state. After state patches commit, route callbacks receive the latest state and can call private helpers. The getter is not re-evaluated each run; do not store request state on shared nodes.
82
82
 
83
83
  ESM/CJS module copies share roots within one JavaScript realm. Processes, workers and separate realms do not share roots. Independently evaluated classes registering the same kind, namespace and id reject rather than merge. Explicitly retain definition modules in the bundle: discarded side-effect-only imports cannot guarantee registration. Shared definitions must not retain request identity, signal or budget. Reading is neither execution nor authorization.
84
+
85
+ ## WorkflowTool and Intent
86
+
87
+ WorkflowTool and WorkflowNode are explicit names for the tool and node decorators. WorkflowTool supports definition classes and public instance methods. A model-only Tool provides inputSchema and resolve; an executable Tool additionally provides kind, authorize, execute and parseOutput. The same pool stores their normalized definitions.
88
+
89
+ ```ts
90
+ import { WorkflowTool, Intent, toolPool } from '@jangts/agent-core/support/decorators';
91
+ import { Support } from '@jangts/agent-core';
92
+
93
+ @Intent('The user wants to remember something')
94
+ @WorkflowTool('memo', { ns: 'assistant' })
95
+ class MemoTool {
96
+ description = 'Accept a memo draft';
97
+ inputSchema = memoSchema;
98
+ resolve(input) { return input; }
99
+ }
100
+ const candidates = Support.defineModelTools(toolPool.getAll('assistant')).withIntent(context);
101
+ ```
102
+
103
+ Intent accepts no argument, a description, a synchronous boolean predicate, or `{ description?, when?, delegates? }`. It must decorate the same target as WorkflowTool and has no independent ID. Alone it registers nothing. Either decorator order works. Do not pass asIntent in WorkflowTool options or define it on the decorated class; use the separate Intent decorator. Explicit object configuration continues to support asIntent.
@@ -106,3 +106,23 @@ Workflow 装配时读取并固定路由表;getter 应无副作用,不依赖
106
106
  agent/model 的 id 是辅助登记键,不覆盖 Core 分支、模型或 transport 身份。工具复用原 defineTool 校验;Workflow 复用原图校验,节点在完整图中验证;fragment 复用原 builder 的 formatter 检查,数据、信任与预算保持原合同;model 复用原配置快照验证,不消耗模型调用。辅助层不公开 metadata+普通函数转换入口,顶层函数直接填入原 options。
107
107
 
108
108
  同一 JavaScript realm 内 ESM/CJS 副本共享池;不同进程、Worker 或独立 realm 不共享。两次独立加载并装饰同命名空间同 id 的类仍会重名拒绝,不自动合并。定义模块必须被打包图明确保留;被 tree-shaking 删除的纯副作用导入不能保证登记。共享定义不能保存请求身份、signal 或请求预算;池读取不是执行或授权。
109
+
110
+ ## WorkflowTool 与 Intent
111
+
112
+ WorkflowTool、WorkflowNode 分别是 tool、node 的明确命名入口。WorkflowTool 支持定义类与公开实例方法。模型 Tool 提供 inputSchema 和 resolve;执行 Tool 另外提供 kind、authorize、execute 和 parseOutput。归一化定义进入同一个 toolPool。
113
+
114
+ ```ts
115
+ import { WorkflowTool, Intent, toolPool } from '@jangts/agent-core/support/decorators';
116
+ import { Support } from '@jangts/agent-core';
117
+
118
+ @Intent('用户希望记录事情或设置提醒')
119
+ @WorkflowTool('memo', { ns: 'assistant' })
120
+ class MemoTool {
121
+ description = '接收备忘草案';
122
+ inputSchema = memoSchema;
123
+ resolve(input) { return input; }
124
+ }
125
+ const candidates = Support.defineModelTools(toolPool.getAll('assistant')).withIntent(context);
126
+ ```
127
+
128
+ Intent 支持无参数、描述字符串、同步布尔判断函数或 `{ description?, when?, delegates? }`。必须与同一目标的 WorkflowTool 配合,没有独立 ID,单用不注册;两者书写顺序均可。WorkflowTool 参数和被装饰类中不提供 asIntent,使用独立 Intent 装饰器;普通配置对象仍支持 asIntent。
@@ -66,7 +66,7 @@ const readNote = Support.defineTool({
66
66
 
67
67
  const catalog = Support.defineToolCatalog([readNote]);
68
68
  const transport = Support.createModelTransport({
69
- id: 'note-selection', capabilities: catalog.capabilities,
69
+ id: 'note-selection', tools: catalog.tools,
70
70
  });
71
71
  ```
72
72
 
@@ -66,7 +66,7 @@ const readNote = Support.defineTool({
66
66
 
67
67
  const catalog = Support.defineToolCatalog([readNote]);
68
68
  const transport = Support.createModelTransport({
69
- id: 'note-selection', capabilities: catalog.capabilities,
69
+ id: 'note-selection', tools: catalog.tools,
70
70
  });
71
71
  ```
72
72
 
@@ -2,13 +2,15 @@
2
2
 
3
3
  [Shared types](types.md) · [Back to home](README.md). Each Kit is imported by named function/constructor from its own subpath, with static declarations separated from the per-run context.
4
4
 
5
- ## Intents, Interaction, Tools
5
+ ## Domain Tools, Scope, Interaction, Tools
6
+
7
+ IntentRegistry registers ModelTool-derived IntentTool declarations, preserving scope/target policies and task constraints. `asIntent.delegates` overrides derived delegates; delegates are optional allowed sets, not a sequence. There is no independent Intent entity or Intent ID. Scope goalIds reference actual Tool IDs. Import the optional registry helpers from `@jangts/agent-core/kits/domains`.
6
8
 
7
9
  | Capability | Preferred interface/key contract |
8
10
  | --- | --- |
9
11
  | IntentRegistry | Defines the primary key id, uses scopePolicy/targetPolicy, implements the shared Registry contract |
10
- | ScopeRegistry | id, intentIds, toolIds, queryScopeIds, knowledgeTopicIds; aliases are retained, and query methods use scopeId |
11
- | defineAgentCatalog | Projects relationships from actual registrations; the current task is `{ intentId, scopeId? }`, and scope cannot be used for both policy and reference |
12
+ | ScopeRegistry | id, goalIds, toolIds, queryScopeIds, knowledgeTopicIds; aliases are retained, and query methods use scopeId |
13
+ | defineAgentCatalog | Projects relationships from actual registrations; the current task is `{ goalId, scopeId? }`, and scope cannot be used for both policy and reference |
12
14
  | defineInteractionProtocol | One commands declaration compiles the protocol; commandField is owned by the App, which is not forced to name its wire field type or kind |
13
15
  | defineCommandCatalog | The closed commands set may be written as a Record; the public definitions are an array, and toRecord() is the explicit mapping |
14
16
  | bindInteraction | Aligns protocol with named handlers; dispatch(input, context) never executes unregistered commands |
@@ -20,7 +22,7 @@ When the complete list is available at construction time, use IntentRegistry.cre
20
22
 
21
23
  InteractionProtocol and CommandCatalog are public constructors; Interaction and Interaction.Commands provide their namespace entries respectively.
22
24
 
23
- The Tools Kit preserves the real order: global check → selected check → authorization → resume/execute → completion → finalize. Lifecycle and contribution are local protocols of this Kit. The receiver field is called receiver and is not conflated with OutputField.owner; the in-request journal reuses the invocationId allocated by Core.
25
+ The Tools Kit preserves the real order: global check → authorization → resume/execute → completion → finalize. Each tool declares one lifecycle block: hooks such as inspect and finalize run for every tool, while id/protocol/call and authorize/resume/complete run only for the selected tool. The receiver field is called receiver and is not conflated with OutputField.owner; the in-request journal reuses the invocationId allocated by Core.
24
26
 
25
27
  ## Evidence and Retrieval
26
28
 
@@ -72,6 +74,22 @@ A TextSkill definition uses id, entry, toolIds, and kind=text-workflow. Catalog
72
74
 
73
75
  TextSkillLoader accepts load({ entries }, { read }). Registration ID, path, tool reference, and duplicate checks precede reading the corresponding file, and both read and custom parsers must be synchronous. The read port, registration entries, and error factory may be implemented by a class, and prototype getters and original method receivers are preserved. App-owned fields in tool receipts are projected explicitly by the App.
74
76
 
77
+ ## TextBlocks
78
+
79
+ ```ts
80
+ interface TextBlock {
81
+ readonly number: number
82
+ readonly text: string
83
+ readonly start: number
84
+ readonly end: number
85
+ }
86
+ TextBlocks.split(text, { targetChars }): readonly TextBlock[]
87
+ ```
88
+
89
+ `split` only processes decoded plain text: headings and horizontal rules start a new block, blank lines end the current one, and other lines break at line boundaries once `targetChars` would be exceeded. A single over-long line stays one block so paging can cut it into fragments later without turning one line into unrelated sections. Blocks reassemble into the original text exactly, including whitespace and CRLF; `number` starts at 1 and `start`/`end` are UTF-16 offsets in the source. `targetChars` must be a positive integer, and empty text returns an empty array.
90
+
91
+ The Kit does not read files, page, call models or touch storage; paging windows, indexing, summaries and prompts remain App decisions. Block boundaries follow structure rather than a fixed character window, so use `start`/`end` when reporting coverage.
92
+
75
93
  ## TextSearch, VectorSearch, RRF, ModelCalls
76
94
 
77
95
  ```ts