@askdkc/kiokuko 0.1.16 → 0.1.19

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 (549) hide show
  1. package/README.ja.md +91 -112
  2. package/README.ko.md +90 -102
  3. package/README.md +103 -260
  4. package/README.zh-CN.md +88 -102
  5. package/dist/agent-file/atomic-write.d.ts +90 -3
  6. package/dist/agent-file/atomic-write.d.ts.map +1 -1
  7. package/dist/agent-file/atomic-write.js +990 -14
  8. package/dist/agent-file/atomic-write.js.map +1 -1
  9. package/dist/agent-file/managed-block.d.ts +12 -1
  10. package/dist/agent-file/managed-block.d.ts.map +1 -1
  11. package/dist/agent-file/managed-block.js +49 -4
  12. package/dist/agent-file/managed-block.js.map +1 -1
  13. package/dist/agent-file/render.d.ts +1 -1
  14. package/dist/agent-file/render.d.ts.map +1 -1
  15. package/dist/agent-file/render.js +10 -7
  16. package/dist/agent-file/render.js.map +1 -1
  17. package/dist/akinator/agent-task.d.ts +14 -24
  18. package/dist/akinator/agent-task.d.ts.map +1 -1
  19. package/dist/akinator/agent-task.js +460 -103
  20. package/dist/akinator/agent-task.js.map +1 -1
  21. package/dist/akinator/capabilities.d.ts +52 -7
  22. package/dist/akinator/capabilities.d.ts.map +1 -1
  23. package/dist/akinator/capabilities.js +226 -28
  24. package/dist/akinator/capabilities.js.map +1 -1
  25. package/dist/akinator/capability-binding.d.ts +11 -0
  26. package/dist/akinator/capability-binding.d.ts.map +1 -0
  27. package/dist/akinator/capability-binding.js +56 -0
  28. package/dist/akinator/capability-binding.js.map +1 -0
  29. package/dist/akinator/domain.js +2 -2
  30. package/dist/akinator/domain.js.map +1 -1
  31. package/dist/akinator/knowledge-path.d.ts.map +1 -1
  32. package/dist/akinator/knowledge-path.js +409 -39
  33. package/dist/akinator/knowledge-path.js.map +1 -1
  34. package/dist/akinator/orchestrator.d.ts +3 -4
  35. package/dist/akinator/orchestrator.d.ts.map +1 -1
  36. package/dist/akinator/orchestrator.js +1 -4
  37. package/dist/akinator/orchestrator.js.map +1 -1
  38. package/dist/akinator/service.d.ts +0 -4
  39. package/dist/akinator/service.d.ts.map +1 -1
  40. package/dist/akinator/service.js +19 -35
  41. package/dist/akinator/service.js.map +1 -1
  42. package/dist/akinator/skill-discovery-attempt.d.ts +20 -0
  43. package/dist/akinator/skill-discovery-attempt.d.ts.map +1 -0
  44. package/dist/akinator/skill-discovery-attempt.js +390 -0
  45. package/dist/akinator/skill-discovery-attempt.js.map +1 -0
  46. package/dist/akinator/store.d.ts.map +1 -1
  47. package/dist/akinator/store.js +107 -52
  48. package/dist/akinator/store.js.map +1 -1
  49. package/dist/akinator/types.d.ts +0 -12
  50. package/dist/akinator/types.d.ts.map +1 -1
  51. package/dist/bin/kiokuko.js +0 -0
  52. package/dist/cli.d.ts +2 -0
  53. package/dist/cli.d.ts.map +1 -1
  54. package/dist/cli.js +561 -144
  55. package/dist/cli.js.map +1 -1
  56. package/dist/client/server-client.d.ts +5 -3
  57. package/dist/client/server-client.d.ts.map +1 -1
  58. package/dist/client/server-client.js +486 -181
  59. package/dist/client/server-client.js.map +1 -1
  60. package/dist/commands/agent.d.ts +2 -0
  61. package/dist/commands/agent.d.ts.map +1 -1
  62. package/dist/commands/agent.js +861 -86
  63. package/dist/commands/agent.js.map +1 -1
  64. package/dist/commands/backup.d.ts +2 -1
  65. package/dist/commands/backup.d.ts.map +1 -1
  66. package/dist/commands/backup.js +64 -8
  67. package/dist/commands/backup.js.map +1 -1
  68. package/dist/commands/doctor.d.ts +5 -1
  69. package/dist/commands/doctor.d.ts.map +1 -1
  70. package/dist/commands/doctor.js +70 -26
  71. package/dist/commands/doctor.js.map +1 -1
  72. package/dist/commands/export.d.ts +0 -4
  73. package/dist/commands/export.d.ts.map +1 -1
  74. package/dist/commands/export.js +191 -32
  75. package/dist/commands/export.js.map +1 -1
  76. package/dist/commands/import.d.ts +10 -1
  77. package/dist/commands/import.d.ts.map +1 -1
  78. package/dist/commands/import.js +592 -113
  79. package/dist/commands/import.js.map +1 -1
  80. package/dist/commands/init.d.ts +19 -1
  81. package/dist/commands/init.d.ts.map +1 -1
  82. package/dist/commands/init.js +569 -22
  83. package/dist/commands/init.js.map +1 -1
  84. package/dist/commands/purge.d.ts.map +1 -1
  85. package/dist/commands/purge.js +3 -0
  86. package/dist/commands/purge.js.map +1 -1
  87. package/dist/commands/setup.d.ts +34 -8
  88. package/dist/commands/setup.d.ts.map +1 -1
  89. package/dist/commands/setup.js +418 -86
  90. package/dist/commands/setup.js.map +1 -1
  91. package/dist/commands/skills.d.ts +9 -0
  92. package/dist/commands/skills.d.ts.map +1 -0
  93. package/dist/commands/skills.js +317 -0
  94. package/dist/commands/skills.js.map +1 -0
  95. package/dist/commands/use.d.ts +10 -2
  96. package/dist/commands/use.d.ts.map +1 -1
  97. package/dist/commands/use.js +851 -73
  98. package/dist/commands/use.js.map +1 -1
  99. package/dist/config/paths.d.ts +11 -1
  100. package/dist/config/paths.d.ts.map +1 -1
  101. package/dist/config/paths.js +64 -29
  102. package/dist/config/paths.js.map +1 -1
  103. package/dist/config/project-config.d.ts +1 -0
  104. package/dist/config/project-config.d.ts.map +1 -1
  105. package/dist/config/project-config.js +70 -32
  106. package/dist/config/project-config.js.map +1 -1
  107. package/dist/context/broker.d.ts +30 -14
  108. package/dist/context/broker.d.ts.map +1 -1
  109. package/dist/context/broker.js +628 -150
  110. package/dist/context/broker.js.map +1 -1
  111. package/dist/context/delivery.d.ts +8 -22
  112. package/dist/context/delivery.d.ts.map +1 -1
  113. package/dist/context/delivery.js +204 -152
  114. package/dist/context/delivery.js.map +1 -1
  115. package/dist/context/feedback.d.ts +11 -12
  116. package/dist/context/feedback.d.ts.map +1 -1
  117. package/dist/context/feedback.js +250 -268
  118. package/dist/context/feedback.js.map +1 -1
  119. package/dist/context/origin.d.ts +9 -0
  120. package/dist/context/origin.d.ts.map +1 -0
  121. package/dist/context/origin.js +15 -0
  122. package/dist/context/origin.js.map +1 -0
  123. package/dist/context/ranking.d.ts +4 -13
  124. package/dist/context/ranking.d.ts.map +1 -1
  125. package/dist/context/ranking.js +21 -5
  126. package/dist/context/ranking.js.map +1 -1
  127. package/dist/context/recommendations.d.ts +0 -5
  128. package/dist/context/recommendations.d.ts.map +1 -1
  129. package/dist/context/recommendations.js +0 -1
  130. package/dist/context/recommendations.js.map +1 -1
  131. package/dist/context/run-state.d.ts +26 -0
  132. package/dist/context/run-state.d.ts.map +1 -0
  133. package/dist/context/run-state.js +399 -0
  134. package/dist/context/run-state.js.map +1 -0
  135. package/dist/context/scoped-broker.d.ts +19 -6
  136. package/dist/context/scoped-broker.d.ts.map +1 -1
  137. package/dist/context/scoped-broker.js +530 -131
  138. package/dist/context/scoped-broker.js.map +1 -1
  139. package/dist/context/selection-state.d.ts +19 -0
  140. package/dist/context/selection-state.d.ts.map +1 -0
  141. package/dist/context/selection-state.js +250 -0
  142. package/dist/context/selection-state.js.map +1 -0
  143. package/dist/db/adapter.d.ts +5 -3
  144. package/dist/db/adapter.d.ts.map +1 -1
  145. package/dist/db/adapter.js +6 -3
  146. package/dist/db/adapter.js.map +1 -1
  147. package/dist/db/capabilities.d.ts.map +1 -1
  148. package/dist/db/capabilities.js +34 -16
  149. package/dist/db/capabilities.js.map +1 -1
  150. package/dist/db/connection.d.ts +8 -0
  151. package/dist/db/connection.d.ts.map +1 -1
  152. package/dist/db/connection.js +55 -26
  153. package/dist/db/connection.js.map +1 -1
  154. package/dist/db/migrate.d.ts +28 -7
  155. package/dist/db/migrate.d.ts.map +1 -1
  156. package/dist/db/migrate.js +106 -78
  157. package/dist/db/migrate.js.map +1 -1
  158. package/dist/db/sqlite-retry.d.ts +11 -0
  159. package/dist/db/sqlite-retry.d.ts.map +1 -0
  160. package/dist/db/sqlite-retry.js +66 -0
  161. package/dist/db/sqlite-retry.js.map +1 -0
  162. package/dist/db/transaction.d.ts +13 -0
  163. package/dist/db/transaction.d.ts.map +1 -1
  164. package/dist/db/transaction.js +53 -24
  165. package/dist/db/transaction.js.map +1 -1
  166. package/dist/db/upgrade-backup.d.ts +58 -2
  167. package/dist/db/upgrade-backup.d.ts.map +1 -1
  168. package/dist/db/upgrade-backup.js +757 -28
  169. package/dist/db/upgrade-backup.js.map +1 -1
  170. package/dist/errors.js +1 -1
  171. package/dist/errors.js.map +1 -1
  172. package/dist/gateway/agent-service.d.ts +4 -1
  173. package/dist/gateway/agent-service.d.ts.map +1 -1
  174. package/dist/gateway/agent-service.js +71 -58
  175. package/dist/gateway/agent-service.js.map +1 -1
  176. package/dist/gateway/checkpoint-service.d.ts +1 -0
  177. package/dist/gateway/checkpoint-service.d.ts.map +1 -1
  178. package/dist/gateway/checkpoint-service.js +47 -24
  179. package/dist/gateway/checkpoint-service.js.map +1 -1
  180. package/dist/ledger/archive.d.ts +1 -4
  181. package/dist/ledger/archive.d.ts.map +1 -1
  182. package/dist/ledger/archive.js +134 -54
  183. package/dist/ledger/archive.js.map +1 -1
  184. package/dist/ledger/maintenance.d.ts +0 -11
  185. package/dist/ledger/maintenance.d.ts.map +1 -1
  186. package/dist/ledger/maintenance.js +41 -44
  187. package/dist/ledger/maintenance.js.map +1 -1
  188. package/dist/ledger/projection.d.ts +0 -1
  189. package/dist/ledger/projection.d.ts.map +1 -1
  190. package/dist/ledger/projection.js.map +1 -1
  191. package/dist/ledger/promotion.d.ts +0 -9
  192. package/dist/ledger/promotion.d.ts.map +1 -1
  193. package/dist/ledger/promotion.js.map +1 -1
  194. package/dist/ledger/query.d.ts +1 -15
  195. package/dist/ledger/query.d.ts.map +1 -1
  196. package/dist/ledger/query.js.map +1 -1
  197. package/dist/ledger/store.d.ts +0 -1
  198. package/dist/ledger/store.d.ts.map +1 -1
  199. package/dist/ledger/store.js +11 -8
  200. package/dist/ledger/store.js.map +1 -1
  201. package/dist/ledger/types.d.ts +0 -4
  202. package/dist/ledger/types.d.ts.map +1 -1
  203. package/dist/ledger/types.js.map +1 -1
  204. package/dist/ledger/validate.d.ts.map +1 -1
  205. package/dist/ledger/validate.js +0 -5
  206. package/dist/ledger/validate.js.map +1 -1
  207. package/dist/mcp/bounded-stdio-transport.d.ts +23 -0
  208. package/dist/mcp/bounded-stdio-transport.d.ts.map +1 -0
  209. package/dist/mcp/bounded-stdio-transport.js +109 -0
  210. package/dist/mcp/bounded-stdio-transport.js.map +1 -0
  211. package/dist/mcp/server.d.ts +4 -0
  212. package/dist/mcp/server.d.ts.map +1 -1
  213. package/dist/mcp/server.js +111 -75
  214. package/dist/mcp/server.js.map +1 -1
  215. package/dist/memory/audit.d.ts +0 -1
  216. package/dist/memory/audit.d.ts.map +1 -1
  217. package/dist/memory/audit.js +0 -1
  218. package/dist/memory/audit.js.map +1 -1
  219. package/dist/memory/curator.d.ts +45 -1
  220. package/dist/memory/curator.d.ts.map +1 -1
  221. package/dist/memory/curator.js +290 -68
  222. package/dist/memory/curator.js.map +1 -1
  223. package/dist/memory/entries.d.ts +12 -2
  224. package/dist/memory/entries.d.ts.map +1 -1
  225. package/dist/memory/entries.js +198 -114
  226. package/dist/memory/entries.js.map +1 -1
  227. package/dist/memory/federated-retrieval.d.ts +78 -0
  228. package/dist/memory/federated-retrieval.d.ts.map +1 -0
  229. package/dist/memory/federated-retrieval.js +441 -0
  230. package/dist/memory/federated-retrieval.js.map +1 -0
  231. package/dist/memory/hybrid-retrieval.d.ts +5 -11
  232. package/dist/memory/hybrid-retrieval.d.ts.map +1 -1
  233. package/dist/memory/hybrid-retrieval.js +78 -58
  234. package/dist/memory/hybrid-retrieval.js.map +1 -1
  235. package/dist/memory/lifecycle.d.ts.map +1 -1
  236. package/dist/memory/lifecycle.js +17 -13
  237. package/dist/memory/lifecycle.js.map +1 -1
  238. package/dist/memory/portability.d.ts +10 -0
  239. package/dist/memory/portability.d.ts.map +1 -0
  240. package/dist/memory/portability.js +44 -0
  241. package/dist/memory/portability.js.map +1 -0
  242. package/dist/memory/rebuild-search.d.ts +5 -0
  243. package/dist/memory/rebuild-search.d.ts.map +1 -1
  244. package/dist/memory/rebuild-search.js +101 -76
  245. package/dist/memory/rebuild-search.js.map +1 -1
  246. package/dist/memory/retrieval-query.d.ts +0 -5
  247. package/dist/memory/retrieval-query.d.ts.map +1 -1
  248. package/dist/memory/retrieval-query.js +0 -5
  249. package/dist/memory/retrieval-query.js.map +1 -1
  250. package/dist/memory/retrieval.d.ts +11 -0
  251. package/dist/memory/retrieval.d.ts.map +1 -1
  252. package/dist/memory/retrieval.js +34 -120
  253. package/dist/memory/retrieval.js.map +1 -1
  254. package/dist/memory/revisions.d.ts +76 -1
  255. package/dist/memory/revisions.d.ts.map +1 -1
  256. package/dist/memory/revisions.js +539 -35
  257. package/dist/memory/revisions.js.map +1 -1
  258. package/dist/memory/scoped-memory.d.ts +22 -13
  259. package/dist/memory/scoped-memory.d.ts.map +1 -1
  260. package/dist/memory/scoped-memory.js +248 -139
  261. package/dist/memory/scoped-memory.js.map +1 -1
  262. package/dist/memory/secrets.d.ts +2 -0
  263. package/dist/memory/secrets.d.ts.map +1 -1
  264. package/dist/memory/secrets.js +36 -0
  265. package/dist/memory/secrets.js.map +1 -1
  266. package/dist/memory/structured-memory.d.ts +8 -1
  267. package/dist/memory/structured-memory.d.ts.map +1 -1
  268. package/dist/memory/structured-memory.js +74 -20
  269. package/dist/memory/structured-memory.js.map +1 -1
  270. package/dist/memory/workspaces.d.ts +9 -0
  271. package/dist/memory/workspaces.d.ts.map +1 -1
  272. package/dist/memory/workspaces.js +67 -0
  273. package/dist/memory/workspaces.js.map +1 -1
  274. package/dist/package-version.d.ts +2 -0
  275. package/dist/package-version.d.ts.map +1 -0
  276. package/dist/package-version.js +7 -0
  277. package/dist/package-version.js.map +1 -0
  278. package/dist/repository/binding.d.ts +5 -0
  279. package/dist/repository/binding.d.ts.map +1 -1
  280. package/dist/repository/binding.js +117 -17
  281. package/dist/repository/binding.js.map +1 -1
  282. package/dist/repository/framework-version.d.ts +8 -0
  283. package/dist/repository/framework-version.d.ts.map +1 -0
  284. package/dist/repository/framework-version.js +29 -0
  285. package/dist/repository/framework-version.js.map +1 -0
  286. package/dist/repository/identity-value.d.ts +4 -0
  287. package/dist/repository/identity-value.d.ts.map +1 -0
  288. package/dist/repository/identity-value.js +24 -0
  289. package/dist/repository/identity-value.js.map +1 -0
  290. package/dist/repository/identity.d.ts.map +1 -1
  291. package/dist/repository/identity.js +2 -0
  292. package/dist/repository/identity.js.map +1 -1
  293. package/dist/repository/project-fingerprint.d.ts +33 -0
  294. package/dist/repository/project-fingerprint.d.ts.map +1 -0
  295. package/dist/repository/project-fingerprint.js +429 -0
  296. package/dist/repository/project-fingerprint.js.map +1 -0
  297. package/dist/repository/remote-url.d.ts +0 -1
  298. package/dist/repository/remote-url.d.ts.map +1 -1
  299. package/dist/repository/remote-url.js +0 -1
  300. package/dist/repository/remote-url.js.map +1 -1
  301. package/dist/runtime-version.d.ts +2 -1
  302. package/dist/runtime-version.d.ts.map +1 -1
  303. package/dist/runtime-version.js +21 -4
  304. package/dist/runtime-version.js.map +1 -1
  305. package/dist/serialization/boundary-json.d.ts +20 -0
  306. package/dist/serialization/boundary-json.d.ts.map +1 -0
  307. package/dist/serialization/boundary-json.js +129 -0
  308. package/dist/serialization/boundary-json.js.map +1 -0
  309. package/dist/serialization/envelope.js +1 -1
  310. package/dist/serialization/envelope.js.map +1 -1
  311. package/dist/serialization/validate.d.ts +7 -0
  312. package/dist/serialization/validate.d.ts.map +1 -1
  313. package/dist/serialization/validate.js +53 -13
  314. package/dist/serialization/validate.js.map +1 -1
  315. package/dist/server/app.js +1 -1
  316. package/dist/server/app.js.map +1 -1
  317. package/dist/server/http.d.ts +4 -3
  318. package/dist/server/http.d.ts.map +1 -1
  319. package/dist/server/http.js +90 -50
  320. package/dist/server/http.js.map +1 -1
  321. package/dist/server/idempotency.d.ts +0 -6
  322. package/dist/server/idempotency.d.ts.map +1 -1
  323. package/dist/server/idempotency.js.map +1 -1
  324. package/dist/server/router.d.ts.map +1 -1
  325. package/dist/server/router.js +21 -4
  326. package/dist/server/router.js.map +1 -1
  327. package/dist/server/routes/agent-capability-gate.d.ts +40 -0
  328. package/dist/server/routes/agent-capability-gate.d.ts.map +1 -0
  329. package/dist/server/routes/agent-capability-gate.js +182 -0
  330. package/dist/server/routes/agent-capability-gate.js.map +1 -0
  331. package/dist/server/routes/agent-events.d.ts.map +1 -1
  332. package/dist/server/routes/agent-events.js +8 -1
  333. package/dist/server/routes/agent-events.js.map +1 -1
  334. package/dist/server/routes/agent-intake.d.ts.map +1 -1
  335. package/dist/server/routes/agent-intake.js +10 -2
  336. package/dist/server/routes/agent-intake.js.map +1 -1
  337. package/dist/server/routes/agent-promotions.d.ts.map +1 -1
  338. package/dist/server/routes/agent-promotions.js +5 -2
  339. package/dist/server/routes/agent-promotions.js.map +1 -1
  340. package/dist/server/routes/agent-runs.d.ts.map +1 -1
  341. package/dist/server/routes/agent-runs.js +18 -4
  342. package/dist/server/routes/agent-runs.js.map +1 -1
  343. package/dist/server/routes/request-binding.d.ts +5 -0
  344. package/dist/server/routes/request-binding.d.ts.map +1 -0
  345. package/dist/server/routes/request-binding.js +49 -0
  346. package/dist/server/routes/request-binding.js.map +1 -0
  347. package/dist/server/routes/task5-support.d.ts +1 -8
  348. package/dist/server/routes/task5-support.d.ts.map +1 -1
  349. package/dist/server/routes/task5-support.js +1 -17
  350. package/dist/server/routes/task5-support.js.map +1 -1
  351. package/dist/server/routes/task5.d.ts.map +1 -1
  352. package/dist/server/routes/task5.js +106 -36
  353. package/dist/server/routes/task5.js.map +1 -1
  354. package/dist/server/write-queue.js +2 -2
  355. package/dist/server/write-queue.js.map +1 -1
  356. package/dist/setup/claude-config.d.ts +2 -1
  357. package/dist/setup/claude-config.d.ts.map +1 -1
  358. package/dist/setup/claude-config.js +54 -4
  359. package/dist/setup/claude-config.js.map +1 -1
  360. package/dist/setup/client-detection.d.ts +7 -2
  361. package/dist/setup/client-detection.d.ts.map +1 -1
  362. package/dist/setup/client-detection.js +27 -9
  363. package/dist/setup/client-detection.js.map +1 -1
  364. package/dist/setup/hermes-config.d.ts +2 -1
  365. package/dist/setup/hermes-config.d.ts.map +1 -1
  366. package/dist/setup/hermes-config.js +53 -12
  367. package/dist/setup/hermes-config.js.map +1 -1
  368. package/dist/setup/legacy-client-cleanup.d.ts +6 -0
  369. package/dist/setup/legacy-client-cleanup.d.ts.map +1 -0
  370. package/dist/setup/legacy-client-cleanup.js +152 -0
  371. package/dist/setup/legacy-client-cleanup.js.map +1 -0
  372. package/dist/setup/managed-text.d.ts.map +1 -1
  373. package/dist/setup/managed-text.js +11 -1
  374. package/dist/setup/managed-text.js.map +1 -1
  375. package/dist/setup/opencode-config.d.ts +2 -1
  376. package/dist/setup/opencode-config.d.ts.map +1 -1
  377. package/dist/setup/opencode-config.js +57 -5
  378. package/dist/setup/opencode-config.js.map +1 -1
  379. package/dist/setup/render.d.ts +2 -1
  380. package/dist/setup/render.d.ts.map +1 -1
  381. package/dist/setup/render.js +91 -17
  382. package/dist/setup/render.js.map +1 -1
  383. package/dist/setup/standard-skills.d.ts +16 -2
  384. package/dist/setup/standard-skills.d.ts.map +1 -1
  385. package/dist/setup/standard-skills.js +37 -13
  386. package/dist/setup/standard-skills.js.map +1 -1
  387. package/dist/setup/strict-json.d.ts +7 -0
  388. package/dist/setup/strict-json.d.ts.map +1 -0
  389. package/dist/setup/strict-json.js +98 -0
  390. package/dist/setup/strict-json.js.map +1 -0
  391. package/dist/setup/strict-toml.d.ts +7 -0
  392. package/dist/setup/strict-toml.d.ts.map +1 -0
  393. package/dist/setup/strict-toml.js +470 -0
  394. package/dist/setup/strict-toml.js.map +1 -0
  395. package/dist/skills/cache.d.ts +15 -0
  396. package/dist/skills/cache.d.ts.map +1 -0
  397. package/dist/skills/cache.js +19 -0
  398. package/dist/skills/cache.js.map +1 -0
  399. package/dist/skills/candidate-ranking.d.ts +15 -0
  400. package/dist/skills/candidate-ranking.d.ts.map +1 -0
  401. package/dist/skills/candidate-ranking.js +52 -0
  402. package/dist/skills/candidate-ranking.js.map +1 -0
  403. package/dist/skills/chunking.d.ts +11 -0
  404. package/dist/skills/chunking.d.ts.map +1 -0
  405. package/dist/skills/chunking.js +291 -0
  406. package/dist/skills/chunking.js.map +1 -0
  407. package/dist/skills/config.d.ts +19 -0
  408. package/dist/skills/config.d.ts.map +1 -0
  409. package/dist/skills/config.js +103 -0
  410. package/dist/skills/config.js.map +1 -0
  411. package/dist/skills/discovery-service.d.ts +26 -0
  412. package/dist/skills/discovery-service.d.ts.map +1 -0
  413. package/dist/skills/discovery-service.js +921 -0
  414. package/dist/skills/discovery-service.js.map +1 -0
  415. package/dist/skills/external-transport.d.ts +2 -0
  416. package/dist/skills/external-transport.d.ts.map +1 -0
  417. package/dist/skills/external-transport.js +30 -0
  418. package/dist/skills/external-transport.js.map +1 -0
  419. package/dist/skills/find.d.ts +16 -0
  420. package/dist/skills/find.d.ts.map +1 -0
  421. package/dist/skills/find.js +58 -0
  422. package/dist/skills/find.js.map +1 -0
  423. package/dist/skills/gap-detection.d.ts +23 -0
  424. package/dist/skills/gap-detection.d.ts.map +1 -0
  425. package/dist/skills/gap-detection.js +62 -0
  426. package/dist/skills/gap-detection.js.map +1 -0
  427. package/dist/skills/import-preparation.d.ts +4 -0
  428. package/dist/skills/import-preparation.d.ts.map +1 -0
  429. package/dist/skills/import-preparation.js +20 -0
  430. package/dist/skills/import-preparation.js.map +1 -0
  431. package/dist/skills/materialization-authority.d.ts +11 -0
  432. package/dist/skills/materialization-authority.d.ts.map +1 -0
  433. package/dist/skills/materialization-authority.js +92 -0
  434. package/dist/skills/materialization-authority.js.map +1 -0
  435. package/dist/skills/materialization-service.d.ts +22 -0
  436. package/dist/skills/materialization-service.d.ts.map +1 -0
  437. package/dist/skills/materialization-service.js +101 -0
  438. package/dist/skills/materialization-service.js.map +1 -0
  439. package/dist/skills/official-catalog.d.ts +31 -0
  440. package/dist/skills/official-catalog.d.ts.map +1 -0
  441. package/dist/skills/official-catalog.js +110 -0
  442. package/dist/skills/official-catalog.js.map +1 -0
  443. package/dist/skills/providers/schema.d.ts +30 -0
  444. package/dist/skills/providers/schema.d.ts.map +1 -0
  445. package/dist/skills/providers/schema.js +354 -0
  446. package/dist/skills/providers/schema.js.map +1 -0
  447. package/dist/skills/providers/skills-sh-compat.d.ts +17 -0
  448. package/dist/skills/providers/skills-sh-compat.d.ts.map +1 -0
  449. package/dist/skills/providers/skills-sh-compat.js +71 -0
  450. package/dist/skills/providers/skills-sh-compat.js.map +1 -0
  451. package/dist/skills/providers/skills-sh-v1.d.ts +23 -0
  452. package/dist/skills/providers/skills-sh-v1.d.ts.map +1 -0
  453. package/dist/skills/providers/skills-sh-v1.js +134 -0
  454. package/dist/skills/providers/skills-sh-v1.js.map +1 -0
  455. package/dist/skills/query-builder.d.ts +18 -0
  456. package/dist/skills/query-builder.d.ts.map +1 -0
  457. package/dist/skills/query-builder.js +93 -0
  458. package/dist/skills/query-builder.js.map +1 -0
  459. package/dist/skills/source/errors.d.ts +9 -0
  460. package/dist/skills/source/errors.d.ts.map +1 -0
  461. package/dist/skills/source/errors.js +15 -0
  462. package/dist/skills/source/errors.js.map +1 -0
  463. package/dist/skills/source/frontmatter.d.ts +9 -0
  464. package/dist/skills/source/frontmatter.d.ts.map +1 -0
  465. package/dist/skills/source/frontmatter.js +77 -0
  466. package/dist/skills/source/frontmatter.js.map +1 -0
  467. package/dist/skills/source/github-fetcher.d.ts +20 -0
  468. package/dist/skills/source/github-fetcher.d.ts.map +1 -0
  469. package/dist/skills/source/github-fetcher.js +292 -0
  470. package/dist/skills/source/github-fetcher.js.map +1 -0
  471. package/dist/skills/source/snapshot-validator.d.ts +28 -0
  472. package/dist/skills/source/snapshot-validator.d.ts.map +1 -0
  473. package/dist/skills/source/snapshot-validator.js +186 -0
  474. package/dist/skills/source/snapshot-validator.js.map +1 -0
  475. package/dist/skills/store.d.ts +181 -0
  476. package/dist/skills/store.d.ts.map +1 -0
  477. package/dist/skills/store.js +1710 -0
  478. package/dist/skills/store.js.map +1 -0
  479. package/dist/skills/types.d.ts +169 -0
  480. package/dist/skills/types.d.ts.map +1 -0
  481. package/dist/skills/types.js +2 -0
  482. package/dist/skills/types.js.map +1 -0
  483. package/dist/web/i18n.d.ts +56 -8
  484. package/dist/web/i18n.d.ts.map +1 -1
  485. package/dist/web/i18n.js +224 -32
  486. package/dist/web/i18n.js.map +1 -1
  487. package/dist/web/server.d.ts.map +1 -1
  488. package/dist/web/server.js +458 -42
  489. package/dist/web/server.js.map +1 -1
  490. package/dist/web/ui.d.ts +4 -0
  491. package/dist/web/ui.d.ts.map +1 -1
  492. package/dist/web/ui.js +697 -61
  493. package/dist/web/ui.js.map +1 -1
  494. package/migrations/008_federated_memory.sql +46 -0
  495. package/migrations/009_external_skill_discovery.sql +126 -0
  496. package/package.json +6 -3
  497. package/skills/kiokuko-single-purpose-functions/SKILL.md +288 -0
  498. package/skills/kiokuko-single-purpose-functions/references/kiokuko-patterns.md +344 -0
  499. package/skills/kiokuko-single-purpose-functions/references/review-checklist.md +97 -0
  500. package/skills/kiokuko-ui-design-soul/SKILL.md +1186 -28
  501. package/templates/AGENTS.md +8 -7
  502. package/dist/client/runtime-discovery.d.ts +0 -15
  503. package/dist/client/runtime-discovery.d.ts.map +0 -1
  504. package/dist/client/runtime-discovery.js +0 -45
  505. package/dist/client/runtime-discovery.js.map +0 -1
  506. package/dist/commands/call.d.ts +0 -7
  507. package/dist/commands/call.d.ts.map +0 -1
  508. package/dist/commands/call.js +0 -10
  509. package/dist/commands/call.js.map +0 -1
  510. package/dist/commands/link.d.ts +0 -6
  511. package/dist/commands/link.d.ts.map +0 -1
  512. package/dist/commands/link.js +0 -6
  513. package/dist/commands/link.js.map +0 -1
  514. package/dist/commands/promote.d.ts +0 -6
  515. package/dist/commands/promote.d.ts.map +0 -1
  516. package/dist/commands/promote.js +0 -6
  517. package/dist/commands/promote.js.map +0 -1
  518. package/dist/commands/read.d.ts +0 -6
  519. package/dist/commands/read.d.ts.map +0 -1
  520. package/dist/commands/read.js +0 -4
  521. package/dist/commands/read.js.map +0 -1
  522. package/dist/commands/recall.d.ts +0 -6
  523. package/dist/commands/recall.d.ts.map +0 -1
  524. package/dist/commands/recall.js +0 -4
  525. package/dist/commands/recall.js.map +0 -1
  526. package/dist/commands/record.d.ts +0 -6
  527. package/dist/commands/record.d.ts.map +0 -1
  528. package/dist/commands/record.js +0 -4
  529. package/dist/commands/record.js.map +0 -1
  530. package/dist/commands/search.d.ts +0 -6
  531. package/dist/commands/search.d.ts.map +0 -1
  532. package/dist/commands/search.js +0 -4
  533. package/dist/commands/search.js.map +0 -1
  534. package/dist/commands/supersede.d.ts +0 -6
  535. package/dist/commands/supersede.d.ts.map +0 -1
  536. package/dist/commands/supersede.js +0 -6
  537. package/dist/commands/supersede.js.map +0 -1
  538. package/dist/knowledge/sources.d.ts +0 -72
  539. package/dist/knowledge/sources.d.ts.map +0 -1
  540. package/dist/knowledge/sources.js +0 -388
  541. package/dist/knowledge/sources.js.map +0 -1
  542. package/dist/setup/opencode-evidence.d.ts +0 -37
  543. package/dist/setup/opencode-evidence.d.ts.map +0 -1
  544. package/dist/setup/opencode-evidence.js +0 -58
  545. package/dist/setup/opencode-evidence.js.map +0 -1
  546. package/dist/setup/opencode-loop-guard.d.ts +0 -9
  547. package/dist/setup/opencode-loop-guard.d.ts.map +0 -1
  548. package/dist/setup/opencode-loop-guard.js +0 -248
  549. package/dist/setup/opencode-loop-guard.js.map +0 -1
