@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
@@ -35,7 +35,7 @@ class ScopeRegistry {
35
35
  ...(0, registration_js_1.registrationData)(policy, [
36
36
  'idPattern',
37
37
  'assertDefinition',
38
- 'acceptsIntent',
38
+ 'acceptsTool',
39
39
  'errors',
40
40
  ...listFields,
41
41
  ]),
@@ -47,7 +47,7 @@ class ScopeRegistry {
47
47
  invalid: typeof invalid === 'function' ? invalid.bind(errorPorts) : invalid,
48
48
  }),
49
49
  assertDefinition: policy.assertDefinition?.bind(policy),
50
- acceptsIntent: policy.acceptsIntent?.bind(policy),
50
+ acceptsTool: policy.acceptsTool?.bind(policy),
51
51
  });
52
52
  }
53
53
  /**
@@ -56,11 +56,11 @@ class ScopeRegistry {
56
56
  * Every name is checked for conflicts before any of them is stored, so a rejected scope
57
57
  * leaves no partial alias entry behind.
58
58
  *
59
- * @param input - Scope declaration; the raw object is retained for `acceptsIntent` overrides
59
+ * @param input - Scope declaration; the raw object is retained for `acceptsTool` overrides
60
60
  * while the compiled copy serves lookups.
61
61
  * @returns This registry, for chaining.
62
62
  * @throws A configured error for a sealed registry, an invalid name/description/category,
63
- * a missing required binding, duplicate intent ids or an already-claimed name.
63
+ * a missing required binding, duplicate Tool ids or an already-claimed name.
64
64
  */
