@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,8 +1,9 @@
1
1
  import { randomBytes } from 'node:crypto';
2
2
  import { KiokukoError } from '../errors.js';
3
+ import { rollbackFailedTransaction } from '../db/transaction.js';
3
4
  import { readEntry, updateCandidateEntry } from '../memory/entries.js';
4
5
  import { searchEntries } from '../memory/retrieval.js';
5
- import { ENTRY_KINDS, ENTRY_STATUSES, requireWorkspace } from '../serialization/validate.js';
6
+ import { compareCanonicalStrings, ENTRY_KINDS, ENTRY_STATUSES, requireWorkspace } from '../serialization/validate.js';
6
7
  import { AgentGatewayService } from '../gateway/agent-service.js';
7
8
  import { ContextBroker } from '../context/broker.js';
8
9
  import { listContextFeedback, listIntakeFeedback, listRunFeedback } from '../context/feedback.js';
@@ -11,11 +12,28 @@ import { readAkinatorSession, readRunIntakeLink } from '../akinator/store.js';
11
12
  import { startHttpServer } from '../server/http.js';
12
13
  import { createAgentV1Handler } from '../server/agent-application.js';
13
14
  import { WEB_HTML } from './ui.js';
14
- import { curateMemoryCandidates, globalizeCuratorCandidate } from '../memory/curator.js';
15
+ import { curateMemoryCandidates, curatorFacets, globalizeCuratorCandidate } from '../memory/curator.js';
16
+ import { MEMORY_CLASSES } from '../memory/structured-memory.js';
17
+ import { GLOBAL_WORKSPACE } from '../memory/workspaces.js';
18
+ import { recallScopedMemory } from '../memory/scoped-memory.js';
19
+ import { documentsFromSkillSnapshot } from '../skills/import-preparation.js';
20
+ import { readSkillDiscoveryConfig } from '../skills/config.js';
21
+ import { GitHubSkillSourceFetcher } from '../skills/source/github-fetcher.js';
22
+ import { SkillSourceError } from '../skills/source/errors.js';
23
+ import { externalSkillRequirement, externalSkillSourceFetchRequest, listExternalSkills, listExternalSkillsPage, markExternalSkillRefreshFailure, readExternalSkill, refreshExternalSkillSnapshot, setExternalSkillState } from '../skills/store.js';
24
+ import { createSkillRegistryProvider } from '../skills/find.js';
25
+ import { parseStrictJson } from '../setup/strict-json.js';
26
+ import { fetchMaterializableSkillSnapshot } from '../skills/materialization-service.js';
15
27
  const DEFAULT_HOST = '127.0.0.1';
16
28
  const DEFAULT_PORT = 4173;
17
29
  const MAX_BODY_BYTES = 2 * 1024 * 1024;
18
30
  const MAX_WEB_ENTRIES = 200;
