@jangts/agent-core 0.1.1 → 0.2.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 (523) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/development/docs/api/reference.md +1907 -1874
  3. package/development/docs/api/support.md +27 -0
  4. package/development/skills/agent-core-app/scripts/create-app.mjs +267 -70
  5. package/development/skills/agent-core-app/scripts/lib/knowledge.mjs +40 -15
  6. package/development/skills/agent-core-app/scripts/lib/source.mjs +30 -2
  7. package/development/skills/agent-core-app/scripts/plan.mjs +37 -12
  8. package/development/skills/agent-core-app/scripts/prepare-source.mjs +61 -10
  9. package/development/skills/agent-core-app/scripts/resources.mjs +45 -17
  10. package/development/skills/agent-core-app/scripts/validate-knowledge.mjs +18 -1
  11. package/development/skills/agent-core-app/templates/catalog.json +36 -22
  12. package/dist/cjs/capabilities/index.js +13 -0
  13. package/dist/cjs/capabilities/invocation.js +80 -10
  14. package/dist/cjs/capabilities/model.js +126 -13
  15. package/dist/cjs/capabilities/tool-runtime.js +64 -12
  16. package/dist/cjs/capabilities/tools.js +266 -31
  17. package/dist/cjs/context/assembly.js +46 -5
  18. package/dist/cjs/context/audit.js +31 -6
  19. package/dist/cjs/context/fragments.js +54 -11
  20. package/dist/cjs/context/index.js +12 -0
  21. package/dist/cjs/context/journal.js +84 -7
  22. package/dist/cjs/context/plan.js +30 -2
  23. package/dist/cjs/diagnostics/catalog.js +11 -3
  24. package/dist/cjs/diagnostics/index.js +149 -29
  25. package/dist/cjs/diagnostics/sub-flow.js +240 -40
  26. package/dist/cjs/errors.js +99 -17
  27. package/dist/cjs/execution/branch.js +20 -4
  28. package/dist/cjs/execution/engine.js +470 -56
  29. package/dist/cjs/execution/events.js +136 -18
  30. package/dist/cjs/execution/index.js +7 -0
  31. package/dist/cjs/execution/reporting.js +75 -6
  32. package/dist/cjs/execution/state.js +161 -22
  33. package/dist/cjs/execution/workflow.js +224 -32
  34. package/dist/cjs/index.js +18 -0
  35. package/dist/cjs/kits/aggregation.js +45 -3
  36. package/dist/cjs/kits/answering/batch.js +23 -4
  37. package/dist/cjs/kits/answering/check-result.js +31 -8
  38. package/dist/cjs/kits/answering/checks.js +24 -3
  39. package/dist/cjs/kits/answering/flow.js +192 -36
  40. package/dist/cjs/kits/answering/index.js +19 -1
  41. package/dist/cjs/kits/answering/tasks.js +88 -13
  42. package/dist/cjs/kits/artifacts.js +36 -4
  43. package/dist/cjs/kits/candidates.js +47 -5
  44. package/dist/cjs/kits/delivery.js +40 -5
  45. package/dist/cjs/kits/durable.js +155 -31
  46. package/dist/cjs/kits/evidence.js +66 -15
  47. package/dist/cjs/kits/family.js +152 -22
  48. package/dist/cjs/kits/index.js +12 -1
  49. package/dist/cjs/kits/inference.js +104 -16
  50. package/dist/cjs/kits/intents/catalog.js +67 -16
  51. package/dist/cjs/kits/intents/index.js +11 -0
  52. package/dist/cjs/kits/intents/registry.js +188 -43
  53. package/dist/cjs/kits/intents/scopes.js +215 -46
  54. package/dist/cjs/kits/interaction/command.js +140 -36
  55. package/dist/cjs/kits/interaction/commands.js +86 -11
  56. package/dist/cjs/kits/interaction/handlers.js +27 -10
  57. package/dist/cjs/kits/interaction/index.js +10 -0
  58. package/dist/cjs/kits/interaction/transfer.js +80 -14
  59. package/dist/cjs/kits/knowledge/catalog.js +62 -11
  60. package/dist/cjs/kits/knowledge/index.js +16 -1
  61. package/dist/cjs/kits/knowledge/publication.js +99 -23
  62. package/dist/cjs/kits/knowledge/sections.js +33 -4
  63. package/dist/cjs/kits/normalization.js +51 -7
  64. package/dist/cjs/kits/policies.js +79 -15
  65. package/dist/cjs/kits/presentation/events.js +54 -10
  66. package/dist/cjs/kits/presentation/index.js +24 -1
  67. package/dist/cjs/kits/presentation/outputs.js +176 -38
  68. package/dist/cjs/kits/presentation/templates.js +33 -5
  69. package/dist/cjs/kits/presentation/variants.js +31 -2
  70. package/dist/cjs/kits/projection.js +63 -8
  71. package/dist/cjs/kits/rank-fusion.js +27 -4
  72. package/dist/cjs/kits/reflection-log-source.js +89 -16
  73. package/dist/cjs/kits/reflection.js +234 -60
  74. package/dist/cjs/kits/retrieval.js +98 -18
  75. package/dist/cjs/kits/search.js +180 -27
  76. package/dist/cjs/kits/text-skills.js +104 -19
  77. package/dist/cjs/kits/tools.js +415 -74
  78. package/dist/cjs/kits/vector-search.js +50 -16
  79. package/dist/cjs/mock/node.js +7 -1
  80. package/dist/cjs/mock/web.js +7 -1
  81. package/dist/cjs/mock.js +7 -1
  82. package/dist/cjs/model/binding.js +68 -17
  83. package/dist/cjs/model/call-budget.js +45 -4
  84. package/dist/cjs/model/decision-retry.js +19 -1
  85. package/dist/cjs/model/defaults.js +27 -4
  86. package/dist/cjs/model/index.js +7 -0
  87. package/dist/cjs/model/interactions/arguments.js +36 -1
  88. package/dist/cjs/model/interactions/json-object.js +48 -12
  89. package/dist/cjs/model/interactions/native-functions.js +52 -10
  90. package/dist/cjs/model/message-diagnostics.js +17 -4
  91. package/dist/cjs/model/options.js +9 -1
  92. package/dist/cjs/model/preparation.js +86 -12
  93. package/dist/cjs/model/runner.js +413 -79
  94. package/dist/cjs/model/selection-transport.js +48 -8
  95. package/dist/cjs/model/settings.js +67 -13
  96. package/dist/cjs/model/token-budget.js +69 -11
  97. package/dist/cjs/model/transports.js +59 -6
  98. package/dist/cjs/structs/common.js +11 -0
  99. package/dist/cjs/structs/debug.js +34 -5
  100. package/dist/cjs/structs/errors.js +26 -1
  101. package/dist/cjs/structs/index.js +11 -1
  102. package/dist/cjs/structs/kits/durable.js +7 -0
  103. package/dist/cjs/structs/kits/family.js +1 -0
  104. package/dist/cjs/structs/kits/interaction.js +8 -1
  105. package/dist/cjs/structs/kits/knowledge-publication.js +1 -0
  106. package/dist/cjs/structs/kits/reflection.js +18 -3
  107. package/dist/cjs/structs/model/chat-provider.js +6 -0
  108. package/dist/cjs/structs/support/model/completion.js +2 -0
  109. package/dist/cjs/structs/support/model/messages.js +2 -0
  110. package/dist/cjs/support/capabilities.js +43 -6
  111. package/dist/cjs/support/context/assembly.js +88 -16
  112. package/dist/cjs/support/context/compression.js +48 -6
  113. package/dist/cjs/support/context/fragments.js +6 -0
  114. package/dist/cjs/support/context/history.js +36 -1
  115. package/dist/cjs/support/context/index.js +11 -0
  116. package/dist/cjs/support/context/nodes.js +164 -35
  117. package/dist/cjs/support/context/processing.js +319 -61
  118. package/dist/cjs/support/context/selection-policy.js +98 -21
  119. package/dist/cjs/support/context/selection.js +61 -10
  120. package/dist/cjs/support/context/snapshot.js +29 -7
  121. package/dist/cjs/support/context/strategies.js +120 -28
  122. package/dist/cjs/support/index.js +9 -1
  123. package/dist/cjs/support/model/capabilities.js +20 -1
  124. package/dist/cjs/support/model/chat-completions.js +92 -20
  125. package/dist/cjs/support/model/children.js +34 -6
  126. package/dist/cjs/support/model/compatible-provider.js +189 -59
  127. package/dist/cjs/support/model/completion/calls.js +61 -0
  128. package/dist/cjs/support/model/completion/default.js +32 -0
  129. package/dist/cjs/support/model/completion/index.js +28 -0
  130. package/dist/cjs/support/model/completion/session.js +102 -0
  131. package/dist/cjs/support/model/index.js +12 -0
  132. package/dist/cjs/support/model/interactions/index.js +12 -1
  133. package/dist/cjs/support/model/interactions/json-object.js +6 -0
  134. package/dist/cjs/support/model/interactions/native-functions.js +6 -0
  135. package/dist/cjs/support/model/observer.js +32 -6
  136. package/dist/cjs/support/model/preview-rules.js +66 -16
  137. package/dist/cjs/support/model/reply-preview.js +77 -17
  138. package/dist/cjs/support/model/stage-transport.js +33 -7
  139. package/dist/cjs/support/model/strategies.js +75 -14
  140. package/dist/cjs/support/model/transports.js +53 -11
  141. package/dist/cjs/support/registration.js +49 -7
  142. package/dist/cjs/support/schema.js +46 -4
  143. package/dist/cjs/support/stream-events.js +60 -8
  144. package/dist/cjs/support/tool-runtime.js +6 -0
  145. package/dist/cjs/support/tools.js +79 -10
  146. package/dist/cjs/support/transport/index.js +7 -0
  147. package/dist/cjs/support/transport/json.js +28 -4
  148. package/dist/cjs/support/transport/sse.js +25 -2
  149. package/dist/cjs/utils/break-observer.js +20 -2
  150. package/dist/cjs/utils/cancellation.js +77 -9
  151. package/dist/cjs/utils/catalog.js +19 -4
  152. package/dist/cjs/utils/debug.js +14 -2
  153. package/dist/cjs/utils/index.js +8 -0
  154. package/dist/cjs/utils/interaction-definition.js +26 -6
  155. package/dist/cjs/utils/invocation.js +42 -4
  156. package/dist/cjs/utils/model-protocol.js +20 -1
  157. package/dist/cjs/utils/object.js +16 -0
  158. package/dist/cjs/utils/observer.js +22 -2
  159. package/dist/cjs/utils/protocol-registry.js +47 -4
  160. package/dist/cjs/utils/query-key.js +21 -2
  161. package/dist/cjs/utils/registration.js +18 -2
  162. package/dist/cjs/utils/rules.js +39 -11
  163. package/dist/cjs/utils/schema-adapter.js +25 -2
  164. package/dist/cjs/utils/synchronous.js +64 -7
  165. package/dist/cjs/utils/text.js +15 -1
  166. package/dist/esm/capabilities/index.d.ts +13 -0
  167. package/dist/esm/capabilities/index.js +13 -0
  168. package/dist/esm/capabilities/invocation.d.ts +16 -2
  169. package/dist/esm/capabilities/invocation.js +80 -10
  170. package/dist/esm/capabilities/model.d.ts +68 -1
  171. package/dist/esm/capabilities/model.js +126 -13
  172. package/dist/esm/capabilities/tool-runtime.d.ts +11 -0
  173. package/dist/esm/capabilities/tool-runtime.js +64 -12
  174. package/dist/esm/capabilities/tools.d.ts +96 -3
  175. package/dist/esm/capabilities/tools.js +267 -32
  176. package/dist/esm/context/assembly.d.ts +13 -2
  177. package/dist/esm/context/assembly.js +46 -5
  178. package/dist/esm/context/audit.d.ts +23 -1
  179. package/dist/esm/context/audit.js +31 -6
  180. package/dist/esm/context/fragments.d.ts +37 -3
  181. package/dist/esm/context/fragments.js +54 -11
  182. package/dist/esm/context/index.d.ts +12 -0
  183. package/dist/esm/context/index.js +12 -0
  184. package/dist/esm/context/journal.d.ts +32 -1
  185. package/dist/esm/context/journal.js +84 -7
  186. package/dist/esm/context/plan.d.ts +11 -1
  187. package/dist/esm/context/plan.js +30 -2
  188. package/dist/esm/diagnostics/catalog.js +11 -3
  189. package/dist/esm/diagnostics/index.d.ts +30 -2
  190. package/dist/esm/diagnostics/index.js +149 -29
  191. package/dist/esm/diagnostics/sub-flow.d.ts +41 -3
  192. package/dist/esm/diagnostics/sub-flow.js +240 -40
  193. package/dist/esm/errors.d.ts +22 -2
  194. package/dist/esm/errors.js +99 -17
  195. package/dist/esm/execution/branch.d.ts +19 -1
  196. package/dist/esm/execution/branch.js +20 -4
  197. package/dist/esm/execution/engine.d.ts +291 -5
  198. package/dist/esm/execution/engine.js +471 -57
  199. package/dist/esm/execution/events.d.ts +16 -2
  200. package/dist/esm/execution/events.js +136 -18
  201. package/dist/esm/execution/index.d.ts +7 -0
  202. package/dist/esm/execution/index.js +7 -0
  203. package/dist/esm/execution/reporting.d.ts +49 -1
  204. package/dist/esm/execution/reporting.js +75 -6
  205. package/dist/esm/execution/state.d.ts +126 -10
  206. package/dist/esm/execution/state.js +161 -22
  207. package/dist/esm/execution/workflow.d.ts +121 -3
  208. package/dist/esm/execution/workflow.js +224 -32
  209. package/dist/esm/index.d.ts +17 -1
  210. package/dist/esm/index.js +18 -0
  211. package/dist/esm/kits/aggregation.d.ts +34 -2
  212. package/dist/esm/kits/aggregation.js +45 -3
  213. package/dist/esm/kits/answering/batch.d.ts +17 -0
  214. package/dist/esm/kits/answering/batch.js +23 -4
  215. package/dist/esm/kits/answering/check-result.d.ts +18 -1
  216. package/dist/esm/kits/answering/check-result.js +31 -8
  217. package/dist/esm/kits/answering/checks.d.ts +11 -0
  218. package/dist/esm/kits/answering/checks.js +24 -3
  219. package/dist/esm/kits/answering/flow.d.ts +25 -2
  220. package/dist/esm/kits/answering/flow.js +192 -36
  221. package/dist/esm/kits/answering/index.d.ts +12 -0
  222. package/dist/esm/kits/answering/index.js +19 -1
  223. package/dist/esm/kits/answering/tasks.d.ts +32 -1
  224. package/dist/esm/kits/answering/tasks.js +88 -13
  225. package/dist/esm/kits/artifacts.d.ts +11 -0
  226. package/dist/esm/kits/artifacts.js +36 -4
  227. package/dist/esm/kits/candidates.d.ts +23 -1
  228. package/dist/esm/kits/candidates.js +47 -5
  229. package/dist/esm/kits/delivery.d.ts +34 -0
  230. package/dist/esm/kits/delivery.js +40 -5
  231. package/dist/esm/kits/durable.d.ts +19 -0
  232. package/dist/esm/kits/durable.js +155 -31
  233. package/dist/esm/kits/evidence.d.ts +28 -5
  234. package/dist/esm/kits/evidence.js +66 -15
  235. package/dist/esm/kits/family.d.ts +17 -1
  236. package/dist/esm/kits/family.js +152 -22
  237. package/dist/esm/kits/index.d.ts +12 -1
  238. package/dist/esm/kits/index.js +12 -1
  239. package/dist/esm/kits/inference.d.ts +64 -0
  240. package/dist/esm/kits/inference.js +104 -16
  241. package/dist/esm/kits/intents/catalog.d.ts +13 -1
  242. package/dist/esm/kits/intents/catalog.js +67 -16
  243. package/dist/esm/kits/intents/index.d.ts +11 -0
  244. package/dist/esm/kits/intents/index.js +11 -0
  245. package/dist/esm/kits/intents/registry.d.ts +61 -3
  246. package/dist/esm/kits/intents/registry.js +188 -43
  247. package/dist/esm/kits/intents/scopes.d.ts +73 -3
  248. package/dist/esm/kits/intents/scopes.js +215 -46
  249. package/dist/esm/kits/interaction/command.d.ts +38 -4
  250. package/dist/esm/kits/interaction/command.js +140 -36
  251. package/dist/esm/kits/interaction/commands.d.ts +66 -2
  252. package/dist/esm/kits/interaction/commands.js +86 -11
  253. package/dist/esm/kits/interaction/handlers.d.ts +19 -2
  254. package/dist/esm/kits/interaction/handlers.js +27 -10
  255. package/dist/esm/kits/interaction/index.d.ts +10 -0
  256. package/dist/esm/kits/interaction/index.js +10 -0
  257. package/dist/esm/kits/interaction/transfer.d.ts +39 -2
  258. package/dist/esm/kits/interaction/transfer.js +80 -14
  259. package/dist/esm/kits/knowledge/catalog.d.ts +13 -0
  260. package/dist/esm/kits/knowledge/catalog.js +62 -11
  261. package/dist/esm/kits/knowledge/index.d.ts +11 -0
  262. package/dist/esm/kits/knowledge/index.js +16 -1
  263. package/dist/esm/kits/knowledge/publication.d.ts +15 -1
  264. package/dist/esm/kits/knowledge/publication.js +99 -23
  265. package/dist/esm/kits/knowledge/sections.d.ts +31 -1
  266. package/dist/esm/kits/knowledge/sections.js +33 -4
  267. package/dist/esm/kits/normalization.d.ts +25 -2
  268. package/dist/esm/kits/normalization.js +51 -7
  269. package/dist/esm/kits/policies.d.ts +26 -3
  270. package/dist/esm/kits/policies.js +79 -15
  271. package/dist/esm/kits/presentation/events.d.ts +51 -4
  272. package/dist/esm/kits/presentation/events.js +54 -10
  273. package/dist/esm/kits/presentation/index.d.ts +12 -0
  274. package/dist/esm/kits/presentation/index.js +25 -2
  275. package/dist/esm/kits/presentation/outputs.d.ts +30 -1
  276. package/dist/esm/kits/presentation/outputs.js +176 -38
  277. package/dist/esm/kits/presentation/templates.d.ts +32 -3
  278. package/dist/esm/kits/presentation/templates.js +33 -5
  279. package/dist/esm/kits/presentation/variants.d.ts +29 -0
  280. package/dist/esm/kits/presentation/variants.js +31 -2
  281. package/dist/esm/kits/projection.d.ts +42 -5
  282. package/dist/esm/kits/projection.js +63 -8
  283. package/dist/esm/kits/rank-fusion.d.ts +21 -1
  284. package/dist/esm/kits/rank-fusion.js +28 -5
  285. package/dist/esm/kits/reflection-log-source.d.ts +28 -1
  286. package/dist/esm/kits/reflection-log-source.js +89 -16
  287. package/dist/esm/kits/reflection.d.ts +17 -1
  288. package/dist/esm/kits/reflection.js +235 -61
  289. package/dist/esm/kits/retrieval.d.ts +18 -2
  290. package/dist/esm/kits/retrieval.js +98 -18
  291. package/dist/esm/kits/search.d.ts +56 -3
  292. package/dist/esm/kits/search.js +180 -27
  293. package/dist/esm/kits/text-skills.d.ts +16 -2
  294. package/dist/esm/kits/text-skills.js +104 -19
  295. package/dist/esm/kits/tools.d.ts +122 -2
  296. package/dist/esm/kits/tools.js +416 -74
  297. package/dist/esm/kits/vector-search.d.ts +47 -1
  298. package/dist/esm/kits/vector-search.js +51 -17
  299. package/dist/esm/mock/node.d.ts +7 -0
  300. package/dist/esm/mock/node.js +7 -1
  301. package/dist/esm/mock/web.d.ts +7 -0
  302. package/dist/esm/mock/web.js +7 -1
  303. package/dist/esm/mock.d.ts +7 -0
  304. package/dist/esm/mock.js +7 -1
  305. package/dist/esm/model/binding.d.ts +32 -3
  306. package/dist/esm/model/binding.js +68 -17
  307. package/dist/esm/model/call-budget.d.ts +30 -2
  308. package/dist/esm/model/call-budget.js +45 -4
  309. package/dist/esm/model/decision-retry.d.ts +10 -1
  310. package/dist/esm/model/decision-retry.js +19 -1
  311. package/dist/esm/model/defaults.d.ts +13 -2
  312. package/dist/esm/model/defaults.js +27 -4
  313. package/dist/esm/model/index.d.ts +7 -0
  314. package/dist/esm/model/index.js +7 -0
  315. package/dist/esm/model/interactions/arguments.d.ts +27 -0
  316. package/dist/esm/model/interactions/arguments.js +36 -1
  317. package/dist/esm/model/interactions/json-object.d.ts +7 -1
  318. package/dist/esm/model/interactions/json-object.js +48 -12
  319. package/dist/esm/model/interactions/native-functions.d.ts +6 -0
  320. package/dist/esm/model/interactions/native-functions.js +52 -10
  321. package/dist/esm/model/message-diagnostics.d.ts +17 -1
  322. package/dist/esm/model/message-diagnostics.js +17 -4
  323. package/dist/esm/model/options.d.ts +18 -1
  324. package/dist/esm/model/options.js +9 -1
  325. package/dist/esm/model/preparation.d.ts +30 -2
  326. package/dist/esm/model/preparation.js +86 -12
  327. package/dist/esm/model/runner.d.ts +129 -5
  328. package/dist/esm/model/runner.js +414 -80
  329. package/dist/esm/model/selection-transport.d.ts +14 -1
  330. package/dist/esm/model/selection-transport.js +48 -8
  331. package/dist/esm/model/settings.d.ts +11 -0
  332. package/dist/esm/model/settings.js +67 -13
  333. package/dist/esm/model/token-budget.d.ts +59 -1
  334. package/dist/esm/model/token-budget.js +69 -11
  335. package/dist/esm/model/transports.d.ts +20 -2
  336. package/dist/esm/model/transports.js +59 -6
  337. package/dist/esm/structs/capabilities/invocation.d.ts +36 -0
  338. package/dist/esm/structs/capabilities/model.d.ts +27 -0
  339. package/dist/esm/structs/capabilities/tools.d.ts +38 -0
  340. package/dist/esm/structs/common.d.ts +62 -2
  341. package/dist/esm/structs/common.js +11 -0
  342. package/dist/esm/structs/context/fragments.d.ts +28 -0
  343. package/dist/esm/structs/context/journal.d.ts +28 -3
  344. package/dist/esm/structs/context/processing.d.ts +11 -0
  345. package/dist/esm/structs/debug.d.ts +58 -1
  346. package/dist/esm/structs/debug.js +34 -5
  347. package/dist/esm/structs/diagnostics.d.ts +119 -1
  348. package/dist/esm/structs/errors.d.ts +42 -1
  349. package/dist/esm/structs/errors.js +26 -1
  350. package/dist/esm/structs/execution/engine.d.ts +24 -1
  351. package/dist/esm/structs/execution/events.d.ts +12 -0
  352. package/dist/esm/structs/execution/workflow.d.ts +71 -0
  353. package/dist/esm/structs/index.d.ts +11 -1
  354. package/dist/esm/structs/index.js +11 -1
  355. package/dist/esm/structs/invocation.d.ts +30 -0
  356. package/dist/esm/structs/kits/aggregation.d.ts +12 -0
  357. package/dist/esm/structs/kits/answering/checks.d.ts +11 -0
  358. package/dist/esm/structs/kits/answering/flow.d.ts +35 -1
  359. package/dist/esm/structs/kits/answering/state.d.ts +21 -0
  360. package/dist/esm/structs/kits/answering/tasks.d.ts +21 -0
  361. package/dist/esm/structs/kits/artifacts.d.ts +14 -0
  362. package/dist/esm/structs/kits/candidates.d.ts +19 -0
  363. package/dist/esm/structs/kits/delivery.d.ts +22 -0
  364. package/dist/esm/structs/kits/durable.d.ts +56 -3
  365. package/dist/esm/structs/kits/durable.js +7 -0
  366. package/dist/esm/structs/kits/evidence.d.ts +23 -0
  367. package/dist/esm/structs/kits/family.d.ts +49 -1
  368. package/dist/esm/structs/kits/family.js +1 -0
  369. package/dist/esm/structs/kits/intents/catalog.d.ts +26 -0
  370. package/dist/esm/structs/kits/intents/registry.d.ts +34 -0
  371. package/dist/esm/structs/kits/intents/scopes.d.ts +36 -1
  372. package/dist/esm/structs/kits/interaction.d.ts +64 -0
  373. package/dist/esm/structs/kits/interaction.js +8 -1
  374. package/dist/esm/structs/kits/knowledge-publication.d.ts +43 -1
  375. package/dist/esm/structs/kits/knowledge-publication.js +1 -0
  376. package/dist/esm/structs/kits/knowledge.d.ts +39 -2
  377. package/dist/esm/structs/kits/normalization.d.ts +15 -0
  378. package/dist/esm/structs/kits/policies.d.ts +25 -1
  379. package/dist/esm/structs/kits/presentation/events.d.ts +28 -4
  380. package/dist/esm/structs/kits/presentation/outputs.d.ts +38 -1
  381. package/dist/esm/structs/kits/presentation/templates.d.ts +15 -0
  382. package/dist/esm/structs/kits/projection.d.ts +21 -0
  383. package/dist/esm/structs/kits/reflection.d.ts +61 -2
  384. package/dist/esm/structs/kits/reflection.js +18 -3
  385. package/dist/esm/structs/kits/retrieval.d.ts +38 -0
  386. package/dist/esm/structs/kits/search.d.ts +22 -0
  387. package/dist/esm/structs/kits/text-skills.d.ts +36 -0
  388. package/dist/esm/structs/kits/tools.d.ts +87 -0
  389. package/dist/esm/structs/model/chat-provider.d.ts +24 -1
  390. package/dist/esm/structs/model/chat-provider.js +6 -0
  391. package/dist/esm/structs/model/interactions.d.ts +38 -0
  392. package/dist/esm/structs/model/messages.d.ts +30 -0
  393. package/dist/esm/structs/model/runtime.d.ts +104 -6
  394. package/dist/esm/structs/support/capabilities.d.ts +19 -2
  395. package/dist/esm/structs/support/context-processing.d.ts +88 -9
  396. package/dist/esm/structs/support/context.d.ts +29 -1
  397. package/dist/esm/structs/support/model/completion.d.ts +50 -0
  398. package/dist/esm/structs/support/model/completion.js +1 -0
  399. package/dist/esm/structs/support/model/interactions.d.ts +13 -1
  400. package/dist/esm/structs/support/model/messages.d.ts +52 -0
  401. package/dist/esm/structs/support/model/messages.js +1 -0
  402. package/dist/esm/structs/support/model/provider-observer.d.ts +22 -1
  403. package/dist/esm/structs/support/model/provider.d.ts +71 -6
  404. package/dist/esm/structs/support/registration.d.ts +13 -0
  405. package/dist/esm/structs/support/schema.d.ts +14 -0
  406. package/dist/esm/structs/support/tools.d.ts +28 -0
  407. package/dist/esm/structs/support/transport/json.d.ts +16 -0
  408. package/dist/esm/structs/support/transport/sse.d.ts +15 -0
  409. package/dist/esm/structs/utils/rules.d.ts +19 -0
  410. package/dist/esm/support/capabilities.d.ts +25 -2
  411. package/dist/esm/support/capabilities.js +43 -6
  412. package/dist/esm/support/context/assembly.d.ts +35 -4
  413. package/dist/esm/support/context/assembly.js +88 -16
  414. package/dist/esm/support/context/compression.d.ts +17 -1
  415. package/dist/esm/support/context/compression.js +48 -6
  416. package/dist/esm/support/context/fragments.d.ts +6 -0
  417. package/dist/esm/support/context/fragments.js +6 -0
  418. package/dist/esm/support/context/history.d.ts +43 -0
  419. package/dist/esm/support/context/history.js +36 -1
  420. package/dist/esm/support/context/index.d.ts +13 -2
  421. package/dist/esm/support/context/index.js +12 -1
  422. package/dist/esm/support/context/nodes.d.ts +49 -3
  423. package/dist/esm/support/context/nodes.js +165 -36
  424. package/dist/esm/support/context/processing.d.ts +145 -1
  425. package/dist/esm/support/context/processing.js +320 -62
  426. package/dist/esm/support/context/selection-policy.d.ts +42 -2
  427. package/dist/esm/support/context/selection-policy.js +98 -21
  428. package/dist/esm/support/context/selection.d.ts +14 -1
  429. package/dist/esm/support/context/selection.js +61 -10
  430. package/dist/esm/support/context/snapshot.d.ts +23 -1
  431. package/dist/esm/support/context/snapshot.js +29 -7
  432. package/dist/esm/support/context/strategies.d.ts +35 -2
  433. package/dist/esm/support/context/strategies.js +120 -28
  434. package/dist/esm/support/index.d.ts +9 -1
  435. package/dist/esm/support/index.js +9 -1
  436. package/dist/esm/support/model/capabilities.d.ts +10 -0
  437. package/dist/esm/support/model/capabilities.js +20 -1
  438. package/dist/esm/support/model/chat-completions.d.ts +44 -15
  439. package/dist/esm/support/model/chat-completions.js +92 -20
  440. package/dist/esm/support/model/children.d.ts +32 -2
  441. package/dist/esm/support/model/children.js +34 -6
  442. package/dist/esm/support/model/compatible-provider.d.ts +29 -3
  443. package/dist/esm/support/model/compatible-provider.js +190 -60
  444. package/dist/esm/support/model/completion/calls.d.ts +40 -0
  445. package/dist/esm/support/model/completion/calls.js +58 -0
  446. package/dist/esm/support/model/completion/default.d.ts +10 -0
  447. package/dist/esm/support/model/completion/default.js +29 -0
  448. package/dist/esm/support/model/completion/index.d.ts +10 -0
  449. package/dist/esm/support/model/completion/index.js +22 -0
  450. package/dist/esm/support/model/completion/session.d.ts +11 -0
  451. package/dist/esm/support/model/completion/session.js +99 -0
  452. package/dist/esm/support/model/index.d.ts +14 -0
  453. package/dist/esm/support/model/index.js +12 -0
  454. package/dist/esm/support/model/interactions/index.d.ts +1 -1
  455. package/dist/esm/support/model/interactions/index.js +12 -1
  456. package/dist/esm/support/model/interactions/json-object.d.ts +6 -0
  457. package/dist/esm/support/model/interactions/json-object.js +6 -0
  458. package/dist/esm/support/model/interactions/native-functions.d.ts +6 -0
  459. package/dist/esm/support/model/interactions/native-functions.js +6 -0
  460. package/dist/esm/support/model/observer.d.ts +25 -2
  461. package/dist/esm/support/model/observer.js +32 -6
  462. package/dist/esm/support/model/preview-rules.d.ts +20 -2
  463. package/dist/esm/support/model/preview-rules.js +66 -16
  464. package/dist/esm/support/model/reply-preview.d.ts +15 -1
  465. package/dist/esm/support/model/reply-preview.js +77 -17
  466. package/dist/esm/support/model/stage-transport.d.ts +9 -1
  467. package/dist/esm/support/model/stage-transport.js +33 -7
  468. package/dist/esm/support/model/strategies.d.ts +24 -2
  469. package/dist/esm/support/model/strategies.js +75 -14
  470. package/dist/esm/support/model/transports.d.ts +17 -1
  471. package/dist/esm/support/model/transports.js +53 -11
  472. package/dist/esm/support/registration.d.ts +20 -1
  473. package/dist/esm/support/registration.js +49 -7
  474. package/dist/esm/support/schema.d.ts +31 -1
  475. package/dist/esm/support/schema.js +46 -4
  476. package/dist/esm/support/stream-events.d.ts +22 -1
  477. package/dist/esm/support/stream-events.js +60 -8
  478. package/dist/esm/support/tool-runtime.d.ts +6 -0
  479. package/dist/esm/support/tool-runtime.js +6 -0
  480. package/dist/esm/support/tools.d.ts +22 -0
  481. package/dist/esm/support/tools.js +79 -10
  482. package/dist/esm/support/transport/index.d.ts +7 -0
  483. package/dist/esm/support/transport/index.js +7 -0
  484. package/dist/esm/support/transport/json.d.ts +29 -2
  485. package/dist/esm/support/transport/json.js +28 -4
  486. package/dist/esm/support/transport/sse.d.ts +31 -1
  487. package/dist/esm/support/transport/sse.js +25 -2
  488. package/dist/esm/types.d.ts +9 -1
  489. package/dist/esm/utils/break-observer.d.ts +27 -2
  490. package/dist/esm/utils/break-observer.js +20 -2
  491. package/dist/esm/utils/cancellation.d.ts +56 -5
  492. package/dist/esm/utils/cancellation.js +77 -9
  493. package/dist/esm/utils/catalog.d.ts +20 -1
  494. package/dist/esm/utils/catalog.js +19 -4
  495. package/dist/esm/utils/debug.d.ts +20 -1
  496. package/dist/esm/utils/debug.js +14 -2
  497. package/dist/esm/utils/index.d.ts +8 -0
  498. package/dist/esm/utils/index.js +8 -0
  499. package/dist/esm/utils/interaction-definition.d.ts +18 -1
  500. package/dist/esm/utils/interaction-definition.js +26 -6
  501. package/dist/esm/utils/invocation.d.ts +36 -1
  502. package/dist/esm/utils/invocation.js +42 -4
  503. package/dist/esm/utils/model-protocol.d.ts +8 -0
  504. package/dist/esm/utils/model-protocol.js +20 -1
  505. package/dist/esm/utils/object.d.ts +16 -0
  506. package/dist/esm/utils/object.js +16 -0
  507. package/dist/esm/utils/observer.d.ts +19 -1
  508. package/dist/esm/utils/observer.js +22 -2
  509. package/dist/esm/utils/protocol-registry.d.ts +38 -1
  510. package/dist/esm/utils/protocol-registry.js +47 -4
  511. package/dist/esm/utils/query-key.d.ts +11 -1
  512. package/dist/esm/utils/query-key.js +21 -2
  513. package/dist/esm/utils/registration.d.ts +34 -2
  514. package/dist/esm/utils/registration.js +18 -2
  515. package/dist/esm/utils/rules.d.ts +81 -4
  516. package/dist/esm/utils/rules.js +39 -11
  517. package/dist/esm/utils/schema-adapter.d.ts +12 -1
  518. package/dist/esm/utils/schema-adapter.js +25 -2
  519. package/dist/esm/utils/synchronous.d.ts +60 -4
  520. package/dist/esm/utils/synchronous.js +64 -7
  521. package/dist/esm/utils/text.d.ts +15 -1
  522. package/dist/esm/utils/text.js +15 -1
  523. package/package.json +3 -2
