theokit 0.4.0-beta.0 → 0.4.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 (297) hide show
  1. package/dist/{actions-virtual-module-HWNTIEPI.js → actions-virtual-module-IY46EEEX.js} +2 -2
  2. package/dist/{actions-virtual-module-SEIPACG5.js → actions-virtual-module-XNHDNCZ6.js} +2 -2
  3. package/dist/add-2ZFFGGE4.js +0 -0
  4. package/dist/{app-typed-client-ITIYTBXO.js → app-typed-client-OUJO3V5J.js} +10 -5
  5. package/dist/{app-typed-client-62FYBLVJ.js.map → app-typed-client-OUJO3V5J.js.map} +1 -1
  6. package/dist/{app-typed-client-62FYBLVJ.js → app-typed-client-YOMWSA3F.js} +11 -6
  7. package/dist/{app-typed-client-ITIYTBXO.js.map → app-typed-client-YOMWSA3F.js.map} +1 -1
  8. package/dist/audit-log-BQWM5YLG.d.ts +60 -0
  9. package/dist/{aws-lambda-XYCGZH3I.js → aws-lambda-GKSTX6HD.js} +3 -3
  10. package/dist/body-parser-web-MUWBKZ3F.js +70 -0
  11. package/dist/body-parser-web-MUWBKZ3F.js.map +1 -0
  12. package/dist/broadcast-QOQGUNNK.js +0 -0
  13. package/dist/{build-HIGHJQQV.js → build-D4J7XECU.js} +31 -22
  14. package/dist/build-D4J7XECU.js.map +1 -0
  15. package/dist/build-request-body-preview-II2235E6.js +0 -0
  16. package/dist/{bun-K73TQEWC.js → bun-ISHSNFIO.js} +3 -3
  17. package/dist/{check-PZR67OY5.js → check-NXYPLM6M.js} +2 -2
  18. package/dist/{chunk-WZ7CPVQB.js → chunk-27LWMYNK.js} +28 -24
  19. package/dist/chunk-27LWMYNK.js.map +1 -0
  20. package/dist/{chunk-BIGBFZSU.js → chunk-2F4FROEQ.js} +1689 -1521
  21. package/dist/chunk-2F4FROEQ.js.map +1 -0
  22. package/dist/chunk-4HBI7DHP.js +20 -0
  23. package/dist/chunk-4HBI7DHP.js.map +1 -0
  24. package/dist/{chunk-X4JAX2U3.js → chunk-4S2UCILN.js} +180 -125
  25. package/dist/chunk-4S2UCILN.js.map +1 -0
  26. package/dist/{chunk-C52GSJPF.js → chunk-4S6YHNG2.js} +11 -8
  27. package/dist/chunk-4S6YHNG2.js.map +1 -0
  28. package/dist/chunk-5ODOE6EF.js +0 -0
  29. package/dist/{chunk-KJVEJILQ.js → chunk-5PU65T5W.js} +9 -3
  30. package/dist/chunk-5PU65T5W.js.map +1 -0
  31. package/dist/chunk-5QW7IQQU.js +36 -0
  32. package/dist/chunk-5QW7IQQU.js.map +1 -0
  33. package/dist/chunk-5Z2727GV.js +1324 -0
  34. package/dist/chunk-5Z2727GV.js.map +1 -0
  35. package/dist/{chunk-YLBSSEHX.js → chunk-6NEXVBPY.js} +5 -15
  36. package/dist/chunk-6NEXVBPY.js.map +1 -0
  37. package/dist/chunk-7MQOHNHE.js +36 -0
  38. package/dist/chunk-7MQOHNHE.js.map +1 -0
  39. package/dist/{chunk-TPCT3MXV.js → chunk-ABVITXFH.js} +405 -272
  40. package/dist/chunk-ABVITXFH.js.map +1 -0
  41. package/dist/chunk-ASDXVRJD.js +185 -0
  42. package/dist/chunk-ASDXVRJD.js.map +1 -0
  43. package/dist/chunk-B3L3TJVF.js +406 -0
  44. package/dist/chunk-B3L3TJVF.js.map +1 -0
  45. package/dist/{chunk-PB4GR7EP.js → chunk-C3ZZ56YZ.js} +1 -18
  46. package/dist/chunk-C3ZZ56YZ.js.map +1 -0
  47. package/dist/{chunk-O7335ZGH.js → chunk-CG563V5M.js} +5 -3
  48. package/dist/chunk-CG563V5M.js.map +1 -0
  49. package/dist/{chunk-5OFPQK6N.js → chunk-COXLEZCN.js} +2 -1
  50. package/dist/chunk-COXLEZCN.js.map +1 -0
  51. package/dist/{chunk-O4BLVPML.js → chunk-DNMSV3R3.js} +22 -28
  52. package/dist/chunk-DNMSV3R3.js.map +1 -0
  53. package/dist/chunk-E3JH6YUM.js +1 -0
  54. package/dist/chunk-ESC54TAK.js +220 -0
  55. package/dist/chunk-ESC54TAK.js.map +1 -0
  56. package/dist/chunk-FI7MPTJW.js +77 -0
  57. package/dist/chunk-FI7MPTJW.js.map +1 -0
  58. package/dist/chunk-H4J2LECY.js +201 -0
  59. package/dist/chunk-H4J2LECY.js.map +1 -0
  60. package/dist/chunk-IAJ2JVEH.js +256 -0
  61. package/dist/chunk-IAJ2JVEH.js.map +1 -0
  62. package/dist/{chunk-F3TG5FJV.js → chunk-IEZCAT2I.js} +7 -1
  63. package/dist/{chunk-F3TG5FJV.js.map → chunk-IEZCAT2I.js.map} +1 -1
  64. package/dist/chunk-JHEAWR3L.js +1 -0
  65. package/dist/chunk-JQSKBMXP.js +17 -0
  66. package/dist/chunk-JQSKBMXP.js.map +1 -0
  67. package/dist/{chunk-4QTKSLTO.js → chunk-K4M64WD6.js} +9 -5
  68. package/dist/{chunk-4QTKSLTO.js.map → chunk-K4M64WD6.js.map} +1 -1
  69. package/dist/chunk-KI7OWQUX.js +293 -0
  70. package/dist/chunk-KI7OWQUX.js.map +1 -0
  71. package/dist/chunk-KT3MWNZG.js +0 -0
  72. package/dist/{chunk-ZJW5FFYJ.js → chunk-LC5PYNJP.js} +2 -2
  73. package/dist/{chunk-JAAHOGKI.js → chunk-M2EY7KDR.js} +1223 -1124
  74. package/dist/chunk-M2EY7KDR.js.map +1 -0
  75. package/dist/{chunk-2VQKDRVF.js → chunk-MR7OLIC6.js} +3 -3
  76. package/dist/chunk-NM4WF3XD.js +63 -0
  77. package/dist/chunk-NM4WF3XD.js.map +1 -0
  78. package/dist/chunk-NPMCKOX4.js +1 -0
  79. package/dist/{chunk-VRHXOKRP.js → chunk-NZXH2LQQ.js} +86 -83
  80. package/dist/chunk-NZXH2LQQ.js.map +1 -0
  81. package/dist/{chunk-B6RP57M3.js → chunk-OLPB36O2.js} +4 -4
  82. package/dist/chunk-PIVX3DYW.js +142 -0
  83. package/dist/chunk-PIVX3DYW.js.map +1 -0
  84. package/dist/{chunk-7TOMTMHT.js → chunk-R7OC6UDK.js} +2 -1
  85. package/dist/chunk-R7OC6UDK.js.map +1 -0
  86. package/dist/chunk-RESN62GB.js +269 -0
  87. package/dist/chunk-RESN62GB.js.map +1 -0
  88. package/dist/{chunk-64JI5LTO.js → chunk-RMU7EBRO.js} +2 -2
  89. package/dist/chunk-RMU7EBRO.js.map +1 -0
  90. package/dist/chunk-TQYSPYKU.js +131 -0
  91. package/dist/chunk-TQYSPYKU.js.map +1 -0
  92. package/dist/chunk-TSLSIRBR.js +107 -0
  93. package/dist/chunk-TSLSIRBR.js.map +1 -0
  94. package/dist/{chunk-XP7YXRHO.js → chunk-U6TPSW4L.js} +37 -5
  95. package/dist/chunk-U6TPSW4L.js.map +1 -0
  96. package/dist/chunk-UD3LFGDL.js +45 -0
  97. package/dist/chunk-UD3LFGDL.js.map +1 -0
  98. package/dist/chunk-UUFYP2UM.js +161 -0
  99. package/dist/chunk-UUFYP2UM.js.map +1 -0
  100. package/dist/{chunk-OXIQI2XZ.js → chunk-VBZCVFSA.js} +2 -2
  101. package/dist/chunk-VMEWD57H.js +137 -0
  102. package/dist/chunk-VMEWD57H.js.map +1 -0
  103. package/dist/{chunk-TRH2L3FI.js → chunk-WEGALZEU.js} +3 -3
  104. package/dist/{chunk-ZOXNJV2O.js → chunk-WGHJD6I7.js} +35 -138
  105. package/dist/chunk-WGHJD6I7.js.map +1 -0
  106. package/dist/chunk-XMS5VRIK.js +0 -0
  107. package/dist/chunk-Y4H3JNVK.js +18 -0
  108. package/dist/chunk-Y4H3JNVK.js.map +1 -0
  109. package/dist/chunk-Z5IGLBWE.js +329 -0
  110. package/dist/chunk-Z5IGLBWE.js.map +1 -0
  111. package/dist/chunk-ZEGYW52B.js +26 -0
  112. package/dist/chunk-ZEGYW52B.js.map +1 -0
  113. package/dist/chunk-ZJQ4O76G.js +87 -0
  114. package/dist/chunk-ZJQ4O76G.js.map +1 -0
  115. package/dist/cli/index.js +32 -21
  116. package/dist/cli/index.js.map +1 -1
  117. package/dist/client/index.d.ts +107 -1
  118. package/dist/client/index.js +152 -6
  119. package/dist/client/index.js.map +1 -1
  120. package/dist/{cloudflare-LCAOTRYZ.js → cloudflare-OJGJ7R2D.js} +3 -3
  121. package/dist/configure-agent-registry-6YGTJYBC.js +0 -0
  122. package/dist/cookies-MJKMGJ7N.js +22 -0
  123. package/dist/csrf-BBrEZSBW.d.ts +107 -0
  124. package/dist/csrf-readiness-store-CjIoub3U.d.ts +43 -0
  125. package/dist/define-websocket-CdK94O-D.d.ts +64 -0
  126. package/dist/{deno-deploy-ZN4RE5HF.js → deno-deploy-BHWKFTOW.js} +3 -3
  127. package/dist/{dev-266MVCVA.js → dev-MJVSRZGF.js} +11 -11
  128. package/dist/{dev-emit-RBSFZZNO.js → dev-emit-5VPRCHOD.js} +39 -142
  129. package/dist/dev-emit-5VPRCHOD.js.map +1 -0
  130. package/dist/{dev-emit-NO6OZJOQ.js → dev-emit-HHP2XJXE.js} +5 -5
  131. package/dist/devtools/entry.js +185 -131
  132. package/dist/devtools/entry.js.map +1 -1
  133. package/dist/{dispatcher-AQJGI3HU.js → dispatcher-63LBXYLE.js} +2 -2
  134. package/dist/{dispatcher-E6QV32BO.js → dispatcher-EJME6C6M.js} +5 -2
  135. package/dist/dispatcher-EJME6C6M.js.map +1 -0
  136. package/dist/{dist-5V77Z223.js → dist-KRW6OVD4.js} +7 -7
  137. package/dist/dist-KRW6OVD4.js.map +1 -0
  138. package/dist/docker-EZDA5FT7.js +0 -0
  139. package/dist/error-envelope-BsNzzAV5.d.ts +62 -0
  140. package/dist/{generate-DT4IIAHF.js → generate-AZ2K6Z2Z.js} +75 -2
  141. package/dist/generate-AZ2K6Z2Z.js.map +1 -0
  142. package/dist/index-DWWEdFh5.d.ts +399 -0
  143. package/dist/index.d.ts +161 -1391
  144. package/dist/index.js +20 -8
  145. package/dist/index.js.map +1 -1
  146. package/dist/{info-FJ4NXKTB.js → info-47VB62MV.js} +5 -5
  147. package/dist/job-backend-CgC8Xf33.d.ts +68 -0
  148. package/dist/{lib-NL5JXGEB.js → lib-NST3PNZX.js} +31 -31
  149. package/dist/lib-NST3PNZX.js.map +1 -0
  150. package/dist/module-loader-Cfz7dgCP.d.ts +26 -0
  151. package/dist/{netlify-5VQ22Z2P.js → netlify-GSNSJGMN.js} +3 -3
  152. package/dist/{node-3APTLGWB.js → node-6I5B6RL3.js} +3 -3
  153. package/dist/node-6I5B6RL3.js.map +1 -0
  154. package/dist/{openapi-FNVSWZOL.js → openapi-NFLSNNVQ.js} +10 -10
  155. package/dist/plugin-runner-BGBkzgi0.d.ts +95 -0
  156. package/dist/plugin-types-DNJGxr4Z.d.ts +79 -0
  157. package/dist/{proper-lockfile-4Y3DP3RP.js → proper-lockfile-MVKMQGFK.js} +27 -27
  158. package/dist/proper-lockfile-MVKMQGFK.js.map +1 -0
  159. package/dist/rate-limit-BdNDZ3vt.d.ts +58 -0
  160. package/dist/registry-QHEZ3BWB.js +25 -0
  161. package/dist/router-RGZFX75G.js +0 -0
  162. package/dist/{routes-H4SPLFHJ.js → routes-3A4XGIEJ.js} +6 -6
  163. package/dist/{scan-C2BOKLSY.js → scan-NQFI5S7P.js} +2 -2
  164. package/dist/scan-NQFI5S7P.js.map +1 -0
  165. package/dist/schema-D3v8VB7o.d.ts +76 -0
  166. package/dist/{schema-VR6YNVLQ.js → schema-KZVOV333.js} +5 -3
  167. package/dist/schema-KZVOV333.js.map +1 -0
  168. package/dist/server/agent/index.d.ts +229 -0
  169. package/dist/server/agent/index.js +16 -0
  170. package/dist/server/agent/index.js.map +1 -0
  171. package/dist/server/auth/index.d.ts +46 -1
  172. package/dist/server/auth/index.js +10 -3
  173. package/dist/server/cost/index.d.ts +1 -3
  174. package/dist/server/cost/index.js +1 -1
  175. package/dist/server/cron/index.js +4 -2
  176. package/dist/server/define/index.d.ts +281 -0
  177. package/dist/server/define/index.js +26 -0
  178. package/dist/server/define/index.js.map +1 -0
  179. package/dist/server/http/index.d.ts +10 -0
  180. package/dist/server/http/index.js +74 -0
  181. package/dist/server/http/index.js.map +1 -0
  182. package/dist/server/index.d.ts +151 -1677
  183. package/dist/server/index.js +558 -1102
  184. package/dist/server/index.js.map +1 -1
  185. package/dist/server/jobs/index.d.ts +348 -2
  186. package/dist/server/jobs/index.js +5 -3
  187. package/dist/server/observability/index.d.ts +324 -0
  188. package/dist/server/observability/index.js +48 -0
  189. package/dist/server/observability/index.js.map +1 -0
  190. package/dist/server/plugins/index.d.ts +17 -0
  191. package/dist/server/plugins/index.js +17 -0
  192. package/dist/server/plugins/index.js.map +1 -0
  193. package/dist/server/rate-limit/index.d.ts +105 -0
  194. package/dist/server/rate-limit/index.js +25 -0
  195. package/dist/server/rate-limit/index.js.map +1 -0
  196. package/dist/server/realtime/index.d.ts +15 -0
  197. package/dist/server/realtime/index.js +8 -0
  198. package/dist/server/realtime/index.js.map +1 -0
  199. package/dist/server/scan/index.d.ts +106 -0
  200. package/dist/server/scan/index.js +43 -0
  201. package/dist/server/scan/index.js.map +1 -0
  202. package/dist/server/security/index.d.ts +193 -0
  203. package/dist/server/security/index.js +50 -0
  204. package/dist/server/security/index.js.map +1 -0
  205. package/dist/server/storage/index.d.ts +22 -0
  206. package/dist/server/storage/index.js +14 -0
  207. package/dist/server/storage/index.js.map +1 -0
  208. package/dist/server/webhook/index.d.ts +148 -0
  209. package/dist/server/webhook/index.js +19 -0
  210. package/dist/server/webhook/index.js.map +1 -0
  211. package/dist/server-error-to-envelope-NO4CCAFQ.js +8 -0
  212. package/dist/server-error-to-envelope-NO4CCAFQ.js.map +1 -0
  213. package/dist/server-error-to-envelope-UJK6OWDJ.js +134 -0
  214. package/dist/server-error-to-envelope-UJK6OWDJ.js.map +1 -0
  215. package/dist/server-routes-hmr-GZJGPWMS.js +0 -0
  216. package/dist/services-json-Z2QNGVPW.js +142 -0
  217. package/dist/services-json-Z2QNGVPW.js.map +1 -0
  218. package/dist/{services-typed-client-XWYYBWGW.js → services-typed-client-KK6RHRDG.js} +2 -2
  219. package/dist/{services-typed-client-ZX5JUHH3.js → services-typed-client-T7M5VPBP.js} +2 -2
  220. package/dist/{sqlite-vec-ARPNUBWT.js → sqlite-vec-54KB4RD3.js} +2 -2
  221. package/dist/sqlite-vec-54KB4RD3.js.map +1 -0
  222. package/dist/{start-HX3QUSOS.js → start-CGSZPBAG.js} +23 -23
  223. package/dist/start-CGSZPBAG.js.map +1 -0
  224. package/dist/{static-TZBVBDTB.js → static-QI5NQT2X.js} +6 -6
  225. package/dist/storage-manager-C4jsO0Tp.d.ts +89 -0
  226. package/dist/storage-manager-D5KBXXKB.js +0 -0
  227. package/dist/{storage-types-DtIVejC1.d.ts → storage-types-DsDTCPbp.d.ts} +1 -1
  228. package/dist/{theo-cloud-3K4DGB3S.js → theo-cloud-RSQCBNXL.js} +4 -4
  229. package/dist/theo-cloud-RSQCBNXL.js.map +1 -0
  230. package/dist/upgrade-readiness-GUJBCJIS.js +0 -0
  231. package/dist/{vercel-MWW24ABC.js → vercel-TKPZK62A.js} +3 -3
  232. package/dist/vite-plugin/index.d.ts +3 -1
  233. package/dist/vite-plugin/index.js +20 -8
  234. package/dist/{vite-plugin-IK3NOWXS.js → vite-plugin-CR4JDFUQ.js} +9 -9
  235. package/dist/vite-plugin-CR4JDFUQ.js.map +1 -0
  236. package/package.json +59 -10
  237. package/LICENSE +0 -201
  238. package/dist/build-HIGHJQQV.js.map +0 -1
  239. package/dist/chunk-5OFPQK6N.js.map +0 -1
  240. package/dist/chunk-64JI5LTO.js.map +0 -1
  241. package/dist/chunk-7TOMTMHT.js.map +0 -1
  242. package/dist/chunk-BIGBFZSU.js.map +0 -1
  243. package/dist/chunk-C52GSJPF.js.map +0 -1
  244. package/dist/chunk-CZM6WWWS.js +0 -2450
  245. package/dist/chunk-CZM6WWWS.js.map +0 -1
  246. package/dist/chunk-JAAHOGKI.js.map +0 -1
  247. package/dist/chunk-KJVEJILQ.js.map +0 -1
  248. package/dist/chunk-O4BLVPML.js.map +0 -1
  249. package/dist/chunk-O7335ZGH.js.map +0 -1
  250. package/dist/chunk-PB4GR7EP.js.map +0 -1
  251. package/dist/chunk-TPCT3MXV.js.map +0 -1
  252. package/dist/chunk-VRHXOKRP.js.map +0 -1
  253. package/dist/chunk-WZ7CPVQB.js.map +0 -1
  254. package/dist/chunk-X4JAX2U3.js.map +0 -1
  255. package/dist/chunk-XP7YXRHO.js.map +0 -1
  256. package/dist/chunk-YLBSSEHX.js.map +0 -1
  257. package/dist/chunk-ZOXNJV2O.js.map +0 -1
  258. package/dist/dev-emit-RBSFZZNO.js.map +0 -1
  259. package/dist/dispatcher-E6QV32BO.js.map +0 -1
  260. package/dist/dist-5V77Z223.js.map +0 -1
  261. package/dist/generate-DT4IIAHF.js.map +0 -1
  262. package/dist/index-li83Swxa.d.ts +0 -506
  263. package/dist/lib-NL5JXGEB.js.map +0 -1
  264. package/dist/proper-lockfile-4Y3DP3RP.js.map +0 -1
  265. package/dist/registry-4MZ26TZD.js +0 -25
  266. package/dist/schema-CjVly9c_.d.ts +0 -274
  267. package/dist/sqlite-vec-ARPNUBWT.js.map +0 -1
  268. package/dist/start-HX3QUSOS.js.map +0 -1
  269. package/dist/theo-cloud-3K4DGB3S.js.map +0 -1
  270. /package/dist/{actions-virtual-module-HWNTIEPI.js.map → actions-virtual-module-IY46EEEX.js.map} +0 -0
  271. /package/dist/{actions-virtual-module-SEIPACG5.js.map → actions-virtual-module-XNHDNCZ6.js.map} +0 -0
  272. /package/dist/{aws-lambda-XYCGZH3I.js.map → aws-lambda-GKSTX6HD.js.map} +0 -0
  273. /package/dist/{bun-K73TQEWC.js.map → bun-ISHSNFIO.js.map} +0 -0
  274. /package/dist/{check-PZR67OY5.js.map → check-NXYPLM6M.js.map} +0 -0
  275. /package/dist/{dispatcher-AQJGI3HU.js.map → chunk-E3JH6YUM.js.map} +0 -0
  276. /package/dist/{node-3APTLGWB.js.map → chunk-JHEAWR3L.js.map} +0 -0
  277. /package/dist/{chunk-ZJW5FFYJ.js.map → chunk-LC5PYNJP.js.map} +0 -0
  278. /package/dist/{chunk-2VQKDRVF.js.map → chunk-MR7OLIC6.js.map} +0 -0
  279. /package/dist/{scan-C2BOKLSY.js.map → chunk-NPMCKOX4.js.map} +0 -0
  280. /package/dist/{chunk-B6RP57M3.js.map → chunk-OLPB36O2.js.map} +0 -0
  281. /package/dist/{chunk-OXIQI2XZ.js.map → chunk-VBZCVFSA.js.map} +0 -0
  282. /package/dist/{chunk-TRH2L3FI.js.map → chunk-WEGALZEU.js.map} +0 -0
  283. /package/dist/{cloudflare-LCAOTRYZ.js.map → cloudflare-OJGJ7R2D.js.map} +0 -0
  284. /package/dist/{schema-VR6YNVLQ.js.map → cookies-MJKMGJ7N.js.map} +0 -0
  285. /package/dist/{deno-deploy-ZN4RE5HF.js.map → deno-deploy-BHWKFTOW.js.map} +0 -0
  286. /package/dist/{dev-266MVCVA.js.map → dev-MJVSRZGF.js.map} +0 -0
  287. /package/dist/{dev-emit-NO6OZJOQ.js.map → dev-emit-HHP2XJXE.js.map} +0 -0
  288. /package/dist/{vite-plugin-IK3NOWXS.js.map → dispatcher-63LBXYLE.js.map} +0 -0
  289. /package/dist/{info-FJ4NXKTB.js.map → info-47VB62MV.js.map} +0 -0
  290. /package/dist/{netlify-5VQ22Z2P.js.map → netlify-GSNSJGMN.js.map} +0 -0
  291. /package/dist/{openapi-FNVSWZOL.js.map → openapi-NFLSNNVQ.js.map} +0 -0
  292. /package/dist/{registry-4MZ26TZD.js.map → registry-QHEZ3BWB.js.map} +0 -0
  293. /package/dist/{routes-H4SPLFHJ.js.map → routes-3A4XGIEJ.js.map} +0 -0
  294. /package/dist/{services-typed-client-XWYYBWGW.js.map → services-typed-client-KK6RHRDG.js.map} +0 -0
  295. /package/dist/{services-typed-client-ZX5JUHH3.js.map → services-typed-client-T7M5VPBP.js.map} +0 -0
  296. /package/dist/{static-TZBVBDTB.js.map → static-QI5NQT2X.js.map} +0 -0
  297. /package/dist/{vercel-MWW24ABC.js.map → vercel-TKPZK62A.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server/jobs/define-job.ts","../src/server/jobs/job-backend.ts","../src/server/jobs/job-backend-memory.ts","../src/server/jobs/job-backend-postgres.ts","../src/server/jobs/job-runner.ts","../src/server/jobs/job-manifest.ts","../src/server/jobs/job-scan.ts"],"sourcesContent":["import type { JobDefinition, JobOptions } from './job-types.js'\n\nconst NAME_RE = /^[a-z0-9][a-z0-9-]{0,63}$/\n\nfunction validateName(name: string): void {\n if (typeof name !== 'string' || !NAME_RE.test(name)) {\n throw new Error(\n `defineJob: invalid name \"${name}\". ` +\n 'Must be 1-64 chars, lowercase alphanumeric + hyphen, starting with [a-z0-9].',\n )\n }\n}\n\n/**\n * Declare a background job. Pure identity helper — no registration side\n * effect; the build-time scanner (T2.3) discovers definitions by walking\n * `server/jobs/` and emits `.theo/jobs.json`.\n *\n * Per ADR-0003, handler returns `void` (or `Promise<void>`); no workflow\n * API. To run another job after this one, call `ctx.queue.enqueue` from\n * the handler.\n *\n * @example\n * ```ts\n * // server/jobs/process-document.ts\n * import { defineJob } from 'theokit/server'\n * import { z } from 'zod'\n *\n * export default defineJob('process-document', {\n * input: z.object({ documentId: z.string() }),\n * maxAttempts: 3,\n * async handler({ input, traceId }) {\n * // process input.documentId\n * },\n * })\n * ```\n */\nexport function defineJob<TInput = unknown>(\n name: string,\n options: JobOptions<TInput>,\n): JobDefinition<TInput> {\n validateName(name)\n return {\n name,\n maxAttempts: options.maxAttempts ?? 1,\n hasInputSchema: options.input !== undefined,\n handler: options.handler,\n inputSchema: options.input,\n }\n}\n","/**\n * Neutral `JobBackend` interface per ADR-0002.\n *\n * Implementations ship in core:\n * - `InMemoryJobBackend` (T2.2) — dev + tests; no external deps\n * - `PostgresJobBackend` (T3.1) — production; requires `pg` peer dep\n *\n * Community packages (`@theokit/jobs-redis`, `@theokit/jobs-sqs`, etc.)\n * implement this same interface to plug in alternate substrates without\n * modifying TheoKit core.\n */\n\nexport interface JobEnqueueInput {\n /** The job name (matches a `defineJob` declaration). */\n name: string\n /** Validated input (already passed through Zod or equivalent at the queue-client layer). */\n input: unknown\n /** Optional idempotency key for at-most-once dispatch within TTL. */\n idempotencyKey?: string\n /** Optional delay before the job becomes available for dispatch. */\n delaySeconds?: number\n /** W3C Trace Context propagation per ADR/R0.5.9. */\n traceparent?: string\n /** Maximum dispatch attempts (read from JobDefinition by the queue client). */\n maxAttempts?: number\n}\n\nexport interface JobLease {\n readonly jobId: string\n readonly name: string\n readonly input: unknown\n readonly attempts: number\n readonly maxAttempts: number\n readonly traceparent?: string\n readonly lockExpiresAt: Date\n}\n\nexport interface JobBackend {\n /** Human-readable name for logging (e.g., \"memory\", \"postgres\"). */\n readonly name: string\n\n /** Persist a job for later dispatch. Returns the generated jobId. */\n enqueue(input: JobEnqueueInput): Promise<{ jobId: string }>\n\n /** Worker loop polls for the next available leases. */\n dequeue(opts: { batchSize?: number; lockSeconds?: number }): Promise<JobLease[]>\n\n /** Mark a job complete (success). */\n ack(jobId: string): Promise<void>\n\n /** Mark a job failed; backend decides retry vs DLQ via attempts. */\n nack(jobId: string, opts: { error: string; nonRetryable?: boolean }): Promise<void>\n\n /** Optional: return existing jobId if `key` was enqueued within `ttlSeconds`. */\n idempotency?(key: string, ttlSeconds: number): Promise<{ jobId: string } | null>\n}\n\n/**\n * Thrown from a job handler to opt out of retry policy. The backend MUST\n * nack with `nonRetryable: true` and permanently remove the job.\n */\nexport class NonRetryableError extends Error {\n readonly code = 'NON_RETRYABLE'\n constructor(message: string) {\n super(message)\n this.name = 'NonRetryableError'\n }\n}\n","// T5a.1a — Web Standards migration (leaf-first slice). Web Crypto's\n// `crypto.randomUUID()` is available on globalThis in every supported\n// runtime per ADR-0028 (Node 22+, CF Workers, Bun, Deno, browsers).\n// No node:crypto import needed.\n\nimport type { JobBackend, JobEnqueueInput, JobLease } from './job-backend.js'\n\n/**\n * In-memory job backend for dev + tests + single-instance prototypes.\n *\n * Zero external dependencies. Storage is two Maps:\n * - `pending: Map<jobId, PendingEntry>` — all enqueued jobs (locked or not)\n * - `idempotencyMap: Map<key, { jobId; expiresAt }>` — dedup window\n *\n * Per ADR-0002: this is one of two first-party backends shipped in core.\n * Production deploys plug in PostgresJobBackend (T3.1).\n *\n * EC-104 (jobs-crons-webhooks-cost-tracking-plan): registers a\n * `process.on('beforeExit')` handler that clears pending dispatch timers\n * and logs a warning with the dropped count. Failure mode is visible,\n * not silent. `destroy()` removes the listener for test isolation.\n */\n\nexport interface InMemoryJobBackendOptions {\n /** Maximum pending entries before oldest is dropped + warning logged. */\n maxPending?: number\n}\n\ninterface PendingEntry {\n jobId: string\n name: string\n input: unknown\n attempts: number\n maxAttempts: number\n traceparent?: string\n availableAt: number\n lockExpiresAt: number | null\n dispatchTimer: NodeJS.Timeout | null\n}\n\ninterface IdempotencyEntry {\n jobId: string\n expiresAt: number\n}\n\nconst DEFAULT_MAX_PENDING = 10_000\n\nexport class InMemoryJobBackend implements JobBackend {\n readonly name = 'memory'\n readonly #pending = new Map<string, PendingEntry>()\n readonly #idempotency = new Map<string, IdempotencyEntry>()\n readonly #maxPending: number\n #beforeExitHandler: (() => void) | null = null\n #destroyed = false\n\n constructor(opts: InMemoryJobBackendOptions = {}) {\n this.#maxPending = opts.maxPending ?? DEFAULT_MAX_PENDING\n // EC-104 — register graceful shutdown handler. We keep a reference\n // so `destroy()` can remove it (test isolation; avoid leaking\n // listeners across vitest test files).\n this.#beforeExitHandler = (): void => {\n this.#cleanupOnShutdown()\n }\n process.on('beforeExit', this.#beforeExitHandler)\n }\n\n async enqueue(input: JobEnqueueInput): Promise<{ jobId: string }> {\n // Overflow eviction (visible failure, not silent leak)\n if (this.#pending.size >= this.#maxPending) {\n const oldestKey = this.#pending.keys().next().value\n if (oldestKey) {\n const oldest = this.#pending.get(oldestKey)\n if (oldest?.dispatchTimer) clearTimeout(oldest.dispatchTimer)\n this.#pending.delete(oldestKey)\n }\n\n console.warn(\n `[theokit:jobs:memory] pending overflow at ${this.#maxPending} — dropped oldest. ` +\n 'Switch to PostgresJobBackend for production.',\n )\n }\n\n // Idempotency dedup\n if (input.idempotencyKey) {\n const existing = this.#idempotency.get(input.idempotencyKey)\n const now = Date.now()\n if (existing && existing.expiresAt > now) {\n return { jobId: existing.jobId }\n }\n }\n\n const jobId = globalThis.crypto.randomUUID()\n const now = Date.now()\n const availableAt = now + (input.delaySeconds ?? 0) * 1000\n const entry: PendingEntry = {\n jobId,\n name: input.name,\n input: input.input,\n attempts: 0,\n maxAttempts: input.maxAttempts ?? 1,\n traceparent: input.traceparent,\n availableAt,\n lockExpiresAt: null,\n dispatchTimer: null,\n }\n this.#pending.set(jobId, entry)\n\n if (input.idempotencyKey) {\n // Default TTL window matches typical idempotency expectations;\n // explicit idempotency(key, ttl) check overrides per caller.\n this.#idempotency.set(input.idempotencyKey, {\n jobId,\n expiresAt: now + 60_000,\n })\n }\n\n return Promise.resolve({ jobId })\n }\n\n async dequeue(opts: { batchSize?: number; lockSeconds?: number }): Promise<JobLease[]> {\n const batchSize = opts.batchSize ?? 1\n const lockSeconds = opts.lockSeconds ?? 30\n const now = Date.now()\n\n const leases: JobLease[] = []\n for (const entry of this.#pending.values()) {\n if (leases.length >= batchSize) break\n // Skip if locked + lock still valid\n if (entry.lockExpiresAt !== null && entry.lockExpiresAt > now) continue\n // Skip if not yet available (delay)\n if (entry.availableAt > now) continue\n\n entry.lockExpiresAt = now + lockSeconds * 1000\n entry.attempts += 1\n leases.push({\n jobId: entry.jobId,\n name: entry.name,\n input: entry.input,\n attempts: entry.attempts,\n maxAttempts: entry.maxAttempts,\n traceparent: entry.traceparent,\n lockExpiresAt: new Date(entry.lockExpiresAt),\n })\n }\n return Promise.resolve(leases)\n }\n\n async ack(jobId: string): Promise<void> {\n const entry = this.#pending.get(jobId)\n if (entry?.dispatchTimer) clearTimeout(entry.dispatchTimer)\n this.#pending.delete(jobId)\n return Promise.resolve()\n }\n\n async nack(jobId: string, opts: { error: string; nonRetryable?: boolean }): Promise<void> {\n const entry = this.#pending.get(jobId)\n if (!entry) return Promise.resolve()\n if (opts.nonRetryable || entry.attempts >= entry.maxAttempts) {\n if (entry.dispatchTimer) clearTimeout(entry.dispatchTimer)\n this.#pending.delete(jobId)\n } else {\n // Release lock — becomes available again\n entry.lockExpiresAt = null\n }\n return Promise.resolve()\n }\n\n idempotency(key: string, ttlSeconds: number): Promise<{ jobId: string } | null> {\n const now = Date.now()\n const existing = this.#idempotency.get(key)\n if (!existing || existing.expiresAt <= now) {\n return Promise.resolve(null)\n }\n // Renew if caller's ttl differs\n existing.expiresAt = Math.max(existing.expiresAt, now + ttlSeconds * 1000)\n return Promise.resolve({ jobId: existing.jobId })\n }\n\n /**\n * Remove the beforeExit listener and clear all pending timers.\n * Idempotent — safe to call multiple times. Use in test teardown to\n * avoid leaking listeners across vitest test files.\n */\n destroy(): void {\n if (this.#destroyed) return\n this.#destroyed = true\n if (this.#beforeExitHandler) {\n process.off('beforeExit', this.#beforeExitHandler)\n this.#beforeExitHandler = null\n }\n for (const entry of this.#pending.values()) {\n if (entry.dispatchTimer) clearTimeout(entry.dispatchTimer)\n }\n }\n\n /** EC-104 test hook — invokes the shutdown handler synchronously. */\n triggerBeforeExitForTest(): void {\n this.#cleanupOnShutdown()\n }\n\n #cleanupOnShutdown(): void {\n const droppedCount = this.#pending.size\n for (const entry of this.#pending.values()) {\n if (entry.dispatchTimer) clearTimeout(entry.dispatchTimer)\n }\n if (droppedCount > 0) {\n console.warn(\n `[theokit:jobs:memory] ${droppedCount} jobs dropped on shutdown — ` +\n 'use PostgresJobBackend for durability across restarts.',\n )\n }\n }\n}\n","import type { PostgresFactory, StorageManager } from '../storage/storage-manager.js'\nimport type { PoolLike } from '../storage/storage-types.js'\n\nimport type { JobBackend, JobEnqueueInput, JobLease } from './job-backend.js'\n\n/**\n * Postgres-backed `JobBackend` per ADR-0002 (T3.1).\n *\n * Uses the Graphile Worker pattern:\n * - Single `theokit_jobs` table.\n * - Dequeue via `SELECT ... FOR UPDATE SKIP LOCKED` (concurrent workers\n * never race for the same job).\n * - Idempotency via UNIQUE INDEX on (name, idempotency_key).\n *\n * `pg` is an OPTIONAL peer dependency — the caller provides their own\n * `pg.Pool` (or compatible). This avoids forcing every TheoKit user to\n * install Postgres tooling for in-memory dev work.\n *\n * Pool size recommendation (EC-108): set `connectionTimeoutMillis` to\n * a finite value (e.g., 5000) so a saturated pool errors instead of\n * deadlocking. Suggested pool size: `min(workerConcurrency * 1.5, 20)`.\n *\n * @see https://github.com/graphile/worker (Postgres SKIP LOCKED reference)\n * @see docs/adr/0002-job-backend-interface-neutral-contract.md\n */\n\n/**\n * `PoolLike` moved to `../storage/storage-types.ts` (T0.2 / ADR-0007 D7) to\n * deduplicate the shape across multiple adapters. Re-exported here so existing\n * `import { PoolLike } from 'theokit/server'` (which routes through the jobs\n * barrel today) continues to compile unchanged.\n */\nexport type { PoolLike } from '../storage/storage-types.js'\n\nexport interface PostgresJobBackendOptions {\n pool: PoolLike\n /** Table name override (default `theokit_jobs`). */\n tableName?: string\n}\n\nconst DEFAULT_TABLE = 'theokit_jobs'\n\nexport class PostgresJobBackend implements JobBackend {\n readonly name = 'postgres'\n readonly #pool: PoolLike\n readonly #table: string\n\n constructor(opts: PostgresJobBackendOptions) {\n // Runtime guard for users who pass `pool: undefined` despite the type;\n // helps surface \"you forgot to install pg\" early with an actionable\n // error rather than a cryptic TypeError later.\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!opts.pool) {\n throw new Error(\n 'PostgresJobBackend requires a `pool` option (pg.Pool or compatible). ' +\n 'Install pg via `pnpm add pg` and pass a configured Pool instance.',\n )\n }\n this.#pool = opts.pool\n this.#table = opts.tableName ?? DEFAULT_TABLE\n }\n\n /**\n * T2.1 — Construct a `PostgresJobBackend` using a pool managed by the\n * shared `StorageManager`. The manager caches the pool per `dbName`, so\n * repeated calls (in the same process) re-use the same connection pool.\n *\n * Equivalent to:\n * ```ts\n * const pool = manager.usePostgres(dbName, factory)\n * new PostgresJobBackend({ pool, ...options })\n * ```\n *\n * Errors thrown by the manager (unknown dbName, dangling server reference,\n * manager already disposed) propagate to the caller with actionable text.\n *\n * @see ADR-0007\n */\n static fromStorageManager(\n manager: StorageManager,\n dbName: string,\n factory: PostgresFactory,\n options?: Omit<PostgresJobBackendOptions, 'pool'>,\n ): PostgresJobBackend {\n const pool = manager.usePostgres(dbName, factory)\n return new PostgresJobBackend({ pool, ...options })\n }\n\n /**\n * Create or upgrade the schema. Idempotent (uses IF NOT EXISTS).\n * Call once at process start; safe to re-run on every deploy.\n */\n async migrate(): Promise<void> {\n const t = this.#table\n await this.#pool.query(`\n CREATE TABLE IF NOT EXISTS ${t} (\n id TEXT PRIMARY KEY,\n name TEXT NOT NULL,\n input JSONB NOT NULL,\n attempts INT NOT NULL DEFAULT 0,\n max_attempts INT NOT NULL DEFAULT 1,\n available_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),\n locked_until TIMESTAMPTZ,\n traceparent TEXT,\n idempotency_key TEXT,\n created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()\n )\n `)\n await this.#pool.query(`\n CREATE UNIQUE INDEX IF NOT EXISTS ${t}_idempotency_key_idx\n ON ${t} (name, idempotency_key)\n WHERE idempotency_key IS NOT NULL\n `)\n await this.#pool.query(`\n CREATE INDEX IF NOT EXISTS ${t}_available_at_idx\n ON ${t} (available_at)\n WHERE locked_until IS NULL\n `)\n }\n\n async enqueue(input: JobEnqueueInput): Promise<{ jobId: string }> {\n const id = randomId()\n const delaySeconds = input.delaySeconds ?? 0\n const t = this.#table\n\n // Idempotency: explicit SELECT-then-INSERT. The UNIQUE INDEX is the\n // safety net under race conditions (we surface the conflict by\n // re-selecting on insert-error). This 2-step path is pg-mem compatible\n // AND works on real Postgres.\n if (input.idempotencyKey) {\n const existing = await this.#pool.query<{ id: string }>(\n `SELECT id FROM ${t} WHERE name = $1 AND idempotency_key = $2 LIMIT 1`,\n [input.name, input.idempotencyKey],\n )\n if (existing.rows.length > 0) {\n return { jobId: existing.rows[0].id }\n }\n }\n\n await this.#pool.query(\n `INSERT INTO ${t} (id, name, input, max_attempts, available_at, traceparent, idempotency_key)\n VALUES ($1, $2, $3::jsonb, $4, NOW() + ($5 || ' seconds')::interval, $6, $7)`,\n [\n id,\n input.name,\n JSON.stringify(input.input),\n input.maxAttempts ?? 1,\n delaySeconds.toString(),\n input.traceparent ?? null,\n input.idempotencyKey ?? null,\n ],\n )\n return { jobId: id }\n }\n\n async dequeue(opts: { batchSize?: number; lockSeconds?: number }): Promise<JobLease[]> {\n const t = this.#table\n const batchSize = opts.batchSize ?? 1\n const lockSeconds = opts.lockSeconds ?? 30\n\n // Two-step pattern (pg-mem compatible AND real-Postgres compatible):\n // 1. SELECT FOR UPDATE SKIP LOCKED to claim candidate IDs.\n // 2. UPDATE in-place to mark lock_until + bump attempts.\n // On real Postgres, the FOR UPDATE SKIP LOCKED prevents concurrent\n // workers from seeing the same rows. On pg-mem the lock is silently\n // ignored, but pg-mem serializes all queries through one in-memory\n // db so the test still verifies single-claim semantics.\n const candidates = await this.#pool.query<{ id: string }>(\n `SELECT id FROM ${t}\n WHERE (locked_until IS NULL OR locked_until < NOW())\n AND available_at <= NOW()\n ORDER BY available_at ASC\n LIMIT $1\n FOR UPDATE SKIP LOCKED`,\n [batchSize],\n )\n\n if (candidates.rows.length === 0) return []\n\n const ids = candidates.rows.map((r) => r.id)\n // Build a parameterized IN clause: ($2, $3, ...). pg-mem's UPDATE\n // does not support `ANY($1::text[])`, so we materialize the list.\n // For batch sizes we expect (typically ≤100), this is fine.\n const placeholders = ids.map((_, i) => `$${i + 2}`).join(', ')\n\n const r = await this.#pool.query<{\n id: string\n name: string\n input: unknown\n attempts: number\n max_attempts: number\n traceparent: string | null\n locked_until: Date | string\n }>(\n `UPDATE ${t}\n SET locked_until = NOW() + ($1 || ' seconds')::interval,\n attempts = attempts + 1\n WHERE id IN (${placeholders})\n RETURNING id, name, input, attempts, max_attempts, traceparent, locked_until`,\n [lockSeconds.toString(), ...ids],\n )\n\n return r.rows.map((row) => ({\n jobId: row.id,\n name: row.name,\n input: row.input,\n attempts: row.attempts,\n maxAttempts: row.max_attempts,\n traceparent: row.traceparent ?? undefined,\n lockExpiresAt:\n row.locked_until instanceof Date ? row.locked_until : new Date(row.locked_until),\n }))\n }\n\n async ack(jobId: string): Promise<void> {\n await this.#pool.query(`DELETE FROM ${this.#table} WHERE id = $1`, [jobId])\n }\n\n async nack(jobId: string, opts: { error: string; nonRetryable?: boolean }): Promise<void> {\n const t = this.#table\n if (opts.nonRetryable) {\n await this.#pool.query(`DELETE FROM ${t} WHERE id = $1`, [jobId])\n return\n }\n // Check attempts >= maxAttempts → permanent removal.\n const r = await this.#pool.query<{\n attempts: number\n max_attempts: number\n }>(`SELECT attempts, max_attempts FROM ${t} WHERE id = $1`, [jobId])\n if (r.rows.length === 0) return\n const { attempts, max_attempts } = r.rows[0]\n if (attempts >= max_attempts) {\n await this.#pool.query(`DELETE FROM ${t} WHERE id = $1`, [jobId])\n } else {\n // Release lock — next dequeue picks it up again.\n await this.#pool.query(`UPDATE ${t} SET locked_until = NULL WHERE id = $1`, [jobId])\n }\n }\n\n async idempotency(key: string, _ttlSeconds: number): Promise<{ jobId: string } | null> {\n // The UNIQUE INDEX is the source of truth. Look for any non-deleted\n // row with this idempotency_key.\n const r = await this.#pool.query<{ id: string }>(\n `SELECT id FROM ${this.#table} WHERE idempotency_key = $1 LIMIT 1`,\n [key],\n )\n return r.rows.length > 0 ? { jobId: r.rows[0].id } : null\n }\n}\n\nfunction randomId(): string {\n // Use crypto.randomUUID if available; this is process-local, not DB-generated.\n // The DB UNIQUE constraint is on (name, idempotency_key), not on id, so\n // collisions across processes are functionally impossible.\n return globalThis.crypto.randomUUID()\n}\n","import {\n extractTraceContext,\n generateNewTraceContext,\n} from '../observability/trace-context-propagation.js'\n\nimport { type JobBackend, type JobLease, NonRetryableError } from './job-backend.js'\nimport type { JobContext, JobDefinition } from './job-types.js'\n\n/**\n * Job runner — pulls leases from a backend and invokes the matching\n * handler. Each invocation wires up `JobContext` with:\n * - `traceId` extracted from the lease's `traceparent` header (W3C\n * Trace Context per R0.5.9), OR a fresh generated trace_id when\n * the upstream had no traceparent OR it was malformed.\n * - `attempt` from the lease.\n * - `signal` that aborts when the lease times out.\n *\n * `tick()` runs one dequeue+dispatch cycle and returns when all leases\n * have been ack'd or nack'd. Production deploys call `tick()` in a loop\n * with backoff (the loop is outside this module's scope).\n *\n * EC-6 (trace continuity edge): when a lease has no traceparent OR a\n * malformed one, the handler still gets a valid traceId (generated) —\n * never null/undefined. The job MAY itself enqueue child jobs that\n * continue the new trace_id.\n */\n\nexport interface JobRunner {\n /** Run one dequeue+dispatch cycle. */\n tick(opts?: { batchSize?: number; lockSeconds?: number }): Promise<number>\n}\n\nexport function createJobRunner(\n backend: JobBackend,\n definitions: readonly JobDefinition[],\n): JobRunner {\n const byName = new Map<string, JobDefinition>()\n for (const def of definitions) {\n byName.set(def.name, def)\n }\n\n const runOne = async (lease: JobLease): Promise<void> => {\n const def = byName.get(lease.name)\n if (!def) {\n // Job name not registered in this runner's definition set. Nack\n // permanently — the lease can't be processed by this runner.\n await backend.nack(lease.jobId, {\n error: `No job definition for \"${lease.name}\"`,\n nonRetryable: true,\n })\n return\n }\n\n // Resolve trace ID from lease's traceparent, or fall back to fresh.\n let traceId: string\n if (lease.traceparent) {\n const headers = new Headers({ traceparent: lease.traceparent })\n const ctx = extractTraceContext(headers)\n traceId = ctx?.trace_id ?? generateNewTraceContext().trace_id\n } else {\n traceId = generateNewTraceContext().trace_id\n }\n\n // Optional Zod validation on input.\n let parsedInput: unknown = lease.input\n if (def.inputSchema) {\n try {\n parsedInput = def.inputSchema.parse(lease.input)\n } catch (err) {\n await backend.nack(lease.jobId, {\n error: `Input validation failed: ${err instanceof Error ? err.message : String(err)}`,\n nonRetryable: true,\n })\n return\n }\n }\n\n const abortController = new AbortController()\n // Auto-abort when lease expires\n const lockMs = lease.lockExpiresAt.getTime() - Date.now()\n const lockTimer = setTimeout(\n () => {\n abortController.abort()\n },\n Math.max(0, lockMs),\n )\n\n const jobCtx: JobContext = {\n traceId,\n input: parsedInput,\n signal: abortController.signal,\n attempt: lease.attempts,\n }\n\n try {\n await def.handler(jobCtx)\n await backend.ack(lease.jobId)\n } catch (err) {\n const isNonRetryable = err instanceof NonRetryableError\n await backend.nack(lease.jobId, {\n error: err instanceof Error ? err.message : String(err),\n nonRetryable: isNonRetryable,\n })\n } finally {\n clearTimeout(lockTimer)\n }\n }\n\n return {\n async tick(opts) {\n const leases = await backend.dequeue({\n batchSize: opts?.batchSize ?? 10,\n lockSeconds: opts?.lockSeconds ?? 30,\n })\n // Process leases sequentially — caller controls concurrency via\n // batchSize and tick frequency.\n for (const lease of leases) {\n await runOne(lease)\n }\n return leases.length\n },\n }\n}\n","import { writeAtomic } from '../_internal/atomic-write.js'\n\nimport type { JobNode } from './job-scan.js'\n\nexport const JOB_MANIFEST_SCHEMA_VERSION = 1 as const\n\nexport interface JobManifestEntry {\n readonly name: string\n readonly filePath: string\n readonly maxAttempts: number\n readonly hasInputSchema: boolean\n}\n\nexport interface JobManifest {\n readonly schemaVersion: typeof JOB_MANIFEST_SCHEMA_VERSION\n readonly generatedAt: string\n readonly jobs: readonly JobManifestEntry[]\n}\n\nexport function buildJobManifest(nodes: readonly JobNode[], projectRoot?: string): JobManifest {\n const jobs: JobManifestEntry[] = nodes.map((n) => ({\n name: n.name,\n filePath: projectRoot ? relativize(n.filePath, projectRoot) : n.filePath,\n maxAttempts: n.maxAttempts,\n hasInputSchema: n.hasInputSchema,\n }))\n return {\n schemaVersion: JOB_MANIFEST_SCHEMA_VERSION,\n generatedAt: new Date().toISOString(),\n jobs,\n }\n}\n\nexport function writeJobManifest(\n path: string,\n input: readonly JobNode[] | JobManifest,\n projectRoot?: string,\n): void {\n const manifest: JobManifest = isManifest(input) ? input : buildJobManifest(input, projectRoot)\n writeAtomic(path, JSON.stringify(manifest, null, 2))\n}\n\nfunction isManifest(value: unknown): value is JobManifest {\n return typeof value === 'object' && value !== null && 'schemaVersion' in value && 'jobs' in value\n}\n\nfunction relativize(absPath: string, root: string): string {\n if (absPath.startsWith(root)) {\n const trimmed = absPath.slice(root.length)\n return trimmed.startsWith('/') ? trimmed.slice(1) : trimmed\n }\n return absPath\n}\n","/* eslint-disable security/detect-non-literal-fs-filename --\n * Build-time scanner: caller-controlled directory paths only.\n */\nimport { existsSync } from 'node:fs'\nimport { basename } from 'node:path'\n\nimport { importUserModule } from '../../config/import-user-module.js'\nimport { walkSourceFiles } from '../_internal/scan-walker.js'\n\nimport type { JobDefinition } from './job-types.js'\n\nexport interface JobNode {\n readonly name: string\n readonly filePath: string\n readonly maxAttempts: number\n readonly hasInputSchema: boolean\n}\n\nexport class DuplicateJobNameError extends Error {\n readonly code = 'DUPLICATE_JOB_NAME'\n constructor(\n public readonly jobName: string,\n public readonly filePaths: readonly string[],\n ) {\n super(\n `Duplicate job name \"${jobName}\" defined in: ${filePaths.join(', ')}. ` +\n 'Job names must be unique across server/jobs/.',\n )\n this.name = 'DuplicateJobNameError'\n }\n}\n\nconst JOB_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.mjs'])\n\ninterface JobModule {\n default?: unknown\n}\n\nfunction isJobDefinition(value: unknown): value is JobDefinition {\n if (typeof value !== 'object' || value === null) return false\n const def = value as Record<string, unknown>\n return (\n typeof def.name === 'string' &&\n typeof def.handler === 'function' &&\n typeof def.maxAttempts === 'number' &&\n typeof def.hasInputSchema === 'boolean'\n )\n}\n\nexport async function scanJobs(jobsDir: string): Promise<JobNode[]> {\n if (!existsSync(jobsDir)) return []\n\n const filePaths: string[] = []\n walkSourceFiles(jobsDir, { extensions: JOB_EXTENSIONS }, (p) => {\n const base = basename(p)\n if (base.startsWith('_') || base.startsWith('.')) return\n filePaths.push(p)\n })\n\n const nodes: JobNode[] = []\n for (const filePath of filePaths) {\n let mod: JobModule\n try {\n mod = await importUserModule(filePath)\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err)\n throw new Error(`Failed to import job file \"${filePath}\": ${reason}`)\n }\n const exported = mod.default\n if (!isJobDefinition(exported)) {\n throw new Error(\n `Job file \"${filePath}\" is missing a valid default export. ` +\n 'Expected `export default defineJob(name, { handler })`.',\n )\n }\n nodes.push({\n name: exported.name,\n filePath,\n maxAttempts: exported.maxAttempts,\n hasInputSchema: exported.hasInputSchema,\n })\n }\n\n const byName = new Map<string, string[]>()\n for (const node of nodes) {\n const bucket = byName.get(node.name) ?? []\n bucket.push(node.filePath)\n byName.set(node.name, bucket)\n }\n for (const [name, paths] of byName) {\n if (paths.length > 1) {\n throw new DuplicateJobNameError(name, paths)\n }\n }\n\n return nodes.sort((a, b) => a.name.localeCompare(b.name))\n}\n"],"mappings":"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","names":["now","r"]}
File without changes
@@ -14,15 +14,17 @@ var initialState = {
14
14
  actionCalls: [],
15
15
  routeManifest: null,
16
16
  activeRoutePath: null,
17
- activeChain: []
17
+ activeChain: [],
18
+ agentStreamEvents: []
18
19
  };
19
20
  var CHANNEL_REQUEST = "theo:devtools:request";
20
21
  var CHANNEL_ERROR = "theo:devtools:error";
21
22
  var CHANNEL_CSRF_WARN = "theo:devtools:csrf.warn";
22
23
  var CHANNEL_MANIFEST = "theo:devtools:manifest";
23
24
  var CHANNEL_ROUTE_MATCHED = "theo:devtools:route-matched";
25
+ var CHANNEL_AGENT_STREAM = "theo:devtools:agent.stream";
24
26
 
25
- // src/devtools/dispatcher.ts
27
+ // src/devtools/bridge/dispatcher.ts
26
28
  var _dispatch = null;
27
29
  var _queue = [];
28
30
  function queuable(fn) {
@@ -74,6 +76,9 @@ var dispatcher = {
74
76
  onActionCall: queuable((d, record) => {
75
77
  d({ type: "ACTION_CALL_ADD", record });
76
78
  }),
79
+ onAgentStreamEvent: queuable((d, event) => {
80
+ d({ type: "AGENT_STREAM_EVENT", event });
81
+ }),
77
82
  /**
78
83
  * Wire React's dispatch function in. Idempotent (EC-24): only the
79
84
  * NULL → non-null transition flushes the queue; subsequent non-null
@@ -104,6 +109,7 @@ export {
104
109
  CHANNEL_CSRF_WARN,
105
110
  CHANNEL_MANIFEST,
106
111
  CHANNEL_ROUTE_MATCHED,
112
+ CHANNEL_AGENT_STREAM,
107
113
  dispatcher
108
114
  };
109
- //# sourceMappingURL=chunk-KJVEJILQ.js.map
115
+ //# sourceMappingURL=chunk-5PU65T5W.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/devtools/shared.ts","../src/devtools/bridge/dispatcher.ts"],"sourcesContent":["/**\n * Devtools — shared types.\n *\n * NEVER use dangerouslySetInnerHTML in any devtools component — see plan EC-20.\n */\n\nexport type DevtoolsPosition = 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right'\nexport type DevtoolsTab =\n | 'requests'\n | 'routes'\n | 'agents'\n | 'actions'\n | 'errors'\n | 'csrf-readiness'\n | 'settings'\nexport type DevtoolsTheme = 'light' | 'dark' | 'system'\n\nexport interface RequestRecord {\n id: string\n traceId: string\n method: string\n path: string\n status: number\n durationMs: number\n startedAt: number\n csrfWarn?: { code: string; docsUrl: string }\n headers?: Record<string, string>\n bodyPreview?: string\n bodyLength?: number\n bodyTruncated?: boolean\n}\n\nexport interface ErrorRecord {\n id: string\n type: 'console' | 'unhandled' | 'csrf.warn'\n message: string\n stack?: string\n code?: string\n docsUrl?: string\n timestamp: number\n}\n\nexport interface CsrfWarnPayload {\n event: 'csrf.warn'\n code: string\n docsUrl: string\n method: string\n path: string\n reason: string\n}\n\nexport interface RouteInfo {\n path: string\n absoluteFilePath: string\n layoutChain: string[]\n hasLoading: boolean\n hasError: boolean\n hasNotFound: boolean\n}\n\nexport interface RouteManifest {\n routes: RouteInfo[]\n}\n\n/**\n * Per-agent-run telemetry surfaced to the Agents devtools tab.\n *\n * Emitted by `trackAgentRun` (server-side) via the dispatcher in dev mode;\n * prod tree-shakes the entire wire (v1.1 EC-4 `__IS_DEV` IIFE guard).\n * Type lives here (devtools/shared) since both producer (server/cost) and\n * consumer (AgentsTab) need the shape; following architecture v3 ADR-0001\n * rule \"shared types in core/contracts\" is the canonical home — for this\n * one we keep it in devtools/shared to minimize churn in core/contracts/.\n */\nexport interface AgentRunRecord {\n id: string\n timestamp: number\n userId: string\n model: string\n tokensInput: number\n tokensOutput: number\n costUsd: number\n status: 'finished' | 'error' | 'aborted'\n}\n\n/**\n * T5.1 — Per-action-call telemetry surfaced to the Actions devtools tab.\n *\n * Emitted by `action-execute.ts` (server-side) via the dispatcher in dev\n * mode; prod tree-shakes the wire (mirrors AgentRunRecord pattern).\n * Field-level error pins consume `error.fields` directly when status='error'\n * (per plan ADR D6).\n */\nexport interface ActionCallRecord {\n id: string\n timestamp: number\n name: string\n input: unknown\n output?: unknown\n error?: {\n code: string\n message: string\n fields?: Record<string, string[]>\n issues?: unknown[]\n }\n durationMs: number\n status: 'success' | 'error'\n}\n\nexport interface DevtoolsState {\n open: boolean\n visible: boolean\n position: DevtoolsPosition\n theme: DevtoolsTheme\n activeTab: DevtoolsTab\n requests: RequestRecord[]\n errors: ErrorRecord[]\n agentRuns: AgentRunRecord[]\n actionCalls: ActionCallRecord[]\n routeManifest: RouteManifest | null\n activeRoutePath: string | null\n activeChain: string[]\n agentStreamEvents: AgentStreamRecord[]\n}\n\nexport type DevtoolsAction =\n | { type: 'TOGGLE_PANEL' }\n | { type: 'TOGGLE_VISIBLE' }\n | { type: 'SET_TAB'; tab: DevtoolsTab }\n | { type: 'SET_POSITION'; position: DevtoolsPosition }\n | { type: 'SET_THEME'; theme: DevtoolsTheme }\n | { type: 'REQUEST_ADD'; request: RequestRecord }\n | { type: 'ERROR_ADD'; error: ErrorRecord }\n | { type: 'CSRF_WARN'; payload: CsrfWarnPayload }\n | { type: 'MANIFEST_UPDATED'; manifest: RouteManifest }\n | { type: 'ROUTE_MATCHED'; path: string; chain: string[] }\n | { type: 'AGENT_RUN_ADD'; run: AgentRunRecord }\n | { type: 'ACTION_CALL_ADD'; record: ActionCallRecord }\n | { type: 'RESET_REQUESTS' }\n | { type: 'RESET_ERRORS' }\n | { type: 'RESET_AGENT_RUNS' }\n | { type: 'RESET_ACTION_CALLS' }\n | { type: 'AGENT_STREAM_EVENT'; event: AgentStreamRecord }\n | { type: 'RESET_AGENT_STREAM' }\n\nexport const RING_BUFFER_CAP = 50\nexport const MAX_QUEUE_SIZE = 100\nexport const STORAGE_VERSION = 2\n\nexport const initialState: DevtoolsState = {\n open: false,\n visible: true,\n position: 'bottom-right',\n theme: 'dark',\n activeTab: 'requests',\n requests: [],\n errors: [],\n agentRuns: [],\n actionCalls: [],\n routeManifest: null,\n activeRoutePath: null,\n activeChain: [],\n agentStreamEvents: [],\n}\n\nexport const CHANNEL_REQUEST = 'theo:devtools:request' as const\nexport const CHANNEL_ERROR = 'theo:devtools:error' as const\nexport const CHANNEL_CSRF_WARN = 'theo:devtools:csrf.warn' as const\nexport const CHANNEL_MANIFEST = 'theo:devtools:manifest' as const\nexport const CHANNEL_ROUTE_MATCHED = 'theo:devtools:route-matched' as const\nexport const CHANNEL_AGENT_RUN = 'theo:devtools:agent.run' as const\nexport const CHANNEL_ACTION_CALL = 'theo:devtools:action.call' as const\nexport const CHANNEL_AGENT_STREAM = 'theo:devtools:agent.stream' as const\n\nexport interface AgentStreamRecord {\n runId: string\n agentName: string\n type: string\n content?: string\n toolName?: string\n timestamp: number\n}\n","/**\n * T2.1 — Devtools dispatcher with pre-mount event queue.\n *\n * Pattern: events emitted from anywhere (server WS, browser console.error,\n * dispatcher.onCsrfWarn) can fire BEFORE the React tree mounts. Each call\n * either dispatches immediately (when `setDispatch` registered a dispatch\n * fn) or queues until React is ready, then flushes on first mount.\n *\n * EC-23: queue capped at MAX_QUEUE_SIZE (FIFO eviction).\n * EC-24: setDispatch is idempotent — flush only on NULL → non-null\n * transition (StrictMode re-mount safe).\n *\n * NEVER use dangerouslySetInnerHTML in any devtools component — see plan EC-20.\n */\nimport {\n type ActionCallRecord,\n type AgentRunRecord,\n type AgentStreamRecord,\n type CsrfWarnPayload,\n type DevtoolsAction,\n type ErrorRecord,\n MAX_QUEUE_SIZE,\n type RequestRecord,\n type RouteManifest,\n} from '../shared.js'\n\ntype Dispatch = (action: DevtoolsAction) => void\ntype QueuedItem = (d: Dispatch) => void\n\nlet _dispatch: Dispatch | null = null\nconst _queue: QueuedItem[] = []\n\nfunction queuable<Args extends unknown[]>(\n fn: (d: Dispatch, ...args: Args) => void,\n): (...args: Args) => void {\n return (...args: Args) => {\n if (_dispatch) {\n try {\n fn(_dispatch, ...args)\n } catch (err) {\n // EC-25: an error inside reducer-bound dispatch path MUST NOT bubble\n // to the original event source (e.g. logger / HMR callback / global\n // error handler). Log and continue.\n\n console.error('[theo devtools] dispatch failed', err)\n }\n } else {\n // EC-23: cap queue, FIFO-evict if full\n if (_queue.length >= MAX_QUEUE_SIZE) _queue.shift()\n _queue.push((d) => {\n fn(d, ...args)\n })\n }\n }\n}\n\nfunction flushQueue(): void {\n while (_queue.length) {\n const fn = _queue.shift()\n if (!fn || !_dispatch) break\n try {\n fn(_dispatch)\n } catch (err) {\n console.error('[theo devtools] queued event failed', err)\n }\n }\n}\n\nexport const dispatcher = {\n onRequest: queuable((d: Dispatch, req: RequestRecord) => {\n d({ type: 'REQUEST_ADD', request: req })\n }),\n onError: queuable((d: Dispatch, err: ErrorRecord) => {\n d({ type: 'ERROR_ADD', error: err })\n }),\n onCsrfWarn: queuable((d: Dispatch, payload: CsrfWarnPayload) => {\n d({ type: 'CSRF_WARN', payload })\n }),\n onManifestUpdated: queuable((d: Dispatch, manifest: RouteManifest) => {\n d({ type: 'MANIFEST_UPDATED', manifest })\n }),\n onRouteMatched: queuable((d: Dispatch, path: string, chain: string[]) => {\n d({ type: 'ROUTE_MATCHED', path, chain })\n }),\n onAgentRun: queuable((d: Dispatch, run: AgentRunRecord) => {\n d({ type: 'AGENT_RUN_ADD', run })\n }),\n onActionCall: queuable((d: Dispatch, record: ActionCallRecord) => {\n d({ type: 'ACTION_CALL_ADD', record })\n }),\n onAgentStreamEvent: queuable((d: Dispatch, event: AgentStreamRecord) => {\n d({ type: 'AGENT_STREAM_EVENT', event })\n }),\n\n /**\n * Wire React's dispatch function in. Idempotent (EC-24): only the\n * NULL → non-null transition flushes the queue; subsequent non-null\n * sets just replace the reference (used for StrictMode re-mount).\n */\n setDispatch(d: Dispatch | null): void {\n const prev = _dispatch\n _dispatch = d\n if (d && !prev) flushQueue()\n },\n\n /** Testing helper — clear queue + dispatch reference between tests. */\n _reset(): void {\n _dispatch = null\n _queue.length = 0\n },\n\n /** Testing helper — observe queue length. */\n _queueLength(): number {\n return _queue.length\n },\n}\n\nexport type Dispatcher = typeof dispatcher\n"],"mappings":";AAiJO,IAAM,kBAAkB;AACxB,IAAM,iBAAiB;AACvB,IAAM,kBAAkB;AAExB,IAAM,eAA8B;AAAA,EACzC,MAAM;AAAA,EACN,SAAS;AAAA,EACT,UAAU;AAAA,EACV,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU,CAAC;AAAA,EACX,QAAQ,CAAC;AAAA,EACT,WAAW,CAAC;AAAA,EACZ,aAAa,CAAC;AAAA,EACd,eAAe;AAAA,EACf,iBAAiB;AAAA,EACjB,aAAa,CAAC;AAAA,EACd,mBAAmB,CAAC;AACtB;AAEO,IAAM,kBAAkB;AACxB,IAAM,gBAAgB;AACtB,IAAM,oBAAoB;AAC1B,IAAM,mBAAmB;AACzB,IAAM,wBAAwB;AAG9B,IAAM,uBAAuB;;;AC/IpC,IAAI,YAA6B;AACjC,IAAM,SAAuB,CAAC;AAE9B,SAAS,SACP,IACyB;AACzB,SAAO,IAAI,SAAe;AACxB,QAAI,WAAW;AACb,UAAI;AACF,WAAG,WAAW,GAAG,IAAI;AAAA,MACvB,SAAS,KAAK;AAKZ,gBAAQ,MAAM,mCAAmC,GAAG;AAAA,MACtD;AAAA,IACF,OAAO;AAEL,UAAI,OAAO,UAAU,eAAgB,QAAO,MAAM;AAClD,aAAO,KAAK,CAAC,MAAM;AACjB,WAAG,GAAG,GAAG,IAAI;AAAA,MACf,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAAS,aAAmB;AAC1B,SAAO,OAAO,QAAQ;AACpB,UAAM,KAAK,OAAO,MAAM;AACxB,QAAI,CAAC,MAAM,CAAC,UAAW;AACvB,QAAI;AACF,SAAG,SAAS;AAAA,IACd,SAAS,KAAK;AACZ,cAAQ,MAAM,uCAAuC,GAAG;AAAA,IAC1D;AAAA,EACF;AACF;AAEO,IAAM,aAAa;AAAA,EACxB,WAAW,SAAS,CAAC,GAAa,QAAuB;AACvD,MAAE,EAAE,MAAM,eAAe,SAAS,IAAI,CAAC;AAAA,EACzC,CAAC;AAAA,EACD,SAAS,SAAS,CAAC,GAAa,QAAqB;AACnD,MAAE,EAAE,MAAM,aAAa,OAAO,IAAI,CAAC;AAAA,EACrC,CAAC;AAAA,EACD,YAAY,SAAS,CAAC,GAAa,YAA6B;AAC9D,MAAE,EAAE,MAAM,aAAa,QAAQ,CAAC;AAAA,EAClC,CAAC;AAAA,EACD,mBAAmB,SAAS,CAAC,GAAa,aAA4B;AACpE,MAAE,EAAE,MAAM,oBAAoB,SAAS,CAAC;AAAA,EAC1C,CAAC;AAAA,EACD,gBAAgB,SAAS,CAAC,GAAa,MAAc,UAAoB;AACvE,MAAE,EAAE,MAAM,iBAAiB,MAAM,MAAM,CAAC;AAAA,EAC1C,CAAC;AAAA,EACD,YAAY,SAAS,CAAC,GAAa,QAAwB;AACzD,MAAE,EAAE,MAAM,iBAAiB,IAAI,CAAC;AAAA,EAClC,CAAC;AAAA,EACD,cAAc,SAAS,CAAC,GAAa,WAA6B;AAChE,MAAE,EAAE,MAAM,mBAAmB,OAAO,CAAC;AAAA,EACvC,CAAC;AAAA,EACD,oBAAoB,SAAS,CAAC,GAAa,UAA6B;AACtE,MAAE,EAAE,MAAM,sBAAsB,MAAM,CAAC;AAAA,EACzC,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOD,YAAY,GAA0B;AACpC,UAAM,OAAO;AACb,gBAAY;AACZ,QAAI,KAAK,CAAC,KAAM,YAAW;AAAA,EAC7B;AAAA;AAAA,EAGA,SAAe;AACb,gBAAY;AACZ,WAAO,SAAS;AAAA,EAClB;AAAA;AAAA,EAGA,eAAuB;AACrB,WAAO,OAAO;AAAA,EAChB;AACF;","names":[]}
@@ -0,0 +1,36 @@
1
+ // src/server/observability/suggest.ts
2
+ function levenshtein(a, b) {
3
+ const m = a.length;
4
+ const n = b.length;
5
+ const dp = Array.from(
6
+ { length: m + 1 },
7
+ () => Array.from({ length: n + 1 }).fill(0)
8
+ );
9
+ for (let i = 0; i <= m; i++) dp[i][0] = i;
10
+ for (let j = 0; j <= n; j++) dp[0][j] = j;
11
+ for (let i = 1; i <= m; i++) {
12
+ for (let j = 1; j <= n; j++) {
13
+ const cost = a[i - 1] === b[j - 1] ? 0 : 1;
14
+ dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost);
15
+ }
16
+ }
17
+ return dp[m][n];
18
+ }
19
+ function findSuggestion(input, candidates, maxDistance = 3) {
20
+ let best = null;
21
+ let bestDist = maxDistance + 1;
22
+ for (const c of candidates) {
23
+ const d = levenshtein(input, c);
24
+ if (d < bestDist) {
25
+ bestDist = d;
26
+ best = c;
27
+ }
28
+ }
29
+ return best;
30
+ }
31
+
32
+ export {
33
+ levenshtein,
34
+ findSuggestion
35
+ };
36
+ //# sourceMappingURL=chunk-5QW7IQQU.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server/observability/suggest.ts"],"sourcesContent":["export function levenshtein(a: string, b: string): number {\n const m = a.length\n const n = b.length\n const dp: number[][] = Array.from({ length: m + 1 }, () =>\n Array.from<number>({ length: n + 1 }).fill(0),\n )\n\n for (let i = 0; i <= m; i++) dp[i][0] = i\n for (let j = 0; j <= n; j++) dp[0][j] = j\n\n for (let i = 1; i <= m; i++) {\n for (let j = 1; j <= n; j++) {\n const cost = a[i - 1] === b[j - 1] ? 0 : 1\n dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1, dp[i - 1][j - 1] + cost)\n }\n }\n\n return dp[m][n]\n}\n\nexport function findSuggestion(\n input: string,\n candidates: string[],\n maxDistance = 3,\n): string | null {\n let best: string | null = null\n let bestDist = maxDistance + 1\n\n for (const c of candidates) {\n const d = levenshtein(input, c)\n if (d < bestDist) {\n bestDist = d\n best = c\n }\n }\n\n return best\n}\n"],"mappings":";AAAO,SAAS,YAAY,GAAW,GAAmB;AACxD,QAAM,IAAI,EAAE;AACZ,QAAM,IAAI,EAAE;AACZ,QAAM,KAAiB,MAAM;AAAA,IAAK,EAAE,QAAQ,IAAI,EAAE;AAAA,IAAG,MACnD,MAAM,KAAa,EAAE,QAAQ,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC;AAAA,EAC9C;AAEA,WAAS,IAAI,GAAG,KAAK,GAAG,IAAK,IAAG,CAAC,EAAE,CAAC,IAAI;AACxC,WAAS,IAAI,GAAG,KAAK,GAAG,IAAK,IAAG,CAAC,EAAE,CAAC,IAAI;AAExC,WAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,aAAS,IAAI,GAAG,KAAK,GAAG,KAAK;AAC3B,YAAM,OAAO,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,IAAI;AACzC,SAAG,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC,IAAI,GAAG,GAAG,CAAC,EAAE,IAAI,CAAC,IAAI,GAAG,GAAG,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI;AAAA,IACjF;AAAA,EACF;AAEA,SAAO,GAAG,CAAC,EAAE,CAAC;AAChB;AAEO,SAAS,eACd,OACA,YACA,cAAc,GACC;AACf,MAAI,OAAsB;AAC1B,MAAI,WAAW,cAAc;AAE7B,aAAW,KAAK,YAAY;AAC1B,UAAM,IAAI,YAAY,OAAO,CAAC;AAC9B,QAAI,IAAI,UAAU;AAChB,iBAAW;AACX,aAAO;AAAA,IACT;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}