@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
@@ -6,7 +6,7 @@ exports.defineToolCatalog = defineToolCatalog;
6
6
  * Tool support: turn typed application tool definitions into a Core-schedulable tool catalog.
7
7
  *
8
8
  * A tool declaration pairs an input schema with authorization, execution and output parsing. The
9
- * catalog projects those tools into model capabilities and binds them to the Core tool registry
9
+ * catalog projects those tools into model tools and binds them to the Core tool registry
10
10
  * when a runtime request supplies the application. Support only assembles the registration; Core
11
11
  * still performs authorization, invocation, budgets and cancellation.
12
12
  *
@@ -17,6 +17,7 @@ const tool_runtime_js_1 = require("./tool-runtime.js");
17
17
  const schema_js_1 = require("./schema.js");
18
18
  const catalog_js_1 = require("../utils/catalog.js");
19
19
  const synchronous_js_1 = require("../utils/synchronous.js");
20
+ const tool_conditions_js_1 = require("../capabilities/tool-conditions.js");
20
21
  /**
21
22
  * Validate one tool declaration and freeze a detached copy of it.
22
23
  *
@@ -39,11 +40,24 @@ function defineTool(definition) {
39
40
  throw new TypeError('Missing tool handler');
40
41
  const inputSchema = (0, schema_js_1.defineSchema)(definition.inputSchema);
41
42
  const authorize = definition.authorize.bind(definition);
43
+ if (definition.active !== undefined &&
44
+ typeof definition.active !== 'boolean' &&
45
+ typeof definition.active !== 'function')
46
+ throw new TypeError('Invalid tool active condition');
47
+ const active = typeof definition.active === 'function'
48
+ ? definition.active.bind(definition)
49
+ : definition.active;
50
+ const asIntent = (0, tool_conditions_js_1.bindIntent)((0, tool_conditions_js_1.snapshotIntent)(typeof definition.asIntent === 'function'
51
+ ? definition.asIntent.bind(definition)
52
+ : definition.asIntent), definition);
42
53
  return Object.freeze({
43
54
  id,
44
55
  kind,
45
56
  description,
46
57
  inputSchema,
58
+ active,
59
+ asIntent,
60
+ resolve: definition.resolve?.bind(definition) ?? ((input) => ({ toolId: id, input })),
47
61
  authorize(input, context) {
48
62
  return (0, synchronous_js_1.maybeAssertion)(authorize(input, context), 'Authorization must return void; rejection must throw');
49
63
  },
@@ -52,22 +66,14 @@ function defineTool(definition) {
52
66
  parseOutput: definition.parseOutput.bind(definition),
53
67
  });
54
68
  }
55
- /**
56
- * Compile tool declarations into a frozen catalog with model capabilities and runtime binding.
57
- *
58
- * Each tool becomes a model capability whose resolver returns `{ toolId, input }`; the model only
59
- * chooses among registered tools, it never invokes them directly.
60
- *
61
- * @param definitions Tool declarations in catalog order.
62
- * @returns A frozen catalog with `capabilities`, `select` and `bind`.
63
- * @throws {TypeError} When a tool declaration is invalid or a tool ID is duplicated.
64
- */
65
69
  function defineToolCatalog(definitions) {
66
70
  const entries = definitions.map((definition) => defineTool(definition));
67
71
  const view = (0, catalog_js_1.readonlyCatalog)(entries, (id) => new TypeError(`Unknown tool: ${id}`));
68
- const capabilities = new model_js_1.ModelCapabilityRegistry(entries.map((tool) => ({
72
+ const tools = new model_js_1.ModelToolRegistry(entries.map((tool) => ({
69
73
  id: tool.id,
70
74
  description: tool.description,
75
+ active: tool.active,
76
+ asIntent: tool.asIntent,
71
77
  inputSchema: (0, schema_js_1.defineSchema)({
72
78
  jsonSchema: tool.inputSchema.jsonSchema,
73
79
  parse: (input) => input,
@@ -76,7 +82,7 @@ function defineToolCatalog(definitions) {
76
82
  }))).seal();
77
83
  return Object.freeze({
78
84
  ...view,
79
- capabilities,
85
+ tools,
80
86
  /**
81
87
  * Narrow the catalog to the given tool IDs, preserving their declaration order.
82
88
  *
@@ -84,9 +90,28 @@ function defineToolCatalog(definitions) {
84
90
  * @returns A new catalog containing only the selected tools.
85
91
  * @throws {TypeError} When an ID is not registered in this catalog.
86
92
  */
87
- select(ids) {
88
- capabilities.select(ids);
89
- return defineToolCatalog(ids.map((id) => view.require(id)));
93
+ select(ids, ...context) {
94
+ const seen = new Set();
95
+ const selected = ids
96
+ .map((id) => {
97
+ if (seen.has(id))
98
+ throw new TypeError(`Duplicate tool selection: ${id}`);
99
+ seen.add(id);
100
+ if (!view.has(id))
101
+ throw new TypeError(`Tool is not registered: ${id}`);
102
+ return view.require(id);
103
+ })
104
+ .filter((tool) => !context.length || (0, tool_conditions_js_1.toolActive)(tool.active, context[0]));
105
+ return defineToolCatalog(selected);
106
+ },
107
+ /** Discover demand-facing executable tools while preserving their execution contracts. */
108
+ withIntent(context) {
109
+ return defineToolCatalog(entries.flatMap((tool) => {
110
+ if (!(0, tool_conditions_js_1.toolActive)(tool.active, context))
111
+ return [];
112
+ const description = (0, tool_conditions_js_1.intentDescription)(tool.asIntent, tool.description, context);
113
+ return description === undefined ? [] : [{ ...tool, description }];
114
+ }));
90
115
  },
91
116
  /**
92
117
  * Bind the catalog to one application runtime request.
@@ -103,7 +128,7 @@ function defineToolCatalog(definitions) {
103
128
  errors: request.errors,
104
129
  });
105
130
  return Object.freeze({
106
- capabilities,
131
+ tools,
107
132
  get events() {
108
133
  return registry.events;
109
134
  },
@@ -1,22 +1,17 @@
1
1
  /**
2
- * Capability registration surface: model capabilities, executable tools and host-selected
2
+ * Capability registration surface: model tools, executable tools and host-selected
3
3
  * invocations.
4
4
  *
5
- * These registries hold declarations only. Which capabilities a stage may use, whether a
5
+ * These registries hold declarations only. Which tools a stage may use, whether a
6
6
  * call is authorized, and what a payload means remain App decisions; this barrel provides
7
- * the mechanisms that validate, seal and execute those declarations.
7
+ * the mechanisms that validate, seal and execute those declarations. Optional Kit helpers
8
+ * such as interaction protocols and commands are imported from their own `/kits/*` entries.
8
9
  *
9
10
  * Exports: the model capability registry (`model`), the executable tool registry and its
10
11
  * sync/async invocation entry points (`tools`), host-selected invocation execution
11
- * (`invocation`), and the Interaction Kit's protocol, command and handler definitions that
12
- * shape and validate model-produced interactions.
12
+ * (`invocation`) and the shared protocol registry.
13
13
  */
14
14
  export * from './model.js';
15
15
  export * from './tools.js';
16
16
  export * from './invocation.js';
17
17
  export * from '../utils/protocol-registry.js';
18
- export { defineCommand, commandSchema } from '../kits/interaction/command.js';
19
- export type { Command, CommandDefinition, ProtocolCheck, ProtocolField, ProtocolReason, ProtocolPredicate, ProtocolShape, RegisteredProtocol, } from '../structs/kits/interaction.js';
20
- export * from '../kits/interaction/commands.js';
21
- export * from '../kits/interaction/transfer.js';
22
- export * from '../kits/interaction/handlers.js';
@@ -1,21 +1,17 @@
1
1
  /**
2
- * Capability registration surface: model capabilities, executable tools and host-selected
2
+ * Capability registration surface: model tools, executable tools and host-selected
3
3
  * invocations.
4
4
  *
5
- * These registries hold declarations only. Which capabilities a stage may use, whether a
5
+ * These registries hold declarations only. Which tools a stage may use, whether a
6
6
  * call is authorized, and what a payload means remain App decisions; this barrel provides
7
- * the mechanisms that validate, seal and execute those declarations.
7
+ * the mechanisms that validate, seal and execute those declarations. Optional Kit helpers
8
+ * such as interaction protocols and commands are imported from their own `/kits/*` entries.
8
9
  *
9
10
  * Exports: the model capability registry (`model`), the executable tool registry and its
10
11
  * sync/async invocation entry points (`tools`), host-selected invocation execution
11
- * (`invocation`), and the Interaction Kit's protocol, command and handler definitions that
12
- * shape and validate model-produced interactions.
12
+ * (`invocation`) and the shared protocol registry.
13
13
  */
14
14
  export * from './model.js';
15
15
  export * from './tools.js';
16
16
  export * from './invocation.js';
17
17
  export * from '../utils/protocol-registry.js';
18
- export { defineCommand, commandSchema } from '../kits/interaction/command.js';
19
- export * from '../kits/interaction/commands.js';
20
- export * from '../kits/interaction/transfer.js';
21
- export * from '../kits/interaction/handlers.js';
@@ -1,7 +1,7 @@
1
- import type { ModelCapabilityRegistration, RegisteredModelCapability, ModelSelection } from '../structs/capabilities/model.js';
1
+ import type { ModelToolRegistration, RegisteredModelTool, ModelSelection } from '../structs/capabilities/model.js';
2
2
  export { modelProtocolError } from '../utils/model-protocol.js';
3
3
  /** A request/stage projection is a sealed registry. Hosts filter availability before projection. */
4
- export declare class ModelCapabilityRegistry {
4
+ export declare class ModelToolRegistry {
5
5
  /** Insertion-ordered entries; iteration order is the declaration order of the catalog. */
6
6
  private readonly definitionsById;
7
7
  /** Sealing is one-way: stage-time code must never extend the catalog it is executing. */
@@ -11,7 +11,7 @@ export declare class ModelCapabilityRegistry {
11
11
  * @throws TypeError when a definition is invalid or its id is duplicated (raised by
12
12
  * `register`).
13
13
  */
14
- constructor(definitions?: Iterable<ModelCapabilityRegistration>);
14
+ constructor(definitions?: Iterable<ModelToolRegistration>);
15
15
  /**
16
16
  * Register one capability.
17
17
  *
@@ -21,28 +21,28 @@ export declare class ModelCapabilityRegistry {
21
21
  * @throws Error when the registry is already sealed.
22
22
  * @throws TypeError when the declaration is invalid or its id is already registered.
23
23
  */
24
- register<Result>(capability: ModelCapabilityRegistration<Result>): this;
24
+ register<Result>(capability: ModelToolRegistration<Result>): this;
25
25
  /** Frozen snapshot of the registered definitions, in insertion order. */
26
- get definitions(): readonly Readonly<RegisteredModelCapability>[];
26
+ get definitions(): readonly Readonly<RegisteredModelTool>[];
27
27
  /** Registered ids in declaration order. */
28
28
  ids(): readonly string[];
29
29
  /** Live iterator over `[id, definition]` pairs; it reflects only entries added before sealing. */
30
- entries(): IterableIterator<readonly [string, RegisteredModelCapability]>;
30
+ entries(): IterableIterator<readonly [string, RegisteredModelTool]>;
31
31
  /**
32
- * Register several capabilities.
32
+ * Register several tools.
33
33
  *
34
34
  * @param definitions Declarations applied in iteration order.
35
35
  * @returns This registry, for chaining.
36
36
  * @throws Error or TypeError under the same conditions as `register`.
37
37
  */
38
- registerAll(definitions: Iterable<ModelCapabilityRegistration>): this;
38
+ registerAll(definitions: Iterable<ModelToolRegistration>): this;
39
39
  /**
40
40
  * @param id Capability id.
41
41
  * @returns The registered definition.
42
42
  * @throws TypeError when the id is not registered, which usually means a stage projection
43
43
  * omitted it.
44
44
  */
45
- require(id: string): RegisteredModelCapability;
45
+ require(id: string): RegisteredModelTool;
46
46
  /**
47
47
  * @param id Capability id.
48
48
  * @returns Whether the id is registered in this registry.
@@ -52,9 +52,9 @@ export declare class ModelCapabilityRegistry {
52
52
  * @param id Capability id.
53
53
  * @returns The registered definition, or undefined when absent.
54
54
  */
55
- get(id: string): RegisteredModelCapability | undefined;
55
+ get(id: string): RegisteredModelTool | undefined;
56
56
  /** Live iterator over the registered definitions. */
57
- values(): IterableIterator<RegisteredModelCapability>;
57
+ values(): IterableIterator<RegisteredModelTool>;
58
58
  /**
59
59
  * Close the registry to further registration.
60
60
  *
@@ -72,7 +72,11 @@ export declare class ModelCapabilityRegistry {
72
72
  * @throws TypeError when the selection is empty or contains a duplicate id.
73
73
  * @throws Error when an id was never registered.
74
74
  */
75
- select(ids: readonly string[]): ModelCapabilityRegistry;
75
+ select(ids: readonly string[], context?: unknown): ModelToolRegistry;
76
+ /** Discover active demand-facing tools without tying the projection to a workflow entry. */
77
+ withIntent(context: unknown): ModelToolRegistry;
78
+ /** Pin the host context and recheck activation before accepting a model proposal. */
79
+ private bound;
76
80
  /**
77
81
  * Parse model-supplied arguments and run the selected capability.
78
82
  *
@@ -87,4 +91,4 @@ export declare class ModelCapabilityRegistry {
87
91
  stageId: string;
88
92
  }>): unknown;
89
93
  }
90
- export type { ModelCapability, ModelCapabilityRegistration, RegisteredModelCapability, ModelSelection, ModelCapabilitySource, ModelCapabilityCatalog, } from '../structs/capabilities/model.js';
94
+ export type { AsIntent, IntentOptions, ToolCondition, ToolContext, ToolProposal, ModelTool, ModelToolRegistration, RegisteredModelTool, ModelSelection, ModelToolSource, ModelToolCatalog, } from '../structs/capabilities/model.js';
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Declarative catalog of model capabilities for a request or one stage projection.
2
+ * Declarative catalog of model tools for a request or one stage projection.
3
3
  *
4
4
  * A capability pairs an id and description with an input schema and a synchronous resolver,
5
5
  * letting stage code parse model-supplied arguments and produce a typed value. Registration
@@ -9,14 +9,15 @@
9
9
  * The registry is mutable until `seal()`. `select()` derives a sealed subset for a stage and
10
10
  * shares the already-frozen entries rather than re-validating or re-wrapping them.
11
11
  *
12
- * Exports: `ModelCapabilityRegistry`, `modelProtocolError`, and the capability types.
12
+ * Exports: `ModelToolRegistry`, `modelProtocolError`, and the capability types.
13
13
  */
14
14
  import { synchronous } from '../utils/synchronous.js';
15
15
  import { modelProtocolError } from '../utils/model-protocol.js';
16
16
  import { snapshotSchemaAdapter } from '../utils/schema-adapter.js';
17
+ import { snapshotIntent, toolActive, intentDescription, bindIntent } from './tool-conditions.js';
17
18
  export { modelProtocolError } from '../utils/model-protocol.js';
18
19
  /** A request/stage projection is a sealed registry. Hosts filter availability before projection. */
19
- export class ModelCapabilityRegistry {
20
+ export class ModelToolRegistry {
20
21
  /** Insertion-ordered entries; iteration order is the declaration order of the catalog. */
21
22
  definitionsById = new Map();
22
23
  /** Sealing is one-way: stage-time code must never extend the catalog it is executing. */
@@ -47,13 +48,22 @@ export class ModelCapabilityRegistry {
47
48
  if (!capability.id?.trim() ||
48
49
  !capability.description?.trim() ||
49
50
  schema?.type !== 'object' ||
50
- typeof capability.resolve !== 'function' ||
51
+ (capability.resolve !== undefined && typeof capability.resolve !== 'function') ||
52
+ (capability.active !== undefined &&
53
+ typeof capability.active !== 'function' &&
54
+ typeof capability.active !== 'boolean') ||
51
55
  this.definitionsById.has(capability.id))
52
56
  throw new TypeError('Invalid or duplicate model capability');
53
57
  // Clone and freeze the schema, and pin `parse`, so the stored entry is independent of
54
58
  // the definition object the host may keep mutating.
55
59
  const inputSchema = snapshotSchemaAdapter(capability.inputSchema, 'Model input parsers must be synchronous');
56
- const resolver = capability.resolve.bind(capability);
60
+ const resolver = capability.resolve?.bind(capability) ?? ((value) => value);
61
+ const asIntent = bindIntent(snapshotIntent(typeof capability.asIntent === 'function'
62
+ ? capability.asIntent.bind(capability)
63
+ : capability.asIntent), capability);
64
+ const active = typeof capability.active === 'function'
65
+ ? capability.active.bind(capability)
66
+ : capability.active;
57
67
  // Bind once here: a later caller cannot substitute its own receiver for the resolver.
58
68
  const resolve = (value, context) => synchronous(resolver(value, context), 'Model capability resolvers must be synchronous');
59
69
  this.definitionsById.set(capability.id, Object.freeze({
@@ -61,6 +71,8 @@ export class ModelCapabilityRegistry {
61
71
  description: capability.description,
62
72
  inputSchema,
63
73
  resolve,
74
+ ...(asIntent !== undefined ? { asIntent } : {}),
75
+ ...(active !== undefined ? { active } : {}),
64
76
  }));
65
77
  return this;
66
78
  }
@@ -77,7 +89,7 @@ export class ModelCapabilityRegistry {
77
89
  return this.definitionsById.entries();
78
90
  }
79
91
  /**
80
- * Register several capabilities.
92
+ * Register several tools.
81
93
  *
82
94
  * @param definitions Declarations applied in iteration order.
83
95
  * @returns This registry, for chaining.
@@ -138,21 +150,53 @@ export class ModelCapabilityRegistry {
138
150
  * @throws TypeError when the selection is empty or contains a duplicate id.
139
151
  * @throws Error when an id was never registered.
140
152
  */
141
- select(ids) {
153
+ select(ids, context) {
142
154
  if (!ids.length || new Set(ids).size !== ids.length)
143
155
  throw new TypeError('Invalid capability selection');
144
- const selected = new ModelCapabilityRegistry();
156
+ const selected = new ModelToolRegistry();
145
157
  for (const id of ids) {
146
158
  const capability = this.definitionsById.get(id);
147
159
  if (!capability)
148
160
  throw new Error(`Model capability is not registered: ${id}`);
161
+ if (arguments.length > 1) {
162
+ if (!toolActive(capability.active, context))
163
+ continue;
164
+ }
165
+ else if (capability.active === false) {
166
+ // Boolean activation is evaluable without a host context; predicate activation still
167
+ // needs an explicit context projection.
168
+ continue;
169
+ }
149
170
  // Registration already detached/froze the schema and pinned its handlers.
150
171
  // Stage projections share those immutable entries, not another clone and
151
172
  // another layer of parser/resolver wrappers for every selection.
152
- selected.definitionsById.set(id, capability);
173
+ selected.definitionsById.set(id, arguments.length > 1 ? this.bound(capability, context) : capability);
153
174
  }
154
175
  return selected.seal();
155
176
  }
177
+ /** Discover active demand-facing tools without tying the projection to a workflow entry. */
178
+ withIntent(context) {
179
+ const selected = new ModelToolRegistry();
180
+ for (const tool of this.definitionsById.values()) {
181
+ if (!toolActive(tool.active, context))
182
+ continue;
183
+ const description = intentDescription(tool.asIntent, tool.description, context);
184
+ if (description !== undefined)
185
+ selected.definitionsById.set(tool.id, Object.freeze({ ...this.bound(tool, context), description }));
186
+ }
187
+ return selected.seal();
188
+ }
189
+ /** Pin the host context and recheck activation before accepting a model proposal. */
190
+ bound(tool, context) {
191
+ return Object.freeze({
192
+ ...tool,
193
+ resolve: (input, stage) => {
194
+ if (!toolActive(tool.active, context))
195
+ modelProtocolError('Tool is inactive');
196
+ return tool.resolve(input, stage);
197
+ },
198
+ });
199
+ }
156
200
  /**
157
201
  * Parse model-supplied arguments and run the selected capability.
158
202
  *
@@ -167,7 +211,7 @@ export class ModelCapabilityRegistry {
167
211
  const { stageId } = context;
168
212
  // Model output is untrusted: unknown ids and non-object arguments are protocol failures,
169
213
  // not ordinary `undefined` results.
170
- const capability = this.definitionsById.get(selection.capabilityId) ??
214
+ const capability = this.definitionsById.get(selection.toolId) ??
171
215
  modelProtocolError('Model capability is unavailable in this stage');
172
216
  if (!selection.input || typeof selection.input !== 'object' || Array.isArray(selection.input))
173
217
  modelProtocolError('Model capability input must be an object');
@@ -0,0 +1,9 @@
1
+ import type { AsIntent, ToolCondition } from '../structs/capabilities/model.js';
2
+ /** Validate and snapshot discovery metadata without evaluating host predicates. */
3
+ export declare function snapshotIntent<Context>(value: AsIntent<Context> | undefined): AsIntent<Context> | undefined;
4
+ /** Bind an optional object-form predicate to its owning Tool, without touching other forms. */
5
+ export declare function bindIntent<Context>(value: AsIntent<Context> | undefined, owner: unknown): AsIntent<Context> | undefined;
6
+ /** Check activation and reject asynchronous or nonboolean predicate results. */
7
+ export declare function toolActive<Context>(condition: ToolCondition<Context> | undefined, context: Context): boolean;
8
+ /** Resolve the demand-facing description only when discovery is enabled. */
9
+ export declare function intentDescription<Context>(metadata: AsIntent<Context> | undefined, fallback: string, context: Context): string | undefined;
@@ -0,0 +1,59 @@
1
+ /** Tool metadata validation and synchronous activation shared by registration and execution. */
2
+ import { booleanResult } from '../utils/synchronous.js';
3
+ /** Validate and snapshot discovery metadata without evaluating host predicates. */
4
+ export function snapshotIntent(value) {
5
+ if (value === undefined || value === true || typeof value === 'function')
6
+ return value;
7
+ if (typeof value === 'string') {
8
+ if (!value.trim())
9
+ throw new TypeError('Intent description must not be blank');
10
+ return value;
11
+ }
12
+ if (!value || typeof value !== 'object' || Array.isArray(value))
13
+ throw new TypeError('Invalid asIntent metadata');
14
+ if (value.description !== undefined &&
15
+ (typeof value.description !== 'string' || !value.description.trim()))
16
+ throw new TypeError('Invalid intent description');
17
+ if (value.when !== undefined && typeof value.when !== 'function')
18
+ throw new TypeError('Invalid intent predicate');
19
+ const delegates = value.delegates;
20
+ if (delegates !== undefined &&
21
+ (!Array.isArray(delegates) ||
22
+ !delegates.length ||
23
+ delegates.some((id) => typeof id !== 'string' || !id.trim()) ||
24
+ new Set(delegates).size !== delegates.length))
25
+ throw new TypeError('Invalid intent delegates');
26
+ return Object.freeze({
27
+ description: value.description,
28
+ ...(value.when !== undefined ? { when: value.when } : {}),
29
+ ...(delegates ? { delegates: Object.freeze([...delegates]) } : {}),
30
+ });
31
+ }
32
+ /** Bind an optional object-form predicate to its owning Tool, without touching other forms. */
33
+ export function bindIntent(value, owner) {
34
+ if (!value || typeof value !== 'object' || typeof value.when !== 'function')
35
+ return value;
36
+ return Object.freeze({ ...value, when: value.when.bind(owner) });
37
+ }
38
+ /** Check activation and reject asynchronous or nonboolean predicate results. */
39
+ export function toolActive(condition, context) {
40
+ if (condition === undefined)
41
+ return true;
42
+ if (typeof condition === 'boolean')
43
+ return condition;
44
+ if (typeof condition !== 'function')
45
+ throw new TypeError('Invalid tool active condition');
46
+ return booleanResult(condition(context), 'Tool predicates must be synchronous', 'Tool predicates must return boolean');
47
+ }
48
+ /** Resolve the demand-facing description only when discovery is enabled. */
49
+ export function intentDescription(metadata, fallback, context) {
50
+ if (metadata === undefined)
51
+ return undefined;
52
+ if (typeof metadata === 'string')
53
+ return metadata;
54
+ if (metadata === true)
55
+ return fallback;
56
+ if (typeof metadata === 'function')
57
+ return toolActive(metadata, context) ? fallback : undefined;
58
+ return toolActive(metadata.when, context) ? (metadata.description ?? fallback) : undefined;
59
+ }
@@ -3,13 +3,14 @@
3
3
  *
4
4
  * A `ToolDefinition` is the App-facing declaration: a schema adapter plus authorize, execute
5
5
  * and parseOutput handlers. This module pins those handlers to their definition and adapts
6
- * them to the lower-level `ExecutableTool` contract, while keeping the synchronous and
6
+ * them to the lower-level `ErasedTool` contract, while keeping the synchronous and
7
7
  * asynchronous boundaries explicit: `invokeAsync` awaits authorization and execution,
8
8
  * `invoke` rejects a promise from either.
9
9
  *
10
10
  * Exports: `createToolRegistry`.
11
11
  */
12
12
  import { assertion, synchronous, isPromiseLike } from '../utils/synchronous.js';
13
+ import { toolActive } from './tool-conditions.js';
13
14
  import { ToolRegistry } from './tools.js';
14
15
  /**
15
16
  * Run authorization and execution for one call, in that order.
@@ -18,9 +19,11 @@ import { ToolRegistry } from './tools.js';
18
19
  * violation instead of being silently ignored. Cancellation is checked before and after each
19
20
  * phase so an aborted request never produces a successful value.
20
21
  */
21
- function execute(definition, input, context, execution) {
22
+ function execute(definition, input, context, execution, unavailable) {
22
23
  const { signal, mode, diagnostics, report, createSubFlowLogger } = execution;
23
24
  signal.throwIfAborted();
25
+ if (!toolActive(definition.active, context))
26
+ throw unavailable?.(definition.id) ?? new Error(`Tool is inactive: ${definition.id}`);
24
27
  // Re-check after the handler returned: work that completed during cancellation must not be
25
28
  // reported as a success.
26
29
  const complete = (value) => {
@@ -65,6 +68,7 @@ function execute(definition, input, context, execution) {
65
68
  */
66
69
  export function createToolRegistry(definitions, context, options) {
67
70
  const registry = new ToolRegistry(options);
71
+ const unavailable = options.errors?.unavailable?.bind(options.errors);
68
72
  registry.registerAll(definitions.map((definition) => {
69
73
  // Every entry point pins the same canonical handlers, including callers
70
74
  // that use this creator directly rather than defineToolCatalog.
@@ -74,6 +78,9 @@ export function createToolRegistry(definitions, context, options) {
74
78
  kind,
75
79
  description,
76
80
  inputSchema,
81
+ active: typeof definition.active === 'function'
82
+ ? definition.active.bind(definition)
83
+ : definition.active,
77
84
  authorize: authorize.bind(definition),
78
85
  execute: handle.bind(definition),
79
86
  parseOutput: parseOutput.bind(definition),
@@ -87,7 +94,7 @@ export function createToolRegistry(definitions, context, options) {
87
94
  // definition cannot change what this registry validates.
88
95
  parseInput: inputSchema.parse.bind(inputSchema),
89
96
  parseOutput: bound.parseOutput,
90
- execute: (input, execution) => execute(bound, input, context, execution),
97
+ execute: (input, execution) => execute(bound, input, context, execution, unavailable),
91
98
  };
92
99
  }));
93
100
  registry.seal();
@@ -1,10 +1,10 @@
1
1
  import type { ToolResult } from '../structs/invocation.js';
2
- import type { ExecutableTool, RegisteredTool, ToolExecutionEvent, ToolRegistryPorts, ToolRegistryOptions, ToolInvocationRequest } from '../structs/capabilities/tools.js';
2
+ import type { ErasedTool, RegisteredTool, ToolExecutionEvent, ToolRegistryPorts, ToolRegistryOptions, ToolInvocationRequest } from '../structs/capabilities/tools.js';
3
3
  /**
4
4
  * Registry mechanism only: visibility, authorization policy, schemas and semantic metadata
5
5
  * are host registrations. A registry is mutable until sealed and keeps its own call log.
6
6
  */
7
- export declare class ToolRegistry<Tool extends ExecutableTool = ExecutableTool> {
7
+ export declare class ToolRegistry<Tool extends ErasedTool = ErasedTool> {
8
8
  /** Insertion order is the declaration order and is preserved by every enumeration below. */
9
9
  private readonly tools;
10
10
  /** Sealing is one-way: a running stage must not add tools to the registry it executes. */
@@ -117,6 +117,6 @@ export declare class ToolRegistry<Tool extends ExecutableTool = ExecutableTool>
117
117
  */
118
118
  seal(): this;
119
119
  }
120
- export type { ToolDefinition, ToolExecutionContext, ExecutableTool, RegisteredTool, ToolExecutionEvent, ToolRegistryPorts, ToolRegistryOptions, ToolInvocationRequest, } from '../structs/capabilities/tools.js';
120
+ export type { ToolDefinition, ToolExecutionContext, ErasedTool, RegisteredTool, ToolExecutionEvent, ToolRegistryPorts, ToolRegistryOptions, ToolInvocationRequest, } from '../structs/capabilities/tools.js';
121
121
  export { executeInvocation } from './invocation.js';
122
122
  export type { InvocationHandler, ToolInvocationPorts, ToolJournal, } from '../structs/capabilities/invocation.js';
@@ -32,13 +32,10 @@ export function auditContextChange(original, current, mutable) {
32
32
  const changed = JSON.stringify(before.value) !== JSON.stringify(after.value);
33
33
  breakWhile(changed &&
34
34
  (!mutable.has(before.id) || before.role === 'system' || before.trust === 'instruction'), fail(`Protected context changed: ${before.id}`));
35
- if (changed &&
36
- before.value !== null &&
37
- after.value !== null &&
38
- typeof before.value === 'object' &&
39
- typeof after.value === 'object')
40
- // Only the field set is compared here; field order is not meaningful for context data.
41
- breakWhile(JSON.stringify(Object.keys(before.value).sort()) !==
42
- JSON.stringify(Object.keys(after.value).sort()), fail('Context fields must be preserved'));
35
+ if (changed && typeof before.value === 'object' && typeof after.value === 'object')
36
+ // A null value carries no fields. Treat it as an empty field set so turning it into an
37
+ // object, or dropping an object back to null, is still rejected as a structural change.
38
+ breakWhile(JSON.stringify(Object.keys(before.value ?? {}).sort()) !==
39
+ JSON.stringify(Object.keys(after.value ?? {}).sort()), fail('Context fields must be preserved'));
43
40
  }
44
41
  }
@@ -5,14 +5,13 @@
5
5
  * Core owns the guarantees here. A fragment declares its trust, lifetime and character
6
6
  * budget in one place; assembly validates those declarations and refuses to truncate;
7
7
  * auditing rejects structural change to protected fragments. Selection, ordering, compression
8
- * and model choice remain App-side nodes that run before this boundary.
8
+ * and model choice remain App-side nodes that run before this boundary. Optional Kit helpers
9
+ * such as evidence checks are imported from their own `/kits/*` entries, not from here.
9
10
  *
10
- * Exports: `assembleFragments`, `assembleContextPlan`, `ContextJournal`, the fragment helpers,
11
- * and the evidence Kit helpers consumed alongside assembled context.
11
+ * Exports: `assembleFragments`, `assembleContextPlan`, `ContextJournal` and the fragment helpers.
12
12
  */
13
13
  export * from './fragments.js';
14
14
  export { assembleFragments } from './assembly.js';
15
15
  export * from './journal.js';
16
- export * from '../kits/evidence.js';
17
16
  export type { ContextPlan } from '../structs/context/processing.js';
18
17
  export { assembleContextPlan } from './plan.js';
@@ -5,13 +5,12 @@
5
5
  * Core owns the guarantees here. A fragment declares its trust, lifetime and character
6
6
  * budget in one place; assembly validates those declarations and refuses to truncate;
7
7
  * auditing rejects structural change to protected fragments. Selection, ordering, compression
8
- * and model choice remain App-side nodes that run before this boundary.
8
+ * and model choice remain App-side nodes that run before this boundary. Optional Kit helpers
9
+ * such as evidence checks are imported from their own `/kits/*` entries, not from here.
9
10
  *
10
- * Exports: `assembleFragments`, `assembleContextPlan`, `ContextJournal`, the fragment helpers,
11
- * and the evidence Kit helpers consumed alongside assembled context.
11
+ * Exports: `assembleFragments`, `assembleContextPlan`, `ContextJournal` and the fragment helpers.
12
12
  */
13
13
  export * from './fragments.js';
14
14
  export { assembleFragments } from './assembly.js';
15
15
  export * from './journal.js';
16
- export * from '../kits/evidence.js';
17
16
  export { assembleContextPlan } from './plan.js';