@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
@@ -0,0 +1,105 @@
1
+ /**
2
+ * Presentation Kit: template-bound reply formats and their shared checks.
3
+ *
4
+ * Place in the package: part of the `presentation` Kit. A format is declared only where the App
5
+ * owns a template for the final reply; `resolve` returns `undefined` for every other reply, so the
6
+ * caller has no output-format requirement and does not re-ask the model. Apps keep their own copy,
7
+ * limits and checks; this module only compiles the declarations and evaluates failures.
8
+ *
9
+ * Exports: `defineReplyFormats`, `replyFormatChecks`, `mergeReplyBubbles`, and their types.
10
+ */
11
+ import { breakWhile } from '../../utils/rules.js';
12
+ const validId = (id) => typeof id === 'string' && /^[a-z][a-z0-9-]*$/.test(id);
13
+ /**
14
+ * Checks shared by text replies. Limits stay with the App template; only the comparison lives here.
15
+ */
16
+ export const replyFormatChecks = Object.freeze({
17
+ /**
18
+ * Every bubble is non-empty and the total (primary text included) stays within the limit.
19
+ *
20
+ * @param totalLimit - Maximum bubble count including the primary text.
21
+ * @returns The reusable `bubbles` check.
22
+ */
23
+ bubbles(totalLimit) {
24
+ breakWhile(!Number.isSafeInteger(totalLimit) || totalLimit < 1, 'Bubble limit must be a positive integer');
25
+ return Object.freeze({
26
+ id: 'bubbles',
27
+ description: `回复气泡总数不超过 ${totalLimit} 条且每条非空。`,
28
+ accepts: (bubbles) => bubbles.length >= 1 &&
29
+ bubbles.length <= totalLimit &&
30
+ bubbles.every((text) => typeof text === 'string' && !!text.trim()),
31
+ });
32
+ },
33
+ /**
34
+ * The joined reply stays within the app's text budget.
35
+ *
36
+ * @param maxChars - Maximum total characters across bubbles.
37
+ * @returns The reusable `text-budget` check.
38
+ */
39
+ textBudget(maxChars) {
40
+ breakWhile(!Number.isSafeInteger(maxChars) || maxChars < 1, 'Text budget must be a positive integer');
41
+ return Object.freeze({
42
+ id: 'text-budget',
43
+ description: `回复正文总长不超过 ${maxChars} 字符。`,
44
+ accepts: (bubbles) => bubbles.reduce((length, text) => length + (typeof text === 'string' ? text.length : 0), 0) <= maxChars,
45
+ });
46
+ },
47
+ });
48
+ /**
49
+ * Normalize a reply that has no declared format: drop blank bubbles and merge overflow into the
50
+ * last allowed one. Text content is preserved.
51
+ *
52
+ * @param bubbles - Primary text followed by follow-up bubbles.
53
+ * @param limit - Maximum number of bubbles to keep.
54
+ * @returns Non-empty bubbles within the limit.
55
+ */
56
+ export function mergeReplyBubbles(bubbles, limit) {
57
+ breakWhile(!Number.isSafeInteger(limit) || limit < 1, 'Bubble limit must be a positive integer');
58
+ const kept = bubbles.map((text) => text.trim()).filter(Boolean);
59
+ // 超出部分按原顺序合并到最后一条允许的气泡,不改变正文内容。
60
+ if (kept.length > limit)
61
+ kept.push(kept.splice(limit - 1).join('\n\n'));
62
+ return kept;
63
+ }
64
+ /**
65
+ * Compile reply formats so that checks run only for templates the current turn uses.
66
+ *
67
+ * @param options - Declared formats and the checks their ids refer to.
68
+ * @returns A frozen catalog with `resolve(context)`.
69
+ * @throws TypeError For duplicate or invalid ids, a format without checks, an unknown check id,
70
+ * or a non-function `when`/`accepts`.
71
+ */
72
+ export function defineReplyFormats(options) {
73
+ const { formats, checks } = options;
74
+ breakWhile(!formats?.length || !checks?.length, 'Reply formats require formats and checks');
75
+ const checkMap = new Map();
76
+ for (const check of checks) {
77
+ breakWhile(!validId(check.id) || checkMap.has(check.id) || typeof check.accepts !== 'function', 'Invalid reply format check');
78
+ checkMap.set(check.id, Object.freeze({ ...check, accepts: check.accepts.bind(check) }));
79
+ }
80
+ const seen = new Set();
81
+ const compiled = formats.map((format) => {
82
+ breakWhile(!validId(format.id) ||
83
+ seen.has(format.id) ||
84
+ typeof format.when !== 'function' ||
85
+ !format.checks?.length ||
86
+ format.checks.some((id) => !checkMap.has(id)), 'Invalid reply format');
87
+ seen.add(format.id);
88
+ const required = Object.freeze([...format.checks]);
89
+ return Object.freeze({
90
+ id: format.id,
91
+ description: format.description,
92
+ checks: required,
93
+ when: format.when,
94
+ inspect(bubbles) {
95
+ return required.map((id) => checkMap.get(id)).filter((check) => !check.accepts(bubbles));
96
+ },
97
+ });
98
+ });
99
+ return Object.freeze({
100
+ /** The template this turn uses, or `undefined` when it has no output-format requirement. */
101
+ resolve(context) {
102
+ return compiled.find((format) => format.when(context));
103
+ },
104
+ });
105
+ }
@@ -1,26 +1,35 @@
1
1
  /**
2
- * Presentation Kit entry: output contracts, text templates, semantic slots, variants and the
3
- * reply/chunk event stream.
2
+ * Presentation Kit entry: output contracts, text templates, semantic slots, reply formats,
3
+ * variants and the reply/chunk event stream.
4
4
  *
5
5
  * Place in the package: an optional App-side library for shaping what the user finally sees.
6
6
  * The App owns copy, styling and transport; this directory owns contract validation, template
7
- * substitution, variant selection and the bubble/chunk protocol.
7
+ * substitution, format checks, variant selection and the bubble/chunk protocol.
8
8
  *
9
- * Exports: everything from `./outputs.js`, `./variants.js`, `./templates.js` and `./events.js`,
10
- * plus the `Presentation` namespace object.
9
+ * Exports: everything from `./outputs.js`, `./formats.js`, `./variants.js`, `./templates.js` and
10
+ * `./events.js`, plus the `Presentation` namespace object.
11
11
  */