65
65
  register(input) {
66
66
  const definition = {
@@ -68,7 +68,7 @@ class ScopeRegistry {
68
68
  'id',
69
69
  'description',
70
70
  'category',
71
- 'intentIds',
71
+ 'goalIds',
72
72
  'queryScopeIds',
73
73
  'knowledgeTopicIds',
74
74
  'toolIds',
@@ -79,7 +79,7 @@ class ScopeRegistry {
79
79
  id: input.id,
80
80
  description: input.description,
81
81
  category: input.category,
82
- intentIds: input.intentIds ?? [],
82
+ goalIds: input.goalIds ?? [],
83
83
  queryScopeIds: input.queryScopeIds ?? [],
84
84
  knowledgeTopicIds: input.knowledgeTopicIds ?? [],
85
85
  toolIds: input.toolIds ?? [],
@@ -114,9 +114,9 @@ class ScopeRegistry {
114
114
  tags: ['identity'],
115
115
  },
116
116
  {
117
- occur: () => policy.requireIntents === true && !definition.intentIds.length,
117
+ occur: () => policy.requireGoals === true && !definition.goalIds.length,
118
118
  error: invalid,
119
- tags: ['intents', 'required'],
119
+ tags: ['goals', 'required'],
120
120
  },
121
121
  {
122
122
  occur: [
@@ -130,18 +130,18 @@ class ScopeRegistry {
130
130
  },
131
131
  {
132
132
  occur: [
133
- () => definition.intentIds.some((intent) => typeof intent !== 'string'),
134
- () => new Set(definition.intentIds).size !== definition.intentIds.length,
133
+ () => definition.goalIds.some((intent) => typeof intent !== 'string'),
134
+ () => new Set(definition.goalIds).size !== definition.goalIds.length,
135
135
  ],
136
136
  error: invalid,
137
- tags: ['intents', 'values'],
137
+ tags: ['goals', 'values'],
138
138
  },
139
139
  ], tags);
140
140
  (0, synchronous_js_1.assertion)(policy.assertDefinition?.(input), 'Registry definition assertions must return void synchronously');
141
141
  (0, rules_js_1.breakWhile)(names.some((name) => this.byId.has(name) || this.aliases.has(name)), invalid, [...tags, 'duplicate']);
142
142
  const frozen = Object.freeze({
143
143
  ...definition,
144
- intentIds: Object.freeze([...definition.intentIds]),
144
+ goalIds: Object.freeze([...definition.goalIds]),
145
145
  toolIds: Object.freeze([...definition.toolIds]),
146
146
  queryScopeIds: Object.freeze([...definition.queryScopeIds]),
147
147
  knowledgeTopicIds: Object.freeze([...definition.knowledgeTopicIds]),
@@ -207,16 +207,16 @@ class ScopeRegistry {
207
207
  /**
208
208
  * Whether a scope accepts an intent.
209
209
  *
210
- * The App may override the declared `intentIds` through `acceptsIntent`; without an
210
+ * The App may override the declared `goalIds` through `acceptsTool`; without an
211
211
  * override the membership check applies.
212
212
  */
213
- acceptsIntent(scope, goal) {
213
+ acceptsTool(scope, goal) {
214
214
  const definition = this.get(scope);
215
215
  if (!definition)
216
216
  return false;
217
- const ids = definition.intentIds;
218
- return this.policy.acceptsIntent
219
- ? (0, synchronous_js_1.booleanResult)(this.policy.acceptsIntent(this.sources.get(this.normalize(scope)), goal), 'Scope intent predicates must return boolean synchronously')
217
+ const ids = definition.goalIds;
218
+ return this.policy.acceptsTool
219
+ ? (0, synchronous_js_1.booleanResult)(this.policy.acceptsTool(this.sources.get(this.normalize(scope)), goal), 'Scope intent predicates must return boolean synchronously')
220
220
  : ids.includes(goal);
221
221
  }
222
222
  /** Whether the scope declares this query scope; a null scope accepts nothing. */
@@ -245,18 +245,18 @@ class ScopeRegistry {
245
245
  return this.get(scope)?.contextTier;
246
246
  }
247
247
  /**
248
- * Copy the scopes that accept at least one of the given intents.
248
+ * Copy the scopes that accept at least one of the given goals.
249
249
  *
250
- * @param goals - Intent ids to filter by; omit to include every registered scope.
250
+ * @param goals - Goal ids to filter by; omit to include every registered scope.
251
251
  * @returns Descriptions whose arrays are copied so callers cannot mutate registry state.
252
252
  */
253
253
  describe(goals) {
254
254
  const selected = goals ? new Set(goals) : undefined;
255
255
  return [...this.byId.values()]
256
- .filter((item) => !selected || item.intentIds.some((goal) => selected.has(goal)))
256
+ .filter((item) => !selected || item.goalIds.some((goal) => selected.has(goal)))
257
257
  .map((item) => ({
258
258
  ...item,
259
- intentIds: [...item.intentIds],
259
+ goalIds: [...item.goalIds],
260
260
  queryScopeIds: [...item.queryScopeIds],
261
261
  knowledgeTopicIds: [...item.knowledgeTopicIds],
262
262
  toolIds: [...item.toolIds],
@@ -14,7 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.reciprocalRankFusion = exports.VectorSearch = exports.ModelCalls = exports.TextSearch = exports.TextSkills = exports.Candidates = exports.Policies = exports.Evidence = exports.Retrieval = exports.Aggregation = exports.Projection = exports.Delivery = exports.Normalization = exports.Presentation = exports.Answering = exports.Knowledge = exports.Tools = exports.Intents = exports.Interaction = void 0;
17
+ exports.reciprocalRankFusion = exports.VectorSearch = exports.ModelCalls = exports.TextBlocks = exports.TextSearch = exports.TextSkills = exports.Candidates = exports.Policies = exports.Evidence = exports.Retrieval = exports.Aggregation = exports.Projection = exports.Delivery = exports.Normalization = exports.Presentation = exports.Answering = exports.Knowledge = exports.Tools = exports.Interaction = void 0;
18
18
  /**
19
19
  * Explicit bulk Kit entry.
20
20
  *
@@ -22,23 +22,22 @@ exports.reciprocalRankFusion = exports.VectorSearch = exports.ModelCalls = expor
22
22
  * path; this file only exists for callers that prefer one import for the whole set. Core
23
23
  * never imports from this directory, so nothing here becomes a runtime requirement.
24
24
  *
25
- * Exports: the Kit namespaces (`Interaction`, `Intents`, `Tools`, `Knowledge`, `Answering`,
25
+ * Exports: the Kit namespaces (`Interaction`, `Tools`, `Knowledge`, `Answering`,
26
26
  * `Presentation`, `Normalization`, `Delivery`, `Projection`, `Aggregation`, `Retrieval`,
27
- * `Evidence`, `Policies`, `Candidates`, `TextSkills`, `TextSearch`, `ModelCalls`,
28
- * `VectorSearch`) plus every Kit type. Individual Kit paths stay the default.
27
+ * `Evidence`, `Policies`, `Candidates`, `TextSkills`, `TextSearch`, `TextBlocks`,
28
+ * `ModelCalls`, `VectorSearch`) plus every Kit type. Individual Kit paths stay the default.
29
29
  */
30
30
  var index_js_1 = require("./interaction/index.js");
31
31
  Object.defineProperty(exports, "Interaction", { enumerable: true, get: function () { return index_js_1.Interaction; } });
32
- var index_js_2 = require("./intents/index.js");
33
- Object.defineProperty(exports, "Intents", { enumerable: true, get: function () { return index_js_2.Intents; } });
32
+ __exportStar(require("./domains/index.js"), exports);
34
33
  var tools_js_1 = require("./tools.js");
35
34
  Object.defineProperty(exports, "Tools", { enumerable: true, get: function () { return tools_js_1.Tools; } });
36
- var index_js_3 = require("./knowledge/index.js");
37
- Object.defineProperty(exports, "Knowledge", { enumerable: true, get: function () { return index_js_3.Knowledge; } });
38
- var index_js_4 = require("./answering/index.js");
39
- Object.defineProperty(exports, "Answering", { enumerable: true, get: function () { return index_js_4.Answering; } });
40
- var index_js_5 = require("./presentation/index.js");
41
- Object.defineProperty(exports, "Presentation", { enumerable: true, get: function () { return index_js_5.Presentation; } });
35
+ var index_js_2 = require("./knowledge/index.js");
36
+ Object.defineProperty(exports, "Knowledge", { enumerable: true, get: function () { return index_js_2.Knowledge; } });
37
+ var index_js_3 = require("./answering/index.js");
38
+ Object.defineProperty(exports, "Answering", { enumerable: true, get: function () { return index_js_3.Answering; } });
39
+ var index_js_4 = require("./presentation/index.js");
40
+ Object.defineProperty(exports, "Presentation", { enumerable: true, get: function () { return index_js_4.Presentation; } });
42
41
  var normalization_js_1 = require("./normalization.js");
43
42
  Object.defineProperty(exports, "Normalization", { enumerable: true, get: function () { return normalization_js_1.Normalization; } });
44
43
  var delivery_js_1 = require("./delivery.js");
@@ -60,9 +59,11 @@ Object.defineProperty(exports, "TextSkills", { enumerable: true, get: function (
60
59
  var search_js_1 = require("./search.js");
61
60
  Object.defineProperty(exports, "TextSearch", { enumerable: true, get: function () { return search_js_1.TextSearch; } });
62
61
  __exportStar(require("./search.js"), exports);
62
+ var text_blocks_js_1 = require("./text-blocks.js");
63
+ Object.defineProperty(exports, "TextBlocks", { enumerable: true, get: function () { return text_blocks_js_1.TextBlocks; } });
64
+ __exportStar(require("./text-blocks.js"), exports);
63
65
  // Types remain available with either individual or explicit bulk imports.
64
66
  __exportStar(require("./interaction/index.js"), exports);
65
- __exportStar(require("./intents/index.js"), exports);
66
67
  __exportStar(require("./tools.js"), exports);
67
68
  __exportStar(require("./knowledge/index.js"), exports);
68
69
  __exportStar(require("./answering/index.js"), exports);
@@ -10,6 +10,7 @@ exports.defineKnowledgeCatalog = defineKnowledgeCatalog;
10
10
  *
11
11
  * Exports: `defineKnowledgeCatalog`, and the knowledge document/read/snapshot types.
12
12
  */
13
+ const native_sub_flow_js_1 = require("../../diagnostics/native-sub-flow.js");
13
14
  const catalog_js_1 = require("../../utils/catalog.js");
14
15
  const sections_js_1 = require("./sections.js");
15
16
  const observer_js_1 = require("../../utils/observer.js");
@@ -68,37 +69,39 @@ function defineKnowledgeCatalog(documents, options = {}) {
68
69
  ...(0, catalog_js_1.readonlyCatalog)([...catalog.values()].map((entry) => entry.document), (id) => new TypeError(`Unknown knowledge document: ${id}`)),
69
70
  sectionIds,
70
71
  assertSelection,
71
- read(input) {
72
- const { read, entry } = resolve(input), raw = read.selection;
73
- const selection = raw.mode === 'document'
74
- ? Object.freeze({ mode: 'document' })
75
- : Object.freeze({ mode: raw.mode, sectionIds: Object.freeze([...raw.sectionIds]) });
76
- const content = (selection.mode === 'document'
77
- ? (0, sections_js_1.knowledgeText)(entry.document.parts)
78
- : selection.sectionIds
79
- .map((id) => (0, sections_js_1.knowledgeText)(entry.sections.get(id).parts, selection.mode === 'subtree'))
80
- .join('\n\n')).trim();
81
- if (maxChars !== undefined && content.length > maxChars)
82
- throw new RangeError('Knowledge selection exceeds its budget');
83
- // Preserve the existing opaque snapshot identity format.
84
- const identitySelection = selection.mode === 'document'
85
- ? selection
86
- : { mode: selection.mode, sections: selection.sectionIds };
87
- const snapshot = Object.freeze({
88
- documentId: read.documentId,
89
- selection,
90
- revision: entry.document.revision,
91
- locale: entry.document.locale,
92
- content,
93
- id: JSON.stringify([
94
- read.documentId,
95
- entry.document.revision,
96
- entry.document.locale,
97
- identitySelection,
98
- ]),
72
+ read(input, context = {}) {
73
+ return (0, native_sub_flow_js_1.nativeSubFlowSync)(context, 'knowledge', input.documentId, () => {
74
+ const { read, entry } = resolve(input), raw = read.selection;
75
+ const selection = raw.mode === 'document'
76
+ ? Object.freeze({ mode: 'document' })
77
+ : Object.freeze({ mode: raw.mode, sectionIds: Object.freeze([...raw.sectionIds]) });
78
+ const content = (selection.mode === 'document'
79
+ ? (0, sections_js_1.knowledgeText)(entry.document.parts)
80
+ : selection.sectionIds
81
+ .map((id) => (0, sections_js_1.knowledgeText)(entry.sections.get(id).parts, selection.mode === 'subtree'))
82
+ .join('\n\n')).trim();
83
+ if (maxChars !== undefined && content.length > maxChars)
84
+ throw new RangeError('Knowledge selection exceeds its budget');
85
+ // Preserve the existing opaque snapshot identity format.
86
+ const identitySelection = selection.mode === 'document'
87
+ ? selection
88
+ : { mode: selection.mode, sections: selection.sectionIds };
89
+ const snapshot = Object.freeze({
90
+ documentId: read.documentId,
91
+ selection,
92
+ revision: entry.document.revision,
93
+ locale: entry.document.locale,
94
+ content,
95
+ id: JSON.stringify([
96
+ read.documentId,
97
+ entry.document.revision,
98
+ entry.document.locale,
99
+ identitySelection,
100
+ ]),
101
+ });
102
+ (0, observer_js_1.observeSafely)(observe, snapshot);
103
+ return snapshot;
99
104
  });
100
- (0, observer_js_1.observeSafely)(observe, snapshot);
101
- return snapshot;
102
105
  },
103
106
  });
104
107
  }
@@ -12,6 +12,7 @@ exports.defineRecoveryChain = defineRecoveryChain;
12
12
  *
13
13
  * Exports: `definePolicySet`, `defineRecoveryChain`, `Policies`, and the policy types.
14
14
  */
15
+ const native_sub_flow_js_1 = require("../diagnostics/native-sub-flow.js");
15
16
  const catalog_js_1 = require("../utils/catalog.js");
16
17
  const synchronous_js_1 = require("../utils/synchronous.js");
17
18
  const rules_js_1 = require("../utils/rules.js");
@@ -70,9 +71,9 @@ function defineRecoveryChain(definitions) {
70
71
  },
71
72
  });
72
73
  });
73
- const tryRecover = (input) => {
74
+ const tryRecover = (input, execution = {}) => {
74
75
  for (const policy of catalog) {
75
- const result = policy.tryRecover(input);
76
+ const result = (0, native_sub_flow_js_1.nativeSubFlowSync)(execution, 'recovery', policy.id, () => policy.tryRecover(input));
76
77
  if (result.handled)
77
78
  return result;
78
79
  }
@@ -0,0 +1,110 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.replyFormatChecks = void 0;
4
+ exports.mergeReplyBubbles = mergeReplyBubbles;
5
+ exports.defineReplyFormats = defineReplyFormats;
6
+ /**
7
+ * Presentation Kit: template-bound reply formats and their shared checks.
8
+ *
9
+ * Place in the package: part of the `presentation` Kit. A format is declared only where the App
10
+ * owns a template for the final reply; `resolve` returns `undefined` for every other reply, so the
11
+ * caller has no output-format requirement and does not re-ask the model. Apps keep their own copy,
12
+ * limits and checks; this module only compiles the declarations and evaluates failures.
13
+ *
14
+ * Exports: `defineReplyFormats`, `replyFormatChecks`, `mergeReplyBubbles`, and their types.
15
+ */
16
+ const rules_js_1 = require("../../utils/rules.js");
17
+ const validId = (id) => typeof id === 'string' && /^[a-z][a-z0-9-]*$/.test(id);
18
+ /**
19
+ * Checks shared by text replies. Limits stay with the App template; only the comparison lives here.
20
+ */
21
+ exports.replyFormatChecks = Object.freeze({
22
+ /**
23
+ * Every bubble is non-empty and the total (primary text included) stays within the limit.
24
+ *
25
+ * @param totalLimit - Maximum bubble count including the primary text.
26
+ * @returns The reusable `bubbles` check.
27
+ */
28
+ bubbles(totalLimit) {
29
+ (0, rules_js_1.breakWhile)(!Number.isSafeInteger(totalLimit) || totalLimit < 1, 'Bubble limit must be a positive integer');
30
+ return Object.freeze({
31
+ id: 'bubbles',
32
+ description: `回复气泡总数不超过 ${totalLimit} 条且每条非空。`,
33
+ accepts: (bubbles) => bubbles.length >= 1 &&
34
+ bubbles.length <= totalLimit &&
35
+ bubbles.every((text) => typeof text === 'string' && !!text.trim()),
36
+ });
37
+ },
38
+ /**
39
+ * The joined reply stays within the app's text budget.
40
+ *
41
+ * @param maxChars - Maximum total characters across bubbles.
42
+ * @returns The reusable `text-budget` check.
43
+ */
44
+ textBudget(maxChars) {
45
+ (0, rules_js_1.breakWhile)(!Number.isSafeInteger(maxChars) || maxChars < 1, 'Text budget must be a positive integer');
46
+ return Object.freeze({
47
+ id: 'text-budget',
48
+ description: `回复正文总长不超过 ${maxChars} 字符。`,
49
+ accepts: (bubbles) => bubbles.reduce((length, text) => length + (typeof text === 'string' ? text.length : 0), 0) <= maxChars,
50
+ });
51
+ },
52
+ });
53
+ /**
54
+ * Normalize a reply that has no declared format: drop blank bubbles and merge overflow into the
55
+ * last allowed one. Text content is preserved.
56
+ *
57
+ * @param bubbles - Primary text followed by follow-up bubbles.
58
+ * @param limit - Maximum number of bubbles to keep.
59
+ * @returns Non-empty bubbles within the limit.
60
+ */
61
+ function mergeReplyBubbles(bubbles, limit) {
62
+ (0, rules_js_1.breakWhile)(!Number.isSafeInteger(limit) || limit < 1, 'Bubble limit must be a positive integer');
63
+ const kept = bubbles.map((text) => text.trim()).filter(Boolean);
64
+ // 超出部分按原顺序合并到最后一条允许的气泡,不改变正文内容。
65
+ if (kept.length > limit)
66
+ kept.push(kept.splice(limit - 1).join('\n\n'));
67
+ return kept;
68
+ }
69
+ /**
70
+ * Compile reply formats so that checks run only for templates the current turn uses.
71
+ *
72
+ * @param options - Declared formats and the checks their ids refer to.
73
+ * @returns A frozen catalog with `resolve(context)`.
74
+ * @throws TypeError For duplicate or invalid ids, a format without checks, an unknown check id,
75
+ * or a non-function `when`/`accepts`.
76
+ */
77
+ function defineReplyFormats(options) {
78
+ const { formats, checks } = options;
79
+ (0, rules_js_1.breakWhile)(!formats?.length || !checks?.length, 'Reply formats require formats and checks');
80
+ const checkMap = new Map();
81
+ for (const check of checks) {
82
+ (0, rules_js_1.breakWhile)(!validId(check.id) || checkMap.has(check.id) || typeof check.accepts !== 'function', 'Invalid reply format check');
83
+ checkMap.set(check.id, Object.freeze({ ...check, accepts: check.accepts.bind(check) }));
84
+ }
85
+ const seen = new Set();
86
+ const compiled = formats.map((format) => {
87
+ (0, rules_js_1.breakWhile)(!validId(format.id) ||
88
+ seen.has(format.id) ||
89
+ typeof format.when !== 'function' ||
90
+ !format.checks?.length ||
91
+ format.checks.some((id) => !checkMap.has(id)), 'Invalid reply format');
92
+ seen.add(format.id);
93
+ const required = Object.freeze([...format.checks]);
94
+ return Object.freeze({
95
+ id: format.id,
96
+ description: format.description,
97
+ checks: required,
98
+ when: format.when,
99
+ inspect(bubbles) {
100
+ return required.map((id) => checkMap.get(id)).filter((check) => !check.accepts(bubbles));
101
+ },
102
+ });
103
+ });
104
+ return Object.freeze({
105
+ /** The template this turn uses, or `undefined` when it has no output-format requirement. */
106
+ resolve(context) {
107
+ return compiled.find((format) => format.when(context));
108
+ },
109
+ });
110
+ }
@@ -16,27 +16,32 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.Presentation = void 0;
18
18
  /**
19
- * Presentation Kit entry: output contracts, text templates, semantic slots, variants and the
20
- * reply/chunk event stream.
19
+ * Presentation Kit entry: output contracts, text templates, semantic slots, reply formats,
20
+ * variants and the reply/chunk event stream.
21
21
  *
22
22
  * Place in the package: an optional App-side library for shaping what the user finally sees.
23
23
  * The App owns copy, styling and transport; this directory owns contract validation, template
24
- * substitution, variant selection and the bubble/chunk protocol.
24
+ * substitution, format checks, variant selection and the bubble/chunk protocol.
25
25
  *
26
- * Exports: everything from `./outputs.js`, `./variants.js`, `./templates.js` and `./events.js`,
27
- * plus the `Presentation` namespace object.
26
+ * Exports: everything from `./outputs.js`, `./formats.js`, `./variants.js`, `./templates.js` and
27
+ * `./events.js`, plus the `Presentation` namespace object.
28
28
  */
29
29
  __exportStar(require("./outputs.js"), exports);
30
+ __exportStar(require("./formats.js"), exports);
30
31
  __exportStar(require("./variants.js"), exports);
31
32
  __exportStar(require("./templates.js"), exports);
32
33
  __exportStar(require("./events.js"), exports);
33
34
  const outputs_js_1 = require("./outputs.js");
35
+ const formats_js_1 = require("./formats.js");
34
36
  const templates_js_1 = require("./templates.js");
35
37
  const variants_js_1 = require("./variants.js");
36
38
  const events_js_1 = require("./events.js");
37
39
  /** Namespace object for callers that prefer one import over named helpers. */
38
40
  exports.Presentation = Object.freeze({
39
41
  defineOutputCatalog: outputs_js_1.defineOutputCatalog,
42
+ defineReplyFormats: formats_js_1.defineReplyFormats,
43
+ replyFormatChecks: formats_js_1.replyFormatChecks,
44
+ mergeReplyBubbles: formats_js_1.mergeReplyBubbles,
40
45
  defineTextTemplate: templates_js_1.defineTextTemplate,
41
46
  defineSemanticSlots: templates_js_1.defineSemanticSlots,
42
47
  selectVariant: variants_js_1.selectVariant,
@@ -10,6 +10,7 @@ exports.defineOutputCatalog = defineOutputCatalog;
10
10
  *
11
11
  * Exports: `defineOutputCatalog`, and the output definition/field/provider/result types.
12
12
  */
13
+ const native_sub_flow_js_1 = require("../../diagnostics/native-sub-flow.js");
13
14
  const schema_adapter_js_1 = require("../../utils/schema-adapter.js");
14
15
  const catalog_js_1 = require("../../utils/catalog.js");
15
16
  const synchronous_js_1 = require("../../utils/synchronous.js");
@@ -324,7 +325,7 @@ function defineOutputCatalog(definitions, options = {}) {
324
325
  throw new TypeError('Use a named output request');
325
326
  if (!context?.signal)
326
327
  throw new TypeError('Output composition requires OperationContext');
327
- return composeInternal(request.outputId, request.input, context);
328
+ return (0, native_sub_flow_js_1.nativeSubFlowSync)(context, 'output', request.outputId, () => composeInternal(request.outputId, request.input, context));
328
329
  },
329
330
  });
330
331
  }
@@ -229,7 +229,7 @@ function defineReflection(definition) {
229
229
  ...extraTools,
230
230
  ];
231
231
  const catalog = (0, tools_js_1.defineToolCatalog)(toolDefinitions);
232
- const capabilities = (0, capabilities_js_1.defineModelCapabilities)([
232
+ const modelTools = (0, capabilities_js_1.defineModelTools)([
233
233
  ...catalog.definitions.map((tool) => ({
234
234
  id: tool.id,
235
235
  description: tool.description,
@@ -248,7 +248,7 @@ function defineReflection(definition) {
248
248
  ]);
249
249
  const transport = (0, selection_transport_js_1.createModelTransport)({
250
250
  id: 'core:reflection',
251
- capabilities,
251
+ tools: modelTools,
252
252
  adapter: json_object_js_1.jsonObjectInteraction,
253
253
  });
254
254
  const child = model.createChild({
@@ -12,6 +12,7 @@ exports.defineRetrieval = defineRetrieval;
12
12
  *
13
13
  * Exports: `defineRetrieval`, `retrievalQueryKey`, `Retrieval`, and the retrieval port types.
14
14
  */
15
+ const native_sub_flow_js_1 = require("../diagnostics/native-sub-flow.js");
15
16
  const synchronous_js_1 = require("../utils/synchronous.js");
16
17
  const query_key_js_1 = require("../utils/query-key.js");
17
18
  const rules_js_1 = require("../utils/rules.js");
@@ -148,7 +149,12 @@ function defineRetrieval(definition) {
148
149
  }
149
150
  return receipt;
150
151
  }
151
- return Object.freeze({ id, description, effects, run });
152
+ return Object.freeze({
153
+ id,
154
+ description,
155
+ effects,
156
+ run: (input, context) => (0, native_sub_flow_js_1.nativeSubFlowSync)(context, 'retrieval', id, () => run(input, context)),
157
+ });
152
158
  }
153
159
  function reason(value, query, context) {
154
160
  return () => (typeof value === 'function' ? value(query, context) : value);
@@ -0,0 +1,101 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TextBlocks = void 0;
4
+ exports.splitTextBlocks = splitTextBlocks;
5
+ /**
6
+ * Text Blocks Kit: structure-aware splitting for long plain text.
7
+ *
8
+ * Place in the package: an optional App-side helper used before a long document is paged
9
+ * into a model or indexed for retrieval. The Kit owns boundary selection, block numbering
10
+ * and exact reassembly; file reading, paging, search, storage and prompt wording stay with
11
+ * the App. No model call or Core dependency is involved.
12
+ *
13
+ * Exports: `splitTextBlocks`, `TextBlocks` and the block option/result types.
14
+ */
15
+ const rules_js_1 = require("../utils/rules.js");
16
+ /**
17
+ * Whether one line starts a new structural section.
18
+ *
19
+ * @param line - A full line including its trailing newline.
20
+ * @returns `true` for Markdown headings and horizontal rules.
21
+ */
22
+ function headingLine(line) {
23
+ return /^\s*#{1,6}\s/.test(line) || /^\s*(?:[-*_]{3,}|={3,})\s*$/.test(line);
24
+ }
25
+ /**
26
+ * Split long plain text on structural boundaries.
27
+ *
28
+ * Headings and horizontal rules start a new block, blank lines end the current one, and all
29
+ * other lines break only when the target size would be exceeded. A single line longer than
30
+ * the target becomes its own block so that paging can cut it into fragments later without
31
+ * splitting the line into unrelated sections. Concatenating every block reproduces the input
32
+ * exactly: no truncation, padding or dropped whitespace.
33
+ *
34
+ * The input must be plain text; binaries and rich documents are read elsewhere.
35
+ *
36
+ * @param text - Decoded source text.
37
+ * @param options - Target block size in characters.
38
+ * @returns Blocks in source order, each with one-based `number` and source offsets. Empty
39
+ * text returns an empty list.
40
+ * @throws TypeError When the text is not a string or `targetChars` is not a positive integer.
41
+ */
42
+ function splitTextBlocks(text, options) {
43
+ (0, rules_js_1.breakWhile)(typeof text !== 'string' ||
44
+ !options ||
45
+ !Number.isSafeInteger(options.targetChars) ||
46
+ options.targetChars < 1, 'Text block splitting requires text and a positive integer target size');
47
+ const targetChars = options.targetChars;
48
+ const blocks = [];
49
+ let buffer = '';
50
+ let bufferStart = 0;
51
+ let cursor = 0;
52
+ const flush = () => {
53
+ if (!buffer)
54
+ return;
55
+ const previous = blocks.at(-1);
56
+ if (!buffer.trim() && previous) {
57
+ // Whitespace-only blocks carry no section, so they stay attached to the previous block
58
+ // instead of becoming a block the reader has to page through.
59
+ blocks[blocks.length - 1] = {
60
+ ...previous,
61
+ text: previous.text + buffer,
62
+ end: previous.end + buffer.length,
63
+ };
64
+ }
65
+ else {
66
+ blocks.push({ number: blocks.length + 1, text: buffer, start: bufferStart, end: cursor });
67
+ }
68
+ buffer = '';
69
+ };
70
+ // Keeping a line's trailing newline makes every block reassemble into the original text,
71
+ // including CRLF input.
72
+ for (const line of text.match(/[^\n]*\n|[^\n]+$/g) ?? []) {
73
+ if (line.length > targetChars) {
74
+ flush();
75
+ blocks.push({
76
+ number: blocks.length + 1,
77
+ text: line,
78
+ start: cursor,
79
+ end: cursor + line.length,
80
+ });
81
+ cursor += line.length;
82
+ continue;
83
+ }
84
+ if (headingLine(line))
85
+ flush();
86
+ if (buffer.length + line.length > targetChars)
87
+ flush();
88
+ if (!buffer)
89
+ bufferStart = cursor;
90
+ buffer += line;
91
+ cursor += line.length;
92
+ if ((!line.trim() || headingLine(line)) && buffer.length >= targetChars / 2)
93
+ flush();
94
+ else if (buffer.length >= targetChars)
95
+ flush();
96
+ }
97
+ flush();
98
+ return blocks;
99
+ }
100
+ /** Namespace form of the Kit, for callers that prefer one aggregate entry. */
101
+ exports.TextBlocks = { split: splitTextBlocks };