@@ -1,24 +1,57 @@
1
+ /**
2
+ * Context processing engine: validate, select, apply and audit context reductions.
3
+ *
4
+ * A processing state snapshots the plan once, then reductions mutate working fragments until the
5
+ * target size is met. Core guarantees (fragment trust, character/token budgets, structural audit
6
+ * and cancellation) are enforced here; application code supplies policies, handlers and selection
7
+ * strategies. Each mode and reduction kind is a registered entry, so validation and execution
8
+ * cannot diverge.
9
+ *
10
+ * Main exports: `processContext` (complete run), `beginContextProcessing` /
11
+ * `finishContextProcessing` (staged runs), the policy/reduction catalogs and the individual
12
+ * validation, measurement and reduction helpers used by workflow nodes.
13
+ */
1
14
  import { snapshotFragment, snapshotMessage } from './snapshot.js';
2
15
  import { auditContextChange as audit } from '../../context/audit.js';
3
16
  import { historyGroups, validateRecentHistory } from './history.js';
4
- import { contextHandlerCalls, reservedContextCalls, selectContextSteps, validateContextSelection } from './selection-policy.js';
17
+ import { contextHandlerCalls, reservedContextCalls, selectContextSteps, validateContextSelection, } from './selection-policy.js';
5
18
  import { assembleFragments } from '../../context/assembly.js';