12
12
  export * from './outputs.js';
13
+ export * from './formats.js';
13
14
  export * from './variants.js';
14
15
  export type * from '../../structs/kits/presentation/outputs.js';
16
+ export type * from '../../structs/kits/presentation/formats.js';
15
17
  export * from './templates.js';
16
18
  export * from './events.js';
17
19
  import { defineOutputCatalog } from './outputs.js';
20
+ import { defineReplyFormats, mergeReplyBubbles } from './formats.js';
18
21
  import { defineTextTemplate, defineSemanticSlots } from './templates.js';
19
22
  import { selectVariant, resolvePreference } from './variants.js';
20
23
  import { replyBubbleTexts, publishReplyEvents, serializeOutputEvents, textOutputEvents } from './events.js';
21
24
  /** Namespace object for callers that prefer one import over named helpers. */
22
25
  export declare const Presentation: Readonly<{
23
26
  defineOutputCatalog: typeof defineOutputCatalog;
27
+ defineReplyFormats: typeof defineReplyFormats;
28
+ replyFormatChecks: Readonly<{
29
+ bubbles(totalLimit: number): import("./formats.js").ReplyFormatCheck;
30
+ textBudget(maxChars: number): import("./formats.js").ReplyFormatCheck;
31
+ }>;
32
+ mergeReplyBubbles: typeof mergeReplyBubbles;
24
33
  defineTextTemplate: typeof defineTextTemplate;
25
34
  defineSemanticSlots: typeof defineSemanticSlots;
26
35
  selectVariant: typeof selectVariant;
@@ -1,25 +1,30 @@
1
1
  /**
2
- * Presentation Kit entry: output contracts, text templates, semantic slots, variants and the
3
- * reply/chunk event stream.
2
+ * Presentation Kit entry: output contracts, text templates, semantic slots, reply formats,
3
+ * variants and the reply/chunk event stream.
4
4
  *
5
5
  * Place in the package: an optional App-side library for shaping what the user finally sees.
6
6
  * The App owns copy, styling and transport; this directory owns contract validation, template
7
- * substitution, variant selection and the bubble/chunk protocol.
7
+ * substitution, format checks, variant selection and the bubble/chunk protocol.
8
8
  *
9
- * Exports: everything from `./outputs.js`, `./variants.js`, `./templates.js` and `./events.js`,
10
- * plus the `Presentation` namespace object.
9
+ * Exports: everything from `./outputs.js`, `./formats.js`, `./variants.js`, `./templates.js` and
10
+ * `./events.js`, plus the `Presentation` namespace object.
11
11
  */
12
12
  export * from './outputs.js';
13
+ export * from './formats.js';
13
14
  export * from './variants.js';
14
15
  export * from './templates.js';
15
16
  export * from './events.js';
16
17
  import { defineOutputCatalog } from './outputs.js';
18
+ import { defineReplyFormats, mergeReplyBubbles, replyFormatChecks } from './formats.js';
17
19
  import { defineTextTemplate, defineSemanticSlots } from './templates.js';
18
20
  import { selectVariant, resolvePreference } from './variants.js';
19
21
  import { REPLY_BUBBLE_BOUNDARY, replyBubbleTexts, publishReplyEvents, serializeOutputEvents, textOutputEvents, } from './events.js';
20
22
  /** Namespace object for callers that prefer one import over named helpers. */
21
23
  export const Presentation = Object.freeze({
22
24
  defineOutputCatalog,
25
+ defineReplyFormats,
26
+ replyFormatChecks,
27
+ mergeReplyBubbles,
23
28
  defineTextTemplate,
24
29
  defineSemanticSlots,
25
30
  selectVariant,
@@ -11,7 +11,7 @@
11
11
  */
12
12
  import { AgentCoreEngine } from '../execution/engine.js';
13
13
  import { defineToolCatalog } from '../support/tools.js';
14
- import { defineModelCapabilities } from '../support/model/capabilities.js';
14
+ import { defineModelTools } from '../support/model/capabilities.js';
15
15
  import { createModelTransport } from '../model/selection-transport.js';
16
16
  import { jsonObjectInteraction } from '../model/interactions/json-object.js';
17
17
  import { coreEventCatalog } from '../diagnostics/catalog.js';
@@ -225,7 +225,7 @@ export function defineReflection(definition) {
225
225
  ...extraTools,
226
226
  ];
227
227
  const catalog = defineToolCatalog(toolDefinitions);
228
- const capabilities = defineModelCapabilities([
228
+ const modelTools = defineModelTools([
229
229
  ...catalog.definitions.map((tool) => ({
230
230
  id: tool.id,
231
231
  description: tool.description,
@@ -244,7 +244,7 @@ export function defineReflection(definition) {
244
244
  ]);
245
245
  const transport = createModelTransport({
246
246
  id: 'core:reflection',
247
- capabilities,
247
+ tools: modelTools,
248
248
  adapter: jsonObjectInteraction,
249
249
  });
250
250
  const child = model.createChild({
@@ -0,0 +1,24 @@
1
+ import type { TextBlock, TextBlockOptions } from '../structs/kits/text-blocks.js';
2
+ /**
3
+ * Split long plain text on structural boundaries.
4
+ *
5
+ * Headings and horizontal rules start a new block, blank lines end the current one, and all
6
+ * other lines break only when the target size would be exceeded. A single line longer than
7
+ * the target becomes its own block so that paging can cut it into fragments later without
8
+ * splitting the line into unrelated sections. Concatenating every block reproduces the input
9
+ * exactly: no truncation, padding or dropped whitespace.
10
+ *
11
+ * The input must be plain text; binaries and rich documents are read elsewhere.
12
+ *
13
+ * @param text - Decoded source text.
14
+ * @param options - Target block size in characters.
15
+ * @returns Blocks in source order, each with one-based `number` and source offsets. Empty
16
+ * text returns an empty list.
17
+ * @throws TypeError When the text is not a string or `targetChars` is not a positive integer.
18
+ */
19
+ export declare function splitTextBlocks(text: string, options: TextBlockOptions): TextBlock[];
20
+ /** Namespace form of the Kit, for callers that prefer one aggregate entry. */
21
+ export declare const TextBlocks: {
22
+ readonly split: typeof splitTextBlocks;
23
+ };
24
+ export type { TextBlock, TextBlockOptions } from '../structs/kits/text-blocks.js';
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Text Blocks Kit: structure-aware splitting for long plain text.
3
+ *
4
+ * Place in the package: an optional App-side helper used before a long document is paged
5
+ * into a model or indexed for retrieval. The Kit owns boundary selection, block numbering
6
+ * and exact reassembly; file reading, paging, search, storage and prompt wording stay with
7
+ * the App. No model call or Core dependency is involved.
8
+ *
9
+ * Exports: `splitTextBlocks`, `TextBlocks` and the block option/result types.
10
+ */
11
+ import { breakWhile } from '../utils/rules.js';
12
+ /**
13
+ * Whether one line starts a new structural section.
14
+ *
15
+ * @param line - A full line including its trailing newline.
16
+ * @returns `true` for Markdown headings and horizontal rules.
17
+ */
18
+ function headingLine(line) {
19
+ return /^\s*#{1,6}\s/.test(line) || /^\s*(?:[-*_]{3,}|={3,})\s*$/.test(line);
20
+ }
21
+ /**
22
+ * Split long plain text on structural boundaries.
23
+ *
24
+ * Headings and horizontal rules start a new block, blank lines end the current one, and all
25
+ * other lines break only when the target size would be exceeded. A single line longer than
26
+ * the target becomes its own block so that paging can cut it into fragments later without
27
+ * splitting the line into unrelated sections. Concatenating every block reproduces the input
28
+ * exactly: no truncation, padding or dropped whitespace.
29
+ *
30
+ * The input must be plain text; binaries and rich documents are read elsewhere.
31
+ *
32
+ * @param text - Decoded source text.
33
+ * @param options - Target block size in characters.
34
+ * @returns Blocks in source order, each with one-based `number` and source offsets. Empty
35
+ * text returns an empty list.
36
+ * @throws TypeError When the text is not a string or `targetChars` is not a positive integer.
37
+ */
38
+ export function splitTextBlocks(text, options) {
39
+ breakWhile(typeof text !== 'string' ||
40
+ !options ||
41
+ !Number.isSafeInteger(options.targetChars) ||
42
+ options.targetChars < 1, 'Text block splitting requires text and a positive integer target size');
43
+ const targetChars = options.targetChars;
44
+ const blocks = [];
45
+ let buffer = '';
46
+ let bufferStart = 0;
47
+ let cursor = 0;
48
+ const flush = () => {
49
+ if (!buffer)
50
+ return;
51
+ const previous = blocks.at(-1);
52
+ if (!buffer.trim() && previous) {
53
+ // Whitespace-only blocks carry no section, so they stay attached to the previous block
54
+ // instead of becoming a block the reader has to page through.
55
+ blocks[blocks.length - 1] = {
56
+ ...previous,
57
+ text: previous.text + buffer,
58
+ end: previous.end + buffer.length,
59
+ };
60
+ }
61
+ else {
62
+ blocks.push({ number: blocks.length + 1, text: buffer, start: bufferStart, end: cursor });
63
+ }
64
+ buffer = '';
65
+ };
66
+ // Keeping a line's trailing newline makes every block reassemble into the original text,
67
+ // including CRLF input.
68
+ for (const line of text.match(/[^\n]*\n|[^\n]+$/g) ?? []) {
69
+ if (line.length > targetChars) {
70
+ flush();
71
+ blocks.push({
72
+ number: blocks.length + 1,
73
+ text: line,
74
+ start: cursor,
75
+ end: cursor + line.length,
76
+ });
77
+ cursor += line.length;
78
+ continue;
79
+ }
80
+ if (headingLine(line))
81
+ flush();
82
+ if (buffer.length + line.length > targetChars)
83
+ flush();
84
+ if (!buffer)
85
+ bufferStart = cursor;
86
+ buffer += line;
87
+ cursor += line.length;
88
+ if ((!line.trim() || headingLine(line)) && buffer.length >= targetChars / 2)
89
+ flush();
90
+ else if (buffer.length >= targetChars)
91
+ flush();
92
+ }
93
+ flush();
94
+ return blocks;
95
+ }
96
+ /** Namespace form of the Kit, for callers that prefer one aggregate entry. */
97
+ export const TextBlocks = { split: splitTextBlocks };
@@ -1,25 +1,27 @@
1
1
  import type { ToolInvocationRequest } from '../structs/capabilities/tools.js';
2
2
  import type { ToolResult } from '../structs/invocation.js';
3
- import type { ToolRuntimeTypes, LifecycleTool, RegisteredLifecycleTool, ToolLifecycleOptions, ToolNormalizer, ToolFinalizer, ToolProtocol } from '../structs/kits/tools.js';
3
+ import type { ToolRuntimeTypes, Tool, ToolRegistration, RegisteredToolDefinition, ToolsOptions, ToolNormalizer, ToolFinalizer, ToolProtocol } from '../structs/kits/tools.js';
4
4
  import type { ToolRegistryPorts } from '../structs/capabilities/tools.js';
5
5
  import { ProtocolRegistry } from '../utils/protocol-registry.js';
6
6
  /**
7
- * Registered lifecycle and delivery hooks. Domain predicates and phase names are host
8
- * configuration.
7
+ * Registered lifecycle hooks. Domain predicates and phase names are host configuration.
9
8
  */
10
- type PreparedTool<Types extends ToolRuntimeTypes, Tool extends LifecycleTool<Types>> = RegisteredLifecycleTool<Types, Tool> & LifecycleTool<Types>;
9
+ type PreparedTool<Types extends ToolRuntimeTypes, Declaration extends ToolRegistration<Types>> = RegisteredToolDefinition<Types, Declaration> & Tool<Types>;
11
10
  /**
12
- * Registry of tools whose lifecycle, protocols and contributions are declared by the App.
11
+ * Registry of tools whose lifecycle, protocols and context contributions the App declares.
13
12
  *
14
13
  * Registration is only possible before `seal()`; afterwards the catalog is read-only, so a run
15
- * cannot change which tools exist. Every contribution hook is optional and is applied in
16
- * registration order, which is why `registerAll` preserves iteration order.
14
+ * cannot change which tools exist. Every hook is optional and is applied in registration order,
15
+ * which is why `registerAll` preserves iteration order.
17
16
  */
18
- export declare class ToolLifecycleRegistry<Types extends ToolRuntimeTypes, Tool extends LifecycleTool<Types> = LifecycleTool<Types>> {
17
+ export declare class ToolLifecycleRegistry<Types extends ToolRuntimeTypes, Declaration extends ToolRegistration<Types> = ToolRegistration<Types>> {
19
18
  private readonly tools;
20
19
  private readonly registered;
21
20
  private readonly sources;
21
+ /** Tools that own an invocation id; dispatch by decision next reads this index. */
22
22
  private readonly invocations;
23
+ /** Tools that answer a delegate id; dispatch by node reads this index. */
24
+ private readonly delegateIndex;
23
25
  private normalizer?;
24
26
  private finalizer?;
25
27
  private sealed;
@@ -30,11 +32,11 @@ export declare class ToolLifecycleRegistry<Types extends ToolRuntimeTypes, Tool
30
32
  /**
31
33
  * @param options - Receiver, execution context, error wording, registration policy, protocol
32
34
  * providers and optional journal/receipt ports; contract methods are bound to their owner.
33
- * @throws TypeError When no `intentIds` provider is supplied.
35
+ * @throws TypeError When no `goalIds` provider is supplied.
34
36
  */
35
- constructor(options: ToolLifecycleOptions<Types, Tool>);
37
+ constructor(options: ToolsOptions<Types, Declaration>);
36
38
  /** Core tool events, forwarded unchanged. */
37
- get events(): readonly Readonly<import("../index.js").ToolExecutionEvent<PreparedTool<Types, Tool>["kind"]>>[];
39
+ get events(): readonly Readonly<import("../index.js").ToolExecutionEvent<PreparedTool<Types, Declaration>["kind"]>>[];
38
40
  /** Swap the diagnostics sink for later invocations; the Core registry is updated as well. */
39
41
  setDiagnostics(value: ToolRegistryPorts['diagnostics']): void;
40
42
  /**
@@ -44,16 +46,19 @@ export declare class ToolLifecycleRegistry<Types extends ToolRuntimeTypes, Tool
44
46
  * hooks must return `void` synchronously, while the remaining handlers are checked for
45
47
  * accidental thenables only.
46
48
  *
47
- * @param input - Tool definition with identity, audience, effect and its handlers.
49
+ * @param input - Tool definition with identity, audience, effect and its hooks.
48
50
  * @returns This registry, for chaining.
49
51
  * @throws A configured registration error for a sealed registry, invalid identity,
50
- * description, audience, effect, intent ids, missing handlers, duplicate tool id,
51
- * incomplete invocation contract, protocol version mismatch or duplicate invocation step.
52
+ * description, audience, effect, goal ids, missing handlers, duplicate tool id,
53
+ * duplicate delegate id, incomplete lifecycle contract, protocol version mismatch or
54
+ * duplicate invocation id.
52
55
  */
53
- register(input: Tool): this;
56
+ register(input: Declaration): this;
57
+ /** Validate one declaration in the fixed order documented by `register`. */
58
+ private assertRegistration;
54
59
  private install;
55
60
  /** Register every tool in iteration order. */
56
- registerAll(tools: Iterable<Tool>): this;
61
+ registerAll(tools: Iterable<Declaration>): this;
57
62
  /**
58
63
  * Invoke one Core tool by its already-validated request.
59
64
  *
@@ -62,23 +67,25 @@ export declare class ToolLifecycleRegistry<Types extends ToolRuntimeTypes, Tool
62
67
  */
63
68
  invoke(request: ToolInvocationRequest): ToolResult<unknown>;
64
69
  /** Registered tools in registration order. */
65
- get definitions(): readonly RegisteredLifecycleTool<Types, Tool>[];
70
+ get definitions(): readonly RegisteredToolDefinition<Types, Declaration>[];
66
71
  /** Registered tool ids, delegated to the Core registry. */
67
72
  ids(): readonly string[];
68
73
  /** Iterate `[id, tool]` pairs. */
69
- entries(): IterableIterator<[string, RegisteredLifecycleTool<Types, Tool>]>;
74
+ entries(): IterableIterator<[string, RegisteredToolDefinition<Types, Declaration>]>;
70
75
  /** Registered tool for `id`, or `undefined` when it is absent. */
71
- get(id: string): RegisteredLifecycleTool<Types, Tool> | undefined;
76
+ get(id: string): RegisteredToolDefinition<Types, Declaration> | undefined;
72
77
  /**
73
78
  * Registered tool for `id`.
74
79
  *
75
80
  * @throws TypeError When the id is not registered.
76
81
  */
77
- require(id: string): RegisteredLifecycleTool<Types, Tool>;
82
+ require(id: string): RegisteredToolDefinition<Types, Declaration>;
78
83
  /** Whether a tool id is registered. */
79
84
  has(name: string): boolean;
80
85
  /** Iterate the registered tools. */
81
- values(): IterableIterator<RegisteredLifecycleTool<Types, Tool>>;
86
+ values(): IterableIterator<RegisteredToolDefinition<Types, Declaration>>;
87
+ /** Whether a delegate id is claimed by a registered tool. */
88
+ hasDelegate(id: string): boolean;
82
89
  /**
83
90
  * Install the single normalization handler.
84
91
  *
@@ -101,30 +108,40 @@ export declare class ToolLifecycleRegistry<Types extends ToolRuntimeTypes, Tool
101
108
  */
102
109
  finish(receiver: Types['receiver'], decision: Types['decision'], context: Types['context']): Types['result'];
103
110
  /**
104
- * Execute the invocation registered for a step type.
111
+ * Run the invocation that answers one decision next.
112
+ *
113
+ * Delegation is the App's choice; this method only executes the tool that claimed the id, so a
114
+ * purely programmatic node, a model choice and a mixed pipeline all dispatch the same way.
105
115
  *
106
116
  * Diagnostics are swapped to the invocation's own sink for the duration of the call and
107
117
  * restored afterwards, so nested tool calls report under the innermost scope.
108
118
  *
109
- * @param step - Step carrying the registered `type`.
119
+ * @param next - Decision next carrying the claimed delegate id in `type`.
110
120
  * @param context - Execution context forwarded to Core's invocation executor.
111
- * @throws A configured error when the step is unknown or the tool is unavailable.
121
+ * @throws A configured error when the delegate is unknown or the tool is unavailable.
112
122
  */
113
- call(step: {
123
+ call(next: {
114
124
  type: string;
115
125
  }, context: Types['context']): void;
116
- /** Output protocols plus one protocol per registered invocation step. */
117
- protocols(): ProtocolRegistry<ToolProtocol<Tool>>;
126
+ /** Output protocols plus one protocol per registered invocation. */
127
+ protocols(): ProtocolRegistry<ToolProtocol<Declaration>>;
118
128
  /**
119
- * Protocols exposed to the model: output protocols plus steps whose audience is `model` and
129
+ * Protocols exposed to the model: output protocols plus invocations whose audience is `model` and
120
130
  * which are currently available in `context`.
121
131
  */
122
- modelProtocols(context: Types['context']): ProtocolRegistry<ToolProtocol<Tool>>;
123
- /** Whether the protocol registered for this step is declared terminal. */
124
- isTerminal(step: {
132
+ modelProtocols(context: Types['context']): ProtocolRegistry<ToolProtocol<Declaration>>;
133
+ /** Whether the protocol registered for this invocation is declared terminal. */
134
+ isTerminal(next: {
125
135
  type: string;
126
136
  }): boolean;
127
- /** Run contribution inspection for every tool, then the selected invocation's own check. */
137
+ /** `[invocationId, protocol]` pairs, optionally filtered by the owning tool. */
138
+ private invocationProtocols;
139
+ /**
140
+ * Run `inspect` for every registered tool in registration order.
141
+ *
142
+ * `inspect` belongs to the all-tools group, so the selected tool participates exactly once
143
+ * through the same loop rather than through a second selected-only pass.
144
+ */
128
145
  assertDecision(decision: Types['decision'], context: Types['context']): void;
129
146
  /** Run the selected invocation's authorization hook, if any. */
130
147
  authorize(decision: Types['decision'], context: Types['context']): void;
@@ -132,33 +149,33 @@ export declare class ToolLifecycleRegistry<Types extends ToolRuntimeTypes, Tool
132
149
  resume(decision: Types['decision'], context: Types['context']): boolean;
133
150
  /** Let the selected invocation rewrite the decision on completion, if it declares a hook. */
134
151
  complete(decision: Types['decision'], context: Types['context']): Types['decision'] | undefined;
135
- /** Fold every contribution's context projection over the value, in registration order. */
152
+ /** Fold every tool's context projection over the value, in registration order. */
136
153
  projectContext(value: unknown): unknown;
137
- /** Fold every contribution's visible-text transform over the text. */
154
+ /** Fold every tool's visible-text transform over the text. */
138
155
  visibleText(text: string, context: Types['context']): string;
139
- /** Fold every contribution's review transform over the draft. */
156
+ /** Fold every tool's review transform over the draft. */
140
157
  reviewDraft(draft: unknown, context: Types['context']): unknown;
141
158
  /** Collected recovery context values; `undefined` results are omitted. */
142
159
  recoveryContext(context: Types['context']): unknown[];
143
160
  /**
144
161
  * The single output template that owns this delivery.
145
162
  *
146
- * @throws An error when more than one contribution claims composition, because delivery
147
- * would otherwise depend on registration order.
163
+ * @throws An error when more than one tool claims composition, because delivery would
164
+ * otherwise depend on registration order.
148
165
  */
149
166
  composition(context: Types['context']): Types['composition'] | undefined;
150
- /** Run every contribution's finalize hook for the given phase. */
167
+ /** Run every tool's finalize hook for the given phase. */
151
168
  finalize(decision: Types['decision'], context: Types['context'], phase: Types['phase']): void;
152
- /** Whether any contribution permits the interaction to be missing. */
169
+ /** Whether any tool permits the interaction to be missing. */
153
170
  missingInteractionAllowed(decision: Types['decision'], context: Types['context']): boolean;
154
171
  /** Task rules ordered by their declared `order`, joined into one prompt block. */
155
172
  taskRules(context: Types['context']): string;
156
173
  /** Model-context fragments for one placement, ordered by each field's `order`. */
157
174
  contextFields(context: Types['context'], placement: Types['placement']): import("../index.js").ContextFragment[];
158
175
  /** Merged model-context values for one placement; later fragments win per key. */
159
- modelFields(context: Types['context'], placement: Types['placement']): any;
160
- /** A contribution may veto an intent by returning `false`; silence means support. */
161
- supportsIntent(intentId: string, context: Types['context']): boolean;
176
+ modelFields(context: Types['context'], placement: Types['placement']): Record<string, unknown>;
177
+ /** A tool may veto a goal by returning `false`; silence means support. */
178
+ supportsGoal(intentId: string, context: Types['context']): boolean;
162
179
  /**
163
180
  * Describe registered tools, optionally limited by audience and availability.
164
181
  *
@@ -167,15 +184,15 @@ export declare class ToolLifecycleRegistry<Types extends ToolRuntimeTypes, Tool
167
184
  *
168
185
  * @param audience - Audience to keep; omit to include every audience.
169
186
  * @param context - Context for availability checks.
170
- * @returns Plain metadata; `intentIds: 'all'` is expanded to the current intent ids.
187
+ * @returns Plain metadata; `goalIds: 'all'` is expanded to the current goal ids.
171
188
  */
172
189
  describe(audience?: string, context?: Types['context']): {
173
- id: Tool['id'];
174
- kind: Tool['kind'];
175
- description: Tool['description'];
176
- audience: Tool['audience'];
177
- effect: Tool['effect'];
178
- intentIds: string[];
190
+ id: Declaration['id'];
191
+ kind: Declaration['kind'];
192
+ description: Declaration['description'];
193
+ audience: Declaration['audience'];
194
+ effect: Declaration['effect'];
195
+ goalIds: string[];
179
196
  }[];
180
197
  /**
181
198
  * Reinstall every registered tool, plus the finalizer and normalizer, into another registry.
@@ -183,12 +200,12 @@ export declare class ToolLifecycleRegistry<Types extends ToolRuntimeTypes, Tool
183
200
  * The original definitions are reused rather than the compiled views, so the target applies
184
201
  * its own policy checks and binding exactly as it would for a first registration.
185
202
  */
186
- copyTo(target: ToolLifecycleRegistry<Types, Tool>): void;
203
+ copyTo(target: ToolLifecycleRegistry<Types, Declaration>): void;
187
204
  /** Freeze the registry: no further registration, normalizer or finalizer is accepted. */
188
205
  seal(): this;
189
- /** Tool that owns the invocation step named by the decision, if any. */
206
+ /** Tool that owns the invocation id named by the decision, if any. */
190
207
  private selected;
191
208
  }
192
- export type { ToolRuntimeTypes, LifecycleTool, RegisteredLifecycleTool, ToolLifecycleOptions, Policy, ToolInvocation, ToolContribution, ToolModelField, ToolNormalizer, ToolFinalizer, ToolJournal, ToolProtocol, LifecycleProtocol, } from '../structs/kits/tools.js';
209
+ export type { ToolRuntimeTypes, Tool, ToolRegistration, RegisteredToolDefinition, ToolsOptions, Policy, LifecycleHooks, LifecycleProtocol, ToolModelField, ToolNormalizer, ToolFinalizer, ToolJournal, ToolProtocol, } from '../structs/kits/tools.js';
193
210
  /** The lifecycle registry is the public `Tools` Kit entry point. */
194
211
  export { ToolLifecycleRegistry as Tools };