@jangts/agent-core 0.3.6 → 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 (214) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +5 -5
  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 +4 -2
  7. package/development/docs/api/README.md +2 -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/reference.en.md +508 -410
  23. package/development/docs/api/reference.md +508 -410
  24. package/development/docs/api/support.en.md +55 -9
  25. package/development/docs/api/support.md +53 -7
  26. package/development/docs/api/types.en.md +35 -1
  27. package/development/docs/api/types.md +43 -0
  28. package/development/docs/basic-usage.en.md +1 -1
  29. package/development/docs/basic-usage.md +1 -1
  30. package/development/docs/create-app.en.md +1 -1
  31. package/development/docs/examples/registration/associated.mjs +8 -0
  32. package/development/docs/examples/registration/independent.mjs +20 -0
  33. package/development/docs/examples/registration/protocol.mjs +48 -0
  34. package/development/docs/examples/registration/run.mjs +47 -0
  35. package/development/docs/examples/registration/tools.mjs +75 -0
  36. package/development/docs/examples/registration/workflow.mjs +109 -0
  37. package/development/docs/flows/knowledge-maintenance.en.md +1 -1
  38. package/development/docs/materials.en.md +1 -1
  39. package/development/docs/mechanisms.en.md +2 -2
  40. package/development/docs/mechanisms.md +1 -1
  41. package/development/docs/operations.en.md +1 -1
  42. package/development/docs/records.en.md +1 -1
  43. package/development/docs/registration.en.md +4 -4
  44. package/development/docs/registration.md +2 -2
  45. package/development/skills/agent-core-app/SKILL.md +4 -4
  46. package/development/skills/agent-core-app/templates/node-ts/README.md.tpl +1 -1
  47. package/development/skills/agent-core-app/templates/node-ts/src/catalog.ts.tpl +2 -2
  48. package/development/skills/agent-core-app/templates/node-ts/test/app.test.mjs.tpl +1 -1
  49. package/dist/cjs/capabilities/index.js +5 -12
  50. package/dist/cjs/capabilities/model.js +56 -12
  51. package/dist/cjs/capabilities/tool-conditions.js +65 -0
  52. package/dist/cjs/capabilities/tool-runtime.js +10 -3
  53. package/dist/cjs/context/audit.js +5 -8
  54. package/dist/cjs/context/index.js +3 -4
  55. package/dist/cjs/index.js +21 -17
  56. package/dist/cjs/kits/answering/tasks.js +5 -5
  57. package/dist/cjs/kits/domains/catalog.js +113 -0
  58. package/dist/cjs/kits/domains/index.js +20 -0
  59. package/dist/cjs/kits/{intents → domains}/registry.js +77 -31
  60. package/dist/cjs/kits/{intents → domains}/scopes.js +21 -21
  61. package/dist/cjs/kits/index.js +14 -13
  62. package/dist/cjs/kits/presentation/formats.js +110 -0
  63. package/dist/cjs/kits/presentation/index.js +10 -5
  64. package/dist/cjs/kits/reflection.js +2 -2
  65. package/dist/cjs/kits/text-blocks.js +101 -0
  66. package/dist/cjs/kits/tools.js +246 -158
  67. package/dist/cjs/model/index.js +2 -6
  68. package/dist/cjs/model/interactions/calls.js +61 -0
  69. package/dist/cjs/model/interactions/json-object.js +11 -11
  70. package/dist/cjs/model/interactions/native-functions.js +17 -23
  71. package/dist/cjs/model/message-diagnostics.js +13 -3
  72. package/dist/cjs/model/options.js +2 -0
  73. package/dist/cjs/model/preparation.js +39 -6
  74. package/dist/cjs/model/runner.js +14 -0
  75. package/dist/cjs/model/selection-transport.js +4 -4
  76. package/dist/cjs/model/token-budget.js +3 -0
  77. package/dist/cjs/model/transports.js +3 -2
  78. package/dist/cjs/structs/index.js +7 -6
  79. package/dist/cjs/structs/kits/presentation/formats.js +2 -0
  80. package/dist/cjs/structs/kits/text-blocks.js +11 -0
  81. package/dist/cjs/structs/model/session.js +11 -0
  82. package/dist/cjs/structs/support/associations.js +2 -0
  83. package/dist/cjs/support/associations.js +79 -0
  84. package/dist/cjs/support/context/snapshot.js +11 -1
  85. package/dist/cjs/support/decorators/index.js +45 -3
  86. package/dist/cjs/support/index.js +1 -0
  87. package/dist/cjs/support/model/capabilities.js +35 -5
  88. package/dist/cjs/support/model/chat-completions.js +11 -2
  89. package/dist/cjs/support/model/completion/calls.js +10 -56
  90. package/dist/cjs/support/model/preview-rules.js +11 -11
  91. package/dist/cjs/support/model/reply-preview.js +3 -3
  92. package/dist/cjs/support/model/session.js +152 -0
  93. package/dist/cjs/support/model/stage-transport.js +8 -8
  94. package/dist/cjs/support/model/transports.js +5 -2
  95. package/dist/cjs/support/tools.js +42 -17
  96. package/dist/esm/capabilities/index.d.ts +5 -10
  97. package/dist/esm/capabilities/index.js +5 -9
  98. package/dist/esm/capabilities/model.d.ts +17 -13
  99. package/dist/esm/capabilities/model.js +54 -10
  100. package/dist/esm/capabilities/tool-conditions.d.ts +9 -0
  101. package/dist/esm/capabilities/tool-conditions.js +59 -0
  102. package/dist/esm/capabilities/tool-runtime.js +10 -3
  103. package/dist/esm/capabilities/tools.d.ts +3 -3
  104. package/dist/esm/context/audit.js +5 -8
  105. package/dist/esm/context/index.d.ts +3 -4
  106. package/dist/esm/context/index.js +3 -4
  107. package/dist/esm/index.d.ts +19 -13
  108. package/dist/esm/index.js +18 -15
  109. package/dist/esm/kits/answering/tasks.d.ts +6 -6
  110. package/dist/esm/kits/answering/tasks.js +5 -5
  111. package/dist/esm/kits/domains/catalog.d.ts +42 -0
  112. package/dist/esm/kits/domains/catalog.js +110 -0
  113. package/dist/esm/kits/domains/index.d.ts +4 -0
  114. package/dist/esm/kits/domains/index.js +4 -0
  115. package/dist/esm/kits/domains/registry.d.ts +100 -0
  116. package/dist/esm/kits/{intents → domains}/registry.js +77 -31
  117. package/dist/esm/kits/{intents → domains}/scopes.d.ts +18 -18
  118. package/dist/esm/kits/{intents → domains}/scopes.js +21 -21
  119. package/dist/esm/kits/index.d.ts +6 -5
  120. package/dist/esm/kits/index.js +6 -5
  121. package/dist/esm/kits/presentation/formats.d.ts +42 -0
  122. package/dist/esm/kits/presentation/formats.js +105 -0
  123. package/dist/esm/kits/presentation/index.d.ts +14 -5
  124. package/dist/esm/kits/presentation/index.js +10 -5
  125. package/dist/esm/kits/reflection.js +3 -3
  126. package/dist/esm/kits/text-blocks.d.ts +24 -0
  127. package/dist/esm/kits/text-blocks.js +97 -0
  128. package/dist/esm/kits/tools.d.ts +69 -52
  129. package/dist/esm/kits/tools.js +246 -158
  130. package/dist/esm/model/index.d.ts +2 -6
  131. package/dist/esm/model/index.js +2 -6
  132. package/dist/esm/model/interactions/calls.d.ts +40 -0
  133. package/dist/esm/model/interactions/calls.js +58 -0
  134. package/dist/esm/model/interactions/json-object.js +11 -11
  135. package/dist/esm/model/interactions/native-functions.js +17 -23
  136. package/dist/esm/model/message-diagnostics.d.ts +6 -5
  137. package/dist/esm/model/message-diagnostics.js +13 -3
  138. package/dist/esm/model/options.js +2 -0
  139. package/dist/esm/model/preparation.js +39 -6
  140. package/dist/esm/model/runner.js +14 -0
  141. package/dist/esm/model/selection-transport.js +4 -4
  142. package/dist/esm/model/token-budget.js +3 -0
  143. package/dist/esm/model/transports.d.ts +2 -1
  144. package/dist/esm/model/transports.js +3 -2
  145. package/dist/esm/structs/capabilities/invocation.d.ts +1 -1
  146. package/dist/esm/structs/capabilities/model.d.ts +42 -11
  147. package/dist/esm/structs/capabilities/tools.d.ts +9 -4
  148. package/dist/esm/structs/common.d.ts +1 -1
  149. package/dist/esm/structs/index.d.ts +7 -6
  150. package/dist/esm/structs/index.js +7 -6
  151. package/dist/esm/structs/kits/answering/tasks.d.ts +2 -2
  152. package/dist/esm/structs/kits/{intents → domains}/catalog.d.ts +20 -20
  153. package/dist/esm/structs/kits/{intents → domains}/registry.d.ts +24 -21
  154. package/dist/esm/structs/kits/{intents → domains}/scopes.d.ts +9 -9
  155. package/dist/esm/structs/kits/presentation/formats.d.ts +42 -0
  156. package/dist/esm/structs/kits/presentation/formats.js +1 -0
  157. package/dist/esm/structs/kits/text-blocks.d.ts +25 -0
  158. package/dist/esm/structs/kits/text-blocks.js +10 -0
  159. package/dist/esm/structs/kits/tools.d.ts +82 -83
  160. package/dist/esm/structs/model/interactions.d.ts +18 -11
  161. package/dist/esm/structs/model/messages.d.ts +34 -2
  162. package/dist/esm/structs/model/runtime.d.ts +7 -0
  163. package/dist/esm/structs/model/session.d.ts +29 -0
  164. package/dist/esm/structs/model/session.js +10 -0
  165. package/dist/esm/structs/support/associations.d.ts +22 -0
  166. package/dist/esm/structs/support/associations.js +1 -0
  167. package/dist/esm/structs/support/model/interactions.d.ts +2 -2
  168. package/dist/esm/structs/support/model/messages.d.ts +6 -13
  169. package/dist/esm/structs/support/tools.d.ts +23 -23
  170. package/dist/esm/support/associations.d.ts +26 -0
  171. package/dist/esm/support/associations.js +76 -0
  172. package/dist/esm/support/context/snapshot.js +11 -1
  173. package/dist/esm/support/decorators/index.d.ts +13 -2
  174. package/dist/esm/support/decorators/index.js +40 -3
  175. package/dist/esm/support/decorators/pool.d.ts +6 -5
  176. package/dist/esm/support/decorators/types.d.ts +3 -1
  177. package/dist/esm/support/index.d.ts +1 -0
  178. package/dist/esm/support/index.js +1 -0
  179. package/dist/esm/support/model/capabilities.d.ts +8 -3
  180. package/dist/esm/support/model/capabilities.js +35 -5
  181. package/dist/esm/support/model/chat-completions.js +11 -2
  182. package/dist/esm/support/model/completion/calls.d.ts +6 -34
  183. package/dist/esm/support/model/completion/calls.js +8 -55
  184. package/dist/esm/support/model/index.d.ts +1 -1
  185. package/dist/esm/support/model/preview-rules.d.ts +13 -8
  186. package/dist/esm/support/model/preview-rules.js +11 -11
  187. package/dist/esm/support/model/reply-preview.d.ts +2 -2
  188. package/dist/esm/support/model/reply-preview.js +3 -3
  189. package/dist/esm/support/model/session.d.ts +61 -0
  190. package/dist/esm/support/model/session.js +148 -0
  191. package/dist/esm/support/model/stage-transport.d.ts +1 -1
  192. package/dist/esm/support/model/stage-transport.js +9 -9
  193. package/dist/esm/support/model/transports.d.ts +2 -0
  194. package/dist/esm/support/model/transports.js +2 -1
  195. package/dist/esm/support/tools.d.ts +11 -3
  196. package/dist/esm/support/tools.js +43 -18
  197. package/dist/esm/utils/catalog.d.ts +1 -1
  198. package/package.json +20 -6
  199. package/dist/cjs/execution/index.js +0 -30
  200. package/dist/cjs/kits/intents/catalog.js +0 -82
  201. package/dist/cjs/kits/intents/index.js +0 -35
  202. package/dist/esm/execution/index.d.ts +0 -11
  203. package/dist/esm/execution/index.js +0 -11
  204. package/dist/esm/kits/intents/catalog.d.ts +0 -39
  205. package/dist/esm/kits/intents/catalog.js +0 -79
  206. package/dist/esm/kits/intents/index.d.ts +0 -22
  207. package/dist/esm/kits/intents/index.js +0 -18
  208. package/dist/esm/kits/intents/registry.d.ts +0 -88
  209. /package/dist/cjs/structs/kits/{intents → domains}/catalog.js +0 -0
  210. /package/dist/cjs/structs/kits/{intents → domains}/registry.js +0 -0
  211. /package/dist/cjs/structs/kits/{intents → domains}/scopes.js +0 -0
  212. /package/dist/esm/structs/kits/{intents → domains}/catalog.js +0 -0
  213. /package/dist/esm/structs/kits/{intents → domains}/registry.js +0 -0
  214. /package/dist/esm/structs/kits/{intents → domains}/scopes.js +0 -0
