@jangts/agent-core 0.3.5 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (288) hide show
  1. package/CHANGELOG.md +41 -0
  2. package/README.md +33 -31
  3. package/development/docs/README.en.md +2 -2
  4. package/development/docs/acceptance.en.md +2 -2
  5. package/development/docs/agent-development.en.md +1 -1
  6. package/development/docs/api/README.en.md +6 -2
  7. package/development/docs/api/README.md +4 -0
  8. package/development/docs/api/configuration-in-workflow.en.md +403 -0
  9. package/development/docs/api/configuration-in-workflow.md +403 -0
  10. package/development/docs/api/core.en.md +7 -7
  11. package/development/docs/api/core.md +6 -6
  12. package/development/docs/api/decorators.en.md +20 -0
  13. package/development/docs/api/decorators.md +20 -0
  14. package/development/docs/api/examples.en.md +1 -1
  15. package/development/docs/api/examples.md +1 -1
  16. package/development/docs/api/kits.en.md +22 -4
  17. package/development/docs/api/kits.md +22 -4
  18. package/development/docs/api/knowledge-answering.en.md +4 -1
  19. package/development/docs/api/knowledge-answering.md +4 -1
  20. package/development/docs/api/mock.en.md +2 -0
  21. package/development/docs/api/mock.md +2 -0
  22. package/development/docs/api/observability.en.md +37 -11
  23. package/development/docs/api/observability.md +64 -11
  24. package/development/docs/api/reference.en.md +876 -657
  25. package/development/docs/api/reference.md +662 -508
  26. package/development/docs/api/support.en.md +55 -9
  27. package/development/docs/api/support.md +53 -7
  28. package/development/docs/api/types.en.md +36 -1
  29. package/development/docs/api/types.md +44 -0
  30. package/development/docs/api/workflow-views.en.md +64 -0
  31. package/development/docs/api/workflow-views.md +78 -0
  32. package/development/docs/api/workflow.en.md +6 -2
  33. package/development/docs/api/workflow.md +6 -2
  34. package/development/docs/basic-usage.en.md +1 -1
  35. package/development/docs/basic-usage.md +1 -1
  36. package/development/docs/create-app.en.md +1 -1
  37. package/development/docs/examples/registration/associated.mjs +8 -0
  38. package/development/docs/examples/registration/independent.mjs +20 -0
  39. package/development/docs/examples/registration/protocol.mjs +48 -0
  40. package/development/docs/examples/registration/run.mjs +47 -0
  41. package/development/docs/examples/registration/tools.mjs +75 -0
  42. package/development/docs/examples/registration/workflow.mjs +109 -0
  43. package/development/docs/flows/knowledge-maintenance.en.md +1 -1
  44. package/development/docs/materials.en.md +1 -1
  45. package/development/docs/mechanisms.en.md +2 -2
  46. package/development/docs/mechanisms.md +1 -1
  47. package/development/docs/operations.en.md +1 -1
  48. package/development/docs/records.en.md +1 -1
  49. package/development/docs/registration.en.md +4 -4
  50. package/development/docs/registration.md +2 -2
  51. package/development/skills/agent-core-app/SKILL.md +16 -4
  52. package/development/skills/agent-core-app/templates/node-ts/README.md.tpl +1 -1
  53. package/development/skills/agent-core-app/templates/node-ts/src/catalog.ts.tpl +2 -2
  54. package/development/skills/agent-core-app/templates/node-ts/test/app.test.mjs.tpl +1 -1
  55. package/dist/cjs/capabilities/index.js +5 -12
  56. package/dist/cjs/capabilities/invocation.js +21 -1
  57. package/dist/cjs/capabilities/model.js +56 -12
  58. package/dist/cjs/capabilities/tool-conditions.js +65 -0
  59. package/dist/cjs/capabilities/tool-runtime.js +18 -4
  60. package/dist/cjs/capabilities/tools.js +12 -17
  61. package/dist/cjs/context/audit.js +5 -8
  62. package/dist/cjs/context/index.js +3 -4
  63. package/dist/cjs/diagnostics/index.js +51 -3
  64. package/dist/cjs/diagnostics/native-sub-flow.js +106 -0
  65. package/dist/cjs/diagnostics/sub-flow.js +278 -32
  66. package/dist/cjs/execution/engine.js +3 -2
  67. package/dist/cjs/execution/events.js +5 -5
  68. package/dist/cjs/execution/reporting.js +18 -28
  69. package/dist/cjs/execution/workflow-chain.js +211 -0
  70. package/dist/cjs/execution/workflow-graph.js +72 -0
  71. package/dist/cjs/execution/workflow.js +34 -6
  72. package/dist/cjs/index.js +21 -17
  73. package/dist/cjs/kits/aggregation.js +17 -14
  74. package/dist/cjs/kits/answering/checks.js +2 -1
  75. package/dist/cjs/kits/answering/flow.js +24 -21
  76. package/dist/cjs/kits/answering/tasks.js +30 -25
  77. package/dist/cjs/kits/delivery.js +36 -24
  78. package/dist/cjs/kits/domains/catalog.js +113 -0
  79. package/dist/cjs/kits/domains/index.js +20 -0
  80. package/dist/cjs/kits/{intents → domains}/registry.js +77 -31
  81. package/dist/cjs/kits/{intents → domains}/scopes.js +21 -21
  82. package/dist/cjs/kits/index.js +14 -13
  83. package/dist/cjs/kits/knowledge/catalog.js +33 -30
  84. package/dist/cjs/kits/policies.js +3 -2
  85. package/dist/cjs/kits/presentation/formats.js +110 -0
  86. package/dist/cjs/kits/presentation/index.js +10 -5
  87. package/dist/cjs/kits/presentation/outputs.js +2 -1
  88. package/dist/cjs/kits/reflection.js +2 -2
  89. package/dist/cjs/kits/retrieval.js +7 -1
  90. package/dist/cjs/kits/text-blocks.js +101 -0
  91. package/dist/cjs/kits/tools.js +247 -158
  92. package/dist/cjs/model/decision-retry.js +2 -1
  93. package/dist/cjs/model/index.js +2 -6
  94. package/dist/cjs/model/interactions/calls.js +61 -0
  95. package/dist/cjs/model/interactions/json-object.js +11 -11
  96. package/dist/cjs/model/interactions/native-functions.js +17 -23
  97. package/dist/cjs/model/message-diagnostics.js +13 -3
  98. package/dist/cjs/model/options.js +2 -0
  99. package/dist/cjs/model/preparation.js +39 -6
  100. package/dist/cjs/model/runner.js +34 -5
  101. package/dist/cjs/model/selection-transport.js +4 -4
  102. package/dist/cjs/model/token-budget.js +3 -0
  103. package/dist/cjs/model/transports.js +3 -2
  104. package/dist/cjs/structs/index.js +7 -6
  105. package/dist/cjs/structs/kits/domains/scopes.js +2 -0
  106. package/dist/cjs/structs/kits/presentation/formats.js +2 -0
  107. package/dist/cjs/structs/kits/text-blocks.js +11 -0
  108. package/dist/cjs/structs/model/session.js +11 -0
  109. package/dist/cjs/structs/support/associations.js +2 -0
  110. package/dist/cjs/support/associations.js +79 -0
  111. package/dist/cjs/support/context/nodes.js +48 -45
  112. package/dist/cjs/support/context/processing.js +6 -3
  113. package/dist/cjs/support/context/snapshot.js +11 -1
  114. package/dist/cjs/support/decorators/index.js +45 -3
  115. package/dist/cjs/support/index.js +1 -0
  116. package/dist/cjs/support/model/capabilities.js +35 -5
  117. package/dist/cjs/support/model/chat-completions.js +11 -2
  118. package/dist/cjs/support/model/completion/calls.js +10 -56
  119. package/dist/cjs/support/model/preview-rules.js +11 -11
  120. package/dist/cjs/support/model/reply-preview.js +3 -3
  121. package/dist/cjs/support/model/session.js +152 -0
  122. package/dist/cjs/support/model/stage-transport.js +8 -8
  123. package/dist/cjs/support/model/transports.js +5 -2
  124. package/dist/cjs/support/tools.js +42 -17
  125. package/dist/cjs/utils/invocation.js +1 -0
  126. package/dist/esm/capabilities/index.d.ts +5 -10
  127. package/dist/esm/capabilities/index.js +5 -9
  128. package/dist/esm/capabilities/invocation.js +21 -1
  129. package/dist/esm/capabilities/model.d.ts +17 -13
  130. package/dist/esm/capabilities/model.js +54 -10
  131. package/dist/esm/capabilities/tool-conditions.d.ts +9 -0
  132. package/dist/esm/capabilities/tool-conditions.js +59 -0
  133. package/dist/esm/capabilities/tool-runtime.js +18 -4
  134. package/dist/esm/capabilities/tools.d.ts +3 -3
  135. package/dist/esm/capabilities/tools.js +12 -17
  136. package/dist/esm/context/audit.js +5 -8
  137. package/dist/esm/context/index.d.ts +3 -4
  138. package/dist/esm/context/index.js +3 -4
  139. package/dist/esm/diagnostics/index.d.ts +1 -0
  140. package/dist/esm/diagnostics/index.js +48 -2
  141. package/dist/esm/diagnostics/native-sub-flow.d.ts +94 -0
  142. package/dist/esm/diagnostics/native-sub-flow.js +101 -0
  143. package/dist/esm/diagnostics/sub-flow.d.ts +56 -4
  144. package/dist/esm/diagnostics/sub-flow.js +271 -32
  145. package/dist/esm/execution/engine.d.ts +1 -0
  146. package/dist/esm/execution/engine.js +3 -2
  147. package/dist/esm/execution/events.js +5 -5
  148. package/dist/esm/execution/reporting.d.ts +6 -12
  149. package/dist/esm/execution/reporting.js +19 -29
  150. package/dist/esm/execution/workflow-chain.d.ts +3 -0
  151. package/dist/esm/execution/workflow-chain.js +208 -0
  152. package/dist/esm/execution/workflow-graph.d.ts +7 -0
  153. package/dist/esm/execution/workflow-graph.js +68 -0
  154. package/dist/esm/execution/workflow.d.ts +6 -0
  155. package/dist/esm/execution/workflow.js +34 -6
  156. package/dist/esm/index.d.ts +19 -13
  157. package/dist/esm/index.js +18 -15
  158. package/dist/esm/kits/aggregation.d.ts +1 -1
  159. package/dist/esm/kits/aggregation.js +17 -14
  160. package/dist/esm/kits/answering/checks.js +2 -1
  161. package/dist/esm/kits/answering/flow.js +24 -21
  162. package/dist/esm/kits/answering/tasks.d.ts +6 -6
  163. package/dist/esm/kits/answering/tasks.js +30 -25
  164. package/dist/esm/kits/delivery.d.ts +0 -9
  165. package/dist/esm/kits/delivery.js +36 -24
  166. package/dist/esm/kits/domains/catalog.d.ts +42 -0
  167. package/dist/esm/kits/domains/catalog.js +110 -0
  168. package/dist/esm/kits/domains/index.d.ts +4 -0
  169. package/dist/esm/kits/domains/index.js +4 -0
  170. package/dist/esm/kits/domains/registry.d.ts +100 -0
  171. package/dist/esm/kits/{intents → domains}/registry.js +77 -31
  172. package/dist/esm/kits/{intents → domains}/scopes.d.ts +18 -18
  173. package/dist/esm/kits/{intents → domains}/scopes.js +21 -21
  174. package/dist/esm/kits/index.d.ts +6 -5
  175. package/dist/esm/kits/index.js +6 -5
  176. package/dist/esm/kits/knowledge/catalog.js +33 -30
  177. package/dist/esm/kits/policies.d.ts +1 -1
  178. package/dist/esm/kits/policies.js +3 -2
  179. package/dist/esm/kits/presentation/formats.d.ts +42 -0
  180. package/dist/esm/kits/presentation/formats.js +105 -0
  181. package/dist/esm/kits/presentation/index.d.ts +14 -5
  182. package/dist/esm/kits/presentation/index.js +10 -5
  183. package/dist/esm/kits/presentation/outputs.js +2 -1
  184. package/dist/esm/kits/reflection.js +3 -3
  185. package/dist/esm/kits/retrieval.js +7 -1
  186. package/dist/esm/kits/text-blocks.d.ts +24 -0
  187. package/dist/esm/kits/text-blocks.js +97 -0
  188. package/dist/esm/kits/tools.d.ts +69 -52
  189. package/dist/esm/kits/tools.js +247 -158
  190. package/dist/esm/model/decision-retry.d.ts +2 -0
  191. package/dist/esm/model/decision-retry.js +2 -1
  192. package/dist/esm/model/index.d.ts +2 -6
  193. package/dist/esm/model/index.js +2 -6
  194. package/dist/esm/model/interactions/calls.d.ts +40 -0
  195. package/dist/esm/model/interactions/calls.js +58 -0
  196. package/dist/esm/model/interactions/json-object.js +11 -11
  197. package/dist/esm/model/interactions/native-functions.js +17 -23
  198. package/dist/esm/model/message-diagnostics.d.ts +6 -5
  199. package/dist/esm/model/message-diagnostics.js +13 -3
  200. package/dist/esm/model/options.js +2 -0
  201. package/dist/esm/model/preparation.js +39 -6
  202. package/dist/esm/model/runner.d.ts +2 -0
  203. package/dist/esm/model/runner.js +34 -5
  204. package/dist/esm/model/selection-transport.js +4 -4
  205. package/dist/esm/model/token-budget.js +3 -0
  206. package/dist/esm/model/transports.d.ts +2 -1
  207. package/dist/esm/model/transports.js +3 -2
  208. package/dist/esm/structs/capabilities/invocation.d.ts +3 -1
  209. package/dist/esm/structs/capabilities/model.d.ts +42 -11
  210. package/dist/esm/structs/capabilities/tools.d.ts +16 -7
  211. package/dist/esm/structs/common.d.ts +3 -1
  212. package/dist/esm/structs/debug.d.ts +36 -20
  213. package/dist/esm/structs/execution/workflow-views.d.ts +123 -0
  214. package/dist/esm/structs/execution/workflow.d.ts +4 -3
  215. package/dist/esm/structs/index.d.ts +8 -6
  216. package/dist/esm/structs/index.js +7 -6
  217. package/dist/esm/structs/kits/answering/tasks.d.ts +2 -2
  218. package/dist/esm/structs/kits/{intents → domains}/catalog.d.ts +20 -20
  219. package/dist/esm/structs/kits/{intents → domains}/registry.d.ts +24 -21
  220. package/dist/esm/structs/kits/{intents → domains}/scopes.d.ts +9 -9
  221. package/dist/esm/structs/kits/domains/scopes.js +1 -0
  222. package/dist/esm/structs/kits/presentation/formats.d.ts +42 -0
  223. package/dist/esm/structs/kits/presentation/formats.js +1 -0
  224. package/dist/esm/structs/kits/text-blocks.d.ts +25 -0
  225. package/dist/esm/structs/kits/text-blocks.js +10 -0
  226. package/dist/esm/structs/kits/tools.d.ts +82 -83
  227. package/dist/esm/structs/model/interactions.d.ts +18 -11
  228. package/dist/esm/structs/model/messages.d.ts +34 -2
  229. package/dist/esm/structs/model/runtime.d.ts +9 -0
  230. package/dist/esm/structs/model/session.d.ts +29 -0
  231. package/dist/esm/structs/model/session.js +10 -0
  232. package/dist/esm/structs/support/associations.d.ts +22 -0
  233. package/dist/esm/structs/support/associations.js +1 -0
  234. package/dist/esm/structs/support/model/interactions.d.ts +2 -2
  235. package/dist/esm/structs/support/model/messages.d.ts +6 -13
  236. package/dist/esm/structs/support/tools.d.ts +23 -23
  237. package/dist/esm/support/associations.d.ts +26 -0
  238. package/dist/esm/support/associations.js +76 -0
  239. package/dist/esm/support/context/nodes.js +48 -45
  240. package/dist/esm/support/context/processing.js +6 -3
  241. package/dist/esm/support/context/snapshot.js +11 -1
  242. package/dist/esm/support/decorators/index.d.ts +13 -2
  243. package/dist/esm/support/decorators/index.js +40 -3
  244. package/dist/esm/support/decorators/pool.d.ts +6 -5
  245. package/dist/esm/support/decorators/types.d.ts +3 -1
  246. package/dist/esm/support/index.d.ts +1 -0
  247. package/dist/esm/support/index.js +1 -0
  248. package/dist/esm/support/model/capabilities.d.ts +8 -3
  249. package/dist/esm/support/model/capabilities.js +35 -5
  250. package/dist/esm/support/model/chat-completions.js +11 -2
  251. package/dist/esm/support/model/completion/calls.d.ts +6 -34
  252. package/dist/esm/support/model/completion/calls.js +8 -55
  253. package/dist/esm/support/model/index.d.ts +1 -1
  254. package/dist/esm/support/model/preview-rules.d.ts +13 -8
  255. package/dist/esm/support/model/preview-rules.js +11 -11
  256. package/dist/esm/support/model/reply-preview.d.ts +2 -2
  257. package/dist/esm/support/model/reply-preview.js +3 -3
  258. package/dist/esm/support/model/session.d.ts +61 -0
  259. package/dist/esm/support/model/session.js +148 -0
  260. package/dist/esm/support/model/stage-transport.d.ts +1 -1
  261. package/dist/esm/support/model/stage-transport.js +9 -9
  262. package/dist/esm/support/model/transports.d.ts +2 -0
  263. package/dist/esm/support/model/transports.js +2 -1
  264. package/dist/esm/support/tools.d.ts +11 -3
  265. package/dist/esm/support/tools.js +43 -18
  266. package/dist/esm/utils/catalog.d.ts +1 -1
  267. package/dist/esm/utils/invocation.d.ts +1 -0
  268. package/dist/esm/utils/invocation.js +1 -0
  269. package/package.json +20 -6
  270. package/dist/cjs/execution/index.js +0 -30
  271. package/dist/cjs/kits/intents/catalog.js +0 -82
  272. package/dist/cjs/kits/intents/index.js +0 -35
  273. package/dist/cjs/utils/debug.js +0 -30
  274. package/dist/esm/execution/index.d.ts +0 -11
  275. package/dist/esm/execution/index.js +0 -11
  276. package/dist/esm/kits/intents/catalog.d.ts +0 -39
  277. package/dist/esm/kits/intents/catalog.js +0 -79
  278. package/dist/esm/kits/intents/index.d.ts +0 -22
  279. package/dist/esm/kits/intents/index.js +0 -18
  280. package/dist/esm/kits/intents/registry.d.ts +0 -88
  281. package/dist/esm/utils/debug.d.ts +0 -27
  282. package/dist/esm/utils/debug.js +0 -27
  283. /package/dist/cjs/structs/{kits/intents/catalog.js → execution/workflow-views.js} +0 -0
  284. /package/dist/cjs/structs/kits/{intents/registry.js → domains/catalog.js} +0 -0
  285. /package/dist/cjs/structs/kits/{intents/scopes.js → domains/registry.js} +0 -0
  286. /package/dist/esm/structs/{kits/intents/catalog.js → execution/workflow-views.js} +0 -0
  287. /package/dist/esm/structs/kits/{intents/registry.js → domains/catalog.js} +0 -0
  288. /package/dist/esm/structs/kits/{intents/scopes.js → domains/registry.js} +0 -0
