@askdkc/kiokuko 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (391) hide show
  1. package/LICENSE +21 -0
  2. package/README.ja.md +112 -0
  3. package/README.ko.md +112 -0
  4. package/README.md +147 -0
  5. package/README.zh-CN.md +112 -0
  6. package/dist/agent-file/atomic-write.d.ts +6 -0
  7. package/dist/agent-file/atomic-write.d.ts.map +1 -0
  8. package/dist/agent-file/atomic-write.js +36 -0
  9. package/dist/agent-file/atomic-write.js.map +1 -0
  10. package/dist/agent-file/managed-block.d.ts +12 -0
  11. package/dist/agent-file/managed-block.d.ts.map +1 -0
  12. package/dist/agent-file/managed-block.js +56 -0
  13. package/dist/agent-file/managed-block.js.map +1 -0
  14. package/dist/agent-file/render.d.ts +14 -0
  15. package/dist/agent-file/render.d.ts.map +1 -0
  16. package/dist/agent-file/render.js +41 -0
  17. package/dist/agent-file/render.js.map +1 -0
  18. package/dist/akinator/domain.d.ts +25 -0
  19. package/dist/akinator/domain.d.ts.map +1 -0
  20. package/dist/akinator/domain.js +255 -0
  21. package/dist/akinator/domain.js.map +1 -0
  22. package/dist/akinator/orchestrator.d.ts +8 -0
  23. package/dist/akinator/orchestrator.d.ts.map +1 -0
  24. package/dist/akinator/orchestrator.js +11 -0
  25. package/dist/akinator/orchestrator.js.map +1 -0
  26. package/dist/akinator/service.d.ts +35 -0
  27. package/dist/akinator/service.d.ts.map +1 -0
  28. package/dist/akinator/service.js +296 -0
  29. package/dist/akinator/service.js.map +1 -0
  30. package/dist/akinator/store.d.ts +96 -0
  31. package/dist/akinator/store.d.ts.map +1 -0
  32. package/dist/akinator/store.js +583 -0
  33. package/dist/akinator/store.js.map +1 -0
  34. package/dist/akinator/types.d.ts +49 -0
  35. package/dist/akinator/types.d.ts.map +1 -0
  36. package/dist/akinator/types.js +2 -0
  37. package/dist/akinator/types.js.map +1 -0
  38. package/dist/bin/kiokuko.d.ts +3 -0
  39. package/dist/bin/kiokuko.d.ts.map +1 -0
  40. package/dist/bin/kiokuko.js +6 -0
  41. package/dist/bin/kiokuko.js.map +1 -0
  42. package/dist/cli.d.ts +10 -0
  43. package/dist/cli.d.ts.map +1 -0
  44. package/dist/cli.js +362 -0
  45. package/dist/cli.js.map +1 -0
  46. package/dist/client/runtime-discovery.d.ts +15 -0
  47. package/dist/client/runtime-discovery.d.ts.map +1 -0
  48. package/dist/client/runtime-discovery.js +45 -0
  49. package/dist/client/runtime-discovery.js.map +1 -0
  50. package/dist/client/server-client.d.ts +20 -0
  51. package/dist/client/server-client.d.ts.map +1 -0
  52. package/dist/client/server-client.js +424 -0
  53. package/dist/client/server-client.js.map +1 -0
  54. package/dist/commands/agent.d.ts +10 -0
  55. package/dist/commands/agent.d.ts.map +1 -0
  56. package/dist/commands/agent.js +283 -0
  57. package/dist/commands/agent.js.map +1 -0
  58. package/dist/commands/backup.d.ts +5 -0
  59. package/dist/commands/backup.d.ts.map +1 -0
  60. package/dist/commands/backup.js +14 -0
  61. package/dist/commands/backup.js.map +1 -0
  62. package/dist/commands/call.d.ts +7 -0
  63. package/dist/commands/call.d.ts.map +1 -0
  64. package/dist/commands/call.js +10 -0
  65. package/dist/commands/call.js.map +1 -0
  66. package/dist/commands/doctor.d.ts +31 -0
  67. package/dist/commands/doctor.d.ts.map +1 -0
  68. package/dist/commands/doctor.js +142 -0
  69. package/dist/commands/doctor.js.map +1 -0
  70. package/dist/commands/export.d.ts +21 -0
  71. package/dist/commands/export.d.ts.map +1 -0
  72. package/dist/commands/export.js +68 -0
  73. package/dist/commands/export.js.map +1 -0
  74. package/dist/commands/import.d.ts +15 -0
  75. package/dist/commands/import.d.ts.map +1 -0
  76. package/dist/commands/import.js +265 -0
  77. package/dist/commands/import.js.map +1 -0
  78. package/dist/commands/init.d.ts +14 -0
  79. package/dist/commands/init.d.ts.map +1 -0
  80. package/dist/commands/init.js +26 -0
  81. package/dist/commands/init.js.map +1 -0
  82. package/dist/commands/ledger.d.ts +7 -0
  83. package/dist/commands/ledger.d.ts.map +1 -0
  84. package/dist/commands/ledger.js +66 -0
  85. package/dist/commands/ledger.js.map +1 -0
  86. package/dist/commands/link.d.ts +6 -0
  87. package/dist/commands/link.d.ts.map +1 -0
  88. package/dist/commands/link.js +6 -0
  89. package/dist/commands/link.js.map +1 -0
  90. package/dist/commands/promote.d.ts +6 -0
  91. package/dist/commands/promote.d.ts.map +1 -0
  92. package/dist/commands/promote.js +6 -0
  93. package/dist/commands/promote.js.map +1 -0
  94. package/dist/commands/purge.d.ts +10 -0
  95. package/dist/commands/purge.d.ts.map +1 -0
  96. package/dist/commands/purge.js +26 -0
  97. package/dist/commands/purge.js.map +1 -0
  98. package/dist/commands/read.d.ts +6 -0
  99. package/dist/commands/read.d.ts.map +1 -0
  100. package/dist/commands/read.js +4 -0
  101. package/dist/commands/read.js.map +1 -0
  102. package/dist/commands/recall.d.ts +6 -0
  103. package/dist/commands/recall.d.ts.map +1 -0
  104. package/dist/commands/recall.js +4 -0
  105. package/dist/commands/recall.js.map +1 -0
  106. package/dist/commands/record.d.ts +6 -0
  107. package/dist/commands/record.d.ts.map +1 -0
  108. package/dist/commands/record.js +4 -0
  109. package/dist/commands/record.js.map +1 -0
  110. package/dist/commands/search.d.ts +6 -0
  111. package/dist/commands/search.d.ts.map +1 -0
  112. package/dist/commands/search.js +4 -0
  113. package/dist/commands/search.js.map +1 -0
  114. package/dist/commands/serve.d.ts +34 -0
  115. package/dist/commands/serve.d.ts.map +1 -0
  116. package/dist/commands/serve.js +120 -0
  117. package/dist/commands/serve.js.map +1 -0
  118. package/dist/commands/server-status.d.ts +20 -0
  119. package/dist/commands/server-status.d.ts.map +1 -0
  120. package/dist/commands/server-status.js +21 -0
  121. package/dist/commands/server-status.js.map +1 -0
  122. package/dist/commands/server.d.ts +13 -0
  123. package/dist/commands/server.d.ts.map +1 -0
  124. package/dist/commands/server.js +89 -0
  125. package/dist/commands/server.js.map +1 -0
  126. package/dist/commands/setup.d.ts +32 -0
  127. package/dist/commands/setup.d.ts.map +1 -0
  128. package/dist/commands/setup.js +121 -0
  129. package/dist/commands/setup.js.map +1 -0
  130. package/dist/commands/supersede.d.ts +6 -0
  131. package/dist/commands/supersede.d.ts.map +1 -0
  132. package/dist/commands/supersede.js +6 -0
  133. package/dist/commands/supersede.js.map +1 -0
  134. package/dist/commands/use.d.ts +28 -0
  135. package/dist/commands/use.d.ts.map +1 -0
  136. package/dist/commands/use.js +176 -0
  137. package/dist/commands/use.js.map +1 -0
  138. package/dist/config/paths.d.ts +18 -0
  139. package/dist/config/paths.d.ts.map +1 -0
  140. package/dist/config/paths.js +104 -0
  141. package/dist/config/paths.js.map +1 -0
  142. package/dist/config/project-config.d.ts +10 -0
  143. package/dist/config/project-config.d.ts.map +1 -0
  144. package/dist/config/project-config.js +59 -0
  145. package/dist/config/project-config.js.map +1 -0
  146. package/dist/context/broker.d.ts +80 -0
  147. package/dist/context/broker.d.ts.map +1 -0
  148. package/dist/context/broker.js +437 -0
  149. package/dist/context/broker.js.map +1 -0
  150. package/dist/context/delivery.d.ts +66 -0
  151. package/dist/context/delivery.d.ts.map +1 -0
  152. package/dist/context/delivery.js +758 -0
  153. package/dist/context/delivery.js.map +1 -0
  154. package/dist/context/feedback.d.ts +75 -0
  155. package/dist/context/feedback.d.ts.map +1 -0
  156. package/dist/context/feedback.js +997 -0
  157. package/dist/context/feedback.js.map +1 -0
  158. package/dist/context/ranking.d.ts +98 -0
  159. package/dist/context/ranking.d.ts.map +1 -0
  160. package/dist/context/ranking.js +513 -0
  161. package/dist/context/ranking.js.map +1 -0
  162. package/dist/context/recommendations.d.ts +85 -0
  163. package/dist/context/recommendations.d.ts.map +1 -0
  164. package/dist/context/recommendations.js +342 -0
  165. package/dist/context/recommendations.js.map +1 -0
  166. package/dist/db/adapter.d.ts +25 -0
  167. package/dist/db/adapter.d.ts.map +1 -0
  168. package/dist/db/adapter.js +37 -0
  169. package/dist/db/adapter.js.map +1 -0
  170. package/dist/db/capabilities.d.ts +13 -0
  171. package/dist/db/capabilities.d.ts.map +1 -0
  172. package/dist/db/capabilities.js +25 -0
  173. package/dist/db/capabilities.js.map +1 -0
  174. package/dist/db/connection.d.ts +6 -0
  175. package/dist/db/connection.d.ts.map +1 -0
  176. package/dist/db/connection.js +42 -0
  177. package/dist/db/connection.js.map +1 -0
  178. package/dist/db/migrate.d.ts +9 -0
  179. package/dist/db/migrate.d.ts.map +1 -0
  180. package/dist/db/migrate.js +102 -0
  181. package/dist/db/migrate.js.map +1 -0
  182. package/dist/db/transaction.d.ts +4 -0
  183. package/dist/db/transaction.d.ts.map +1 -0
  184. package/dist/db/transaction.js +39 -0
  185. package/dist/db/transaction.js.map +1 -0
  186. package/dist/errors.d.ts +9 -0
  187. package/dist/errors.d.ts.map +1 -0
  188. package/dist/errors.js +32 -0
  189. package/dist/errors.js.map +1 -0
  190. package/dist/gateway/agent-service.d.ts +69 -0
  191. package/dist/gateway/agent-service.d.ts.map +1 -0
  192. package/dist/gateway/agent-service.js +581 -0
  193. package/dist/gateway/agent-service.js.map +1 -0
  194. package/dist/gateway/checkpoint-service.d.ts +42 -0
  195. package/dist/gateway/checkpoint-service.d.ts.map +1 -0
  196. package/dist/gateway/checkpoint-service.js +295 -0
  197. package/dist/gateway/checkpoint-service.js.map +1 -0
  198. package/dist/knowledge/sources.d.ts +72 -0
  199. package/dist/knowledge/sources.d.ts.map +1 -0
  200. package/dist/knowledge/sources.js +406 -0
  201. package/dist/knowledge/sources.js.map +1 -0
  202. package/dist/ledger/archive.d.ts +50 -0
  203. package/dist/ledger/archive.d.ts.map +1 -0
  204. package/dist/ledger/archive.js +1072 -0
  205. package/dist/ledger/archive.js.map +1 -0
  206. package/dist/ledger/hash.d.ts +22 -0
  207. package/dist/ledger/hash.d.ts.map +1 -0
  208. package/dist/ledger/hash.js +25 -0
  209. package/dist/ledger/hash.js.map +1 -0
  210. package/dist/ledger/maintenance.d.ts +78 -0
  211. package/dist/ledger/maintenance.d.ts.map +1 -0
  212. package/dist/ledger/maintenance.js +683 -0
  213. package/dist/ledger/maintenance.js.map +1 -0
  214. package/dist/ledger/projection.d.ts +37 -0
  215. package/dist/ledger/projection.d.ts.map +1 -0
  216. package/dist/ledger/projection.js +307 -0
  217. package/dist/ledger/projection.js.map +1 -0
  218. package/dist/ledger/promotion.d.ts +28 -0
  219. package/dist/ledger/promotion.d.ts.map +1 -0
  220. package/dist/ledger/promotion.js +308 -0
  221. package/dist/ledger/promotion.js.map +1 -0
  222. package/dist/ledger/query.d.ts +55 -0
  223. package/dist/ledger/query.d.ts.map +1 -0
  224. package/dist/ledger/query.js +321 -0
  225. package/dist/ledger/query.js.map +1 -0
  226. package/dist/ledger/redaction.d.ts +8 -0
  227. package/dist/ledger/redaction.d.ts.map +1 -0
  228. package/dist/ledger/redaction.js +40 -0
  229. package/dist/ledger/redaction.js.map +1 -0
  230. package/dist/ledger/store.d.ts +46 -0
  231. package/dist/ledger/store.d.ts.map +1 -0
  232. package/dist/ledger/store.js +324 -0
  233. package/dist/ledger/store.js.map +1 -0
  234. package/dist/ledger/types.d.ts +119 -0
  235. package/dist/ledger/types.d.ts.map +1 -0
  236. package/dist/ledger/types.js +22 -0
  237. package/dist/ledger/types.js.map +1 -0
  238. package/dist/ledger/validate.d.ts +10 -0
  239. package/dist/ledger/validate.d.ts.map +1 -0
  240. package/dist/ledger/validate.js +183 -0
  241. package/dist/ledger/validate.js.map +1 -0
  242. package/dist/mcp/server.d.ts +9 -0
  243. package/dist/mcp/server.d.ts.map +1 -0
  244. package/dist/mcp/server.js +86 -0
  245. package/dist/mcp/server.js.map +1 -0
  246. package/dist/memory/audit.d.ts +14 -0
  247. package/dist/memory/audit.d.ts.map +1 -0
  248. package/dist/memory/audit.js +16 -0
  249. package/dist/memory/audit.js.map +1 -0
  250. package/dist/memory/entries.d.ts +65 -0
  251. package/dist/memory/entries.d.ts.map +1 -0
  252. package/dist/memory/entries.js +200 -0
  253. package/dist/memory/entries.js.map +1 -0
  254. package/dist/memory/lifecycle.d.ts +29 -0
  255. package/dist/memory/lifecycle.d.ts.map +1 -0
  256. package/dist/memory/lifecycle.js +61 -0
  257. package/dist/memory/lifecycle.js.map +1 -0
  258. package/dist/memory/retrieval.d.ts +44 -0
  259. package/dist/memory/retrieval.d.ts.map +1 -0
  260. package/dist/memory/retrieval.js +174 -0
  261. package/dist/memory/retrieval.js.map +1 -0
  262. package/dist/memory/scoped-memory.d.ts +41 -0
  263. package/dist/memory/scoped-memory.d.ts.map +1 -0
  264. package/dist/memory/scoped-memory.js +65 -0
  265. package/dist/memory/scoped-memory.js.map +1 -0
  266. package/dist/memory/secrets.d.ts +6 -0
  267. package/dist/memory/secrets.d.ts.map +1 -0
  268. package/dist/memory/secrets.js +17 -0
  269. package/dist/memory/secrets.js.map +1 -0
  270. package/dist/memory/workspaces.d.ts +17 -0
  271. package/dist/memory/workspaces.d.ts.map +1 -0
  272. package/dist/memory/workspaces.js +92 -0
  273. package/dist/memory/workspaces.js.map +1 -0
  274. package/dist/repository/binding.d.ts +19 -0
  275. package/dist/repository/binding.d.ts.map +1 -0
  276. package/dist/repository/binding.js +78 -0
  277. package/dist/repository/binding.js.map +1 -0
  278. package/dist/repository/detect-root.d.ts +12 -0
  279. package/dist/repository/detect-root.d.ts.map +1 -0
  280. package/dist/repository/detect-root.js +57 -0
  281. package/dist/repository/detect-root.js.map +1 -0
  282. package/dist/repository/git-origin.d.ts +2 -0
  283. package/dist/repository/git-origin.d.ts.map +1 -0
  284. package/dist/repository/git-origin.js +15 -0
  285. package/dist/repository/git-origin.js.map +1 -0
  286. package/dist/repository/identity.d.ts +19 -0
  287. package/dist/repository/identity.d.ts.map +1 -0
  288. package/dist/repository/identity.js +23 -0
  289. package/dist/repository/identity.js.map +1 -0
  290. package/dist/repository/remote-url.d.ts +4 -0
  291. package/dist/repository/remote-url.d.ts.map +1 -0
  292. package/dist/repository/remote-url.js +36 -0
  293. package/dist/repository/remote-url.js.map +1 -0
  294. package/dist/security/sanitize.d.ts +4 -0
  295. package/dist/security/sanitize.d.ts.map +1 -0
  296. package/dist/security/sanitize.js +174 -0
  297. package/dist/security/sanitize.js.map +1 -0
  298. package/dist/serialization/envelope.d.ts +20 -0
  299. package/dist/serialization/envelope.d.ts.map +1 -0
  300. package/dist/serialization/envelope.js +11 -0
  301. package/dist/serialization/envelope.js.map +1 -0
  302. package/dist/serialization/validate.d.ts +31 -0
  303. package/dist/serialization/validate.d.ts.map +1 -0
  304. package/dist/serialization/validate.js +168 -0
  305. package/dist/serialization/validate.js.map +1 -0
  306. package/dist/server/agent-application.d.ts +6 -0
  307. package/dist/server/agent-application.d.ts.map +1 -0
  308. package/dist/server/agent-application.js +60 -0
  309. package/dist/server/agent-application.js.map +1 -0
  310. package/dist/server/app.d.ts +5 -0
  311. package/dist/server/app.d.ts.map +1 -0
  312. package/dist/server/app.js +87 -0
  313. package/dist/server/app.js.map +1 -0
  314. package/dist/server/auth.d.ts +2 -0
  315. package/dist/server/auth.d.ts.map +1 -0
  316. package/dist/server/auth.js +22 -0
  317. package/dist/server/auth.js.map +1 -0
  318. package/dist/server/http.d.ts +69 -0
  319. package/dist/server/http.d.ts.map +1 -0
  320. package/dist/server/http.js +349 -0
  321. package/dist/server/http.js.map +1 -0
  322. package/dist/server/idempotency.d.ts +12 -0
  323. package/dist/server/idempotency.d.ts.map +1 -0
  324. package/dist/server/idempotency.js +210 -0
  325. package/dist/server/idempotency.js.map +1 -0
  326. package/dist/server/instance-lock.d.ts +17 -0
  327. package/dist/server/instance-lock.d.ts.map +1 -0
  328. package/dist/server/instance-lock.js +118 -0
  329. package/dist/server/instance-lock.js.map +1 -0
  330. package/dist/server/router.d.ts +29 -0
  331. package/dist/server/router.d.ts.map +1 -0
  332. package/dist/server/router.js +112 -0
  333. package/dist/server/router.js.map +1 -0
  334. package/dist/server/routes/agent-events.d.ts +5 -0
  335. package/dist/server/routes/agent-events.d.ts.map +1 -0
  336. package/dist/server/routes/agent-events.js +46 -0
  337. package/dist/server/routes/agent-events.js.map +1 -0
  338. package/dist/server/routes/agent-intake.d.ts +5 -0
  339. package/dist/server/routes/agent-intake.d.ts.map +1 -0
  340. package/dist/server/routes/agent-intake.js +42 -0
  341. package/dist/server/routes/agent-intake.js.map +1 -0
  342. package/dist/server/routes/agent-promotions.d.ts +5 -0
  343. package/dist/server/routes/agent-promotions.d.ts.map +1 -0
  344. package/dist/server/routes/agent-promotions.js +52 -0
  345. package/dist/server/routes/agent-promotions.js.map +1 -0
  346. package/dist/server/routes/agent-runs.d.ts +25 -0
  347. package/dist/server/routes/agent-runs.d.ts.map +1 -0
  348. package/dist/server/routes/agent-runs.js +151 -0
  349. package/dist/server/routes/agent-runs.js.map +1 -0
  350. package/dist/server/routes/task5-support.d.ts +11 -0
  351. package/dist/server/routes/task5-support.d.ts.map +1 -0
  352. package/dist/server/routes/task5-support.js +22 -0
  353. package/dist/server/routes/task5-support.js.map +1 -0
  354. package/dist/server/routes/task5.d.ts +5 -0
  355. package/dist/server/routes/task5.d.ts.map +1 -0
  356. package/dist/server/routes/task5.js +72 -0
  357. package/dist/server/routes/task5.js.map +1 -0
  358. package/dist/server/runtime-descriptor.d.ts +24 -0
  359. package/dist/server/runtime-descriptor.d.ts.map +1 -0
  360. package/dist/server/runtime-descriptor.js +156 -0
  361. package/dist/server/runtime-descriptor.js.map +1 -0
  362. package/dist/server/write-queue.d.ts +20 -0
  363. package/dist/server/write-queue.d.ts.map +1 -0
  364. package/dist/server/write-queue.js +83 -0
  365. package/dist/server/write-queue.js.map +1 -0
  366. package/dist/setup/managed-text.d.ts +6 -0
  367. package/dist/setup/managed-text.d.ts.map +1 -0
  368. package/dist/setup/managed-text.js +42 -0
  369. package/dist/setup/managed-text.js.map +1 -0
  370. package/dist/setup/opencode-config.d.ts +3 -0
  371. package/dist/setup/opencode-config.d.ts.map +1 -0
  372. package/dist/setup/opencode-config.js +26 -0
  373. package/dist/setup/opencode-config.js.map +1 -0
  374. package/dist/setup/render.d.ts +8 -0
  375. package/dist/setup/render.d.ts.map +1 -0
  376. package/dist/setup/render.js +45 -0
  377. package/dist/setup/render.js.map +1 -0
  378. package/dist/web/server.d.ts +16 -0
  379. package/dist/web/server.d.ts.map +1 -0
  380. package/dist/web/server.js +424 -0
  381. package/dist/web/server.js.map +1 -0
  382. package/dist/web/ui.d.ts +2 -0
  383. package/dist/web/ui.d.ts.map +1 -0
  384. package/dist/web/ui.js +271 -0
  385. package/dist/web/ui.js.map +1 -0
  386. package/migrations/001_initial.sql +89 -0
  387. package/migrations/002_fts.sql +66 -0
  388. package/migrations/003_akinator.sql +30 -0
  389. package/migrations/004_agent_gateway.sql +259 -0
  390. package/package.json +45 -0
  391. package/templates/AGENTS.md +29 -0