package/CHANGELOG.md CHANGED
@@ -2,6 +2,26 @@
2
2
 
3
3
  本文件记录 `@jangts/agent-core` 的行为变更。接口合同与使用方式见[API 手册](development/docs/api/README.md)。
4
4
 
5
+ ## 0.5.0
6
+
7
+ - Add the optional `TextBlocks` Kit: structure-aware splitting of long plain text into numbered blocks with source offsets and exact reassembly; paging, search, storage and prompts stay with the App.
8
+ - Reject mutable context fragments whose declared field set changes through a `null` value, and merge tool model fields as own data properties so `__proto__`-like keys cannot rewrite the merged prototype.
9
+ - Keep Kit implementations out of Core barrels: `/context` and the capability registration surface expose Core helpers only, while Kit helpers remain available from `/kits/*` and the documented root convenience surface. Remove the unused execution barrel.
10
+ - Make `@jangts/mock-gpt` an optional peer dependency used only by the `/mock` entries instead of a production dependency; install it explicitly to use those entries.
11
+ - Support native tool threads in Core: `ModelMessage` accepts assistant `toolCalls` and `role: 'tool'` results; preparation preserves and counts them, and `ModelCallTrace.calls` records every completed call while `functionCall` keeps its single-call meaning.
12
+ - Add the opt-in `Support.createSessionModelTransport`: one response may contain prose and several tool calls. The resolved `toolId` / `input` / `problem` fields live in Support; Core only exposes raw `ModelSessionResult`. `nativeFunctionInteraction` and its single-proposal contract remain unchanged.
13
+ - Keep the Core `/model` barrel free of Support implementations; named Support exports remain available from the package root and `/support`.
14
+ - Keep Kits available from the root convenience surface and from `/kits` / `/kits/*` subpaths. Kits remain optional, not restricted; Apps may use whichever entry is convenient.
15
+ - Add `ModelOptions.toolChoice` and `parallelToolCalls`, including `'omit'` for leaving the wire field out; defaults keep `tool_choice: 'required'` and `parallel_tool_calls: false`.
16
+ - Unify model interfaces as ModelTool and ModelToolRegistry; transports use tools / toolIds, selections use toolId, and the JSON adapter uses a name/input envelope. Skip the 0.4 series.
17
+ - Add asIntent discovery metadata and active conditions, with node-owned withIntent(context) and explicit selection. Intent has no independent identity or aggregation registry.
18
+ - Preserve executable, lifecycle, domain-policy and preview extensions. Derive model interfaces from executable tools without parsing business arguments twice; retain authorization, cancellation, budgets and receipts.
19
+ - Add WorkflowTool / WorkflowNode names and separate Intent decorators for classes and methods, with order-independent ESM/CJS metadata. Tool decorators reject inline asIntent.
20
+ - Retain explicit owner-to-tool associations and local provenance without transmitting registration sources to the model. Domain delegates remain allowed sets with optional explicit overrides.
21
+ - Add one optional `lifecycle` block per tool in place of separate invocation and contribution objects, and one optional `delegate` field that claims a dispatch id. The registry keeps a unique `delegateId → tool` index, so `call(next, context)` stays the single dispatch path; `inspect` runs once for every tool and the remaining selected-only hooks run for the tool that owns the decision.
22
+ - Rename request-tool vocabulary to goals across the domain catalog: ports use `goalIds`/`goals`, projections expose `goalCatalog`/`goalDelegates`, and the model catalog returns `availableGoalIds`/`availableGoals`.
23
+ - Name lifecycle dispatch by `lifecycle.id`; `ToolsOptions.invocationId(decision)` selects the handler, `call(next, context)` routes on `next.type`, and the missing-handler factory is `unavailableInvocation(invocationId)`. No `step` field remains in the lifecycle contract.
24
+
5
25
  ## 0.3.6