@@ -7,6 +7,7 @@
7
7
  *
8
8
  * Exports: `definePolicySet`, `defineRecoveryChain`, `Policies`, and the policy types.
9
9
  */
10
+ import { nativeSubFlowSync } from '../diagnostics/native-sub-flow.js';
10
11
  import { readonlyCatalog } from '../utils/catalog.js';
11
12
  import { synchronous, booleanResult } from '../utils/synchronous.js';
12
13
  import { breakWhile } from '../utils/rules.js';
@@ -65,9 +66,9 @@ export function defineRecoveryChain(definitions) {
65
66
  },
66
67
  });
67
68
  });
68
- const tryRecover = (input) => {
69
+ const tryRecover = (input, execution = {}) => {
69
70
  for (const policy of catalog) {
70
- const result = policy.tryRecover(input);
71
+ const result = nativeSubFlowSync(execution, 'recovery', policy.id, () => policy.tryRecover(input));
71
72
  if (result.handled)
72
73
  return result;
73
74
  }
@@ -0,0 +1,42 @@
1
+ import type { CompiledReplyFormat, ReplyFormatCheck, ReplyFormatOptions } from '../../structs/kits/presentation/formats.js';
2
+ /**
3
+ * Checks shared by text replies. Limits stay with the App template; only the comparison lives here.
4
+ */
5
+ export declare const replyFormatChecks: Readonly<{
6
+ /**
7
+ * Every bubble is non-empty and the total (primary text included) stays within the limit.
8
+ *
9
+ * @param totalLimit - Maximum bubble count including the primary text.
10
+ * @returns The reusable `bubbles` check.
11
+ */
12
+ bubbles(totalLimit: number): ReplyFormatCheck;
13
+ /**
14
+ * The joined reply stays within the app's text budget.
15
+ *
16
+ * @param maxChars - Maximum total characters across bubbles.
17
+ * @returns The reusable `text-budget` check.
18
+ */
19
+ textBudget(maxChars: number): ReplyFormatCheck;
20
+ }>;
21
+ /**
22
+ * Normalize a reply that has no declared format: drop blank bubbles and merge overflow into the
23
+ * last allowed one. Text content is preserved.
24
+ *
25
+ * @param bubbles - Primary text followed by follow-up bubbles.
26
+ * @param limit - Maximum number of bubbles to keep.
27
+ * @returns Non-empty bubbles within the limit.
28
+ */
29
+ export declare function mergeReplyBubbles(bubbles: readonly string[], limit: number): string[];
30
+ /**
31
+ * Compile reply formats so that checks run only for templates the current turn uses.
32
+ *
33
+ * @param options - Declared formats and the checks their ids refer to.
34
+ * @returns A frozen catalog with `resolve(context)`.
35
+ * @throws TypeError For duplicate or invalid ids, a format without checks, an unknown check id,
36
+ * or a non-function `when`/`accepts`.
37
+ */
38
+ export declare function defineReplyFormats<Context = unknown>(options: ReplyFormatOptions<Context>): Readonly<{
39
+ /** The template this turn uses, or `undefined` when it has no output-format requirement. */
40
+ resolve(context: Context): CompiledReplyFormat | undefined;
41
+ }>;
42
+ export type { CompiledReplyFormat, ReplyFormatCheck, ReplyFormatDefinition, ReplyFormatOptions, } from '../../structs/kits/presentation/formats.js';
@@ -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,
@@ -7,6 +7,7 @@
7
7
  *
8
8
  * Exports: `defineOutputCatalog`, and the output definition/field/provider/result types.
9
9
  */
10
+ import { nativeSubFlowSync } from '../../diagnostics/native-sub-flow.js';
10
11
  import { snapshotSchemaAdapter } from '../../utils/schema-adapter.js';
11
12
  import { readonlyCatalog } from '../../utils/catalog.js';
12
13
  import { synchronous } from '../../utils/synchronous.js';
@@ -321,7 +322,7 @@ export function defineOutputCatalog(definitions, options = {}) {
321
322
  throw new TypeError('Use a named output request');
322
323
  if (!context?.signal)
323
324
  throw new TypeError('Output composition requires OperationContext');
324
- return composeInternal(request.outputId, request.input, context);
325
+ return nativeSubFlowSync(context, 'output', request.outputId, () => composeInternal(request.outputId, request.input, context));
325
326
  },
326
327
  });
327
328
  }
@@ -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({
@@ -8,6 +8,7 @@
8
8
  *
9
9
  * Exports: `defineRetrieval`, `retrievalQueryKey`, `Retrieval`, and the retrieval port types.
10
10
  */
11
+ import { nativeSubFlowSync } from '../diagnostics/native-sub-flow.js';
11
12
  import { assertion, synchronous } from '../utils/synchronous.js';
12
13
  import { retrievalQueryKey } from '../utils/query-key.js';
13
14
  import { breakWhile } from '../utils/rules.js';
@@ -144,7 +145,12 @@ export function defineRetrieval(definition) {
144
145
  }
145
146
  return receipt;
146
147
  }
147
- return Object.freeze({ id, description, effects, run });
148
+ return Object.freeze({
149
+ id,
150
+ description,
151
+ effects,
152
+ run: (input, context) => nativeSubFlowSync(context, 'retrieval', id, () => run(input, context)),
153
+ });
148
154
  }
149
155
  function reason(value, query, context) {
150
156
  return () => (typeof value === 'function' ? value(query, context) : value);
@@ -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 };