@@ -1,14 +1,26 @@
1
- import { randomUUID } from 'node:crypto';
2
- import { readFile } from 'node:fs/promises';
1
+ import { createHash, randomUUID } from 'node:crypto';
2
+ import { constants as fsConstants } from 'node:fs';
3
+ import { open } from 'node:fs/promises';
3
4
  import { TextDecoder } from 'node:util';
5
+ import { isProxy } from 'node:util/types';
4
6
  import { KiokukoError } from '../errors.js';
7
+ import { CAPABILITY_KINDS, MAX_CAPABILITY_NAME_CHARS, MEMORY_REASONING_SKILL_NAME, } from '../akinator/capabilities.js';
8
+ import { TASK_TYPES } from '../akinator/types.js';
9
+ import { CONTEXT_RANKING_COMPONENTS, CONTEXT_SELECTION_REASON_ORDER, } from '../context/ranking.js';
10
+ import { RECOMMENDATION_CODES } from '../context/recommendations.js';
11
+ import { findSecret } from '../memory/secrets.js';
5
12
  import { successEnvelope } from '../serialization/envelope.js';
13
+ import { cloneBoundaryJson as cloneStrictBoundaryJson, stringifyBoundaryJson, } from '../serialization/boundary-json.js';
14
+ import { AGENT_MUTATION_OPERATIONS, agentRequestBindingHash, } from '../server/routes/request-binding.js';
15
+ import { MAX_STRICT_JSON_DEPTH, parseStrictJson } from '../setup/strict-json.js';
6
16
  import { createServerClient, } from '../client/server-client.js';