6
19
  import { validateContextFragment, validateContextBudget } from '../../context/fragments.js';
7
20
  import { BudgetError, ValidationError } from '../../structs/errors.js';
8
21
  import { breakWhile } from '../../utils/rules.js';
9
22
  import { awaitWithSignal } from '../../utils/cancellation.js';
10
23
  const fail = (message) => new ValidationError([{ code: 'CONTEXT_POLICY', message }]);
11
- const size = (fragment) => typeof fragment.value === 'string' ? fragment.value.length : JSON.stringify(fragment.value).length;
24
+ // Structured values are measured by their serialized length, matching the character budget that
25
+ // assembly later enforces.
26
+ const size = (fragment) => typeof fragment.value === 'string'
27
+ ? fragment.value.length
28
+ : JSON.stringify(fragment.value).length;
12
29
  const positive = (value) => Number.isSafeInteger(value) && value > 0;
13
- /** Validate a finite ordered plan once; no application names or model prompts in Core. */
30
+ /**
31
+ * Validate a complete context policy and every handler it can reference.
32
+ *
33
+ * Handler IDs must be unique and each handler must declare a non-negative integer call ceiling.
34
+ * Reduction targets and selection modes are checked by their own catalog entries.
35
+ *
36
+ * @param policy Policy to validate; the mode must be one of the registered modes.
37
+ * @param compressors Compressors available to compression steps.
38
+ * @param selectors Selectors available to model-driven selection.
39
+ * @throws {ValidationError} When a handler, mode, reduction step or selection declaration is
40
+ * invalid or references something unregistered.
41
+ */
14
42
  export function validateContextPolicy(policy, compressors, selectors = []) {
15
43
  const handlers = new Set();
16
44
  for (const handler of compressors) {
17
- breakWhile(!handler.id || handlers.has(handler.id) || typeof handler.compress !== 'function'
18
- || !Number.isSafeInteger(contextHandlerCalls(handler)) || contextHandlerCalls(handler) < 0, fail('Invalid context compressor'));
45
+ breakWhile(!handler.id ||
46
+ handlers.has(handler.id) ||
47
+ typeof handler.compress !== 'function' ||
48
+ !Number.isSafeInteger(contextHandlerCalls(handler)) ||
49
+ contextHandlerCalls(handler) < 0, fail('Invalid context compressor'));
19
50
  handlers.add(handler.id);
20
51
  }
21
- const mode = Object.hasOwn(contextPolicyCatalog, policy.mode) ? contextPolicyCatalog[policy.mode] : undefined;
52
+ const mode = Object.hasOwn(contextPolicyCatalog, policy.mode)
53
+ ? contextPolicyCatalog[policy.mode]
54
+ : undefined;
22
55
  breakWhile(!mode, fail('Unknown context processing mode'));
23
56
  mode.validate(policy, handlers);
24
57
  if (policy.mode === 'reduce')
@@ -30,13 +63,19 @@ function validateCorePolicy(policy, handlers) {
30
63
  breakWhile(policy.triggerChars !== undefined && !positive(policy.triggerChars), fail('Invalid context trigger'));
31
64
  for (const value of [policy.targetInputChars, policy.triggerTokens, policy.targetInputTokens])
32
65
  breakWhile(value !== undefined && !positive(value), fail('Invalid context watermark'));
33
- breakWhile(policy.targetInputChars !== undefined && policy.triggerChars !== undefined && policy.targetInputChars > policy.triggerChars, fail('Context target must not exceed trigger'));
34
- breakWhile(policy.targetInputTokens !== undefined && policy.triggerTokens !== undefined && policy.targetInputTokens > policy.triggerTokens, fail('Token target must not exceed trigger'));
66
+ breakWhile(policy.targetInputChars !== undefined &&
67
+ policy.triggerChars !== undefined &&
68
+ policy.targetInputChars > policy.triggerChars, fail('Context target must not exceed trigger'));
69
+ breakWhile(policy.targetInputTokens !== undefined &&
70
+ policy.triggerTokens !== undefined &&
71
+ policy.targetInputTokens > policy.triggerTokens, fail('Token target must not exceed trigger'));
35
72
  const ids = new Set();
36
73
  for (const step of policy.steps) {
37
74
  breakWhile(!step.id || ids.has(step.id) || !step.fragmentId || !positive(step.targetChars), fail('Invalid context reduction'));
38
75
  ids.add(step.id);
39
- const operation = Object.hasOwn(contextReductionCatalog, step.kind) ? contextReductionCatalog[step.kind] : undefined;
76
+ const operation = Object.hasOwn(contextReductionCatalog, step.kind)
77
+ ? contextReductionCatalog[step.kind]
78
+ : undefined;
40
79
  breakWhile(!operation, fail('Unknown context reduction'));
41
80
  operation.validate(step, handlers);
42
81
  }
@@ -64,65 +103,107 @@ function compressionInput(step, fragment) {
64
103
  const older = groups.slice(0, groups.length - kept).flat();
65
104
  const record = fragment.value;
66
105
  const value = { ...record, [step.preserve.field]: older };
67
- const recentChars = size({ ...fragment, value: { ...record, [step.preserve.field]: recent } })
68
- - size({ ...fragment, value: { ...record, [step.preserve.field]: [] } });
69
- return { fragment: { ...fragment, value }, recent, older, targetChars: Math.max(1, step.targetChars - recentChars) };
106
+ const recentChars = size({ ...fragment, value: { ...record, [step.preserve.field]: recent } }) -
107
+ size({ ...fragment, value: { ...record, [step.preserve.field]: [] } });
108
+ return {
109
+ fragment: { ...fragment, value },
110
+ recent,
111
+ older,
112
+ // Recent groups are appended back after compression, so their characters are subtracted from
113
+ // the budget the handler may use; the target stays positive.
114
+ targetChars: Math.max(1, step.targetChars - recentChars),
115
+ };
70
116
  }
71
117
  async function compress(call) {
72
118
  if (call.step.kind !== 'compress')
73
119
  throw fail('Invalid compression step');
74
120
  const step = call.step;
75
- const handler = call.compressors.find(item => item.id === step.handlerId);
121
+ const handler = call.compressors.find((item) => item.id === step.handlerId);
76
122
  const input = compressionInput(step, call.fragment);
77
123
  if (input.older?.length === 0)
78
124
  return call.fragment.value;
79
- const value = await handler.compress({ stageId: call.stageId, fragment: structuredClone(input.fragment), targetChars: input.targetChars,
80
- callModel: call.callModel }, { signal: call.signal, diagnostics: call.diagnostics });
125
+ const value = await handler.compress({
126
+ stageId: call.stageId,
127
+ fragment: structuredClone(input.fragment),
128
+ targetChars: input.targetChars,
129
+ callModel: call.callModel,
130
+ }, { signal: call.signal, diagnostics: call.diagnostics });
81
131
  if (!step.preserve)
82
132
  return value;
83
133
  const field = step.preserve.field;
84
134
  breakWhile(!value || typeof value !== 'object' || !Array.isArray(value[field]), fail('Protected-history compression must return an array'));
85
135
  const summary = value;
86
136
  const record = call.fragment.value;
87
- breakWhile(Object.keys(summary).length !== Object.keys(record).length || Object.keys(record).some(key => !Object.hasOwn(summary, key) || (key !== field && JSON.stringify(summary[key]) !== JSON.stringify(record[key]))), fail('Compression must preserve unrelated history fields'));
137
+ breakWhile(Object.keys(summary).length !== Object.keys(record).length ||
138
+ Object.keys(record).some((key) => !Object.hasOwn(summary, key) ||
139
+ (key !== field && JSON.stringify(summary[key]) !== JSON.stringify(record[key]))), fail('Compression must preserve unrelated history fields'));
88
140
  const merged = { ...record, [field]: [...summary[field], ...input.recent] };
89
141
  historyGroups(merged, step.preserve);
90
142
  return merged;
91
143
  }
92
144
  /** This catalog drives validation and dispatch. Every step executes at most once. */
93
145
  export const contextReductionCatalog = {
94
- trim: { validate(step) {
146
+ trim: {
147
+ validate(step) {
95
148
  if (step.kind !== 'trim')
96
149
  throw fail('Invalid trim step');
97
150
  validateRecentHistory(step);
98
- }, run: trim },
99
- compress: { validate(step, handlers) {
151
+ },
152
+ run: trim,
153
+ },
154
+ compress: {
155
+ validate(step, handlers) {
100
156
  if (step.kind !== 'compress')
101
157
  throw fail('Invalid compression step');
102
158
  breakWhile(!handlers.has(step.handlerId), fail('Unregistered context compressor'));
103
159
  if (step.preserve)
104
160
  validateRecentHistory(step.preserve);
105
- }, run: compress },
161
+ },
162
+ run: compress,
163
+ },
106
164
  };
107
165
  /** A handler ignoring cancellation cannot block delivery or publish a late result. */
108
166
  async function runOperation(run, signal) {
109
167
  signal.throwIfAborted();
110
- return await awaitWithSignal(Promise.resolve().then(() => { signal.throwIfAborted(); return run(); }), signal);
168
+ return await awaitWithSignal(Promise.resolve().then(() => {
169
+ signal.throwIfAborted();
170
+ return run();
171
+ }), signal);
111
172
  }
173
+ /**
174
+ * Validate fragment structure and ID uniqueness without re-checking per-fragment budgets.
175
+ *
176
+ * Per-fragment size is rechecked during reduction, where the fragment's own allowance applies.
177
+ *
178
+ * @param fragments Fragments to validate as one set.
179
+ * @throws {ValidationError} When an ID is malformed or repeated, or required metadata is invalid.
180
+ */
112
181
  export function validateStructure(fragments) {
113
182
  const ids = new Set();
114
183
  for (const fragment of fragments)
115
184
  validateContextFragment(fragment, ids, false);
116
185
  }
117
- const measure = (fragments) => assembleFragments(fragments.map(fragment => ({ ...fragment, maxChars: Number.MAX_SAFE_INTEGER })), Number.MAX_SAFE_INTEGER).inputChars;
186
+ const measure = (fragments) => assembleFragments(fragments.map((fragment) => ({ ...fragment, maxChars: Number.MAX_SAFE_INTEGER })), Number.MAX_SAFE_INTEGER).inputChars;
118
187
  function measuredTokens(fragments, additional, budget) {
119
188
  if (!budget)
120
189
  return undefined;
121
- const context = assembleFragments(fragments.map(fragment => ({ ...fragment, maxChars: Number.MAX_SAFE_INTEGER })), Number.MAX_SAFE_INTEGER);
190
+ const context = assembleFragments(fragments.map((fragment) => ({ ...fragment, maxChars: Number.MAX_SAFE_INTEGER })), Number.MAX_SAFE_INTEGER);
122
191
  const tokens = budget.measure([...context.messages, ...additional]);
123
192
  breakWhile(!Number.isSafeInteger(tokens) || tokens < 0, fail('Invalid measured context tokens'));
124
193
  return tokens;
125
194
  }
195
+ /**
196
+ * Resolve the effective trigger and target watermarks for a reduction policy.
197
+ *
198
+ * Configured values are clamped to the plan's character budget and the runner's token limit, so a
199
+ * policy can never reduce below what the request actually allows. A missing target equals the
200
+ * trigger, which means "reduce until back under the trigger".
201
+ *
202
+ * @param state Processing state carrying the plan and ports.
203
+ * @returns Trigger and target sizes in characters and, when measurable, tokens.
204
+ * @throws {ValidationError} When token thresholds are configured without a token measurement port,
205
+ * or the effective target exceeds the effective trigger.
206
+ */
126
207
  export function watermarks(state) {
127
208
  const policy = state.policy;
128
209
  if (policy.mode !== 'reduce')
@@ -131,30 +212,76 @@ export function watermarks(state) {
131
212
  const targetChars = policy.targetInputChars ?? triggerChars;
132
213
  const budget = state.ports.tokenBudget;
133
214
  breakWhile((policy.triggerTokens !== undefined || policy.targetInputTokens !== undefined) && !budget, fail('Token thresholds require a token measurement port'));
134
- const triggerTokens = budget ? Math.min(policy.triggerTokens ?? budget.inputLimit, budget.inputLimit) : undefined;
215
+ const triggerTokens = budget
216
+ ? Math.min(policy.triggerTokens ?? budget.inputLimit, budget.inputLimit)
217
+ : undefined;
135
218
  const targetTokens = policy.targetInputTokens ?? triggerTokens;
136
219
  breakWhile(targetChars > triggerChars || (targetTokens !== undefined && targetTokens > triggerTokens), fail('Target exceeds effective context trigger'));
137
- return { trigger: { chars: triggerChars, tokens: triggerTokens }, target: { chars: targetChars, tokens: targetTokens } };
220
+ return {
221
+ trigger: { chars: triggerChars, tokens: triggerTokens },
222
+ target: { chars: targetChars, tokens: targetTokens },
223
+ };
138
224
  }
225
+ /**
226
+ * Decide whether the current fragments still need reduction.
227
+ *
228
+ * A fragment exceeding its own `maxChars` also counts as needing reduction, even when the total
229
+ * fits, because per-fragment allowances are part of the plan contract.
230
+ *
231
+ * @param state Processing state to measure.
232
+ * @param threshold Trigger size; `tokens` is checked only when present.
233
+ * @returns `true` when characters, a per-fragment allowance or tokens exceed the threshold.
234
+ */
139
235
  export function needsReduction(state, threshold) {
140
- return measure(state.fragments) + state.additionalChars > threshold.chars
141
- || state.fragments.some(fragment => size(fragment) > fragment.maxChars)
142
- || (threshold.tokens !== undefined && measuredTokens(state.fragments, state.additionalMessages, state.ports.tokenBudget) > threshold.tokens);
236
+ return (measure(state.fragments) + state.additionalChars > threshold.chars ||
237
+ state.fragments.some((fragment) => size(fragment) > fragment.maxChars) ||
238
+ (threshold.tokens !== undefined &&
239
+ measuredTokens(state.fragments, state.additionalMessages, state.ports.tokenBudget) >
240
+ threshold.tokens));
143
241
  }
242
+ /**
243
+ * Validate and record application-made changes for an `audit` policy.
244
+ *
245
+ * Only fragments listed as mutable may have changed; the audit helper enforces the rest. Changes
246
+ * that survive are recorded in the report as `app` entries.
247
+ *
248
+ * @param state Processing state; the policy must be `audit` and carry original fragments.
249
+ * @throws {ValidationError} When the policy is not `audit`, original fragments are missing, a
250
+ * mutable ID does not exist, or a protected fragment changed.
251
+ */
144
252
  export function auditApp({ plan, policy, before, fragments, report }) {
145
253
  if (policy.mode !== 'audit')
146
254
  throw fail('Invalid App audit policy');
147
255
  breakWhile(!plan.originalFragments, fail('App audit requires original fragments'));
148
256
  const mutable = new Set(policy.mutableFragmentIds);
149
- breakWhile([...mutable].some(id => !before.some(fragment => fragment.id === id)), fail('Unknown mutable fragment'));
257
+ breakWhile([...mutable].some((id) => !before.some((fragment) => fragment.id === id)), fail('Unknown mutable fragment'));
150
258
  audit(before, fragments, mutable);
151
259
  for (const [index, fragment] of fragments.entries())
152
260
  if (JSON.stringify(fragment.value) !== JSON.stringify(before[index].value))
153
- report.changes.push({ id: 'app', kind: 'app', fragmentId: fragment.id, beforeChars: size(before[index]), afterChars: size(fragment) });
261
+ report.changes.push({
262
+ id: 'app',
263
+ kind: 'app',
264
+ fragmentId: fragment.id,
265
+ beforeChars: size(before[index]),
266
+ afterChars: size(fragment),
267
+ });
154
268
  }
269
+ /**
270
+ * Wrap the model call port with a handler-local call ceiling and a reply reserve.
271
+ *
272
+ * `reserve` is subtracted from the runner's remaining budget, so handlers can never consume the
273
+ * calls the final reply still needs.
274
+ *
275
+ * @param ports Execution ports providing cancellation and the underlying model call.
276
+ * @param maxCalls Maximum calls this handler may make.
277
+ * @param reserve Calls that must remain available for the reply.
278
+ * @returns A call function that throws instead of overspending.
279
+ * @throws {BudgetError} On each call that would exceed either limit.
280
+ * @throws The signal's abort reason when the request is already cancelled.
281
+ */
155
282
  export function limitedCall(ports, maxCalls, reserve) {
156
283
  let calls = 0;
157
- return request => {
284
+ return (request) => {
158
285
  ports.signal.throwIfAborted();
159
286
  if (calls >= maxCalls || (ports.remainingCalls?.() ?? Infinity) <= reserve)
160
287
  throw new BudgetError('Context handler call allowance exhausted');
@@ -165,23 +292,30 @@ export function limitedCall(ports, maxCalls, reserve) {
165
292
  async function selectionCandidates(state, steps, selection) {
166
293
  const candidates = [];
167
294
  for (const step of steps) {
168
- const fragment = state.fragments.find(item => item.id === step.fragmentId);
295
+ const fragment = state.fragments.find((item) => item.id === step.fragmentId);
169
296
  if (size(fragment) <= step.targetChars)
170
297
  continue;
171
- const candidate = { id: step.id, kind: step.kind, fragmentId: step.fragmentId,
172
- chars: size(fragment), targetChars: step.targetChars, requiredCalls: 0 };
298
+ const candidate = {
299
+ id: step.id,
300
+ kind: step.kind,
301
+ fragmentId: step.fragmentId,
302
+ chars: size(fragment),
303
+ targetChars: step.targetChars,
304
+ requiredCalls: 0,
305
+ };
173
306
  if (step.kind === 'compress') {
174
307
  if (compressionInput(step, fragment).older?.length === 0)
175
308
  continue;
176
- candidate.requiredCalls = contextHandlerCalls(state.ports.compressors.find(handler => handler.id === step.handlerId));
309
+ candidate.requiredCalls = contextHandlerCalls(state.ports.compressors.find((handler) => handler.id === step.handlerId));
177
310
  }
178
311
  if (step.kind === 'trim' && (selection.mode === 'auto' || selection.mode === 'model')) {
179
312
  try {
180
313
  const value = await trim({ ...state.ports, step, fragment });
181
314
  candidate.projectedChars = size({ ...fragment, value });
182
- const retained = state.report.changes.filter(change => change.fragmentId === step.fragmentId && change.kind === 'trim')
183
- .reduce((ratio, change) => ratio * change.afterChars / change.beforeChars, 1);
184
- candidate.trimLossRatio = Math.max(0, 1 - retained * candidate.projectedChars / candidate.chars);
315
+ const retained = state.report.changes
316
+ .filter((change) => change.fragmentId === step.fragmentId && change.kind === 'trim')
317
+ .reduce((ratio, change) => (ratio * change.afterChars) / change.beforeChars, 1);
318
+ candidate.trimLossRatio = Math.max(0, 1 - (retained * candidate.projectedChars) / candidate.chars);
185
319
  if (candidate.projectedChars >= candidate.chars)
186
320
  continue;
187
321
  }
@@ -195,21 +329,43 @@ async function selectionCandidates(state, steps, selection) {
195
329
  }
196
330
  return candidates;
197
331
  }
332
+ /**
333
+ * Choose which reduction steps to run next, under the current selection mode.
334
+ *
335
+ * Candidates that cannot make progress are filtered out: a step whose fragment already fits, a
336
+ * compression with no older history, or a step that needs more calls than the remaining budget.
337
+ *
338
+ * @param state Processing state providing ports, fragments and the report.
339
+ * @param steps Reduction steps still pending.
340
+ * @param selection Selection strategy to apply.
341
+ * @returns Registered step IDs in execution order; records the decision in the report.
342
+ * @throws {BudgetError} When model-driven selection has no calls or no feasible candidate left.
343
+ * @throws {ValidationError} When the selector returns unknown, duplicate or over-budget IDs.
344
+ */
198
345
  export async function chooseSteps(state, steps, selection) {
199
346
  const { ports, report } = state;
200
347
  const candidates = await selectionCandidates(state, steps, selection);
201
348
  if (!candidates.length)
202
349
  return [];
203
- const handler = selection.mode === 'model' ? ports.selectors?.find(item => item.id === selection.handlerId) : undefined;
350
+ const handler = selection.mode === 'model'
351
+ ? ports.selectors?.find((item) => item.id === selection.handlerId)
352
+ : undefined;
204
353
  const currentChars = measure(state.fragments) + state.additionalChars;
205
354
  const target = watermarks(state).target;
206
355
  const currentTokens = measuredTokens(state.fragments, state.additionalMessages, ports.tokenBudget);
207
356
  const fragmentOverflow = state.fragments.reduce((sum, fragment) => sum + Math.max(0, size(fragment) - fragment.maxChars), 0);
208
357
  const result = await runOperation(() => selectContextSteps({
209
- stageId: ports.stageId, signal: ports.signal, diagnostics: ports.diagnostics, selection, selectors: ports.selectors ?? [], candidates,
210
- fragments: structuredClone(state.fragments.filter(fragment => candidates.some(candidate => candidate.fragmentId === fragment.id))),
211
- currentChars, currentTokens,
358
+ stageId: ports.stageId,
359
+ signal: ports.signal,
360
+ diagnostics: ports.diagnostics,
361
+ selection,
362
+ selectors: ports.selectors ?? [],
363
+ candidates,
364
+ fragments: structuredClone(state.fragments.filter((fragment) => candidates.some((candidate) => candidate.fragmentId === fragment.id))),
365
+ currentChars,
366
+ currentTokens,
212
367
  requiredReductionTokens: currentTokens === undefined ? undefined : Math.max(0, currentTokens - target.tokens),
368
+ // Per-fragment overflow also has to be removed even when the total already fits.
213
369
  requiredReductionChars: Math.max(currentChars - target.chars, fragmentOverflow),
214
370
  remainingCalls: ports.remainingCalls?.() ?? Infinity,
215
371
  callModel: limitedCall(ports, handler ? contextHandlerCalls(handler) : 0, reservedContextCalls(selection)),
@@ -217,14 +373,33 @@ export async function chooseSteps(state, steps, selection) {
217
373
  report.decisions.push({ mode: selection.mode, stepIds: result.stepIds, reason: result.reason });
218
374
  return result.stepIds;
219
375
  }
376
+ /**
377
+ * Apply one reduction step to its target fragment in the working state.
378
+ *
379
+ * The fragment is cloned before the handler runs, then validated, audited and size-checked before
380
+ * it replaces the original. A reduction that grows the fragment is rejected.
381
+ *
382
+ * @param state Processing state whose fragments are updated in place.
383
+ * @param step Reduction step to execute.
384
+ * @param selection Selection strategy used to size the handler call budget.
385
+ * @throws {ValidationError} When the result is structurally invalid, changes protected fields, or
386
+ * exceeds the original size.
387
+ * @throws {BudgetError} When the step's handler exceeds its call allowance.
388
+ */
220
389
  export async function applyReduction(state, step, selection) {
221
390
  const { fragments, ports, report } = state;
222
- const index = fragments.findIndex(fragment => fragment.id === step.fragmentId);
391
+ const index = fragments.findIndex((fragment) => fragment.id === step.fragmentId);
223
392
  const fragment = fragments[index];
224
393
  if (size(fragment) <= step.targetChars)
225
394
  return;
226
- const handler = step.kind === 'compress' ? ports.compressors.find(item => item.id === step.handlerId) : undefined;
227
- const value = await runOperation(() => contextReductionCatalog[step.kind].run({ ...ports, step, fragment: structuredClone(fragment),
395
+ const handler = step.kind === 'compress'
396
+ ? ports.compressors.find((item) => item.id === step.handlerId)
397
+ : undefined;
398
+ const value = await runOperation(() => contextReductionCatalog[step.kind].run({
399
+ ...ports,
400
+ step,
401
+ // Clone first: the handler must not observe or mutate state that audit still needs.
402
+ fragment: structuredClone(fragment),
228
403
  callModel: limitedCall(ports, handler ? contextHandlerCalls(handler) : 0, reservedContextCalls(selection)),
229
404
  }), ports.signal);
230
405
  ports.signal.throwIfAborted();
@@ -233,14 +408,29 @@ export async function applyReduction(state, step, selection) {
233
408
  audit([fragment], [next], new Set([fragment.id]));
234
409
  breakWhile(size(next) > size(fragment), fail('Context reduction increased size'));
235
410
  fragments[index] = next;
236
- report.changes.push({ id: step.id, kind: step.kind, fragmentId: fragment.id, beforeChars: size(fragment), afterChars: size(next) });
411
+ report.changes.push({
412
+ id: step.id,
413
+ kind: step.kind,
414
+ fragmentId: fragment.id,
415
+ beforeChars: size(fragment),
416
+ afterChars: size(next),
417
+ });
237
418
  }
419
+ /**
420
+ * Check that every reduction step targets an existing, reducible fragment.
421
+ *
422
+ * System-role and instruction-trust fragments are never reducible, regardless of policy.
423
+ *
424
+ * @param state Processing state whose policy and fragments are checked.
425
+ * @throws {ValidationError} When the policy is not a reduction policy or a target is missing,
426
+ * system-owned or instruction-trusted.
427
+ */
238
428
  export function validateReductionTargets(state) {
239
429
  const { policy, fragments } = state;
240
430
  if (policy.mode !== 'reduce')
241
431
  throw fail('Invalid reduction policy');
242
432
  for (const step of policy.steps) {
243
- const fragment = fragments.find(item => item.id === step.fragmentId);
433
+ const fragment = fragments.find((item) => item.id === step.fragmentId);
244
434
  breakWhile(!fragment || fragment.role === 'system' || fragment.trust === 'instruction', fail(`Invalid reduction target: ${step.fragmentId}`));
245
435
  }
246
436
  }
@@ -256,7 +446,7 @@ async function reduceCore(state) {
256
446
  const thresholds = watermarks(state);
257
447
  if (!needsReduction(state, thresholds.trigger))
258
448
  return;
259
- const pending = new Map(policy.steps.map(step => [step.id, step]));
449
+ const pending = new Map(policy.steps.map((step) => [step.id, step]));
260
450
  let queue;
261
451
  while (pending.size && needsReduction(state, thresholds.target)) {
262
452
  queue ??= await chooseSteps(state, [...pending.values()], selection);
@@ -266,6 +456,7 @@ async function reduceCore(state) {
266
456
  const step = pending.get(id);
267
457
  pending.delete(id);
268
458
  await applyReduction(state, step, selection);
459
+ // Automatic selection scores candidates against current sizes, so recompute after each step.
269
460
  if (selection.mode === 'auto')
270
461
  queue = undefined;
271
462
  }
@@ -273,17 +464,34 @@ async function reduceCore(state) {
273
464
  function validateAppPolicy(policy) {
274
465
  if (policy.mode !== 'audit')
275
466
  throw fail('Invalid App audit policy');
276
- breakWhile(!Array.isArray(policy.mutableFragmentIds) || policy.mutableFragmentIds.some(id => typeof id !== 'string' || !id)
277
- || new Set(policy.mutableFragmentIds).size !== policy.mutableFragmentIds.length, fail('Invalid mutable fragment list'));
467
+ breakWhile(!Array.isArray(policy.mutableFragmentIds) ||
468
+ policy.mutableFragmentIds.some((id) => typeof id !== 'string' || !id) ||
469
+ new Set(policy.mutableFragmentIds).size !== policy.mutableFragmentIds.length, fail('Invalid mutable fragment list'));
278
470
  }
279
471
  /** The modes and their implementations are registered together, consumed by validation and execution. */
280
472
  export const contextPolicyCatalog = {
281
473
  validate: { validate() { }, run() { } },
282
474
  reduce: { validate: validateCorePolicy, run: reduceCore },
283
- 'audit': { validate: validateAppPolicy, run: auditApp },
475
+ audit: { validate: validateAppPolicy, run: auditApp },
284
476
  };
477
+ /**
478
+ * Snapshot and validate a plan before any reduction runs.
479
+ *
480
+ * Messages and fragments are cloned and their getters read inside cancellation checks, so a late
481
+ * abort cannot leave partially copied state. Additional messages must be plain user text.
482
+ *
483
+ * @param source Plan supplied by the request or a context builder.
484
+ * @param policy Validated policy to execute.
485
+ * @param ports Execution ports for cancellation, diagnostics and model calls.
486
+ * @returns A processing state ready for the policy runner.
487
+ * @throws {ValidationError} When the budget, fragments, additional messages or token budget are
488
+ * invalid, or a protected fragment already changed.
489
+ * @throws {TypeError} When the plan budget is not a valid integer or infinity.
490
+ */
285
491
  export function beginContextProcessing(source, policy, ports) {
286
492
  const signal = ports.signal;
493
+ // Caller-provided getters may do work; checking before and after prevents a cancelled request
494
+ // from contributing a value to the snapshot.
287
495
  const read = (get) => {
288
496
  signal.throwIfAborted();
289
497
  try {
@@ -303,24 +511,57 @@ export function beginContextProcessing(source, policy, ports) {
303
511
  const rawFragments = read(() => source.fragments);
304
512
  const originals = read(() => source.originalFragments);
305
513
  const mutable = read(() => source.mutableFragmentIds);
306
- const additionalMessages = [...(rawMessages ?? [])].map(message => read(() => snapshotMessage(message)));
307
- breakWhile(additionalMessages.some(message => message.role !== 'user' || typeof message.content !== 'string'), fail('Additional context must be user messages'));
514
+ const additionalMessages = [...(rawMessages ?? [])].map((message) => read(() => snapshotMessage(message)));
515
+ breakWhile(additionalMessages.some((message) => message.role !== 'user' || typeof message.content !== 'string'), fail('Additional context must be user messages'));
308
516
  const additionalChars = additionalMessages.reduce((sum, message) => sum + message.content.length, 0);
309
517
  breakWhile(!Array.isArray(rawFragments), fail('Context plan requires fragments'));
310
- const fragments = [...rawFragments].map(fragment => read(() => snapshotFragment(fragment)));
518
+ const fragments = [...rawFragments].map((fragment) => read(() => snapshotFragment(fragment)));
311
519
  validateStructure(fragments);
312
- const before = [...(originals ?? fragments)].map(fragment => read(() => snapshotFragment(fragment)));
520
+ const before = [...(originals ?? fragments)].map((fragment) => read(() => snapshotFragment(fragment)));
313
521
  validateStructure(before);
314
522
  const mutableFragmentIds = mutable === undefined ? undefined : [...mutable];
523
+ // Only a plan that declares originals can attribute pre-processing changes; otherwise there is
524
+ // no baseline to compare against.
315
525
  if (originals)
316
- audit(before, fragments, new Set(policy.mode === 'audit' ? policy.mutableFragmentIds : mutableFragmentIds ?? []));
317
- const plan = { maxInputChars, fragments, additionalMessages: additionalMessages,
318
- originalFragments: originals === undefined ? undefined : before, mutableFragmentIds };
319
- const report = { mode: policy.mode, beforeChars: read(() => measure(before)) + additionalChars, afterChars: 0, changes: [] };
526
+ audit(before, fragments, new Set(policy.mode === 'audit' ? policy.mutableFragmentIds : (mutableFragmentIds ?? [])));
527
+ const plan = {
528
+ maxInputChars,
529
+ fragments,
530
+ additionalMessages: additionalMessages,
531
+ originalFragments: originals === undefined ? undefined : before,
532
+ mutableFragmentIds,
533
+ };
534
+ const report = {
535
+ mode: policy.mode,
536
+ beforeChars: read(() => measure(before)) + additionalChars,
537
+ afterChars: 0,
538
+ changes: [],
539
+ };
320
540
  const beforeTokens = read(() => measuredTokens(before, additionalMessages, ports.tokenBudget));
321
- return { plan, policy, ports, fragments, before, report, additionalChars, additionalMessages, beforeTokens };
541
+ return {
542
+ plan,
543
+ policy,
544
+ ports,
545
+ fragments,
546
+ before,
547
+ report,
548
+ additionalChars,
549
+ additionalMessages,
550
+ beforeTokens,
551
+ };
322
552
  });
323
553
  }
554
+ /**
555
+ * Assemble the final context and finalize the processing report.
556
+ *
557
+ * Additional messages are appended after fragments, and the combined size is checked against the
558
+ * same budget. Token measurements are reported only when a measurement port exists.
559
+ *
560
+ * @param state Processing state after the policy has run.
561
+ * @returns The built context and the completed report.
562
+ * @throws {ValidationError} When the final input exceeds the character budget or, with a token
563
+ * counter, the token budget (code `MODEL_TOKEN_BUDGET`).
564
+ */
324
565
  export function finishContextProcessing(state) {
325
566
  const { plan, ports, fragments, report, additionalChars, additionalMessages, beforeTokens } = state;
326
567
  ports.signal.throwIfAborted();
@@ -330,12 +571,29 @@ export function finishContextProcessing(state) {
330
571
  validateContextBudget(context.inputChars, plan.maxInputChars);
331
572
  const afterTokens = measuredTokens(fragments, additionalMessages, ports.tokenBudget);
332
573
  if (afterTokens !== undefined) {
333
- breakWhile(afterTokens > ports.tokenBudget.inputLimit, new ValidationError([{ code: 'MODEL_TOKEN_BUDGET', message: 'Processed context exceeds token budget' }]));
334
- report.tokens = { counterId: ports.tokenBudget.counterId, before: beforeTokens, after: afterTokens, inputLimit: ports.tokenBudget.inputLimit };
574
+ breakWhile(afterTokens > ports.tokenBudget.inputLimit, new ValidationError([
575
+ { code: 'MODEL_TOKEN_BUDGET', message: 'Processed context exceeds token budget' },
576
+ ]));
577
+ report.tokens = {
578
+ counterId: ports.tokenBudget.counterId,
579
+ before: beforeTokens,
580
+ after: afterTokens,
581
+ inputLimit: ports.tokenBudget.inputLimit,
582
+ };
335
583
  }
336
584
  report.afterChars = context.inputChars;
337
585
  return { context, report };
338
586
  }
587
+ /**
588
+ * Run a complete context policy in one call: snapshot, execute and finalize.
589
+ *
590
+ * @param plan Plan to process.
591
+ * @param policy Policy whose mode selects the registered runner.
592
+ * @param ports Execution ports for cancellation, diagnostics and model calls.
593
+ * @returns The processed context and its report.
594
+ * @throws {ValidationError} When validation or the final budget check fails.
595
+ * @throws {BudgetError} When a handler exhausts its call allowance.
596
+ */
339
597
  export async function processContext(plan, policy, ports) {
340
598
  const state = beginContextProcessing(plan, policy, ports);
341
599
  await contextPolicyCatalog[policy.mode].run(state);