@@ -0,0 +1,349 @@
1
+ import { randomBytes, randomUUID } from 'node:crypto';
2
+ import { AsyncLocalStorage } from 'node:async_hooks';
3
+ import { createServer as nodeCreateServer } from 'node:http';
4
+ import path from 'node:path';
5
+ import { getGlobalDatabasePath, getRuntimeDescriptorPath } from '../config/paths.js';
6
+ import { openConnection } from '../db/connection.js';
7
+ import { migrateDatabase as defaultMigrateDatabase } from '../db/migrate.js';
8
+ import { KiokukoError } from '../errors.js';
9
+ import { createApp } from './app.js';
10
+ import { acquireInstanceLock as defaultAcquireInstanceLock, isPidAlive as defaultIsPidAlive, } from './instance-lock.js';
11
+ import { createRuntimeDescriptor as defaultCreateRuntimeDescriptor, readRuntimeDescriptor as defaultReadRuntimeDescriptor, removeRuntimeDescriptor as defaultRemoveRuntimeDescriptor, toPublicRuntimeDescriptor, writeRuntimeDescriptor as defaultWriteRuntimeDescriptor, } from './runtime-descriptor.js';
12
+ import { WriteQueue } from './write-queue.js';
13
+ const DEFAULT_HOST = '127.0.0.1';
14
+ const DEFAULT_PORT = 0;
15
+ const DEFAULT_QUEUE_CAPACITY = 64;
16
+ function invalid(message, details = {}) {
17
+ throw new KiokukoError('VALIDATION_ERROR', message, details);
18
+ }
19
+ function validateHost(host) {
20
+ if (host !== '127.0.0.1' && host !== '::1' && host !== 'localhost') {
21
+ invalid('The HTTP server only accepts loopback hosts');
22
+ }
23
+ return host;
24
+ }
25
+ function validatePort(port) {
26
+ if (!Number.isInteger(port) || port < 0 || port > 65535) {
27
+ invalid('port must be an integer between 0 and 65535');
28
+ }
29
+ return port;
30
+ }
31
+ function validateCapabilityToken(token) {
32
+ if (!/^[a-f0-9]{64}$/.test(token))
33
+ invalid('capabilityToken must be a 256-bit lowercase hexadecimal value');
34
+ return token;
35
+ }
36
+ function validateApplicationComposition(options) {
37
+ if (options.applicationFactory !== undefined && (options.app !== undefined || options.v1 !== undefined)) {
38
+ invalid('applicationFactory cannot be combined with app or v1');
39
+ }
40
+ }
41
+ function descriptorPathFor(options) {
42
+ if (options.descriptorPath !== undefined)
43
+ return options.descriptorPath;
44
+ if (options.runtimeDirectory !== undefined) {
45
+ const join = options.platform === 'win32' ? path.win32.join : path.posix.join;
46
+ return join(options.runtimeDirectory, 'server.json');
47
+ }
48
+ return getRuntimeDescriptorPath(options);
49
+ }
50
+ function databasePathFor(options) {
51
+ return options.databasePath ?? getGlobalDatabasePath(options);
52
+ }
53
+ function lockOptionsFor(options, instanceId, pid, isPidAlive) {
54
+ const lockOptions = {
55
+ instanceId,
56
+ isPidAlive,
57
+ pid,
58
+ };
59
+ if (options.runtimeDirectory !== undefined)
60
+ lockOptions.runtimeDirectory = options.runtimeDirectory;
61
+ if (options.platform !== undefined)
62
+ lockOptions.platform = options.platform;
63
+ if (options.env !== undefined)
64
+ lockOptions.env = options.env;
65
+ return lockOptions;
66
+ }
67
+ function publicUrl(host, port) {
68
+ const renderedHost = host === '::1' ? '[::1]' : host;
69
+ return `http://${renderedHost}:${port}`;
70
+ }
71
+ function listeningPort(server) {
72
+ const address = server.address();
73
+ if (address === null || typeof address === 'string' || !Number.isInteger(address.port)) {
74
+ throw new KiokukoError('DATABASE_ERROR', 'HTTP server did not expose a listening address');
75
+ }
76
+ return address.port;
77
+ }
78
+ function safeRuntimeError(error, fallback) {
79
+ if (error instanceof KiokukoError) {
80
+ const messages = {
81
+ CONFLICT: 'Request conflicts with current runtime state',
82
+ VALIDATION_ERROR: 'Runtime configuration is invalid',
83
+ SECURITY_REJECTION: 'Runtime file was rejected',
84
+ };
85
+ return new KiokukoError(error.code, messages[error.code] ?? fallback);
86
+ }
87
+ return new KiokukoError('DATABASE_ERROR', fallback);
88
+ }
89
+ function safeStartupError(error) {
90
+ return safeRuntimeError(error, 'Unable to start the HTTP server');
91
+ }
92
+ function safeCloseError(error) {
93
+ return safeRuntimeError(error, 'Unable to close the HTTP server');
94
+ }
95
+ async function closeServer(server) {
96
+ await new Promise((resolve, reject) => {
97
+ try {
98
+ server.close((error) => {
99
+ if (error && (!('code' in error) || error.code !== 'ERR_SERVER_NOT_RUNNING')) {
100
+ reject(error);
101
+ return;
102
+ }
103
+ resolve();
104
+ });
105
+ }
106
+ catch (error) {
107
+ if (error instanceof Error && 'code' in error && error.code === 'ERR_SERVER_NOT_RUNNING') {
108
+ resolve();
109
+ return;
110
+ }
111
+ reject(error);
112
+ }
113
+ });
114
+ }
115
+ async function listen(server, port, host) {
116
+ await new Promise((resolve, reject) => {
117
+ const onError = (error) => {
118
+ server.off('listening', onListening);
119
+ reject(error);
120
+ };
121
+ const onListening = () => {
122
+ server.off('error', onError);
123
+ resolve();
124
+ };
125
+ server.once('error', onError);
126
+ server.once('listening', onListening);
127
+ try {
128
+ server.listen(port, host);
129
+ }
130
+ catch (error) {
131
+ server.off('error', onError);
132
+ server.off('listening', onListening);
133
+ reject(error);
134
+ }
135
+ });
136
+ }
137
+ async function removeOwnedDescriptor(removeDescriptor, descriptorPath, instanceId) {
138
+ await removeDescriptor(descriptorPath, instanceId);
139
+ }
140
+ async function assertDescriptorAvailable(readDescriptor, isPidAlive, descriptorPath) {
141
+ const existingDescriptor = await readDescriptor(descriptorPath);
142
+ if (existingDescriptor && await isPidAlive(existingDescriptor.pid)) {
143
+ throw new KiokukoError('CONFLICT', 'Another live Kiokuko instance owns the runtime descriptor');
144
+ }
145
+ }
146
+ export async function startHttpServer(options = {}) {
147
+ const host = validateHost(options.host ?? DEFAULT_HOST);
148
+ const port = validatePort(options.port ?? DEFAULT_PORT);
149
+ validateApplicationComposition(options);
150
+ const queueCapacity = options.queueCapacity ?? DEFAULT_QUEUE_CAPACITY;
151
+ const queue = new WriteQueue(queueCapacity);
152
+ const databasePath = databasePathFor(options);
153
+ const descriptorPath = descriptorPathFor(options);
154
+ const instanceId = options.instanceId ?? randomUUID();
155
+ const pid = options.pid ?? process.pid;
156
+ const capabilityToken = validateCapabilityToken(options.capabilityToken ?? randomBytes(32).toString('hex'));
157
+ const isPidAlive = options.dependencies?.isPidAlive ?? options.isPidAlive ?? defaultIsPidAlive;
158
+ const readDescriptor = options.dependencies?.readRuntimeDescriptor ?? options.readRuntimeDescriptor ?? defaultReadRuntimeDescriptor;
159
+ const writeDescriptor = options.dependencies?.writeRuntimeDescriptor ?? options.writeRuntimeDescriptor ?? defaultWriteRuntimeDescriptor;
160
+ const removeDescriptor = options.dependencies?.removeRuntimeDescriptor ?? options.removeRuntimeDescriptor ?? defaultRemoveRuntimeDescriptor;
161
+ const createDescriptor = options.dependencies?.createRuntimeDescriptor ?? options.createRuntimeDescriptor ?? defaultCreateRuntimeDescriptor;
162
+ const acquireLock = options.dependencies?.acquireInstanceLock ?? options.acquireInstanceLock ?? defaultAcquireInstanceLock;
163
+ const openDatabase = options.dependencies?.openDatabase ?? options.openDatabase ?? openConnection;
164
+ const migrate = options.dependencies?.migrateDatabase ?? options.migrateDatabase ?? defaultMigrateDatabase;
165
+ const createHttpServer = options.dependencies?.createServer ?? options.createServer ?? nodeCreateServer;
166
+ try {
167
+ await assertDescriptorAvailable(readDescriptor, isPidAlive, descriptorPath);
168
+ }
169
+ catch (error) {
170
+ throw safeStartupError(error);
171
+ }
172
+ let database;
173
+ let lock;
174
+ let server;
175
+ let descriptorAttempted = false;
176
+ let databaseClosed = false;
177
+ let lockReleased = false;
178
+ let descriptorRemoved = false;
179
+ const rollback = async (originalError) => {
180
+ if (server !== undefined)
181
+ await closeServer(server).catch(() => undefined);
182
+ await queue.close().catch(() => undefined);
183
+ if (database !== undefined && !databaseClosed) {
184
+ try {
185
+ database.close();
186
+ }
187
+ catch {
188
+ // Preserve the startup error.
189
+ }
190
+ databaseClosed = true;
191
+ }
192
+ if (descriptorAttempted && !descriptorRemoved) {
193
+ await removeOwnedDescriptor(removeDescriptor, descriptorPath, instanceId).catch(() => undefined);
194
+ descriptorRemoved = true;
195
+ }
196
+ if (lock !== undefined && !lockReleased) {
197
+ await lock.release().catch(() => undefined);
198
+ lockReleased = true;
199
+ }
200
+ throw safeStartupError(originalError);
201
+ };
202
+ try {
203
+ lock = await acquireLock(databasePath, lockOptionsFor(options, instanceId, pid, isPidAlive));
204
+ database = await openDatabase(databasePath);
205
+ await migrate(database, options.migrationsDirectory);
206
+ let closing = false;
207
+ let ready = false;
208
+ const requestAdmission = new AsyncLocalStorage();
209
+ let activeRequests = 0;
210
+ const requestDrainWaiters = [];
211
+ const waitForAcceptedRequests = () => {
212
+ if (activeRequests === 0)
213
+ return Promise.resolve();
214
+ return new Promise((resolve) => {
215
+ requestDrainWaiters.push(resolve);
216
+ });
217
+ };
218
+ const enqueueWrite = (operation) => {
219
+ if (closing && requestAdmission.getStore()?.active !== true) {
220
+ return Promise.reject(new KiokukoError('SERVICE_UNAVAILABLE', 'Write queue is closed'));
221
+ }
222
+ return queue.enqueue(operation);
223
+ };
224
+ const createAuthenticatedApp = (v1) => createApp({
225
+ expectedToken: capabilityToken,
226
+ readiness: () => ready && !closing,
227
+ ...(v1 === undefined ? {} : { v1 }),
228
+ });
229
+ const application = options.applicationFactory === undefined
230
+ ? options.app ?? createAuthenticatedApp(options.v1)
231
+ : options.applicationFactory({
232
+ database,
233
+ enqueueWrite,
234
+ createAuthenticatedApp,
235
+ });
236
+ const requestListener = (request, response) => {
237
+ const admission = { active: true };
238
+ activeRequests += 1;
239
+ const settle = () => {
240
+ if (!admission.active)
241
+ return;
242
+ admission.active = false;
243
+ activeRequests -= 1;
244
+ if (activeRequests !== 0)
245
+ return;
246
+ const waiters = requestDrainWaiters.splice(0);
247
+ for (const resolve of waiters)
248
+ resolve();
249
+ };
250
+ response.once('finish', settle);
251
+ response.once('close', settle);
252
+ try {
253
+ requestAdmission.run(admission, () => application(request, response));
254
+ }
255
+ catch (error) {
256
+ settle();
257
+ throw error;
258
+ }
259
+ };
260
+ server = createHttpServer(requestListener);
261
+ await listen(server, port, host);
262
+ const actualPort = listeningPort(server);
263
+ const url = publicUrl(host, actualPort);
264
+ const descriptor = createDescriptor({
265
+ baseUrl: url,
266
+ capabilityToken,
267
+ databasePath,
268
+ instanceId,
269
+ pid,
270
+ ...(options.startedAt === undefined ? {} : { startedAt: options.startedAt }),
271
+ });
272
+ await assertDescriptorAvailable(readDescriptor, isPidAlive, descriptorPath);
273
+ descriptorAttempted = true;
274
+ await writeDescriptor(descriptorPath, descriptor);
275
+ ready = true;
276
+ const publicDescriptor = toPublicRuntimeDescriptor(descriptor);
277
+ let closePromise;
278
+ const handle = {
279
+ server,
280
+ url,
281
+ descriptor: publicDescriptor,
282
+ runtimeDescriptor: publicDescriptor,
283
+ get queueState() {
284
+ return queue.state;
285
+ },
286
+ enqueueWrite(operation) {
287
+ return enqueueWrite(operation);
288
+ },
289
+ close() {
290
+ if (closePromise !== undefined)
291
+ return closePromise;
292
+ closing = true;
293
+ ready = false;
294
+ closePromise = (async () => {
295
+ let firstError;
296
+ const serverClose = closeServer(server).catch((error) => {
297
+ firstError ??= error;
298
+ });
299
+ const requestClose = waitForAcceptedRequests().catch((error) => {
300
+ firstError ??= error;
301
+ });
302
+ const queueClose = activeRequests === 0
303
+ ? queue.close().catch((error) => {
304
+ firstError ??= error;
305
+ })
306
+ : undefined;
307
+ await Promise.all([serverClose, requestClose]);
308
+ if (queueClose === undefined) {
309
+ await queue.close().catch((error) => {
310
+ firstError ??= error;
311
+ });
312
+ }
313
+ else {
314
+ await queueClose;
315
+ }
316
+ if (database !== undefined && !databaseClosed) {
317
+ try {
318
+ database.close();
319
+ }
320
+ catch (error) {
321
+ firstError ??= error;
322
+ }
323
+ databaseClosed = true;
324
+ }
325
+ if (!descriptorRemoved) {
326
+ await removeOwnedDescriptor(removeDescriptor, descriptorPath, instanceId).catch((error) => {
327
+ firstError ??= error;
328
+ });
329
+ descriptorRemoved = true;
330
+ }
331
+ if (lock !== undefined && !lockReleased) {
332
+ await lock.release().catch((error) => {
333
+ firstError ??= error;
334
+ });
335
+ lockReleased = true;
336
+ }
337
+ if (firstError !== undefined)
338
+ throw safeCloseError(firstError);
339
+ })();
340
+ return closePromise;
341
+ },
342
+ };
343
+ return handle;
344
+ }
345
+ catch (error) {
346
+ return rollback(error);
347
+ }
348
+ }
349
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/server/http.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { SqliteDatabase } from '../db/adapter.js';
2
+ import { type JsonValue } from '../serialization/validate.js';
3
+ export interface IdempotencyInput {
4
+ readonly scope: unknown;
5
+ readonly key: unknown;
6
+ readonly request: unknown;
7
+ readonly createdAt?: unknown;
8
+ }
9
+ export type IdempotencyOperation<T extends JsonValue = JsonValue> = () => T;
10
+ export declare function executeIdempotent<T extends JsonValue>(database: SqliteDatabase, input: unknown, operation: IdempotencyOperation<T>): T;
11
+ export declare function executeIdempotentInTransaction<T extends JsonValue>(database: SqliteDatabase, input: unknown, operation: IdempotencyOperation<T>): T;
12
+ //# sourceMappingURL=idempotency.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.d.ts","sourceRoot":"","sources":["../../src/server/idempotency.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAGvD,OAAO,EAAiB,KAAK,SAAS,EAAE,MAAM,8BAA8B,CAAC;AAE7E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,SAAS,GAAG,SAAS,IAAI,MAAM,CAAC,CAAC;AAwO5E,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,SAAS,EACnD,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,oBAAoB,CAAC,CAAC,CAAC,GACjC,CAAC,CAIH;AAED,wBAAgB,8BAA8B,CAAC,CAAC,SAAS,SAAS,EAChE,QAAQ,EAAE,cAAc,EACxB,KAAK,EAAE,OAAO,EACd,SAAS,EAAE,oBAAoB,CAAC,CAAC,CAAC,GACjC,CAAC,CAIH"}
@@ -0,0 +1,210 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { withImmediateTransaction } from '../db/transaction.js';
3
+ import { KiokukoError } from '../errors.js';
4
+ import { canonicalJson } from '../serialization/validate.js';
5
+ const MAX_SCOPE_OR_KEY_LENGTH = 256;
6
+ const INPUT_FIELDS = new Set(['scope', 'key', 'request', 'createdAt']);
7
+ const CONTROL_CHARACTERS = /\p{Cc}/u;
8
+ const CANONICAL_TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$/u;
9
+ const VALIDATION_MESSAGE = 'Invalid idempotency input';
10
+ const RESPONSE_VALIDATION_MESSAGE = 'Invalid idempotency response';
11
+ const INTEGRITY_MESSAGE = 'Stored idempotency record is invalid';
12
+ const CONFLICT_MESSAGE = 'Idempotency key was reused with a different request';
13
+ function invalidInput() {
14
+ throw new KiokukoError('VALIDATION_ERROR', VALIDATION_MESSAGE);
15
+ }
16
+ function invalidResponse() {
17
+ throw new KiokukoError('VALIDATION_ERROR', RESPONSE_VALIDATION_MESSAGE);
18
+ }
19
+ function sha256(value) {
20
+ return createHash('sha256').update(value, 'utf8').digest('hex');
21
+ }
22
+ function isPlainObject(value) {
23
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
24
+ return false;
25
+ try {
26
+ const prototype = Object.getPrototypeOf(value);
27
+ return prototype === Object.prototype || prototype === null;
28
+ }
29
+ catch {
30
+ return false;
31
+ }
32
+ }
33
+ function isCanonicalArrayIndex(value) {
34
+ if (value === '0')
35
+ return true;
36
+ if (!/^[1-9]\d*$/u.test(value))
37
+ return false;
38
+ const index = Number(value);
39
+ return Number.isSafeInteger(index) && index < 4_294_967_295 && String(index) === value;
40
+ }
41
+ function validateJsonValue(value, ancestors, failure) {
42
+ if (value === null || typeof value === 'boolean' || typeof value === 'string')
43
+ return;
44
+ if (typeof value === 'number') {
45
+ if (Number.isFinite(value))
46
+ return;
47
+ failure();
48
+ }
49
+ if (typeof value !== 'object')
50
+ failure();
51
+ if (ancestors.has(value))
52
+ failure();
53
+ ancestors.add(value);
54
+ try {
55
+ if (Array.isArray(value)) {
56
+ for (const key of Reflect.ownKeys(value)) {
57
+ if (typeof key !== 'string' || (key !== 'length' && !isCanonicalArrayIndex(key)))
58
+ failure();
59
+ }
60
+ for (const item of value)
61
+ validateJsonValue(item, ancestors, failure);
62
+ }
63
+ else {
64
+ if (!isPlainObject(value))
65
+ failure();
66
+ for (const key of Reflect.ownKeys(value)) {
67
+ if (typeof key !== 'string')
68
+ failure();
69
+ }
70
+ for (const child of Object.values(value))
71
+ validateJsonValue(child, ancestors, failure);
72
+ }
73
+ }
74
+ finally {
75
+ ancestors.delete(value);
76
+ }
77
+ }
78
+ function boundedString(value) {
79
+ if (typeof value !== 'string'
80
+ || value.trim().length === 0
81
+ || value.length > MAX_SCOPE_OR_KEY_LENGTH
82
+ || CONTROL_CHARACTERS.test(value)) {
83
+ invalidInput();
84
+ }
85
+ return value;
86
+ }
87
+ function isCanonicalTimestamp(value) {
88
+ if (typeof value !== 'string' || !CANONICAL_TIMESTAMP.test(value))
89
+ return false;
90
+ const parsed = new Date(value);
91
+ return !Number.isNaN(parsed.getTime()) && parsed.toISOString() === value;
92
+ }
93
+ function canonicalTimestamp(value) {
94
+ if (!isCanonicalTimestamp(value))
95
+ invalidInput();
96
+ return value;
97
+ }
98
+ function validateInput(input) {
99
+ if (!isPlainObject(input))
100
+ invalidInput();
101
+ try {
102
+ for (const field of Reflect.ownKeys(input)) {
103
+ if (typeof field !== 'string' || !INPUT_FIELDS.has(field))
104
+ invalidInput();
105
+ }
106
+ }
107
+ catch {
108
+ invalidInput();
109
+ }
110
+ const scope = boundedString(input.scope);
111
+ const key = boundedString(input.key);
112
+ let requestJson;
113
+ try {
114
+ validateJsonValue(input.request, new WeakSet(), invalidInput);
115
+ requestJson = canonicalJson(input.request);
116
+ }
117
+ catch {
118
+ invalidInput();
119
+ }
120
+ const createdAt = input.createdAt === undefined
121
+ ? new Date().toISOString()
122
+ : canonicalTimestamp(input.createdAt);
123
+ return {
124
+ scope,
125
+ keyHash: sha256(key),
126
+ requestHash: sha256(requestJson),
127
+ createdAt,
128
+ };
129
+ }
130
+ function invalidStoredRecord() {
131
+ throw new KiokukoError('INTEGRITY_ERROR', INTEGRITY_MESSAGE);
132
+ }
133
+ function isSha256(value) {
134
+ return typeof value === 'string' && /^[0-9a-f]{64}$/u.test(value);
135
+ }
136
+ function storedResponse(row, expectedScope) {
137
+ if (row.scope !== expectedScope
138
+ || !isSha256(row.key_hash)
139
+ || !isSha256(row.request_hash)
140
+ || typeof row.response_json !== 'string'
141
+ || !isCanonicalTimestamp(row.created_at)) {
142
+ invalidStoredRecord();
143
+ }
144
+ let parsed;
145
+ try {
146
+ parsed = JSON.parse(row.response_json);
147
+ if (canonicalJson(parsed) !== row.response_json)
148
+ invalidStoredRecord();
149
+ }
150
+ catch {
151
+ invalidStoredRecord();
152
+ }
153
+ return parsed;
154
+ }
155
+ function findStoredRecord(database, validated) {
156
+ const select = `
157
+ SELECT scope, key_hash, request_hash, response_json, created_at
158
+ FROM gateway_idempotency
159
+ `;
160
+ const direct = database.prepare(`${select} WHERE scope = ? AND key_hash = ?`).get(validated.scope, validated.keyHash);
161
+ if (direct) {
162
+ const response = storedResponse(direct, validated.scope);
163
+ return { requestHash: direct.request_hash, response };
164
+ }
165
+ for (const row of database.prepare(`${select} WHERE scope = ?`).all(validated.scope)) {
166
+ const response = storedResponse(row, validated.scope);
167
+ if (row.key_hash === validated.keyHash) {
168
+ return { requestHash: row.request_hash, response };
169
+ }
170
+ }
171
+ return undefined;
172
+ }
173
+ function validateOperation(operation) {
174
+ if (typeof operation !== 'function')
175
+ invalidInput();
176
+ }
177
+ function executeValidated(database, validated, operation) {
178
+ const existing = findStoredRecord(database, validated);
179
+ if (existing) {
180
+ if (existing.requestHash !== validated.requestHash) {
181
+ throw new KiokukoError('CONFLICT', CONFLICT_MESSAGE, { reason: 'request_mismatch' });
182
+ }
183
+ return existing.response;
184
+ }
185
+ const responseValue = operation();
186
+ let responseJson;
187
+ try {
188
+ validateJsonValue(responseValue, new WeakSet(), invalidResponse);
189
+ responseJson = canonicalJson(responseValue);
190
+ }
191
+ catch {
192
+ throw new KiokukoError('VALIDATION_ERROR', RESPONSE_VALIDATION_MESSAGE);
193
+ }
194
+ database.prepare(`
195
+ INSERT INTO gateway_idempotency (scope, key_hash, request_hash, response_json, created_at)
196
+ VALUES (?, ?, ?, ?, ?)
197
+ `).run(validated.scope, validated.keyHash, validated.requestHash, responseJson, validated.createdAt);
198
+ return JSON.parse(responseJson);
199
+ }
200
+ export function executeIdempotent(database, input, operation) {
201
+ validateOperation(operation);
202
+ const validated = validateInput(input);
203
+ return withImmediateTransaction(database, () => executeValidated(database, validated, operation));
204
+ }
205
+ export function executeIdempotentInTransaction(database, input, operation) {
206
+ validateOperation(operation);
207
+ const validated = validateInput(input);
208
+ return executeValidated(database, validated, operation);
209
+ }
210
+ //# sourceMappingURL=idempotency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"idempotency.js","sourceRoot":"","sources":["../../src/server/idempotency.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import { type PathEnvironment } from '../config/paths.js';
2
+ export type PidLiveness = (pid: number) => boolean | Promise<boolean>;
3
+ export interface InstanceLockOptions extends PathEnvironment {
4
+ runtimeDirectory?: string;
5
+ pid?: number;
6
+ instanceId?: string;
7
+ isPidAlive?: PidLiveness;
8
+ }
9
+ export interface InstanceLock {
10
+ path: string;
11
+ instanceId: string;
12
+ release(): Promise<boolean>;
13
+ }
14
+ export declare function isPidAlive(pid: number): Promise<boolean>;
15
+ export declare function acquireInstanceLock(databasePath: string, options?: InstanceLockOptions): Promise<InstanceLock>;
16
+ export declare function releaseInstanceLock(lockFilePath: string, expectedInstanceId: string): Promise<boolean>;
17
+ //# sourceMappingURL=instance-lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"instance-lock.d.ts","sourceRoot":"","sources":["../../src/server/instance-lock.ts"],"names":[],"mappings":"AAGA,OAAO,EAAuB,KAAK,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAG/E,MAAM,MAAM,WAAW,GAAG,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEtE,MAAM,WAAW,mBAAoB,SAAQ,eAAe;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,WAAW,CAAC;CAC1B;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7B;AAgDD,wBAAsB,UAAU,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAW9D;AAED,wBAAsB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,GAAE,mBAAwB,GAAG,OAAO,CAAC,YAAY,CAAC,CA6BxH;AAED,wBAAsB,mBAAmB,CAAC,YAAY,EAAE,MAAM,EAAE,kBAAkB,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAgB5G"}