7
17
  const MAX_INPUT_BYTES = 2 * 1024 * 1024;
8
18
  const MAX_ID_BYTES = 256;
9
19
  const MAX_TEXT_BYTES = 16 * 1024;
10
20
  const MAX_INPUT_PATH_BYTES = 4 * 1024;
21
+ const MAX_JSON_NODES = 262_144;
11
22
  const CONTROL_CHARACTERS = /\p{Cc}/u;
23
+ const UNSAFE_CAPABILITY_LABEL_CHARACTERS = /[\p{Cc}\p{Cf}]/u;
12
24
  const CAPTURE_PROFILES = new Set(['minimal', 'standard', 'full']);
13
25
  function validationError() {
14
26
  return new KiokukoError('VALIDATION_ERROR', 'Agent input is invalid');
@@ -23,13 +35,28 @@ function boundedString(value, maximumBytes) {
23
35
  function boundedId(value) {
24
36
  return boundedString(value, MAX_ID_BYTES);
25
37
  }
26
- function assertPlainObject(value) {
27
- if (typeof value !== 'object' || value === null || Array.isArray(value))
38
+ function boundedIdempotencyKey(value) {
39
+ const key = boundedString(value, MAX_ID_BYTES);
40
+ if (key.trim() !== key)
28
41
  throw validationError();
29
- const prototype = Object.getPrototypeOf(value);
30
- if (prototype !== Object.prototype && prototype !== null)
42
+ return key;
43
+ }
44
+ function cloneBoundaryJson(value, failure) {
45
+ return cloneStrictBoundaryJson(value, {
46
+ failure,
47
+ maximumDepth: MAX_STRICT_JSON_DEPTH,
48
+ maximumNodes: MAX_JSON_NODES,
49
+ maximumStringBytes: MAX_INPUT_BYTES,
50
+ });
51
+ }
52
+ function inputJson(value) {
53
+ return cloneBoundaryJson(value, validationError);
54
+ }
55
+ function inputObject(value) {
56
+ const cloned = inputJson(value);
57
+ if (typeof cloned !== 'object' || cloned === null || Array.isArray(cloned))
31
58
  throw validationError();
32
- return value;
59
+ return cloned;
33
60
  }
34
61
  function validateInputPath(value) {
35
62
  if (value === '-')
@@ -39,47 +66,110 @@ function validateInputPath(value) {
39
66
  async function readStdinBytes() {
40
67
  const chunks = [];
41
68
  let size = 0;
69
+ for await (const chunk of process.stdin) {
70
+ const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, 'utf8');
71
+ size += bytes.byteLength;
72
+ if (size > MAX_INPUT_BYTES)
73
+ throw validationError();
74
+ chunks.push(bytes);
75
+ }
76
+ return Buffer.concat(chunks);
77
+ }
78
+ const INPUT_FILESYSTEM_ERROR_CODES = new Set([
79
+ 'EACCES', 'EIO', 'EISDIR', 'EMFILE', 'ENFILE', 'ENOENT', 'ENOTDIR', 'EPERM',
80
+ ]);
81
+ function isInputFilesystemError(error) {
82
+ if ((typeof error !== 'object' && typeof error !== 'function') || error === null || isProxy(error))
83
+ return false;
84
+ const descriptor = Object.getOwnPropertyDescriptor(error, 'code');
85
+ return descriptor !== undefined && 'value' in descriptor
86
+ && typeof descriptor.value === 'string'
87
+ && INPUT_FILESYSTEM_ERROR_CODES.has(descriptor.value);
88
+ }
89
+ function isExactAgentKiokukoError(error) {
90
+ return typeof error === 'object' && error !== null && !isProxy(error)
91
+ && Object.getPrototypeOf(error) === KiokukoError.prototype;
92
+ }
93
+ async function readBoundedRegularFile(filePath, closeHandle) {
94
+ let handle;
42
95
  try {
43
- for await (const chunk of process.stdin) {
44
- const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, 'utf8');
45
- size += bytes.byteLength;
46
- if (size > MAX_INPUT_BYTES)
96
+ handle = await open(filePath, fsConstants.O_RDONLY | fsConstants.O_NONBLOCK);
97
+ }
98
+ catch (error) {
99
+ if (isInputFilesystemError(error))
100
+ throw validationError();
101
+ throw error;
102
+ }
103
+ let operationResult;
104
+ let operationFailed = false;
105
+ let operationError;
106
+ try {
107
+ const metadata = await handle.stat();
108
+ if (!metadata.isFile() || !Number.isSafeInteger(metadata.size) || metadata.size < 0
109
+ || metadata.size > MAX_INPUT_BYTES)
110
+ throw validationError();
111
+ const bytes = Buffer.allocUnsafe(MAX_INPUT_BYTES + 1);
112
+ let offset = 0;
113
+ while (offset <= MAX_INPUT_BYTES) {
114
+ const result = await handle.read(bytes, offset, bytes.byteLength - offset, null);
115
+ if (result.bytesRead === 0) {
116
+ operationResult = bytes.subarray(0, offset);
117
+ break;
118
+ }
119
+ offset += result.bytesRead;
120
+ if (offset > MAX_INPUT_BYTES)
47
121
  throw validationError();
48
- chunks.push(bytes);
49
122
  }
50
123
  }
51
124
  catch (error) {
52
- if (error instanceof KiokukoError)
53
- throw error;
54
- throw validationError();
125
+ operationFailed = true;
126
+ operationError = isExactAgentKiokukoError(error) && error.code === 'VALIDATION_ERROR'
127
+ ? error
128
+ : isInputFilesystemError(error)
129
+ ? validationError()
130
+ : error;
55
131
  }
56
- return Buffer.concat(chunks);
132
+ try {
133
+ await closeHandle(handle);
134
+ }
135
+ catch (closeError) {
136
+ if (operationFailed) {
137
+ throw new AggregateError([operationError, closeError], 'Agent input read failed and its file descriptor could not be closed');
138
+ }
139
+ throw closeError;
140
+ }
141
+ if (operationFailed)
142
+ throw operationError;
143
+ if (operationResult === undefined) {
144
+ throw new KiokukoError('INTEGRITY_ERROR', 'Agent input read produced no result');
145
+ }
146
+ return operationResult;
57
147
  }
58
- async function readStrictJsonInput(filePath) {
148
+ async function readStrictJsonInput(filePath, closeHandle) {
59
149
  const safePath = validateInputPath(filePath);
60
150
  let bytes;
61
- try {
62
- bytes = safePath === '-' ? await readStdinBytes() : await readFile(safePath);
151
+ if (safePath === '-') {
152
+ bytes = await readStdinBytes();
63
153
  }
64
- catch (error) {
65
- if (error instanceof KiokukoError)
66
- throw error;
67
- throw validationError();
154
+ else {
155
+ bytes = await readBoundedRegularFile(safePath, closeHandle);
68
156
  }
69
157
  if (bytes.byteLength > MAX_INPUT_BYTES)
70
158
  throw validationError();
71
159
  let text;
72
160
  try {
73
- text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
161
+ text = new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes);
74
162
  }
75
163
  catch {
76
164
  throw validationError();
77
165
  }
78
166
  try {
79
- return JSON.parse(text);
167
+ return parseStrictJson(text, { allowTrailingComma: false, disallowComments: true, allowEmptyContent: false }, 'Agent input is not valid JSON with unique keys');
80
168
  }
81
- catch {
82
- throw validationError();
169
+ catch (error) {
170
+ if (isExactAgentKiokukoError(error) && error.code === 'VALIDATION_ERROR')
171
+ throw validationError();
172
+ throw error;
83
173
  }
84
174
  }
85
175
  function captureProfile(value) {
@@ -102,88 +192,748 @@ function runPath(runId, suffix) {
102
192
  }
103
193
  function keyFromFactory(dependencies) {
104
194
  const factory = dependencies.idempotencyKeyFactory ?? randomUUID;
105
- try {
106
- return boundedString(factory(), MAX_ID_BYTES);
107
- }
108
- catch (error) {
109
- if (error instanceof KiokukoError)
110
- throw error;
111
- throw validationError();
112
- }
195
+ return boundedIdempotencyKey(factory());
196
+ }
197
+ function requestIdempotencyKey(value, dependencies) {
198
+ return value === undefined ? keyFromFactory(dependencies) : boundedIdempotencyKey(value);
113
199
  }
114
200
  function bodyAndKey(value, dependencies) {
115
201
  if (Object.prototype.hasOwnProperty.call(value, 'idempotencyKey')) {
116
- const idempotencyKey = boundedString(value.idempotencyKey, MAX_ID_BYTES);
202
+ const idempotencyKey = boundedIdempotencyKey(value.idempotencyKey);
117
203
  const { idempotencyKey: _removed, ...body } = value;
118
204
  return { body, idempotencyKey };
119
205
  }
120
206
  return { body: value, idempotencyKey: keyFromFactory(dependencies) };
121
207
  }
122
208
  async function readInput(dependencies, filePath) {
123
- const value = await (dependencies.readJsonInput === undefined
124
- ? readStrictJsonInput(filePath)
125
- : dependencies.readJsonInput(validateInputPath(filePath)));
126
- return assertPlainObject(value);
209
+ return inputObject(await readUnknownInput(dependencies, filePath));
210
+ }
211
+ async function readUnknownInput(dependencies, filePath) {
212
+ return dependencies.readJsonInput === undefined
213
+ ? readStrictJsonInput(filePath, dependencies.closeInputFile ?? ((handle) => handle.close()))
214
+ : dependencies.readJsonInput(validateInputPath(filePath));
215
+ }
216
+ async function readCapabilityCatalog(dependencies, filePath) {
217
+ const value = inputJson(await readUnknownInput(dependencies, filePath));
218
+ if (!Array.isArray(value))
219
+ throw validationError();
220
+ return value;
127
221
  }
128
222
  async function getClient(dependencies) {
129
223
  const factory = dependencies.createClient ?? createServerClient;
130
224
  const options = dependencies.fetchImplementation === undefined
131
225
  ? {}
132
226
  : { fetchImplementation: dependencies.fetchImplementation };
133
- try {
134
- return await factory(options);
135
- }
136
- catch (error) {
137
- if (error instanceof KiokukoError)
138
- throw error;
139
- throw new KiokukoError('SERVICE_UNAVAILABLE', 'Kiokuko server is unavailable');
227
+ return factory(options);
228
+ }
229
+ function runIdFromRequestPath(path) {
230
+ const match = /^\/api\/v1\/agent\/runs\/([^/]+)\/(?:intake\/answers|events|checkpoints|close|feedback)$/u.exec(path);
231
+ if (match?.[1] === undefined)
232
+ return undefined;
233
+ return decodeURIComponent(match[1]);
234
+ }
235
+ function responseBindingForRequest(request) {
236
+ if (!AGENT_MUTATION_OPERATIONS.includes(request.operation)) {
237
+ throw new TypeError('Agent request operation is invalid');
140
238
  }
239
+ const requestBody = inputObject(request.body);
240
+ return {
241
+ operation: request.operation,
242
+ expectedRunId: runIdFromRequestPath(request.path),
243
+ requestBody,
244
+ idempotencyKey: boundedIdempotencyKey(request.idempotencyKey),
245
+ };
141
246
  }
142
247
  async function sendRequest(dependencies, request) {
143
- try {
144
- return await (await getClient(dependencies)).request(request);
248
+ const binding = responseBindingForRequest(request);
249
+ if (request.operation !== 'agent.open' && binding.expectedRunId === undefined) {
250
+ throw new TypeError('Agent request path is not bound to a run');
145
251
  }
146
- catch (error) {
147
- if (error instanceof KiokukoError)
148
- throw error;
149
- throw new KiokukoError('SERVICE_UNAVAILABLE', 'Kiokuko server is unavailable');
252
+ const response = await (await getClient(dependencies)).request(request);
253
+ return validateAgentResponse(binding.operation, response, binding);
254
+ }
255
+ function responseIntegrityError() {
256
+ return new KiokukoError('INTEGRITY_ERROR', 'Agent server response is invalid');
257
+ }
258
+ function responseObject(value, required, optional = []) {
259
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
260
+ throw responseIntegrityError();
261
+ const object = value;
262
+ const keys = Object.keys(object);
263
+ const allowed = new Set([...required, ...optional]);
264
+ if (keys.some((key) => !allowed.has(key)) || required.some((key) => !Object.hasOwn(object, key))) {
265
+ throw responseIntegrityError();
150
266
  }
267
+ return object;
268
+ }
269
+ function responseArray(value, maximum) {
270
+ if (!Array.isArray(value) || value.length > maximum)
271
+ throw responseIntegrityError();
272
+ return value;
273
+ }
274
+ function responseString(value, maximumBytes = MAX_INPUT_BYTES, allowEmpty = false) {
275
+ if (typeof value !== 'string' || (!allowEmpty && value.length === 0)
276
+ || Buffer.byteLength(value, 'utf8') > maximumBytes)
277
+ throw responseIntegrityError();
278
+ return value;
279
+ }
280
+ function responseIdentifier(value) {
281
+ const result = responseString(value, MAX_INPUT_BYTES);
282
+ if (result.length > MAX_ID_BYTES || CONTROL_CHARACTERS.test(result))
283
+ throw responseIntegrityError();
284
+ return result;
285
+ }
286
+ function responseEventId(value) {
287
+ if (typeof value !== 'string' || value.trim().length === 0
288
+ || value.length > MAX_ID_BYTES || value.includes('\u0000'))
289
+ throw responseIntegrityError();
290
+ return value;
291
+ }
292
+ function responseEnum(value, allowed) {
293
+ if (typeof value !== 'string' || !allowed.includes(value))
294
+ throw responseIntegrityError();
295
+ return value;
296
+ }
297
+ function responseInteger(value, minimum = 0, maximum = Number.MAX_SAFE_INTEGER) {
298
+ if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < minimum || value > maximum) {
299
+ throw responseIntegrityError();
300
+ }
301
+ return value;
302
+ }
303
+ function responseHash(value) {
304
+ if (typeof value !== 'string' || !/^[0-9a-f]{64}$/u.test(value))
305
+ throw responseIntegrityError();
306
+ return value;
307
+ }
308
+ function validateRequestBindingHash(object, binding) {
309
+ const actual = responseHash(object.requestBindingHash);
310
+ const expected = agentRequestBindingHash({
311
+ operation: binding.operation,
312
+ pathRunId: binding.expectedRunId ?? null,
313
+ idempotencyKey: binding.idempotencyKey,
314
+ requestBody: binding.requestBody,
315
+ });
316
+ if (actual !== expected)
317
+ throw responseIntegrityError();
318
+ }
319
+ function responseTimestamp(value) {
320
+ if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u.test(value)) {
321
+ throw responseIntegrityError();
322
+ }
323
+ const timestamp = Date.parse(value);
324
+ if (!Number.isFinite(timestamp) || new Date(timestamp).toISOString() !== value)
325
+ throw responseIntegrityError();
326
+ return value;
327
+ }
328
+ function responseStringArray(value, maximum, allowed) {
329
+ const items = responseArray(value, maximum).map((item) => responseString(item, MAX_TEXT_BYTES));
330
+ if (new Set(items).size !== items.length || (allowed !== undefined && items.some((item) => !allowed.includes(item)))) {
331
+ throw responseIntegrityError();
332
+ }
333
+ return items;
334
+ }
335
+ function sameResponseValue(left, right) {
336
+ return stringifyBoundaryJson(cloneBoundaryJson(left, responseIntegrityError))
337
+ === stringifyBoundaryJson(cloneBoundaryJson(right, responseIntegrityError));
151
338
  }
152
- function responseStatus(data) {
153
- if (typeof data !== 'object' || data === null || Array.isArray(data))
154
- return 'completed';
155
- const value = data;
156
- for (const field of ['intakeStatus', 'runStatus', 'status']) {
157
- if (typeof value[field] === 'string')
158
- return value[field];
339
+ const PROFILE_FIELDS = ['taskType', 'target', 'expected', 'constraints'];
340
+ const INTAKE_STATUSES = ['needs_answer', 'ready', 'exhausted'];
341
+ const ACTIVE_RUN_STATUSES = ['intake', 'active'];
342
+ const TERMINAL_RUN_STATUSES = ['completed', 'failed', 'cancelled', 'interrupted'];
343
+ const CAPABILITY_AVAILABILITIES = ['known-empty', 'known-nonempty', 'unknown'];
344
+ const CAPABILITY_RECOMMENDATION_AVAILABILITIES = ['available', 'missing', 'unknown'];
345
+ const COVERAGE_FIELDS = ['run', 'tool', 'command', 'file', 'approval'];
346
+ const COVERAGE_LEVELS = ['complete', 'best_effort', 'declared', 'unavailable'];
347
+ const CAPABILITY_WARNING_CODES = [
348
+ 'CAPABILITY_CATALOG_COMPACTED',
349
+ 'CAPABILITY_CATALOG_ITEMS_DROPPED',
350
+ 'CAPABILITY_CATALOG_BUDGET_EXCEEDED',
351
+ 'CAPABILITY_CATALOG_UNAVAILABLE',
352
+ ];
353
+ function validateTaskProfileSchema(value, withSource = false) {
354
+ const object = responseObject(value, withSource ? [...PROFILE_FIELDS, 'source'] : PROFILE_FIELDS);
355
+ if (object.taskType !== null)
356
+ responseEnum(object.taskType, TASK_TYPES);
357
+ for (const field of ['target', 'expected', 'constraints']) {
358
+ if (object[field] !== null)
359
+ responseString(object[field], MAX_INPUT_BYTES, true);
159
360
  }
160
- return 'completed';
361
+ if (withSource && object.source !== 'akinator+ledger-revisions')
362
+ throw responseIntegrityError();
363
+ return object;
161
364
  }
162
- function responseQuestion(data) {
163
- if (typeof data !== 'object' || data === null || Array.isArray(data))
365
+ function validateQuestion(value) {
366
+ if (value === null)
367
+ return null;
368
+ const object = responseObject(value, ['id', 'prompt', 'options', 'required']);
369
+ responseEnum(object.id, PROFILE_FIELDS);
370
+ responseString(object.prompt, MAX_TEXT_BYTES);
371
+ if (object.options !== null)
372
+ responseStringArray(object.options, 100);
373
+ if (typeof object.required !== 'boolean')
374
+ throw responseIntegrityError();
375
+ return object;
376
+ }
377
+ function validateCapabilityWarnings(value) {
378
+ const warnings = responseArray(value, CAPABILITY_WARNING_CODES.length);
379
+ const seen = new Set();
380
+ for (const warning of warnings) {
381
+ const object = responseObject(warning, ['code', 'message']);
382
+ const code = responseEnum(object.code, CAPABILITY_WARNING_CODES);
383
+ responseString(object.message, MAX_TEXT_BYTES);
384
+ if (seen.has(code))
385
+ throw responseIntegrityError();
386
+ seen.add(code);
387
+ }
388
+ return warnings;
389
+ }
390
+ function validateCapabilityRecommendations(value) {
391
+ const recommendations = responseArray(value, 205);
392
+ for (const recommendation of recommendations) {
393
+ const object = responseObject(recommendation, ['kind', 'name', 'availability', 'reason', 'source'], ['required']);
394
+ responseEnum(object.kind, CAPABILITY_KINDS);
395
+ const name = responseString(object.name, MAX_INPUT_BYTES);
396
+ if (Array.from(name).length > MAX_CAPABILITY_NAME_CHARS
397
+ || name.trim() !== name || UNSAFE_CAPABILITY_LABEL_CHARACTERS.test(name))
398
+ throw responseIntegrityError();
399
+ responseEnum(object.availability, CAPABILITY_RECOMMENDATION_AVAILABILITIES);
400
+ responseString(object.reason, MAX_TEXT_BYTES);
401
+ responseEnum(object.source, ['akinator_policy', 'catalog_similarity']);
402
+ if (Object.hasOwn(object, 'required') && typeof object.required !== 'boolean')
403
+ throw responseIntegrityError();
404
+ }
405
+ return recommendations;
406
+ }
407
+ function validateCapabilities(value) {
408
+ const object = responseObject(value, [
409
+ 'availability', 'catalogProvided', 'availableSkillCount', 'diagnostics', 'warnings', 'recommendations',
410
+ ]);
411
+ const availability = responseEnum(object.availability, CAPABILITY_AVAILABILITIES);
412
+ if (typeof object.catalogProvided !== 'boolean' || object.catalogProvided !== (availability !== 'unknown')) {
413
+ throw responseIntegrityError();
414
+ }
415
+ if (availability === 'unknown') {
416
+ if (object.availableSkillCount !== null)
417
+ throw responseIntegrityError();
418
+ }
419
+ else {
420
+ responseInteger(object.availableSkillCount);
421
+ }
422
+ const diagnostics = responseObject(object.diagnostics, ['received', 'accepted', 'truncated', 'dropped']);
423
+ for (const field of ['received', 'accepted', 'truncated', 'dropped'])
424
+ responseInteger(diagnostics[field]);
425
+ if (diagnostics.accepted > diagnostics.received
426
+ || diagnostics.truncated > diagnostics.accepted)
427
+ throw responseIntegrityError();
428
+ validateCapabilityWarnings(object.warnings);
429
+ validateCapabilityRecommendations(object.recommendations);
430
+ return object;
431
+ }
432
+ function validateContextRecommendation(value) {
433
+ const object = responseObject(value, [
434
+ 'code', 'message', 'evidenceEventIds', 'priority', 'untrusted', 'actionable', 'metadata',
435
+ ]);
436
+ responseEnum(object.code, RECOMMENDATION_CODES);
437
+ responseString(object.message, MAX_TEXT_BYTES);
438
+ responseInteger(object.priority, 1, RECOMMENDATION_CODES.length);
439
+ if (object.untrusted !== true
440
+ || object.actionable !== false)
441
+ throw responseIntegrityError();
442
+ responseStringArray(object.evidenceEventIds, 16);
443
+ const metadata = responseObject(object.metadata, ['truncated', 'referenceIds'], ['incompleteCoverageCategories']);
444
+ if (typeof metadata.truncated !== 'boolean')
445
+ throw responseIntegrityError();
446
+ responseStringArray(metadata.referenceIds, 16);
447
+ if (Object.hasOwn(metadata, 'incompleteCoverageCategories')) {
448
+ responseStringArray(metadata.incompleteCoverageCategories, COVERAGE_FIELDS.length, COVERAGE_FIELDS);
449
+ }
450
+ return object;
451
+ }
452
+ function validateContextRecommendations(value) {
453
+ const recommendations = responseArray(value, RECOMMENDATION_CODES.length);
454
+ const codes = new Set();
455
+ for (const recommendation of recommendations) {
456
+ const object = validateContextRecommendation(recommendation);
457
+ const code = object.code;
458
+ if (codes.has(code))
459
+ throw responseIntegrityError();
460
+ codes.add(code);
461
+ }
462
+ return recommendations;
463
+ }
464
+ function validateScoreComponentsSchema(value) {
465
+ const score = responseObject(value, CONTEXT_RANKING_COMPONENTS);
466
+ for (const field of CONTEXT_RANKING_COMPONENTS) {
467
+ if (typeof score[field] !== 'number' || !Number.isSafeInteger(score[field])
468
+ || score[field] < -1_000_000 || score[field] > 1_000_000) {
469
+ throw responseIntegrityError();
470
+ }
471
+ }
472
+ }
473
+ function validateContextSchema(value) {
474
+ if (value === null)
475
+ return null;
476
+ const object = responseObject(value, [
477
+ 'deliveryId', 'runId', 'throughSequence', 'taskProfileHash', 'queryHash', 'policyVersion', 'items', 'untrusted',
478
+ ]);
479
+ if (object.deliveryId !== null)
480
+ responseIdentifier(object.deliveryId);
481
+ responseIdentifier(object.runId);
482
+ responseInteger(object.throughSequence);
483
+ responseHash(object.taskProfileHash);
484
+ responseHash(object.queryHash);
485
+ if (object.policyVersion !== 'context-ranking-v1+recommendations.v1' || object.untrusted !== true) {
486
+ throw responseIntegrityError();
487
+ }
488
+ const items = responseArray(object.items, 100);
489
+ const entryIds = new Set();
490
+ for (const value of items) {
491
+ const item = responseObject(value, [
492
+ 'entryId', 'entryRevision', 'rank', 'scoreComponents', 'selectionReasons', 'content', 'untrusted',
493
+ ], ['origin']);
494
+ const entryId = responseIdentifier(item.entryId);
495
+ if (entryIds.has(entryId))
496
+ throw responseIntegrityError();
497
+ entryIds.add(entryId);
498
+ responseInteger(item.entryRevision, 1);
499
+ responseInteger(item.rank, 1);
500
+ if (item.untrusted !== true)
501
+ throw responseIntegrityError();
502
+ validateScoreComponentsSchema(item.scoreComponents);
503
+ const selectionReasons = responseStringArray(item.selectionReasons, CONTEXT_SELECTION_REASON_ORDER.length, CONTEXT_SELECTION_REASON_ORDER);
504
+ if (selectionReasons.length === 0)
505
+ throw responseIntegrityError();
506
+ const content = responseObject(item.content, ['title', 'summary', 'bodyPreview', 'characterCount', 'truncated']);
507
+ responseString(content.title, MAX_INPUT_BYTES, true);
508
+ if (content.summary !== null)
509
+ responseString(content.summary, MAX_INPUT_BYTES, true);
510
+ responseString(content.bodyPreview, MAX_INPUT_BYTES, true);
511
+ responseInteger(content.characterCount);
512
+ if (typeof content.truncated !== 'boolean')
513
+ throw responseIntegrityError();
514
+ if (Object.hasOwn(item, 'origin'))
515
+ responseEnum(item.origin, ['project', 'ecosystem', 'global']);
516
+ }
517
+ return object;
518
+ }
519
+ function preservedEventId(value) {
520
+ if (typeof value !== 'string')
164
521
  return undefined;
165
- const value = data;
166
- const question = value.currentQuestion;
167
- if (typeof question !== 'object' || question === null || Array.isArray(question))
522
+ responseIdentifier(value);
523
+ return /^[A-Za-z0-9._:-]+$/u.test(value) && findSecret(value) === undefined ? value : undefined;
524
+ }
525
+ function validateAckFields(object) {
526
+ responseIdentifier(object.runId);
527
+ const acceptedThrough = responseInteger(object.acceptedThrough, 1);
528
+ const localSequences = responseArray(object.localSequences, 200).map((value) => responseInteger(value, 1));
529
+ const sourceSequences = responseArray(object.sourceSequences, 200).map((value) => value === null ? null : responseInteger(value));
530
+ const eventIds = responseArray(object.eventIds, 200).map(responseEventId);
531
+ if (new Set(eventIds).size !== eventIds.length)
532
+ throw responseIntegrityError();
533
+ if (localSequences.length === 0 || localSequences.length !== sourceSequences.length || localSequences.length !== eventIds.length
534
+ || new Set(localSequences).size !== localSequences.length
535
+ || localSequences.some((sequence, index) => index > 0 && sequence <= localSequences[index - 1])
536
+ || localSequences.at(-1) !== acceptedThrough)
537
+ throw responseIntegrityError();
538
+ return { acceptedThrough, localSequences, sourceSequences, eventIds };
539
+ }
540
+ function expectedEventAck(value) {
541
+ const events = responseArray(value, 200);
542
+ if (events.length === 0)
543
+ throw responseIntegrityError();
544
+ const sourceSequences = [];
545
+ const eventIds = [];
546
+ for (const event of events) {
547
+ const object = responseObject(event, ['eventType', 'actor', 'payload'], [
548
+ 'eventId', 'sourceEventId', 'sourceSequence', 'sourceType', 'outcome', 'occurredAt',
549
+ ]);
550
+ // The gateway sanitizes event identifiers before persistence, and the CLI
551
+ // does not know the run workspace required to reproduce that transform.
552
+ // Bind the count/order/source sequence here; the response schema still
553
+ // requires unique, bounded event IDs.
554
+ eventIds.push(preservedEventId(object.eventId));
555
+ sourceSequences.push(Object.hasOwn(object, 'sourceSequence')
556
+ ? responseInteger(object.sourceSequence)
557
+ : null);
558
+ }
559
+ return { sourceSequences, eventIds };
560
+ }
561
+ function validateExpectedAck(ack, expected, exactCardinality = true) {
562
+ const orderedSources = (values) => [...values]
563
+ .sort((left, right) => left === null ? (right === null ? 0 : -1) : right === null ? 1 : left - right);
564
+ const explicitIds = expected.eventIds.filter((value) => value !== undefined);
565
+ if (new Set(explicitIds).size !== explicitIds.length
566
+ || (exactCardinality && ack.sourceSequences.length !== expected.sourceSequences.length)
567
+ || (!exactCardinality && ack.sourceSequences.length < expected.sourceSequences.length)) {
568
+ throw responseIntegrityError();
569
+ }
570
+ if (exactCardinality
571
+ && !sameResponseValue(orderedSources(ack.sourceSequences), orderedSources(expected.sourceSequences))) {
572
+ throw responseIntegrityError();
573
+ }
574
+ if (!exactCardinality) {
575
+ const remaining = [...ack.sourceSequences];
576
+ for (const source of expected.sourceSequences) {
577
+ const index = remaining.indexOf(source);
578
+ if (index < 0)
579
+ throw responseIntegrityError();
580
+ remaining.splice(index, 1);
581
+ }
582
+ }
583
+ for (let expectedIndex = 0; expectedIndex < expected.eventIds.length; expectedIndex += 1) {
584
+ const expectedId = expected.eventIds[expectedIndex];
585
+ if (expectedId === undefined)
586
+ continue;
587
+ let actualIndex = -1;
588
+ for (let index = 0; index < ack.eventIds.length; index += 1) {
589
+ if (ack.eventIds[index] === expectedId) {
590
+ actualIndex = index;
591
+ break;
592
+ }
593
+ }
594
+ if (actualIndex < 0 || ack.sourceSequences[actualIndex] !== expected.sourceSequences[expectedIndex]) {
595
+ throw responseIntegrityError();
596
+ }
597
+ }
598
+ }
599
+ function validateAppendResponse(value, binding) {
600
+ const object = responseObject(value, [
601
+ 'runId', 'acceptedThrough', 'localSequences', 'sourceSequences', 'eventIds', 'runStatus', 'untrusted',
602
+ 'requestBindingHash',
603
+ ]);
604
+ validateRequestBindingHash(object, binding);
605
+ const ack = validateAckFields(object);
606
+ if (object.runId !== binding.expectedRunId)
607
+ throw responseIntegrityError();
608
+ const request = responseObject(binding.requestBody, ['apiVersion', 'events']);
609
+ if (request.apiVersion !== '1')
610
+ throw responseIntegrityError();
611
+ responseEnum(object.runStatus, ACTIVE_RUN_STATUSES);
612
+ const expected = expectedEventAck(request.events);
613
+ validateExpectedAck(ack, expected);
614
+ if (object.untrusted !== true)
615
+ throw responseIntegrityError();
616
+ return object;
617
+ }
618
+ function validateCloseResponse(value, binding) {
619
+ const object = responseObject(value, [
620
+ 'runId', 'acceptedThrough', 'localSequences', 'sourceSequences', 'eventIds',
621
+ 'status', 'runStatus', 'untrusted', 'requestBindingHash',
622
+ ]);
623
+ validateRequestBindingHash(object, binding);
624
+ const ack = validateAckFields(object);
625
+ if (object.runId !== binding.expectedRunId)
626
+ throw responseIntegrityError();
627
+ const request = responseObject(binding.requestBody, ['apiVersion', 'status'], ['events']);
628
+ if (request.apiVersion !== '1')
629
+ throw responseIntegrityError();
630
+ if (Object.hasOwn(request, 'events')) {
631
+ const expected = expectedEventAck(request.events);
632
+ if (ack.eventIds.length !== expected.eventIds.length + 1)
633
+ throw responseIntegrityError();
634
+ validateExpectedAck(ack, expected, false);
635
+ }
636
+ else if (ack.eventIds.length !== 1) {
637
+ throw responseIntegrityError();
638
+ }
639
+ const status = responseEnum(object.status, TERMINAL_RUN_STATUSES);
640
+ if (status !== request.status || object.runStatus !== status || object.untrusted !== true)
641
+ throw responseIntegrityError();
642
+ return object;
643
+ }
644
+ function validateCoverage(value) {
645
+ const object = responseObject(value, COVERAGE_FIELDS);
646
+ for (const field of COVERAGE_FIELDS)
647
+ responseEnum(object[field], COVERAGE_LEVELS);
648
+ return object;
649
+ }
650
+ function validateProjectionSchema(value) {
651
+ const object = responseObject(value, [
652
+ 'throughSequence', 'taskProfile', 'profileHash', 'evidenceState', 'unresolvedFailureEventIds',
653
+ 'unknownOutcomeEventIds', 'latestMutationSequence', 'latestPassingVerificationSequence', 'coverage',
654
+ 'declaredCoverage', 'intakeIncomplete', 'missingProfileFields',
655
+ ]);
656
+ responseInteger(object.throughSequence);
657
+ validateTaskProfileSchema(object.taskProfile);
658
+ responseHash(object.profileHash);
659
+ responseEnum(object.evidenceState, ['none', 'failed', 'fresh', 'stale']);
660
+ responseArray(object.unresolvedFailureEventIds, 4096).forEach(responseEventId);
661
+ responseArray(object.unknownOutcomeEventIds, 4096).forEach(responseEventId);
662
+ for (const field of ['latestMutationSequence', 'latestPassingVerificationSequence']) {
663
+ if (object[field] !== null)
664
+ responseInteger(object[field], 1);
665
+ }
666
+ responseEnum(object.coverage, ['complete', 'partial']);
667
+ validateCoverage(object.declaredCoverage);
668
+ if (typeof object.intakeIncomplete !== 'boolean')
669
+ throw responseIntegrityError();
670
+ const projectionMissingFields = ['taskType', 'target', 'expected'];
671
+ responseStringArray(object.missingProfileFields, projectionMissingFields.length, projectionMissingFields);
672
+ return object;
673
+ }
674
+ function validateCapabilityGate(object, intakeNeedsAnswer, requiresMemoryReasoning) {
675
+ const capabilities = validateCapabilities(object.capabilities);
676
+ const warnings = validateCapabilityWarnings(object.warnings);
677
+ if (!sameResponseValue(warnings, capabilities.warnings))
678
+ throw responseIntegrityError();
679
+ validateContextRecommendations(object.recommendations);
680
+ const nextAction = responseEnum(object.nextAction, [
681
+ 'proceed', 'answer_from_evidence_or_ask_user', 'required_capability_unavailable',
682
+ ]);
683
+ const capabilityRecommendations = capabilities.recommendations;
684
+ const required = capabilityRecommendations.filter((recommendation) => (recommendation.required === true));
685
+ const memoryRecommendations = capabilityRecommendations.filter((recommendation) => (recommendation.name === MEMORY_REASONING_SKILL_NAME));
686
+ let memoryAvailability;
687
+ if (requiresMemoryReasoning) {
688
+ if (required.length !== 1 || memoryRecommendations.length !== 1)
689
+ throw responseIntegrityError();
690
+ const memory = memoryRecommendations[0];
691
+ if (memory.kind !== 'skill' || memory.name !== MEMORY_REASONING_SKILL_NAME
692
+ || memory.source !== 'akinator_policy' || memory.required !== true)
693
+ throw responseIntegrityError();
694
+ memoryAvailability = memory.availability;
695
+ }
696
+ else if (required.length !== 0 || memoryRecommendations.length !== 0) {
697
+ throw responseIntegrityError();
698
+ }
699
+ const expectedAction = intakeNeedsAnswer
700
+ ? 'answer_from_evidence_or_ask_user'
701
+ : requiresMemoryReasoning && memoryAvailability !== 'available'
702
+ ? 'required_capability_unavailable'
703
+ : 'proceed';
704
+ if (nextAction !== expectedAction)
705
+ throw responseIntegrityError();
706
+ if (nextAction === 'required_capability_unavailable'
707
+ && (object.context !== null || object.recommendations.length !== 0))
708
+ throw responseIntegrityError();
709
+ return nextAction;
710
+ }
711
+ function validateMemoryPolicy(value) {
712
+ const policy = responseObject(value, ['memoryReasoningRequired']);
713
+ if (typeof policy.memoryReasoningRequired !== 'boolean')
714
+ throw responseIntegrityError();
715
+ return policy.memoryReasoningRequired;
716
+ }
717
+ function validateIntakeResponse(value, binding) {
718
+ const object = responseObject(value, [
719
+ 'runId', 'runStatus', 'intakeSessionId', 'intakeStatus', 'intake', 'question', 'currentQuestion',
720
+ 'missingFields', 'recommendedTags', 'taskProfile', 'profileHash', 'context', 'untrusted',
721
+ 'recommendations', 'capabilities', 'memoryPolicy', 'warnings', 'nextAction', 'requestBindingHash',
722
+ ]);
723
+ validateRequestBindingHash(object, binding);
724
+ const runId = responseIdentifier(object.runId);
725
+ if (binding.expectedRunId !== undefined && runId !== binding.expectedRunId)
726
+ throw responseIntegrityError();
727
+ const runStatus = responseEnum(object.runStatus, ACTIVE_RUN_STATUSES);
728
+ const intakeSessionId = responseIdentifier(object.intakeSessionId);
729
+ const intakeStatus = responseEnum(object.intakeStatus, INTAKE_STATUSES);
730
+ const intake = responseObject(object.intake, ['status', 'sessionId', 'question']);
731
+ const question = validateQuestion(object.question);
732
+ const currentQuestion = validateQuestion(object.currentQuestion);
733
+ if (intake.status !== intakeStatus || intake.sessionId !== intakeSessionId
734
+ || !sameResponseValue(intake.question, question) || !sameResponseValue(currentQuestion, question)) {
735
+ throw responseIntegrityError();
736
+ }
737
+ validateTaskProfileSchema(object.taskProfile);
738
+ const requiredProfileFields = ['taskType', 'target', 'expected'];
739
+ responseStringArray(object.missingFields, requiredProfileFields.length, requiredProfileFields);
740
+ responseStringArray(object.recommendedTags, 10);
741
+ const needsAnswer = intakeStatus === 'needs_answer';
742
+ if (needsAnswer) {
743
+ if (runStatus !== 'intake' || question === null || object.profileHash !== null || object.context !== null) {
744
+ throw responseIntegrityError();
745
+ }
746
+ if (object.recommendations.length !== 0)
747
+ throw responseIntegrityError();
748
+ }
749
+ else {
750
+ if (runStatus !== 'active' || question !== null)
751
+ throw responseIntegrityError();
752
+ responseHash(object.profileHash);
753
+ }
754
+ if (object.untrusted !== true)
755
+ throw responseIntegrityError();
756
+ const context = needsAnswer ? null : validateContextSchema(object.context);
757
+ if (context !== null && (context.runId !== runId || context.taskProfileHash !== object.profileHash)) {
758
+ throw responseIntegrityError();
759
+ }
760
+ const requiresMemoryReasoning = validateMemoryPolicy(object.memoryPolicy);
761
+ const nextAction = validateCapabilityGate(object, needsAnswer, requiresMemoryReasoning);
762
+ if (!needsAnswer) {
763
+ if (nextAction === 'proceed' && context === null)
764
+ throw responseIntegrityError();
765
+ }
766
+ return object;
767
+ }
768
+ function checkpointExpectedAck(body) {
769
+ return Object.hasOwn(body, 'events') ? expectedEventAck(body.events) : undefined;
770
+ }
771
+ function validateCheckpointResponse(value, binding) {
772
+ const object = responseObject(value, [
773
+ 'runId', 'acceptedThrough', 'localSequences', 'sourceSequences', 'eventIds', 'runStatus', 'intakeStatus',
774
+ 'taskProfile', 'profileHash', 'projection', 'recommendations', 'characterBudget', 'context', 'untrusted',
775
+ 'capabilities', 'memoryPolicy', 'warnings', 'nextAction', 'requestBindingHash',
776
+ ]);
777
+ validateRequestBindingHash(object, binding);
778
+ const ack = validateAckFields(object);
779
+ const expectedAck = checkpointExpectedAck(binding.requestBody);
780
+ const runId = responseIdentifier(object.runId);
781
+ if (runId !== binding.expectedRunId)
782
+ throw responseIntegrityError();
783
+ if (expectedAck !== undefined)
784
+ validateExpectedAck(ack, expectedAck, false);
785
+ if (object.runStatus !== 'active')
786
+ throw responseIntegrityError();
787
+ responseEnum(object.intakeStatus, ['ready', 'exhausted']);
788
+ validateTaskProfileSchema(object.taskProfile, true);
789
+ responseHash(object.profileHash);
790
+ validateProjectionSchema(object.projection);
791
+ responseInteger(object.characterBudget, 1, 100_000);
792
+ if (object.untrusted !== true)
793
+ throw responseIntegrityError();
794
+ const context = validateContextSchema(object.context);
795
+ if (context !== null && (context.runId !== runId || context.taskProfileHash !== object.profileHash)) {
796
+ throw responseIntegrityError();
797
+ }
798
+ const requiresMemoryReasoning = validateMemoryPolicy(object.memoryPolicy);
799
+ const nextAction = validateCapabilityGate(object, false, requiresMemoryReasoning);
800
+ if (nextAction === 'proceed') {
801
+ if (context === null)
802
+ throw responseIntegrityError();
803
+ }
804
+ return object;
805
+ }
806
+ function validateFeedbackRecord(category, value) {
807
+ const common = ['feedbackId', 'workspace', 'runId', 'actor', 'idempotencyKeyHash', 'createdAt'];
808
+ const nullableText = (candidate, maximumBytes = 4 * 1024) => {
809
+ if (candidate !== null)
810
+ responseString(candidate, maximumBytes);
811
+ };
812
+ if (category === 'context') {
813
+ const object = responseObject(value, [...common, 'deliveryId', 'entryId', 'verdict', 'comment']);
814
+ for (const field of ['feedbackId', 'workspace', 'runId', 'actor', 'deliveryId', 'entryId'])
815
+ responseIdentifier(object[field]);
816
+ responseEnum(object.verdict, ['helpful', 'irrelevant', 'stale', 'conflicting']);
817
+ nullableText(object.comment);
818
+ responseHash(object.idempotencyKeyHash);
819
+ responseTimestamp(object.createdAt);
820
+ return object;
821
+ }
822
+ if (category === 'intake') {
823
+ const object = responseObject(value, [...common, 'sessionId', 'questionId', 'profileField', 'verdict', 'comment']);
824
+ for (const field of ['feedbackId', 'workspace', 'runId', 'actor', 'sessionId'])
825
+ responseIdentifier(object[field]);
826
+ for (const field of ['questionId', 'profileField']) {
827
+ if (object[field] !== null)
828
+ responseEnum(object[field], PROFILE_FIELDS);
829
+ }
830
+ if ((object.questionId === null) === (object.profileField === null))
831
+ throw responseIntegrityError();
832
+ responseEnum(object.verdict, ['helpful', 'unnecessary', 'corrected']);
833
+ nullableText(object.comment);
834
+ responseHash(object.idempotencyKeyHash);
835
+ responseTimestamp(object.createdAt);
836
+ return object;
837
+ }
838
+ const object = responseObject(value, [
839
+ ...common, 'outcome', 'recommendationCode', 'recommendationVerdict', 'rating', 'comment',
840
+ ]);
841
+ for (const field of ['feedbackId', 'workspace', 'runId', 'actor'])
842
+ responseIdentifier(object[field]);
843
+ nullableText(object.outcome);
844
+ if (object.recommendationCode !== null) {
845
+ const recommendationCode = responseString(object.recommendationCode, MAX_INPUT_BYTES);
846
+ if (recommendationCode.length > MAX_ID_BYTES)
847
+ throw responseIntegrityError();
848
+ }
849
+ nullableText(object.comment);
850
+ if (object.recommendationVerdict !== null)
851
+ responseEnum(object.recommendationVerdict, ['accepted', 'dismissed', 'resolved']);
852
+ if ((object.recommendationCode === null) !== (object.recommendationVerdict === null))
853
+ throw responseIntegrityError();
854
+ if (object.rating !== null)
855
+ responseInteger(object.rating, 1, 5);
856
+ if (object.outcome === null && object.recommendationCode === null && object.rating === null)
857
+ throw responseIntegrityError();
858
+ responseHash(object.idempotencyKeyHash);
859
+ responseTimestamp(object.createdAt);
860
+ return object;
861
+ }
862
+ function validateFeedbackBinding(category, record, binding) {
863
+ if (binding.requestBody.category !== category
864
+ || binding.requestBody.feedbackId !== record.feedbackId
865
+ || record.runId !== binding.expectedRunId
866
+ || record.idempotencyKeyHash !== createHash('sha256').update(binding.idempotencyKey, 'utf8').digest('hex')) {
867
+ throw responseIntegrityError();
868
+ }
869
+ }
870
+ function validateFeedbackResponse(value, binding) {
871
+ const object = responseObject(value, ['category', 'record', 'untrusted', 'requestBindingHash']);
872
+ validateRequestBindingHash(object, binding);
873
+ const category = responseEnum(object.category, ['context', 'recommendation', 'intake', 'run']);
874
+ const record = validateFeedbackRecord(category, object.record);
875
+ validateFeedbackBinding(category, record, binding);
876
+ if (object.untrusted !== true)
877
+ throw responseIntegrityError();
878
+ return object;
879
+ }
880
+ function validateAgentResponse(operation, value, binding) {
881
+ const cloned = cloneBoundaryJson(value, responseIntegrityError);
882
+ if (Buffer.byteLength(stringifyBoundaryJson(cloned), 'utf8') > MAX_INPUT_BYTES)
883
+ throw responseIntegrityError();
884
+ switch (operation) {
885
+ case 'agent.open': return validateIntakeResponse(cloned, binding);
886
+ case 'agent.answer': return validateIntakeResponse(cloned, binding);
887
+ case 'agent.events': return validateAppendResponse(cloned, binding);
888
+ case 'agent.checkpoint': return validateCheckpointResponse(cloned, binding);
889
+ case 'agent.close': return validateCloseResponse(cloned, binding);
890
+ case 'agent.feedback': return validateFeedbackResponse(cloned, binding);
891
+ default: throw responseIntegrityError();
892
+ }
893
+ }
894
+ function responseStatus(operation, data) {
895
+ if (data.nextAction === 'required_capability_unavailable')
896
+ return data.nextAction;
897
+ switch (operation) {
898
+ case 'agent.open':
899
+ case 'agent.answer':
900
+ case 'agent.checkpoint': return data.intakeStatus;
901
+ case 'agent.events': return data.runStatus;
902
+ case 'agent.close': return data.status;
903
+ case 'agent.feedback': return 'recorded';
904
+ default: throw responseIntegrityError();
905
+ }
906
+ }
907
+ function responseQuestion(operation, data) {
908
+ if (operation !== 'agent.open' && operation !== 'agent.answer')
168
909
  return undefined;
169
- const id = question.id;
170
- return typeof id === 'string' ? id : undefined;
910
+ const question = data.currentQuestion;
911
+ return question === null ? undefined : question.id;
912
+ }
913
+ function requiredCapabilitySummary(data) {
914
+ const capabilities = data.capabilities;
915
+ const recommendations = capabilities.recommendations;
916
+ const labels = recommendations
917
+ .filter((recommendation) => recommendation.required === true && recommendation.availability !== 'available')
918
+ .map((recommendation) => `${recommendation.name} (${recommendation.availability})`);
919
+ if (labels.length === 0)
920
+ throw responseIntegrityError();
921
+ return `; required capabilities unavailable: ${labels.join(', ')}`;
171
922
  }
172
923
  function humanSummary(operation, data) {
173
- const question = responseQuestion(data);
174
- const status = responseStatus(data);
175
- const context = typeof data === 'object' && data !== null && !Array.isArray(data)
176
- && data.context !== null
177
- && data.context !== undefined
178
- ? '; initial context available'
179
- : '';
924
+ const question = responseQuestion(operation, data);
925
+ const status = responseStatus(operation, data);
926
+ const context = data.context !== null && data.context !== undefined ? '; initial context available' : '';
927
+ const required = status === 'required_capability_unavailable' ? requiredCapabilitySummary(data) : '';
180
928
  return question === undefined
181
- ? `Kiokuko ${operation}: ${status}${context}`
182
- : `Kiokuko ${operation}: ${status} (current question ${question})${context}`;
929
+ ? `Kiokuko ${operation}: ${status}${required}${context}`
930
+ : `Kiokuko ${operation}: ${status} (current question ${question})${required}${context}`;
183
931
  }
184
932
  function emitResult(json, operation, data) {
185
- if (json)
186
- process.stdout.write(`${JSON.stringify(successEnvelope(operation, data))}\n`);
933
+ if (json) {
934
+ const envelope = cloneBoundaryJson(successEnvelope(operation, data), responseIntegrityError);
935
+ process.stdout.write(`${stringifyBoundaryJson(envelope)}\n`);
936
+ }
187
937
  else
188
938
  process.stdout.write(`${humanSummary(operation, data)}\n`);
189
939
  }
@@ -197,12 +947,17 @@ export function registerAgentCommand(cli, dependencies = {}) {
197
947
  .option('--client-version <version>')
198
948
  .option('--session-id <id>')
199
949
  .option('--capture-profile <profile>', 'Capture profile: minimal, standard, or full', 'standard')
950
+ .option('--capabilities-json <file|->', 'Complete local capability catalog as a JSON array')
951
+ .option('--idempotency-key <key>', 'Reuse the same key only to retry this exact request')
200
952
  .option('--json')
201
953
  .action(async (options) => {
202
954
  const workspace = boundedString(options.workspace, MAX_TEXT_BYTES);
203
955
  const clientKind = boundedId(options.client);
204
956
  const task = boundedString(options.task, MAX_TEXT_BYTES);
205
957
  const profile = captureProfile(options.captureProfile);
958
+ const capabilities = options.capabilitiesJson === undefined
959
+ ? undefined
960
+ : await readCapabilityCatalog(dependencies, options.capabilitiesJson);
206
961
  const client = {
207
962
  kind: clientKind,
208
963
  ...(options.clientVersion === undefined ? {} : { version: boundedId(options.clientVersion) }),
@@ -226,13 +981,14 @@ export function registerAgentCommand(cli, dependencies = {}) {
226
981
  approval: 'unavailable',
227
982
  },
228
983
  metadata: {},
984
+ ...(capabilities === undefined ? {} : { capabilities }),
229
985
  };
230
986
  const data = await sendRequest(dependencies, {
231
987
  method: 'POST',
232
988
  path: '/api/v1/agent/runs',
233
989
  operation: 'agent.open',
234
990
  body,
235
- idempotencyKey: keyFromFactory(dependencies),
991
+ idempotencyKey: requestIdempotencyKey(options.idempotencyKey, dependencies),
236
992
  });
237
993
  emitResult(options.json, 'agent.open', data);
238
994
  });
@@ -241,16 +997,26 @@ export function registerAgentCommand(cli, dependencies = {}) {
241
997
  .argument('<run-id>')
242
998
  .requiredOption('--question-id <id>')
243
999
  .requiredOption('--value <answer>')
1000
+ .option('--capabilities-json <file|->', 'Same complete local capability catalog supplied to agent open')
1001
+ .option('--idempotency-key <key>', 'Reuse the same key only to retry this exact request')
244
1002
  .option('--json')
245
1003
  .action(async (runId, options) => {
246
1004
  const questionId = boundedId(options.questionId);
247
1005
  const value = boundedString(options.value, MAX_TEXT_BYTES);
1006
+ const capabilities = options.capabilitiesJson === undefined
1007
+ ? undefined
1008
+ : await readCapabilityCatalog(dependencies, options.capabilitiesJson);
248
1009
  const data = await sendRequest(dependencies, {
249
1010
  method: 'POST',
250
1011
  path: runPath(runId, 'intake/answers'),
251
1012
  operation: 'agent.answer',
252
- body: { apiVersion: '1', questionId, value },
253
- idempotencyKey: keyFromFactory(dependencies),
1013
+ body: {
1014
+ apiVersion: '1',
1015
+ questionId,
1016
+ value,
1017
+ ...(capabilities === undefined ? {} : { capabilities }),
1018
+ },
1019
+ idempotencyKey: requestIdempotencyKey(options.idempotencyKey, dependencies),
254
1020
  });
255
1021
  emitResult(options.json, 'agent.answer', data);
256
1022
  });
@@ -260,19 +1026,28 @@ export function registerAgentCommand(cli, dependencies = {}) {
260
1026
  ['close', 'agent.close', 'close'],
261
1027
  ['feedback', 'agent.feedback', 'feedback'],
262
1028
  ]) {
263
- agent.command(name)
1029
+ const command = agent.command(name)
264
1030
  .description(`Send an ${name} request for an agent run`)
265
1031
  .argument('<run-id>')
266
1032
  .requiredOption('--input-json <file|->')
267
- .option('--json')
268
- .action(async (runId, options) => {
1033
+ .option('--json');
1034
+ if (name === 'checkpoint') {
1035
+ command.option('--capabilities-json <file|->', 'Same complete local capability catalog supplied to agent open');
1036
+ }
1037
+ command.action(async (runId, options) => {
269
1038
  const input = await readInput(dependencies, options.inputJson);
270
1039
  const request = bodyAndKey(input, dependencies);
1040
+ const capabilities = name === 'checkpoint' && options.capabilitiesJson !== undefined
1041
+ ? await readCapabilityCatalog(dependencies, options.capabilitiesJson)
1042
+ : undefined;
1043
+ if (capabilities !== undefined && Object.prototype.hasOwnProperty.call(request.body, 'capabilities')) {
1044
+ throw validationError();
1045
+ }
271
1046
  const data = await sendRequest(dependencies, {
272
1047
  method: 'POST',
273
1048
  path: runPath(runId, suffix),
274
1049
  operation,
275
- body: request.body,
1050
+ body: capabilities === undefined ? request.body : { ...request.body, capabilities },
276
1051
  idempotencyKey: request.idempotencyKey,
277
1052
  });
278
1053
  emitResult(options.json, operation, data);