31
+ function hasUtf8Bom(bytes) {
32
+ return bytes.byteLength >= 3 && bytes[0] === 0xef && bytes[1] === 0xbb && bytes[2] === 0xbf;
33
+ }
34
+ function isInvalidUtf8EncodingError(error) {
35
+ return error instanceof TypeError && 'code' in error && error.code === 'ERR_ENCODING_INVALID_ENCODED_DATA';
36
+ }
19
37
  function jsonResponse(response, status, value) {
20
38
  const body = JSON.stringify(value);
21
39
  response.writeHead(status, {
@@ -48,20 +66,22 @@ function cookieValue(request, name) {
48
66
  }
49
67
  return undefined;
50
68
  }
51
- function requireUiSession(request, sessionToken) {
52
- if (cookieValue(request, UI_SESSION_COOKIE) !== sessionToken) {
53
- throw new KiokukoError('AUTHENTICATION_ERROR', 'Authorization is invalid');
69
+ function requireTrustedWebOrigin(request, trustedOrigin) {
70
+ if (trustedOrigin === undefined) {
71
+ throw new KiokukoError('AUTHENTICATION_ERROR', 'Origin is invalid');
72
+ }
73
+ const expectedHost = new URL(trustedOrigin).host;
74
+ if (request.headers.host !== expectedHost) {
75
+ throw new KiokukoError('AUTHENTICATION_ERROR', 'Origin is invalid');
54
76
  }
55
77
  const origin = request.headers.origin;
56
- const host = request.headers.host;
57
- const expectedOrigin = host === undefined ? undefined : `http://${host}`;
58
- if (origin !== undefined && (expectedOrigin === undefined || origin !== expectedOrigin)) {
78
+ if (origin !== undefined && origin !== trustedOrigin) {
59
79
  throw new KiokukoError('AUTHENTICATION_ERROR', 'Origin is invalid');
60
80
  }
61
81
  const referer = request.headers.referer;
62
82
  if (referer !== undefined) {
63
83
  try {
64
- if (expectedOrigin === undefined || new URL(referer).origin !== expectedOrigin)
84
+ if (new URL(referer).origin !== trustedOrigin)
65
85
  throw new Error('origin');
66
86
  }
67
87
  catch {
@@ -69,6 +89,11 @@ function requireUiSession(request, sessionToken) {
69
89
  }
70
90
  }
71
91
  }
92
+ function requireUiSession(request, sessionToken) {
93
+ if (cookieValue(request, UI_SESSION_COOKIE) !== sessionToken) {
94
+ throw new KiokukoError('AUTHENTICATION_ERROR', 'Authorization is invalid');
95
+ }
96
+ }
72
97
  function errorStatus(error) {
73
98
  if (!(error instanceof KiokukoError))
74
99
  return 500;
@@ -80,17 +105,48 @@ function errorStatus(error) {
80
105
  return 404;
81
106
  if (error.code === 'CONFLICT')
82
107
  return 409;
108
+ if (error.code === 'BACKPRESSURE')
109
+ return 429;
83
110
  if (error.code === 'SECURITY_REJECTION')
84
111
  return 422;
112
+ if (error.code === 'SERVICE_UNAVAILABLE' || error.code === 'DATABASE_ERROR')
113
+ return 503;
114
+ if (error.code === 'NOT_IMPLEMENTED')
115
+ return 501;
85
116
  return 500;
86
117
  }
118
+ function boundedRetryAfterSeconds(value) {
119
+ if (typeof value !== 'number' || !Number.isFinite(value))
120
+ return 1;
121
+ return Math.min(60, Math.max(1, Math.trunc(value)));
122
+ }
87
123
  function errorBody(error) {
88
- if (error instanceof KiokukoError) {
89
- if (error.code === 'AUTHENTICATION_ERROR')
90
- return { error: { code: error.code, message: 'Authorization is invalid', details: {} } };
91
- return { error: { code: error.code, message: error.message, details: error.details } };
124
+ if (!(error instanceof KiokukoError)) {
125
+ return { error: { code: 'INTEGRITY_ERROR', message: 'Unexpected server error', details: {} } };
92
126
  }
93
- return { error: { code: 'DATABASE_ERROR', message: 'Unexpected server error', details: {} } };
127
+ if (error.code === 'AUTHENTICATION_ERROR')
128
+ return { error: { code: error.code, message: 'Authorization is invalid', details: {} } };
129
+ if (error.code === 'VALIDATION_ERROR' || error.code === 'USAGE_ERROR')
130
+ return { error: { code: error.code, message: 'Request is invalid', details: {} } };
131
+ if (error.code === 'NOT_FOUND')
132
+ return { error: { code: error.code, message: 'Resource not found', details: {} } };
133
+ if (error.code === 'CONFLICT')
134
+ return { error: { code: error.code, message: 'Request conflicts with current state', details: {} } };
135
+ if (error.code === 'BACKPRESSURE')
136
+ return { error: { code: error.code, message: 'Service is busy', details: { retryAfterSeconds: boundedRetryAfterSeconds(error.details.retryAfterSeconds) } } };
137
+ if (error.code === 'DATABASE_ERROR')
138
+ return { error: { code: error.code, message: 'Database unavailable', details: {} } };
139
+ if (error.code === 'SERVICE_UNAVAILABLE')
140
+ return { error: { code: error.code, message: 'Service unavailable', details: {} } };
141
+ if (error.code === 'SECURITY_REJECTION')
142
+ return { error: { code: error.code, message: 'Request rejected', details: {} } };
143
+ if (error.code === 'INTEGRITY_ERROR')
144
+ return { error: { code: error.code, message: 'Internal integrity error', details: {} } };
145
+ if (error.code === 'PARTIAL_FAILURE')
146
+ return { error: { code: error.code, message: 'Operation partially failed', details: {} } };
147
+ if (error.code === 'NOT_IMPLEMENTED')
148
+ return { error: { code: error.code, message: 'Operation is not implemented', details: {} } };
149
+ return { error: { code: 'INTEGRITY_ERROR', message: 'Unexpected server error', details: {} } };
94
150
  }
95
151
  function asRecord(value, label) {
96
152
  if (typeof value !== 'object' || value === null || Array.isArray(value)) {
@@ -122,10 +178,104 @@ function limitQuery(value) {
122
178
  }
123
179
  return limit;
124
180
  }
181
+ function invalidExternalSkillCursor() {
182
+ throw new KiokukoError('VALIDATION_ERROR', 'cursor is invalid');
183
+ }
184
+ function externalSkillCursor(record, listVersion, state) {
185
+ const value = [
186
+ 1,
187
+ listVersion,
188
+ state ?? null,
189
+ record.sourceLocator,
190
+ record.slug,
191
+ record.provider,
192
+ record.skillId,
193
+ ];
194
+ return Buffer.from(JSON.stringify(value), 'utf8').toString('base64url');
195
+ }
196
+ function externalSkillCursorQuery(url) {
197
+ const values = url.searchParams.getAll('cursor');
198
+ if (values.length === 0)
199
+ return undefined;
200
+ if (values.length !== 1 || !/^[A-Za-z0-9_-]{1,4096}$/u.test(values[0]))
201
+ invalidExternalSkillCursor();
202
+ let decoded;
203
+ let parsed;
204
+ try {
205
+ decoded = Buffer.from(values[0], 'base64url');
206
+ if (decoded.toString('base64url') !== values[0] || decoded.byteLength > 3_000 || hasUtf8Bom(decoded))
207
+ invalidExternalSkillCursor();
208
+ parsed = JSON.parse(new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(decoded));
209
+ }
210
+ catch (error) {
211
+ if (error instanceof KiokukoError)
212
+ throw error;
213
+ if (error instanceof SyntaxError || isInvalidUtf8EncodingError(error))
214
+ invalidExternalSkillCursor();
215
+ throw error;
216
+ }
217
+ if (!Array.isArray(parsed) || parsed.length !== 7 || parsed[0] !== 1
218
+ || typeof parsed[1] !== 'number' || !Number.isSafeInteger(parsed[1]) || parsed[1] < 0
219
+ || parsed[2] !== null && (typeof parsed[2] !== 'string'
220
+ || !['discovered', 'imported', 'blocked', 'stale', 'disabled'].includes(parsed[2]))
221
+ || parsed.slice(3).some((value) => typeof value !== 'string' || value.length < 1 || value.length > 2_000 || /\p{Cc}/u.test(value))) {
222
+ invalidExternalSkillCursor();
223
+ }
224
+ return parsed;
225
+ }
226
+ function externalSkillListItem(record) {
227
+ const metadata = record.metadata;
228
+ const documents = record.sourceCommit === null ? 0 : metadata.documents;
229
+ const technology = record.sourceCommit === null ? null : metadata.technology;
230
+ if (typeof documents !== 'number' || !Number.isSafeInteger(documents) || documents < 0 || documents > 64
231
+ || technology !== null && (typeof technology !== 'string' || technology.length < 1 || technology.length > 500)) {
232
+ throw new KiokukoError('INTEGRITY_ERROR', 'External skill list metadata is invalid');
233
+ }
234
+ return { ...record, metadata: { documents, technology } };
235
+ }
236
+ function listQuery(url, name, max = 50) {
237
+ const values = url.searchParams.getAll(name).map((value) => value.trim()).filter(Boolean);
238
+ if (values.length > max || values.some((value) => value.length > 300))
239
+ throw new KiokukoError('VALIDATION_ERROR', `${name} contains too many or too-large values`);
240
+ return [...new Set(values)];
241
+ }
242
+ function requireExactJsonMediaType(request) {
243
+ const contentTypes = [];
244
+ for (let index = 0; index < request.rawHeaders.length; index += 2) {
245
+ if (request.rawHeaders[index]?.toLowerCase() === 'content-type') {
246
+ contentTypes.push(request.rawHeaders[index + 1] ?? '');
247
+ }
248
+ }
249
+ if (contentTypes.length !== 1 || contentTypes[0].trim().toLowerCase() !== 'application/json') {
250
+ request.resume();
251
+ throw new KiokukoError('VALIDATION_ERROR', 'Content-Type must be exactly application/json');
252
+ }
253
+ }
254
+ function decodeJsonBody(bytes) {
255
+ if (hasUtf8Bom(bytes)) {
256
+ throw new KiokukoError('VALIDATION_ERROR', 'Request body must not contain a byte-order mark');
257
+ }
258
+ try {
259
+ return new TextDecoder('utf-8', { fatal: true, ignoreBOM: true }).decode(bytes);
260
+ }
261
+ catch (error) {
262
+ if (isInvalidUtf8EncodingError(error)) {
263
+ throw new KiokukoError('VALIDATION_ERROR', 'Request body must be valid UTF-8');
264
+ }
265
+ throw error;
266
+ }
267
+ }
268
+ function requireOnlyJsonFields(payload, allowed, label) {
269
+ const allowedFields = new Set(allowed);
270
+ if (Object.keys(payload).some((field) => !allowedFields.has(field))) {
271
+ throw new KiokukoError('VALIDATION_ERROR', `${label} contains an unknown field`);
272
+ }
273
+ }
125
274
  async function readJsonBody(request) {
275
+ requireExactJsonMediaType(request);
126
276
  const chunks = [];
127
277
  let size = 0;
128
- const text = await new Promise((resolve, reject) => {
278
+ const bytes = await new Promise((resolve, reject) => {
129
279
  request.on('data', (chunk) => {
130
280
  const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk);
131
281
  size += buffer.byteLength;
@@ -136,33 +286,53 @@ async function readJsonBody(request) {
136
286
  }
137
287
  chunks.push(buffer);
138
288
  });
139
- request.on('end', () => resolve(Buffer.concat(chunks).toString('utf8')));
289
+ request.on('end', () => resolve(Buffer.concat(chunks)));
140
290
  request.on('error', reject);
291
+ request.on('aborted', () => reject(new KiokukoError('VALIDATION_ERROR', 'Request body is incomplete')));
141
292
  });
142
- if (text.trim().length === 0)
143
- throw new KiokukoError('VALIDATION_ERROR', 'Request body must contain JSON');
144
- try {
145
- return asRecord(JSON.parse(text), 'Request body');
146
- }
147
- catch (error) {
148
- if (error instanceof KiokukoError)
149
- throw error;
150
- throw new KiokukoError('VALIDATION_ERROR', 'Request body is not valid JSON');
293
+ const parsed = parseStrictJson(decodeJsonBody(bytes), { allowTrailingComma: false, disallowComments: true, allowEmptyContent: false }, 'Request body is not valid strict JSON');
294
+ return asRecord(parsed, 'Request body');
295
+ }
296
+ function requireNoQueryParameters(url) {
297
+ if (url.searchParams.entries().next().done !== true) {
298
+ throw new KiokukoError('VALIDATION_ERROR', 'This endpoint does not accept query parameters');
151
299
  }
152
300
  }
301
+ async function requireEmptyBody(request) {
302
+ await new Promise((resolve, reject) => {
303
+ request.once('data', () => {
304
+ request.resume();
305
+ reject(new KiokukoError('VALIDATION_ERROR', 'Request body must be empty'));
306
+ });
307
+ request.once('end', resolve);
308
+ request.once('error', reject);
309
+ request.once('aborted', () => reject(new KiokukoError('VALIDATION_ERROR', 'Request body is incomplete')));
310
+ });
311
+ }
153
312
  function workspaceSummaries(database) {
154
- const summaries = new Map();
155
- for (const row of database.prepare('SELECT workspace, display_name FROM repositories ORDER BY workspace ASC').all()) {
156
- summaries.set(row.workspace, { workspace: row.workspace, displayName: row.display_name, count: 0 });
313
+ database.exec('BEGIN DEFERRED');
314
+ try {
315
+ const externalWorkspaces = new Set(listExternalSkills(database).map((skill) => skill.sourceWorkspace));
316
+ const summaries = new Map();
317
+ for (const row of database.prepare('SELECT workspace, display_name FROM repositories ORDER BY workspace ASC').all()) {
318
+ if (!externalWorkspaces.has(row.workspace))
319
+ summaries.set(row.workspace, { workspace: row.workspace, displayName: row.display_name, count: 0 });
320
+ }
321
+ for (const row of database.prepare("SELECT workspace, COUNT(*) AS count FROM entries WHERE status <> 'superseded' GROUP BY workspace").all()) {
322
+ if (externalWorkspaces.has(row.workspace))
323
+ continue;
324
+ const existing = summaries.get(row.workspace);
325
+ if (existing)
326
+ existing.count = Number(row.count);
327
+ else
328
+ summaries.set(row.workspace, { workspace: row.workspace, displayName: '', count: Number(row.count) });
329
+ }
330
+ database.exec('COMMIT');
331
+ return [...summaries.values()].sort((left, right) => compareCanonicalStrings(left.workspace, right.workspace));
157
332
  }
158
- for (const row of database.prepare("SELECT workspace, COUNT(*) AS count FROM entries WHERE status <> 'superseded' GROUP BY workspace").all()) {
159
- const existing = summaries.get(row.workspace);
160
- if (existing)
161
- existing.count = Number(row.count);
162
- else
163
- summaries.set(row.workspace, { workspace: row.workspace, displayName: '', count: Number(row.count) });
333
+ catch (error) {
334
+ rollbackFailedTransaction(database, error);
164
335
  }
165
- return [...summaries.values()].sort((left, right) => left.workspace.localeCompare(right.workspace));
166
336
  }
167
337
  function workspaceTags(database, workspace) {
168
338
  return database
@@ -170,6 +340,12 @@ function workspaceTags(database, workspace) {
170
340
  .all(workspace)
171
341
  .map((row) => ({ tag: row.tag, count: Number(row.count) }));
172
342
  }
343
+ function workspaceProject(database, workspace) {
344
+ const row = database.prepare('SELECT r.repository_id, r.workspace, l.canonical_root FROM repository_locations AS l JOIN repositories AS r ON r.repository_id = l.repository_id WHERE r.workspace = ? ORDER BY l.last_seen_at DESC, l.canonical_root ASC LIMIT 1').get(workspace);
345
+ if (!row)
346
+ return undefined;
347
+ return { repositoryId: row.repository_id, workspace: row.workspace, repositoryRoot: row.canonical_root, source: 'location' };
348
+ }
173
349
  function listEntries(database, workspace, query, kind, status, tag, includeSuperseded, limit) {
174
350
  if (query.trim().length > 0) {
175
351
  const searchInput = { workspace, query, limit, includeSuperseded };
@@ -215,6 +391,112 @@ function entryIdFromPath(pathname) {
215
391
  throw new KiokukoError('VALIDATION_ERROR', 'entry id is not valid URL encoding');
216
392
  }
217
393
  }
394
+ function externalSkillIdFromPath(pathname) {
395
+ const prefix = '/api/skills/';
396
+ if (!pathname.startsWith(prefix))
397
+ return undefined;
398
+ const encoded = pathname.slice(prefix.length);
399
+ if (encoded.length === 0 || encoded.includes('/'))
400
+ throw new KiokukoError('NOT_FOUND', 'Endpoint not found');
401
+ try {
402
+ const skillId = decodeURIComponent(encoded);
403
+ if (skillId.length === 0 || skillId.length > 500)
404
+ throw new Error('invalid');
405
+ return skillId;
406
+ }
407
+ catch {
408
+ throw new KiokukoError('VALIDATION_ERROR', 'skill id is not valid URL encoding');
409
+ }
410
+ }
411
+ function externalSkillSourceFailure(error, code, message) {
412
+ const failure = new KiokukoError(code, message, {
413
+ failureCode: error.code,
414
+ ...(error.retryAfterSeconds === null ? {} : { retryAfterSeconds: error.retryAfterSeconds }),
415
+ });
416
+ Object.defineProperty(failure, 'cause', {
417
+ value: error,
418
+ enumerable: false,
419
+ configurable: false,
420
+ writable: false,
421
+ });
422
+ return failure;
423
+ }
424
+ function refreshExternalSkill(context, skillId, flights) {
425
+ if (flights.database !== context.database) {
426
+ throw new KiokukoError('INTEGRITY_ERROR', 'External skill refresh coordinator is bound to another database');
427
+ }
428
+ const detail = readExternalSkill(context.database, skillId);
429
+ if (!detail)
430
+ throw new KiokukoError('NOT_FOUND', 'External skill not found');
431
+ if (detail.skill.sourceType !== 'github')
432
+ throw new KiokukoError('NOT_IMPLEMENTED', 'Only GitHub external skills can be refreshed automatically');
433
+ const candidate = {
434
+ id: detail.skill.skillId,
435
+ provider: detail.skill.provider,
436
+ name: detail.skill.name,
437
+ slug: detail.skill.slug,
438
+ source: detail.skill.sourceLocator,
439
+ sourceType: 'github',
440
+ installUrl: detail.skill.installUrl,
441
+ installs: detail.skill.installs,
442
+ duplicate: detail.skill.duplicate,
443
+ officialStatus: detail.skill.officialStatus,
444
+ auditStatus: detail.skill.auditStatus,
445
+ };
446
+ const expected = { generation: detail.skill.generation, sourceCommit: detail.skill.sourceCommit, snapshotHash: detail.skill.snapshotHash, state: detail.skill.state, lastCheckedAt: detail.skill.lastCheckedAt };
447
+ const flightKey = JSON.stringify([
448
+ skillId,
449
+ expected.generation,
450
+ expected.sourceCommit,
451
+ expected.snapshotHash,
452
+ expected.state,
453
+ expected.lastCheckedAt,
454
+ ]);
455
+ const existing = flights.operations.get(flightKey);
456
+ if (existing !== undefined)
457
+ return existing;
458
+ const operation = Promise.resolve().then(async () => {
459
+ try {
460
+ const materialized = await fetchMaterializableSkillSnapshot(context.database, candidate, {
461
+ provider: createSkillRegistryProvider(),
462
+ sourceFetcher: new GitHubSkillSourceFetcher({ token: readSkillDiscoveryConfig().githubToken }),
463
+ sourceRequest: externalSkillSourceFetchRequest(detail),
464
+ cacheWrite: (operation) => context.enqueueWrite(operation),
465
+ });
466
+ const snapshot = materialized.snapshot;
467
+ if (!snapshot.files.some((file) => file.primary))
468
+ throw new KiokukoError('VALIDATION_ERROR', 'Skill snapshot has no primary document');
469
+ const requirement = externalSkillRequirement(context.database, skillId);
470
+ return await context.enqueueWrite(() => refreshExternalSkillSnapshot(context.database, skillId, snapshot, documentsFromSkillSnapshot(snapshot), requirement, expected, undefined, materialized.authorization));
471
+ }
472
+ catch (error) {
473
+ if (!(error instanceof SkillSourceError))
474
+ throw error;
475
+ if (error.code === 'source_missing' || error.code === 'candidate_not_found_at_source') {
476
+ await context.enqueueWrite(() => markExternalSkillRefreshFailure(context.database, skillId, 'stale', expected));
477
+ throw externalSkillSourceFailure(error, 'CONFLICT', 'External skill source is stale');
478
+ }
479
+ if (error.code === 'skill_disabled_for_model_invocation' || error.code === 'skill_secret_detected' || error.code === 'skill_blocked') {
480
+ await context.enqueueWrite(() => markExternalSkillRefreshFailure(context.database, skillId, 'blocked', expected));
481
+ throw externalSkillSourceFailure(error, 'SECURITY_REJECTION', 'External skill snapshot was blocked');
482
+ }
483
+ if (error.code === 'source_rate_limited' || error.code === 'source_unavailable') {
484
+ throw externalSkillSourceFailure(error, 'SERVICE_UNAVAILABLE', 'External skill source is temporarily unavailable');
485
+ }
486
+ if (error.code === 'source_tree_truncated' || error.code === 'skill_too_large' || error.code === 'skill_validation_failed') {
487
+ throw externalSkillSourceFailure(error, 'SECURITY_REJECTION', 'External skill source failed validation');
488
+ }
489
+ throw error;
490
+ }
491
+ });
492
+ flights.operations.set(flightKey, operation);
493
+ const cleanup = () => {
494
+ if (flights.operations.get(flightKey) === operation)
495
+ flights.operations.delete(flightKey);
496
+ };
497
+ void operation.then(cleanup, cleanup);
498
+ return operation;
499
+ }
218
500
  function operatorRunIdFromPath(pathname) {
219
501
  const prefix = '/api/operator/runs/';
220
502
  if (!pathname.startsWith(prefix) || pathname.slice(prefix.length).includes('/'))
@@ -308,7 +590,7 @@ function operatorRunDetail(context, runId) {
308
590
  untrusted: true,
309
591
  };
310
592
  }
311
- async function handleRequest(request, response, context, sessionToken) {
593
+ async function handleRequest(request, response, context, sessionToken, externalSkillRefreshFlights) {
312
594
  if (request.method === 'OPTIONS') {
313
595
  response.writeHead(204, { 'cache-control': 'no-store' });
314
596
  response.end();
@@ -324,6 +606,72 @@ async function handleRequest(request, response, context, sessionToken) {
324
606
  return;
325
607
  }
326
608
  requireUiSession(request, sessionToken);
609
+ if (request.method === 'GET' && url.pathname === '/api/skills') {
610
+ if ([...url.searchParams.keys()].some((key) => key !== 'state' && key !== 'limit' && key !== 'cursor')
611
+ || url.searchParams.getAll('state').length > 1 || url.searchParams.getAll('limit').length > 1) {
612
+ throw new KiokukoError('VALIDATION_ERROR', 'External skill list query is invalid');
613
+ }
614
+ const state = enumQuery(url.searchParams.get('state'), ['discovered', 'imported', 'blocked', 'stale', 'disabled'], 'state');
615
+ const limit = limitQuery(url.searchParams.get('limit'));
616
+ const cursor = externalSkillCursorQuery(url);
617
+ const normalizedState = state;
618
+ if (cursor !== undefined && cursor[2] !== (normalizedState ?? null)) {
619
+ throw new KiokukoError('CONFLICT', 'External skill list filter changed; restart pagination');
620
+ }
621
+ const page = listExternalSkillsPage(context.database, {
622
+ ...(normalizedState === undefined ? {} : { state: normalizedState }),
623
+ limit,
624
+ ...(cursor === undefined ? {} : {
625
+ expectedVersion: cursor[1],
626
+ after: { sourceLocator: cursor[3], slug: cursor[4], provider: cursor[5], skillId: cursor[6] },
627
+ }),
628
+ });
629
+ const skills = page.skills.map(externalSkillListItem);
630
+ jsonResponse(response, 200, {
631
+ skills,
632
+ count: skills.length,
633
+ truncated: page.truncated,
634
+ nextCursor: page.truncated ? externalSkillCursor(page.skills.at(-1), page.version, normalizedState) : null,
635
+ untrusted: true,
636
+ });
637
+ return;
638
+ }
639
+ const isExternalSkillAction = url.pathname.endsWith('/refresh') || url.pathname.endsWith('/disable') || url.pathname.endsWith('/enable');
640
+ const externalSkillId = isExternalSkillAction ? undefined : externalSkillIdFromPath(url.pathname);
641
+ if (externalSkillId !== undefined && request.method === 'GET') {
642
+ requireNoQueryParameters(url);
643
+ const detail = readExternalSkill(context.database, externalSkillId);
644
+ if (!detail)
645
+ throw new KiokukoError('NOT_FOUND', 'External skill not found');
646
+ jsonResponse(response, 200, {
647
+ skill: externalSkillListItem(detail.skill),
648
+ entries: detail.entries.slice(0, MAX_WEB_ENTRIES),
649
+ entriesTruncated: detail.entries.length > MAX_WEB_ENTRIES,
650
+ untrusted: true,
651
+ });
652
+ return;
653
+ }
654
+ if (request.method === 'POST' && url.pathname.startsWith('/api/skills/') && url.pathname.endsWith('/refresh')) {
655
+ const skillId = externalSkillIdFromPath(url.pathname.slice(0, -'/refresh'.length));
656
+ if (skillId === undefined)
657
+ throw new KiokukoError('NOT_FOUND', 'Endpoint not found');
658
+ requireNoQueryParameters(url);
659
+ await requireEmptyBody(request);
660
+ jsonResponse(response, 200, await refreshExternalSkill(context, skillId, externalSkillRefreshFlights));
661
+ return;
662
+ }
663
+ if (request.method === 'POST' && url.pathname.startsWith('/api/skills/') && (url.pathname.endsWith('/disable') || url.pathname.endsWith('/enable'))) {
664
+ const suffix = url.pathname.endsWith('/disable') ? '/disable' : '/enable';
665
+ const skillId = externalSkillIdFromPath(url.pathname.slice(0, -suffix.length));
666
+ if (skillId === undefined)
667
+ throw new KiokukoError('NOT_FOUND', 'Endpoint not found');
668
+ requireNoQueryParameters(url);
669
+ await requireEmptyBody(request);
670
+ const state = suffix === '/disable' ? 'disabled' : 'imported';
671
+ const skill = await context.enqueueWrite(() => setExternalSkillState(context.database, skillId, state));
672
+ jsonResponse(response, 200, { skill, untrusted: true });
673
+ return;
674
+ }
327
675
  if (request.method === 'GET' && url.pathname === '/api/operator/runs') {
328
676
  jsonResponse(response, 200, operatorRunList(context, url));
329
677
  return;
@@ -343,17 +691,71 @@ async function handleRequest(request, response, context, sessionToken) {
343
691
  jsonResponse(response, 200, { workspace, tags });
344
692
  return;
345
693
  }
694
+ if (request.method === 'GET' && url.pathname === '/api/memory/recall') {
695
+ const workspace = requireWorkspace(url.searchParams.get('workspace') ?? '');
696
+ const query = url.searchParams.get('q')?.trim() ?? '';
697
+ if (query.length === 0)
698
+ throw new KiokukoError('VALIDATION_ERROR', 'q must be a non-empty search query');
699
+ const scope = enumQuery(url.searchParams.get('scope'), ['auto', 'project', 'ecosystem', 'global'], 'scope') ?? 'auto';
700
+ const project = workspace === GLOBAL_WORKSPACE ? undefined : workspaceProject(context.database, workspace);
701
+ if (scope !== 'global' && workspace !== GLOBAL_WORKSPACE && project === undefined)
702
+ throw new KiokukoError('NOT_FOUND', 'The selected workspace has no repository root for scoped recall');
703
+ const result = await recallScopedMemory(context.database, {
704
+ query,
705
+ scope,
706
+ ...(project === undefined ? {} : { project }),
707
+ limit: Math.min(limitQuery(url.searchParams.get('limit')), 100),
708
+ maxChars: 50_000,
709
+ });
710
+ jsonResponse(response, 200, { workspace, ...result });
711
+ return;
712
+ }
346
713
  if (request.method === 'GET' && url.pathname === '/api/curator/candidates') {
347
714
  const workspaceParam = url.searchParams.get('workspace');
348
715
  const skillReadyOnly = booleanQuery(url.searchParams.get('skillReadyOnly'), 'skillReadyOnly') ?? false;
349
- const result = workspaceParam === null || workspaceParam === 'all'
350
- ? await curateMemoryCandidates(context.database, { allWorkspaces: true, limit: Math.min(limitQuery(url.searchParams.get('limit')), 50), skillReadyOnly })
351
- : await curateMemoryCandidates(context.database, { workspace: requireWorkspace(workspaceParam), limit: Math.min(limitQuery(url.searchParams.get('limit')), 50), skillReadyOnly });
716
+ const workspaces = listQuery(url, 'project');
717
+ const tags = listQuery(url, 'tag');
718
+ const frameworks = listQuery(url, 'framework');
719
+ const languages = listQuery(url, 'language');
720
+ const memoryClasses = listQuery(url, 'memoryClass').map((value) => enumQuery(value, MEMORY_CLASSES, 'memoryClass'));
721
+ const tiers = listQuery(url, 'tier').map((value) => enumQuery(value, ['unobserved', 'observed', 'repeated', 'portable'], 'tier'));
722
+ const tagMode = enumQuery(url.searchParams.get('tagMode'), ['any', 'all'], 'tagMode');
723
+ const includeGlobalized = booleanQuery(url.searchParams.get('includeGlobalized'), 'includeGlobalized') ?? false;
724
+ const cursor = url.searchParams.get('cursor');
725
+ const input = {
726
+ ...(workspaceParam !== null && workspaceParam !== 'all' ? { workspace: requireWorkspace(workspaceParam) } : {}),
727
+ ...(workspaces.length > 0 ? { workspaces } : {}),
728
+ ...(tags.length > 0 ? { tags } : {}),
729
+ ...(tagMode === undefined ? {} : { tagMode }),
730
+ ...(frameworks.length > 0 ? { frameworks } : {}),
731
+ ...(languages.length > 0 ? { languages } : {}),
732
+ ...(memoryClasses.length > 0 ? { memoryClasses } : {}),
733
+ ...(tiers.length > 0 ? { tiers } : {}),
734
+ ...(url.searchParams.get('search') === null ? {} : { search: url.searchParams.get('search') ?? '' }),
735
+ ...(cursor === null ? {} : { cursor }),
736
+ allWorkspaces: workspaceParam === null || workspaceParam === 'all' || workspaces.length > 0,
737
+ skillReadyOnly,
738
+ includeGlobalized,
739
+ limit: Math.min(limitQuery(url.searchParams.get('limit')), 50),
740
+ };
741
+ const result = await curateMemoryCandidates(context.database, input);
352
742
  jsonResponse(response, 200, result);
353
743
  return;
354
744
  }
745
+ if (request.method === 'GET' && url.pathname === '/api/curator/facets') {
746
+ const workspaceParam = url.searchParams.get('workspace');
747
+ const projects = listQuery(url, 'project');
748
+ const includeGlobalized = booleanQuery(url.searchParams.get('includeGlobalized'), 'includeGlobalized') ?? false;
749
+ jsonResponse(response, 200, { facets: curatorFacets(context.database, {
750
+ ...(workspaceParam !== null && workspaceParam !== 'all' ? { workspace: requireWorkspace(workspaceParam) } : {}),
751
+ ...(projects.length > 0 ? { workspaces: projects } : {}),
752
+ includeGlobalized,
753
+ }) });
754
+ return;
755
+ }
355
756
  if (request.method === 'POST' && url.pathname === '/api/curator/globalize') {
356
757
  const payload = await readJsonBody(request);
758
+ requireOnlyJsonFields(payload, ['workspace', 'entryId', 'expectedRevision', 'actor'], 'Curator globalize request');
357
759
  const workspace = requireWorkspace(url.searchParams.get('workspace') ?? (typeof payload.workspace === 'string' ? payload.workspace : ''));
358
760
  const result = await context.enqueueWrite(() => globalizeCuratorCandidate(context.database, {
359
761
  workspace,
@@ -384,6 +786,7 @@ async function handleRequest(request, response, context, sessionToken) {
384
786
  return;
385
787
  }
386
788
  const payload = await readJsonBody(request);
789
+ requireOnlyJsonFields(payload, ['expectedRevision', 'kind', 'title', 'body', 'summary', 'scope', 'provenance', 'tags', 'actor'], 'Entry update request');
387
790
  const expectedRevision = payload.expectedRevision;
388
791
  const input = {
389
792
  workspace,
@@ -412,16 +815,27 @@ async function handleRequest(request, response, context, sessionToken) {
412
815
  function isSharedServerPath(pathname) {
413
816
  return pathname.startsWith('/health/') || pathname === '/api/v1' || pathname.startsWith('/api/v1/');
414
817
  }
415
- function createLegacyApplication(context) {
818
+ function createLegacyApplication(context, trustedOrigin) {
416
819
  const sharedApplication = context.createAuthenticatedApp(createAgentV1Handler(context));
417
820
  const sessionToken = randomBytes(32).toString('base64url');
821
+ const externalSkillRefreshFlights = {
822
+ database: context.database,
823
+ operations: new Map(),
824
+ };
418
825
  return (request, response) => {
826
+ try {
827
+ requireTrustedWebOrigin(request, trustedOrigin());
828
+ }
829
+ catch (error) {
830
+ jsonResponse(response, errorStatus(error), errorBody(error));
831
+ return;
832
+ }
419
833
  const pathname = new URL(request.url ?? '/', 'http://127.0.0.1').pathname;
420
834
  if (isSharedServerPath(pathname)) {
421
835
  sharedApplication(request, response);
422
836
  return;
423
837
  }
424
- void handleRequest(request, response, context, sessionToken).catch((error) => {
838
+ void handleRequest(request, response, context, sessionToken, externalSkillRefreshFlights).catch((error) => {
425
839
  if (!response.headersSent)
426
840
  jsonResponse(response, errorStatus(error), errorBody(error));
427
841
  else
@@ -430,13 +844,15 @@ function createLegacyApplication(context) {
430
844
  };
431
845
  }
432
846
  export async function startWebServer(options = {}) {
847
+ let trustedOrigin;
433
848
  const runtime = await startHttpServer({
434
849
  ...(options.httpOptions ?? {}),
435
850
  ...(options.databasePath === undefined ? {} : { databasePath: options.databasePath }),
436
851
  host: options.host ?? DEFAULT_HOST,
437
852
  port: options.port ?? DEFAULT_PORT,
438
- applicationFactory: createLegacyApplication,
853
+ applicationFactory: (context) => createLegacyApplication(context, () => trustedOrigin),
439
854
  });
855
+ trustedOrigin = new URL(runtime.url).origin;
440
856
  return {
441
857
  server: runtime.server,
442
858
  url: runtime.url,