6
26
 
7
27
  - Preserve explicit recovery targets from workflow error events as execution-chain transitions linked to the original errorEventId.
package/README.md CHANGED
@@ -127,14 +127,14 @@ console.log(result.value); // 42
127
127
 
128
128
  Reuse static tool definitions and bind request dependencies and cancellation with `catalog.bind({ app, execution })`. Successful tool invocation also returns `{ value, invocation }`.
129
129
 
130
- To let the model select a tool, append this to `tools.mjs` and use the `provider.mjs` above. The same catalog supplies model capabilities and actual execution:
130
+ To let the model select a tool, append this to `tools.mjs` and use the `provider.mjs` above. The same catalog supplies model tools and actual execution:
131
131
 
132
132
  ```js
133
133
  import { ModelRunner } from '@jangts/agent-core';
134
134
  import { provider } from './provider.mjs';
135
135
 
136
136
  const selection = Support.createModelTransport({
137
- id: 'choose-tool', capabilities: catalog.capabilities,
137
+ id: 'choose-tool', tools: catalog.tools,
138
138
  });
139
139
  const runner = new ModelRunner({ provider, transports: [selection], maxCalls: 1 });
140
140
  const proposal = await runner.invoke({
@@ -217,7 +217,7 @@ Workflow `context.cache` provides synchronous Engine-lifetime memory partitioned
217
217
  | Integrate with a development agent | [Agent-assisted development and Skill](https://agent-core-docs.pages.jangts.cafe/en/manual/agent-development.html) |
218
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) |
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.
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. The `/mock`, `/mock/node` and `/mock/web` entries require installing `@jangts/mock-gpt`, which is an optional peer dependency and is not installed with this package.
221
221
 
222
222
  ## License
223
223
 
@@ -359,7 +359,7 @@ import { ModelRunner } from '@jangts/agent-core';
359
359
  import { provider } from './provider.mjs';
360
360
 
361
361
  const selection = Support.createModelTransport({
362
- id: 'choose-tool', capabilities: catalog.capabilities,
362
+ id: 'choose-tool', tools: catalog.tools,
363
363
  });
364
364
  const runner = new ModelRunner({ provider, transports: [selection], maxCalls: 1 });
365
365
  const proposal = await runner.invoke({
@@ -442,7 +442,7 @@ console.log(snapshot);
442
442
  | 让开发 Agent 辅助接入 SDK | [Agent 辅助开发与 Skill](https://agent-core-docs.pages.jangts.cafe/zh/manual/agent-development.html) |
443
443
  | 查精确参数、重载和返回值 | [API 目录](https://agent-core-docs.pages.jangts.cafe/zh/api/) · [本地 API 手册](development/docs/api/README.md) |
444
444
 
445
- Core 与 Support 从包根导入,Kit 从 `/kits/<name>` 导入,装饰器从 `/support/decorators` 导入。App 拥有身份、业务权限、外部副作用和存储;Core 提供通用运行保证,Support 与 Kit 按需使用。
445
+ Core 与 Support 从包根导入,Kit 从 `/kits/<name>` 导入,装饰器从 `/support/decorators` 导入。App 拥有身份、业务权限、外部副作用和存储;Core 提供通用运行保证,Support 与 Kit 按需使用。`/mock`、`/mock/node`、`/mock/web` 需要另行安装 `@jangts/mock-gpt`;它是可选 peer 依赖,不会随本包自动安装。
446
446
 
447
447
  ## 许可
448
448
 
@@ -51,11 +51,11 @@ Names, parameters, and conclusions proposed by the model are not authentication,
51
51
  - **Basic run**: the Provider's model connection and the actual input. Core provides the default budget, single-call timeout, signals, and plain text transport; override as needed.
52
52
  - **When enabling tools**: the business implementation plus the required identity, access control, parameter, and result constraints.
53
53
  - **When enabling persistence**: sources, user ownership, storage and retention policy, and failure recovery.
54
- - **When enabling complex orchestration**: associations among declared nodes, tools, model capabilities, knowledge, checks, and output.
54
+ - **When enabling complex orchestration**: associations among declared nodes, tools, model tools, knowledge, checks, and output.
55
55
 
56
56
  No default need to enable long-term memory, user profiles, experience libraries, vector databases, or dynamic tool loading. Deliver a read-only, single-round App with explicit sources first, then integrate each item according to real requirements.
57
57
 
58
- ## Provided versus still-App-owned capabilities
58
+ ## Provided versus still-App-owned tools
59
59
 
60
60
  | Provided by the library | Still to be implemented by the App |
61
61
  | --- | --- |
@@ -2,7 +2,7 @@
2
2
 
3
3
  [Back to development handbook](README.md) · [API reference](api/README.md)
4
4
 
5
- The following are the evidence expected for an integration, chosen by developers according to the capabilities actually enabled; they are not a full command suite to run on every change. Review what the source can confirm first, and run the minimum relevant checks when a concrete question exists. Success with an offline stand-in does not prove real model behavior, and being executable by the framework does not prove the business facts are correct.
5
+ The following are the evidence expected for an integration, chosen by developers according to the tools actually enabled; they are not a full command suite to run on every change. Review what the source can confirm first, and run the minimum relevant checks when a concrete question exists. Success with an offline stand-in does not prove real model behavior, and being executable by the framework does not prove the business facts are correct.
6
6
 
7
7
  | Boundary | What should be proven | Minimal example |
8
8
  | --- | --- | --- |
@@ -21,7 +21,7 @@ The following are the evidence expected for an integration, chosen by developers
21
21
 
22
22
  When long-term memory is chosen, additionally verify message watermarks, concurrent versions, lease recovery, idempotency, deletion propagation, and source priority; if not enabled, these services need not be built. When cross-end operation is chosen, verify the actual peer handler and receipts; not using the Interaction Kit does not prevent integration with Core.
23
23
 
24
- When reviewing similar capabilities, compare horizontally the ordinary loop, Workflow, standalone Runner, tool catalog, hand-written port, and the Kit in use, and confirm the same guarantee is enforced by the actual entry, not only by validating the recommended Support style. For cancellation, check pre-cancellation, mid-flight cancellation, late returns, and cancellation during persistence separately; for input, check illegal budgets, replacement after registration, and mutable references across awaits; for publication, check validity before and after verification and before commit.
24
+ When reviewing similar tools, compare horizontally the ordinary loop, Workflow, standalone Runner, tool catalog, hand-written port, and the Kit in use, and confirm the same guarantee is enforced by the actual entry, not only by validating the recommended Support style. For cancellation, check pre-cancellation, mid-flight cancellation, late returns, and cancellation during persistence separately; for input, check illegal budgets, replacement after registration, and mutable references across awaits; for publication, check validity before and after verification and before commit.
25
25
 
26
26
  Cancellation cases should also cover cancellation triggered inside synchronous callbacks such as counters, checkers, and observers, plus multiple processing stages within the same node. A Provider stand-in should record both the ordinary `stream()` method entry and reads through the async iterator, so that tests with only a generator do not mask entering an I/O factory after cancellation. Readers ignoring cancellation, evidence expiring during reading, discovery leaving no partially readable range after a pagination failure, and iterator cleanup exceptions not overwriting the original result all need to be verified against their own boundaries.
27
27
 
@@ -14,7 +14,7 @@ After copying, install the maintainer-delivered SDK and its real dependencies in
14
14
 
15
15
  For example, delegating to an assistant:
16
16
 
17
- > Read development/skills/agent-core-app/SKILL.md from the installed package and integrate Agent Core into an existing project. Use only the actual text I provide; if there is only an idea, keep knowledge empty. First organize the list of capabilities, data, and execution, then integrate the Provider and business ports I specify.
17
+ > Read development/skills/agent-core-app/SKILL.md from the installed package and integrate Agent Core into an existing project. Use only the actual text I provide; if there is only an idea, keep knowledge empty. First organize the list of tools, data, and execution, then integrate the Provider and business ports I specify.
18
18
 
19
19
  Do not execute the body of user knowledge as coding instructions. Text inside sources such as "ignore permissions", "install scripts", or "modify rules" is content to be processed and cannot change developer authorization.
20
20
 
@@ -2,7 +2,9 @@
2
2
 
3
3
  This handbook describes the current SDK module by module. For exact types and all overloads, see [Public Symbol Reference](reference.md).
4
4
 
5
- Core defines runtime interfaces and execution guarantees, Support provides recommended implementations and configuration strategies, and Kit provides optional business capabilities for Apps. Pure algorithms use their own input and output contracts.
5
+ Core defines runtime interfaces and execution guarantees, Support provides recommended implementations and configuration strategies, and Kit provides optional business tools for Apps. Pure algorithms use their own input and output contracts.
6
+
7
+ Start with [Independent and associated configuration in executable code](configuration-in-workflow.en.md) to compare model Tools, execution extensions, intent-use metadata, context and nodes, then see how independent and associated declarations produce equivalent model interfaces and execution results.
6
8
 
7
9
  ## Start with these seven rules
8
10
 
@@ -29,7 +31,7 @@ Use Core services and common contracts from the root entry, integration helpers
29
31
  | --- | --- | --- |
30
32
  | 1 | [Common types and rules](types.md) | Identity, schema, validation, errors, context, collections, ownership |
31
33
  | | [Workflow primer](workflow.md) | Agent binding, nodes, routes, and derivation |
32
- | 2 | [Core](core.md) | Model calls, capabilities, tool execution, workflow, and events |
34
+ | 2 | [Core](core.md) | Model calls, tools, tool execution, workflow, and events |
33
35
  | 3 | [Support](support.md) | Schema, tool and capability catalogs, transport, and context assembly |
34
36
  | | [Context processing](context-processing.md) | Budget, watermarks, compression, and original-text protection |
35
37
  | 4 | [Knowledge, answering, and presentation](knowledge-answering.md) | Evidence gathering, checks, local repair, program-bound output |
@@ -4,6 +4,8 @@
4
4
 
5
5
  Core 定义运行接口和执行保证,Support 提供推荐实现与配置策略,Kit 提供 App 可选的业务能力。纯算法使用各自的输入输出合同。
6
6
 
7
+ 第一次接触这些配置时,先读[独立配置与关联配置:完整代码对照](configuration-in-workflow.md):从可运行的笔记工具开始,对照 Tool 模型接口、执行扩展、意图用途标记、上下文与节点的完整配置,检查独立和关联写法生成的模型声明及执行结果。
8
+
7
9
  ## 从这七条规律开始
8
10
 
9
11
  1. 实体用 `id`,指向实体用 `toolId`、`documentId` 等;`name` 是显示名。
@@ -0,0 +1,403 @@
1
+ # Independent and associated Tool configuration
2
+
3
+ A Tool is the model-facing interface. ExecutableTool adds authorization, execution and output validation. Tool adds one lifecycle block. Intent is Tool metadata, not an independently registered entity. The examples use public in-memory notes and an offline 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. Executable Tool declarations
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. Independent model and execution interfaces
93
+
94
+ [independent.mjs](../examples/registration/independent.mjs)
95
+
96
+ Model declarations propose `{ toolId, input }`; they do not execute business handlers.
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. One declaration supplies both interfaces
122
+
123
+ [associated.mjs](../examples/registration/associated.mjs)
124
+
125
+ The catalog derives names, descriptions, schemas and invocation mapping. This avoids re-declaring them. It does not skip authorization or execution validation.
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. Node, context, transport and execution
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. A name/input envelope reuses the same tools
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. Offline equivalence checks
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
+ ## Demand discovery and activation
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` accepts `true`, a description, a boolean predicate, or `{ description?, when?, delegates? }`. Omission excludes the tool from discovery; `active` defaults to true. Both selection methods filter activation. Discovery descriptions are view-local. Delegates are an optional allowed set, not a sequence; domain registries validate the vocabulary. No Intent IDs or cross-tool description aggregation are created.
382
+
383
+ ## Decorator configuration
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
+ Import decorators from `@jangts/agent-core/support/decorators`. `@WorkflowTool` supports classes and public instance methods, like `@WorkflowNode`. Use a separate `@Intent` on the same target; it alone registers nothing. Do not pass `asIntent` to the Tool decorator or its definition. Decorator order does not affect the association.
396
+
397
+ ## Run the example
398
+
399
+ ```sh
400
+ node packages/agent-core/development/docs/examples/registration/run.mjs
401
+ ```
402
+
403
+ The fixture checks wiring and contract equivalence, not language understanding or real-provider quality. Cafe preserves its grouped goal/next decision protocol; goal identifies a GoalTool. Banker projects current Tool candidates into its name/input protocol. Both use the same Core Tool contracts without forcing identical business workflows.