@the-open-engine/zeroshot 6.38.1 → 6.39.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 (377) hide show
  1. package/cli/event-copy.js +8 -7
  2. package/cli/event-copy.ts +12 -0
  3. package/cli/index.js +7 -31
  4. package/cli/json-export.js +61 -64
  5. package/cli/json-export.ts +112 -0
  6. package/cli/message-formatter-utils.js +68 -56
  7. package/cli/message-formatter-utils.ts +121 -0
  8. package/cli/message-formatters-normal.js +124 -259
  9. package/cli/message-formatters-normal.ts +250 -0
  10. package/cli/message-formatters-watch.js +81 -84
  11. package/cli/message-formatters-watch.ts +189 -0
  12. package/lib/cluster/generated/protocol-schema.cjs +1 -1
  13. package/lib/cluster/generated/protocol-schema.mjs +1 -1
  14. package/lib/cluster/generated/protocol.d.cts +8 -0
  15. package/lib/cluster/generated/protocol.d.mts +8 -0
  16. package/lib/cluster/generated/protocol.d.ts +8 -0
  17. package/lib/clusters-registry.d.ts +23 -0
  18. package/lib/clusters-registry.js +17 -29
  19. package/lib/completion.d.ts +12 -0
  20. package/lib/completion.js +84 -94
  21. package/lib/compose-utils.d.ts +32 -0
  22. package/lib/compose-utils.js +57 -72
  23. package/lib/detached-startup.d.ts +83 -0
  24. package/lib/detached-startup.js +231 -302
  25. package/lib/docker-config.d.ts +43 -0
  26. package/lib/docker-config.js +150 -325
  27. package/lib/docker-env-auth.d.ts +17 -0
  28. package/lib/docker-env-auth.js +75 -0
  29. package/lib/git-remote-utils.d.ts +48 -0
  30. package/lib/git-remote-utils.js +147 -213
  31. package/lib/id-detector.d.ts +15 -0
  32. package/lib/id-detector.js +37 -41
  33. package/lib/path-check.d.ts +30 -0
  34. package/lib/path-check.js +42 -45
  35. package/lib/process-liveness.d.ts +16 -0
  36. package/lib/process-liveness.js +19 -12
  37. package/lib/provider-credential-path.d.ts +16 -0
  38. package/lib/provider-credential-path.js +31 -29
  39. package/lib/provider-defaults.d.ts +30 -0
  40. package/lib/provider-defaults.js +47 -42
  41. package/lib/provider-detection.d.ts +11 -0
  42. package/lib/provider-detection.js +91 -54
  43. package/lib/provider-names.d.ts +38 -0
  44. package/lib/provider-names.js +56 -64
  45. package/lib/repo-settings.d.ts +28 -0
  46. package/lib/repo-settings.js +83 -59
  47. package/lib/run-mode.d.ts +21 -0
  48. package/lib/run-mode.js +21 -20
  49. package/lib/run-plan.d.ts +28 -0
  50. package/lib/run-plan.js +17 -16
  51. package/lib/settings/claude-auth.d.ts +35 -0
  52. package/lib/settings/claude-auth.js +30 -47
  53. package/lib/settings-defaults.d.ts +20 -0
  54. package/lib/settings-defaults.js +149 -0
  55. package/lib/settings-error.d.ts +7 -0
  56. package/lib/settings-error.js +8 -0
  57. package/lib/settings-issue-providers.d.ts +10 -0
  58. package/lib/settings-issue-providers.js +12 -0
  59. package/lib/settings-models.d.ts +22 -0
  60. package/lib/settings-models.js +93 -0
  61. package/lib/settings-storage.d.ts +23 -0
  62. package/lib/settings-storage.js +205 -0
  63. package/lib/settings-validation.d.ts +7 -0
  64. package/lib/settings-validation.js +182 -0
  65. package/lib/settings.d.ts +29 -0
  66. package/lib/settings.js +41 -736
  67. package/lib/setup-apply-types.d.ts +66 -0
  68. package/lib/setup-apply-types.js +2 -0
  69. package/lib/setup-apply.d.ts +39 -0
  70. package/lib/setup-apply.js +267 -264
  71. package/lib/setup-journal.d.ts +41 -0
  72. package/lib/setup-journal.js +119 -76
  73. package/lib/setup-plan-types.d.ts +102 -0
  74. package/lib/setup-plan-types.js +2 -0
  75. package/lib/setup-plan.d.ts +30 -0
  76. package/lib/setup-plan.js +300 -324
  77. package/lib/setup-undo.d.ts +44 -0
  78. package/lib/setup-undo.js +61 -74
  79. package/lib/start-cluster-config.d.ts +26 -0
  80. package/lib/start-cluster-config.js +56 -0
  81. package/lib/start-cluster-environment.d.ts +40 -0
  82. package/lib/start-cluster-environment.js +134 -0
  83. package/lib/start-cluster-run-options.d.ts +53 -0
  84. package/lib/start-cluster-run-options.js +147 -0
  85. package/lib/start-cluster.d.ts +64 -0
  86. package/lib/start-cluster.js +98 -454
  87. package/lib/stream-json-parser.d.ts +17 -0
  88. package/lib/stream-json-parser.js +51 -52
  89. package/npm-shrinkwrap.json +2 -2
  90. package/package.json +12 -6
  91. package/scripts/postinstall.js +27 -0
  92. package/scripts/rust-distribution.js +23 -14
  93. package/src/agent/agent-command-proofs-context.js +35 -45
  94. package/src/agent/agent-command-proofs-context.ts +87 -0
  95. package/src/agent/agent-config-settings.js +19 -0
  96. package/src/agent/agent-config-settings.ts +41 -0
  97. package/src/agent/agent-config.js +122 -231
  98. package/src/agent/agent-config.ts +285 -0
  99. package/src/agent/agent-context-builder.js +38 -273
  100. package/src/agent/agent-context-builder.ts +51 -0
  101. package/src/agent/agent-context-environment-sections.js +105 -0
  102. package/src/agent/agent-context-environment-sections.ts +134 -0
  103. package/src/agent/agent-context-packs.js +165 -0
  104. package/src/agent/agent-context-packs.ts +296 -0
  105. package/src/agent/agent-context-prompt-sections.js +100 -0
  106. package/src/agent/agent-context-prompt-sections.ts +148 -0
  107. package/src/agent/agent-context-sections.js +25 -334
  108. package/src/agent/agent-context-sections.ts +36 -0
  109. package/src/agent/agent-context-sources.js +96 -149
  110. package/src/agent/agent-context-sources.ts +253 -0
  111. package/src/agent/agent-context-types.js +2 -0
  112. package/src/agent/agent-context-types.ts +132 -0
  113. package/src/agent/agent-context-validation-sections.js +73 -0
  114. package/src/agent/agent-context-validation-sections.ts +129 -0
  115. package/src/agent/agent-input-injector.js +99 -118
  116. package/src/agent/agent-input-injector.ts +195 -0
  117. package/src/agent/agent-liveness-poll.js +74 -78
  118. package/src/agent/agent-liveness-poll.ts +163 -0
  119. package/src/agent/agent-quality-gate-schema.js +77 -86
  120. package/src/agent/agent-quality-gate-schema.ts +135 -0
  121. package/src/agent/agent-quality-gates-context.js +44 -50
  122. package/src/agent/agent-quality-gates-context.ts +91 -0
  123. package/src/agent/agent-stuck-detector.js +171 -239
  124. package/src/agent/agent-stuck-detector.ts +288 -0
  125. package/src/agent/agent-trigger-evaluator.js +29 -46
  126. package/src/agent/agent-trigger-evaluator.ts +98 -0
  127. package/src/agent/context-metrics.js +110 -141
  128. package/src/agent/context-metrics.ts +261 -0
  129. package/src/agent/context-pack-builder.js +72 -358
  130. package/src/agent/context-pack-builder.ts +105 -0
  131. package/src/agent/context-pack-core.js +70 -0
  132. package/src/agent/context-pack-core.ts +96 -0
  133. package/src/agent/context-pack-selection.js +119 -0
  134. package/src/agent/context-pack-selection.ts +187 -0
  135. package/src/agent/context-pack-truncation.js +139 -0
  136. package/src/agent/context-pack-truncation.ts +208 -0
  137. package/src/agent/context-pack-types.js +2 -0
  138. package/src/agent/context-pack-types.ts +98 -0
  139. package/src/agent/context-replay-policy.js +30 -39
  140. package/src/agent/context-replay-policy.ts +71 -0
  141. package/src/agent/critical-agent-policy.js +6 -10
  142. package/src/agent/critical-agent-policy.ts +20 -0
  143. package/src/agent/guidance-queue.js +74 -87
  144. package/src/agent/guidance-queue.ts +166 -0
  145. package/src/agent/output-extraction-error-detail.js +45 -0
  146. package/src/agent/output-extraction-error-detail.ts +49 -0
  147. package/src/agent/output-extraction-failures.js +125 -0
  148. package/src/agent/output-extraction-failures.ts +149 -0
  149. package/src/agent/output-extraction-json.js +234 -0
  150. package/src/agent/output-extraction-json.ts +235 -0
  151. package/src/agent/output-extraction-pi.js +124 -0
  152. package/src/agent/output-extraction-pi.ts +137 -0
  153. package/src/agent/output-extraction-types.js +2 -0
  154. package/src/agent/output-extraction-types.ts +49 -0
  155. package/src/agent/output-extraction.js +17 -617
  156. package/src/agent/output-extraction.ts +30 -0
  157. package/src/agent/output-reformatter-errors.js +83 -0
  158. package/src/agent/output-reformatter-errors.ts +106 -0
  159. package/src/agent/output-reformatter-types.js +2 -0
  160. package/src/agent/output-reformatter-types.ts +86 -0
  161. package/src/agent/output-reformatter.js +140 -185
  162. package/src/agent/output-reformatter.ts +238 -0
  163. package/src/agent/pi-terminal-lifecycle-types.js +2 -0
  164. package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
  165. package/src/agent/pi-terminal-lifecycle.js +186 -206
  166. package/src/agent/pi-terminal-lifecycle.ts +297 -0
  167. package/src/agent/provider-control-plane.js +22 -21
  168. package/src/agent/provider-control-plane.ts +52 -0
  169. package/src/agent/provider-terminal-failure-types.js +2 -0
  170. package/src/agent/provider-terminal-failure-types.ts +60 -0
  171. package/src/agent/provider-terminal-failure.js +194 -191
  172. package/src/agent/provider-terminal-failure.ts +262 -0
  173. package/src/agent/rate-limit-backoff.js +31 -74
  174. package/src/agent/rate-limit-backoff.ts +71 -0
  175. package/src/agent/schema-utils.js +85 -125
  176. package/src/agent/schema-utils.ts +148 -0
  177. package/src/agent/structured-output-error.js +34 -33
  178. package/src/agent/structured-output-error.ts +105 -0
  179. package/src/agent/validation-platform.js +27 -27
  180. package/src/agent/validation-platform.ts +49 -0
  181. package/src/attach/attach-client.js +232 -405
  182. package/src/attach/attach-client.ts +300 -0
  183. package/src/attach/attach-server-cleanup.js +43 -0
  184. package/src/attach/attach-server-cleanup.ts +39 -0
  185. package/src/attach/attach-server-clients.js +117 -0
  186. package/src/attach/attach-server-clients.ts +122 -0
  187. package/src/attach/attach-server-events.js +38 -0
  188. package/src/attach/attach-server-events.ts +36 -0
  189. package/src/attach/attach-server-pty.js +45 -0
  190. package/src/attach/attach-server-pty.ts +64 -0
  191. package/src/attach/attach-server-runtime.js +73 -0
  192. package/src/attach/attach-server-runtime.ts +62 -0
  193. package/src/attach/attach-server-socket.js +28 -0
  194. package/src/attach/attach-server-socket.ts +23 -0
  195. package/src/attach/attach-server-types.js +2 -0
  196. package/src/attach/attach-server-types.ts +82 -0
  197. package/src/attach/attach-server.js +106 -523
  198. package/src/attach/attach-server.ts +158 -0
  199. package/src/attach/index.js +18 -35
  200. package/src/attach/index.ts +18 -0
  201. package/src/attach/protocol.js +95 -184
  202. package/src/attach/protocol.ts +181 -0
  203. package/src/attach/ring-buffer.js +76 -102
  204. package/src/attach/ring-buffer.ts +109 -0
  205. package/src/attach/send-input.js +64 -75
  206. package/src/attach/send-input.ts +94 -0
  207. package/src/attach/socket-discovery.js +164 -218
  208. package/src/attach/socket-discovery.ts +230 -0
  209. package/src/attach/socket-paths.js +42 -61
  210. package/src/attach/socket-paths.ts +81 -0
  211. package/src/claude-credentials.js +51 -54
  212. package/src/claude-credentials.ts +89 -0
  213. package/src/cluster/generated/protocol-schema.ts +1 -1
  214. package/src/cluster/generated/protocol.ts +2 -1
  215. package/src/command-proofs.js +110 -141
  216. package/src/command-proofs.ts +216 -0
  217. package/src/config-router.js +81 -73
  218. package/src/config-router.ts +131 -0
  219. package/src/copy-worker.js +53 -29
  220. package/src/copy-worker.ts +75 -0
  221. package/src/darwin-keychain-boundary.js +80 -111
  222. package/src/darwin-keychain-boundary.ts +148 -0
  223. package/src/guidance-topics.js +4 -5
  224. package/src/guidance-topics.ts +10 -0
  225. package/src/input-helpers.js +33 -54
  226. package/src/input-helpers.ts +58 -0
  227. package/src/ledger-sequence.js +45 -48
  228. package/src/ledger-sequence.ts +63 -0
  229. package/src/legacy-lib/clusters-registry.ts +40 -0
  230. package/src/legacy-lib/completion.ts +148 -0
  231. package/src/legacy-lib/compose-utils.ts +102 -0
  232. package/src/legacy-lib/detached-startup.ts +449 -0
  233. package/src/legacy-lib/docker-config.ts +282 -0
  234. package/src/legacy-lib/docker-env-auth.ts +116 -0
  235. package/src/legacy-lib/git-remote-utils.ts +244 -0
  236. package/src/legacy-lib/id-detector.ts +57 -0
  237. package/src/legacy-lib/js-yaml.d.ts +3 -0
  238. package/src/legacy-lib/omelette.d.ts +15 -0
  239. package/src/legacy-lib/path-check.ts +89 -0
  240. package/src/legacy-lib/process-liveness.ts +36 -0
  241. package/src/legacy-lib/provider-credential-path.ts +57 -0
  242. package/src/legacy-lib/provider-defaults.ts +114 -0
  243. package/src/legacy-lib/provider-detection.ts +67 -0
  244. package/src/legacy-lib/provider-names.ts +126 -0
  245. package/src/legacy-lib/repo-settings.ts +88 -0
  246. package/src/legacy-lib/run-mode.ts +58 -0
  247. package/src/legacy-lib/run-plan.ts +49 -0
  248. package/src/legacy-lib/settings/claude-auth.ts +80 -0
  249. package/src/legacy-lib/settings-defaults.ts +212 -0
  250. package/src/legacy-lib/settings-error.ts +8 -0
  251. package/src/legacy-lib/settings-issue-providers.ts +18 -0
  252. package/src/legacy-lib/settings-models.ts +124 -0
  253. package/src/legacy-lib/settings-storage.ts +277 -0
  254. package/src/legacy-lib/settings-validation.ts +220 -0
  255. package/src/legacy-lib/settings.ts +87 -0
  256. package/src/legacy-lib/setup-apply-types.ts +70 -0
  257. package/src/legacy-lib/setup-apply.ts +456 -0
  258. package/src/legacy-lib/setup-journal.ts +185 -0
  259. package/src/legacy-lib/setup-plan-types.ts +96 -0
  260. package/src/legacy-lib/setup-plan.ts +500 -0
  261. package/src/legacy-lib/setup-undo.ts +142 -0
  262. package/src/legacy-lib/start-cluster-config.ts +124 -0
  263. package/src/legacy-lib/start-cluster-environment.ts +165 -0
  264. package/src/legacy-lib/start-cluster-run-options.ts +279 -0
  265. package/src/legacy-lib/start-cluster.ts +237 -0
  266. package/src/legacy-lib/stream-json-parser.ts +88 -0
  267. package/src/message-buffer.js +55 -71
  268. package/src/message-buffer.ts +107 -0
  269. package/src/message-bus-bridge.js +92 -133
  270. package/src/message-bus-bridge.ts +149 -0
  271. package/src/name-generator-shared.js +220 -0
  272. package/src/name-generator-shared.ts +231 -0
  273. package/src/name-generator.js +8 -217
  274. package/src/name-generator.ts +27 -0
  275. package/src/omp-blob-root.js +83 -64
  276. package/src/omp-blob-root.ts +116 -0
  277. package/src/omp-config-overlay.js +65 -38
  278. package/src/omp-config-overlay.ts +110 -0
  279. package/src/omp-execution-fingerprint.js +38 -43
  280. package/src/omp-execution-fingerprint.ts +92 -0
  281. package/src/omp-session-limits.js +10 -15
  282. package/src/omp-session-limits.ts +53 -0
  283. package/src/omp-session-partition.js +2 -2
  284. package/src/omp-session-verifier.js +1 -1
  285. package/src/orchestrator.js +19 -4
  286. package/src/providers/anthropic/index.js +3 -1
  287. package/src/providers/anthropic/index.ts +13 -0
  288. package/src/providers/capabilities.js +19 -27
  289. package/src/providers/capabilities.ts +44 -0
  290. package/src/providers/google/index.js +3 -1
  291. package/src/providers/google/index.ts +13 -0
  292. package/src/providers/openai/index.js +3 -1
  293. package/src/providers/openai/index.ts +13 -0
  294. package/src/providers/opencode/index.js +3 -1
  295. package/src/providers/opencode/index.ts +13 -0
  296. package/src/quality-gates.js +67 -127
  297. package/src/quality-gates.ts +149 -0
  298. package/src/repo-settings-access.js +40 -0
  299. package/src/repo-settings-access.ts +64 -0
  300. package/src/schemas/sub-cluster.js +127 -183
  301. package/src/schemas/sub-cluster.ts +238 -0
  302. package/src/state-snapshot-normalization.js +224 -0
  303. package/src/state-snapshot-normalization.ts +222 -0
  304. package/src/state-snapshot.js +192 -359
  305. package/src/state-snapshot.ts +291 -0
  306. package/src/state-snapshotter.js +118 -130
  307. package/src/state-snapshotter.ts +167 -0
  308. package/src/sub-cluster-wrapper.js +4 -13
  309. package/src/task-run-model-args.js +87 -124
  310. package/src/task-run-model-args.ts +204 -0
  311. package/src/task-runner.js +5 -25
  312. package/src/task-runner.ts +28 -0
  313. package/src/task-startup-error.js +73 -58
  314. package/src/task-startup-error.ts +126 -0
  315. package/src/template-validation/consensus-gate-contracts.js +2 -0
  316. package/src/template-validation/consensus-gate-contracts.ts +70 -0
  317. package/src/template-validation/consensus-gate-scenarios.js +76 -0
  318. package/src/template-validation/consensus-gate-scenarios.ts +130 -0
  319. package/src/template-validation/consensus-gate-stage.js +34 -0
  320. package/src/template-validation/consensus-gate-stage.ts +56 -0
  321. package/src/template-validation/random-topology-contracts.js +2 -0
  322. package/src/template-validation/random-topology-contracts.ts +54 -0
  323. package/src/template-validation/random-topology-dispatch.js +25 -0
  324. package/src/template-validation/random-topology-dispatch.ts +33 -0
  325. package/src/template-validation/random-topology-message-loop.js +53 -0
  326. package/src/template-validation/random-topology-message-loop.ts +73 -0
  327. package/src/template-validation/random-topology-operations.js +79 -0
  328. package/src/template-validation/random-topology-operations.ts +101 -0
  329. package/src/template-validation/random-topology-runtime.js +25 -0
  330. package/src/template-validation/random-topology-runtime.ts +43 -0
  331. package/src/template-validation/random-topology-scenario.js +52 -0
  332. package/src/template-validation/random-topology-scenario.ts +57 -0
  333. package/src/template-validation/random-topology-schema.js +159 -0
  334. package/src/template-validation/random-topology-schema.ts +190 -0
  335. package/src/template-validation/random-topology-state.js +28 -0
  336. package/src/template-validation/random-topology-state.ts +30 -0
  337. package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
  338. package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
  339. package/src/template-validation/random-topology-trigger.js +75 -0
  340. package/src/template-validation/random-topology-trigger.ts +88 -0
  341. package/src/template-validation/report-formatter.js +40 -46
  342. package/src/template-validation/report-formatter.ts +101 -0
  343. package/src/template-validation/simulate-consensus-gates.js +111 -302
  344. package/src/template-validation/simulate-consensus-gates.ts +196 -0
  345. package/src/template-validation/simulate-random-topology.js +26 -519
  346. package/src/template-validation/simulate-random-topology.ts +57 -0
  347. package/src/template-validation/simulate-two-stage-validation.js +41 -265
  348. package/src/template-validation/simulate-two-stage-validation.ts +55 -0
  349. package/src/template-validation/simulation-agent-runtime.js +25 -0
  350. package/src/template-validation/simulation-agent-runtime.ts +40 -0
  351. package/src/template-validation/simulation-agent.js +29 -0
  352. package/src/template-validation/simulation-agent.ts +73 -0
  353. package/src/template-validation/simulation-runtime.js +34 -0
  354. package/src/template-validation/simulation-runtime.ts +72 -0
  355. package/src/template-validation/two-stage-contracts.js +2 -0
  356. package/src/template-validation/two-stage-contracts.ts +41 -0
  357. package/src/template-validation/two-stage-inputs.js +21 -0
  358. package/src/template-validation/two-stage-inputs.ts +29 -0
  359. package/src/template-validation/two-stage-results.js +30 -0
  360. package/src/template-validation/two-stage-results.ts +40 -0
  361. package/src/template-validation/two-stage-scenario.js +86 -0
  362. package/src/template-validation/two-stage-scenario.ts +120 -0
  363. package/src/worktree-claude-config.js +182 -220
  364. package/src/worktree-claude-config.ts +272 -0
  365. package/src/worktree-tooling-env.js +103 -125
  366. package/src/worktree-tooling-env.ts +142 -0
  367. package/task-lib/completion.js +2 -3
  368. package/task-lib/completion.ts +9 -0
  369. package/task-lib/config.js +1 -4
  370. package/task-lib/config.ts +11 -0
  371. package/task-lib/name-generator.js +4 -226
  372. package/task-lib/name-generator.ts +11 -0
  373. package/task-lib/omp-session-cleanup.js +1 -1
  374. package/task-lib/omp-storage-root.js +8 -12
  375. package/task-lib/omp-storage-root.ts +62 -0
  376. package/task-lib/process-termination.js +143 -166
  377. package/task-lib/process-termination.ts +268 -0
@@ -0,0 +1,282 @@
1
+ interface MountPreset {
2
+ host: string;
3
+ container: string;
4
+ readonly: boolean;
5
+ hostEnv?: string;
6
+ }
7
+
8
+ interface ProviderDockerConfig {
9
+ envPassthrough: readonly string[];
10
+ mount?: MountPreset;
11
+ }
12
+
13
+ interface ProviderMetadata {
14
+ docker: ProviderDockerConfig;
15
+ id: string;
16
+ }
17
+
18
+ interface ProviderNamesFacade {
19
+ listProviderMetadata(): readonly ProviderMetadata[];
20
+ }
21
+
22
+ interface CredentialPathFacade {
23
+ expandProviderCredentialPath(pathValue: string): string;
24
+ }
25
+
26
+ interface ProviderEnvAuthResult {
27
+ ok: boolean;
28
+ satisfiedOneOf: boolean;
29
+ malformed: string[];
30
+ message: string;
31
+ }
32
+
33
+ interface DockerEnvAuthFacade {
34
+ isUsableEnvValue(value: unknown): value is string;
35
+ isUsableHttpUrl(value: unknown): boolean;
36
+ validateEnvPassthrough(value: unknown): string | null;
37
+ validateProviderEnvAuth(
38
+ providerId: string,
39
+ forwardedEnv: Readonly<Record<string, string | undefined>> | null | undefined
40
+ ): ProviderEnvAuthResult;
41
+ }
42
+
43
+ interface CustomMount {
44
+ host?: string;
45
+ container?: string;
46
+ readonly?: boolean;
47
+ }
48
+
49
+ interface ResolvedMount {
50
+ host: string;
51
+ container: string;
52
+ readonly: boolean;
53
+ }
54
+
55
+ interface ResolveMountOptions {
56
+ containerHome?: string;
57
+ }
58
+
59
+ interface ExpandedEnv {
60
+ name: string;
61
+ value: string | null;
62
+ forced: boolean;
63
+ }
64
+
65
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
66
+ const providerNames: ProviderNamesFacade = require('./provider-names');
67
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
68
+ const credentialPaths: CredentialPathFacade = require('./provider-credential-path');
69
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
70
+ const dockerEnvAuth: DockerEnvAuthFacade = require('./docker-env-auth');
71
+
72
+ const { listProviderMetadata } = providerNames;
73
+ const { expandProviderCredentialPath } = credentialPaths;
74
+ const {
75
+ isUsableEnvValue,
76
+ isUsableHttpUrl,
77
+ validateEnvPassthrough,
78
+ validateProviderEnvAuth,
79
+ } = dockerEnvAuth;
80
+
81
+ const BASE_MOUNT_PRESETS: Readonly<Record<string, MountPreset>> = {
82
+ gh: { host: '~/.config/gh', container: '$HOME/.config/gh', readonly: false },
83
+ git: { host: '~/.gitconfig', container: '$HOME/.gitconfig', readonly: true },
84
+ ssh: { host: '~/.ssh', container: '$HOME/.ssh', readonly: true },
85
+ aws: { host: '~/.aws', container: '$HOME/.aws', readonly: true },
86
+ azure: { host: '~/.azure', container: '$HOME/.azure', readonly: true },
87
+ kube: { host: '~/.kube', container: '$HOME/.kube', readonly: true },
88
+ terraform: { host: '~/.terraform.d', container: '$HOME/.terraform.d', readonly: false },
89
+ gcloud: { host: '~/.config/gcloud', container: '$HOME/.config/gcloud', readonly: true },
90
+ };
91
+
92
+ const BASE_ENV_PRESETS: Readonly<Record<string, readonly string[]>> = {
93
+ aws: ['AWS_REGION', 'AWS_DEFAULT_REGION', 'AWS_PROFILE', 'AWS_PAGER='],
94
+ azure: ['AZURE_SUBSCRIPTION_ID', 'AZURE_TENANT_ID', 'AZURE_CLIENT_ID'],
95
+ gcloud: ['CLOUDSDK_CORE_PROJECT', 'GOOGLE_CLOUD_PROJECT'],
96
+ kube: ['KUBECONFIG'],
97
+ terraform: ['TF_VAR_*'],
98
+ };
99
+
100
+ function listProviderDockerPresetEntries(): Array<readonly [string, ProviderDockerConfig]> {
101
+ return listProviderMetadata().map((metadata) => [metadata.id, metadata.docker]);
102
+ }
103
+
104
+ function listProviderMountEntries(): Array<readonly [string, MountPreset]> {
105
+ const entries: Array<readonly [string, MountPreset]> = [];
106
+ for (const [providerId, docker] of listProviderDockerPresetEntries()) {
107
+ if (docker.mount) {
108
+ entries.push([providerId, docker.mount]);
109
+ }
110
+ }
111
+ return entries;
112
+ }
113
+
114
+ const MOUNT_PRESETS: Readonly<Record<string, MountPreset>> = Object.freeze({
115
+ ...BASE_MOUNT_PRESETS,
116
+ ...Object.fromEntries(listProviderMountEntries()),
117
+ });
118
+
119
+ const ENV_PRESETS: Readonly<Record<string, readonly string[]>> = Object.freeze({
120
+ ...BASE_ENV_PRESETS,
121
+ ...Object.fromEntries(
122
+ listProviderDockerPresetEntries().map(([providerId, docker]) => [
123
+ providerId,
124
+ [...docker.envPassthrough],
125
+ ])
126
+ ),
127
+ });
128
+
129
+ const PROVIDER_ENV_ONLY_PRESETS: ReadonlySet<string> = Object.freeze(
130
+ new Set(
131
+ listProviderDockerPresetEntries()
132
+ .filter(([, docker]) => !docker.mount && docker.envPassthrough.length > 0)
133
+ .map(([providerId]) => providerId)
134
+ )
135
+ );
136
+
137
+ function isCustomMount(value: unknown): value is CustomMount {
138
+ return typeof value === 'object' && value !== null;
139
+ }
140
+
141
+ function resolveMountItem(item: unknown, containerHome: string): ResolvedMount[] {
142
+ if (typeof item === 'string') {
143
+ const preset = MOUNT_PRESETS[item];
144
+ if (!preset) {
145
+ if (PROVIDER_ENV_ONLY_PRESETS.has(item)) {
146
+ return [];
147
+ }
148
+ throw new Error(
149
+ `Unknown mount preset: "${item}". Valid presets: ${Object.keys(MOUNT_PRESETS).join(', ')}. ` +
150
+ `Env-only presets (no mount): ${[...PROVIDER_ENV_ONLY_PRESETS].join(', ')}`
151
+ );
152
+ }
153
+ const overriddenHost =
154
+ typeof preset.hostEnv === 'string' && process.env[preset.hostEnv]?.trim()
155
+ ? expandProviderCredentialPath(`$${preset.hostEnv}`)
156
+ : preset.host;
157
+ return [
158
+ {
159
+ host: overriddenHost,
160
+ container: preset.container.replace(/\$HOME/g, containerHome),
161
+ readonly: preset.readonly,
162
+ },
163
+ ];
164
+ }
165
+
166
+ if (isCustomMount(item)) {
167
+ if (!item.host || !item.container) {
168
+ throw new Error('Custom mount must have "host" and "container" properties');
169
+ }
170
+ return [
171
+ {
172
+ host: item.host,
173
+ container: item.container.replace(/\$HOME/g, containerHome),
174
+ readonly: item.readonly !== false,
175
+ },
176
+ ];
177
+ }
178
+
179
+ throw new Error(
180
+ `Invalid mount config: ${JSON.stringify(item)}. Use preset name or {host, container, readonly?}`
181
+ );
182
+ }
183
+
184
+ function resolveMounts(config: unknown, options: ResolveMountOptions = {}): ResolvedMount[] {
185
+ if (!Array.isArray(config)) {
186
+ throw new Error('dockerMounts must be an array');
187
+ }
188
+
189
+ const containerHome = options.containerHome || '/root';
190
+ return config.flatMap((item: unknown) => resolveMountItem(item, containerHome));
191
+ }
192
+
193
+ function resolveEnvs(mountConfig: readonly unknown[], extraEnvs: readonly string[] = []): string[] {
194
+ const envs = new Set(extraEnvs);
195
+
196
+ for (const item of mountConfig) {
197
+ if (typeof item === 'string') {
198
+ const preset = ENV_PRESETS[item];
199
+ if (preset) {
200
+ for (const envVar of preset) {
201
+ envs.add(envVar);
202
+ }
203
+ }
204
+ }
205
+ }
206
+
207
+ return [...envs];
208
+ }
209
+
210
+ function expandEnvPatterns(
211
+ envVars: readonly string[],
212
+ env: Readonly<Record<string, string | undefined>> = process.env
213
+ ): ExpandedEnv[] {
214
+ const result: ExpandedEnv[] = [];
215
+
216
+ for (const envVar of envVars) {
217
+ if (envVar.includes('=')) {
218
+ const separator = envVar.indexOf('=');
219
+ result.push({
220
+ name: envVar.slice(0, separator),
221
+ value: envVar.slice(separator + 1),
222
+ forced: true,
223
+ });
224
+ } else if (envVar.endsWith('*')) {
225
+ const prefix = envVar.slice(0, -1);
226
+ for (const key of Object.keys(env)) {
227
+ if (key.startsWith(prefix)) {
228
+ result.push({ name: key, value: null, forced: false });
229
+ }
230
+ }
231
+ } else {
232
+ result.push({ name: envVar, value: null, forced: false });
233
+ }
234
+ }
235
+
236
+ return result;
237
+ }
238
+
239
+ function validateMountConfig(value: unknown): string | null {
240
+ if (!Array.isArray(value)) {
241
+ return 'dockerMounts must be an array';
242
+ }
243
+
244
+ for (const item of value) {
245
+ if (typeof item === 'string') {
246
+ if (!MOUNT_PRESETS[item] && !PROVIDER_ENV_ONLY_PRESETS.has(item)) {
247
+ return (
248
+ `Unknown mount preset: "${item}". Valid: ${Object.keys(MOUNT_PRESETS).join(', ')}. ` +
249
+ `Env-only presets (no mount): ${[...PROVIDER_ENV_ONLY_PRESETS].join(', ')}`
250
+ );
251
+ }
252
+ } else if (isCustomMount(item)) {
253
+ if (!item.host) {
254
+ return 'Custom mount missing "host" property';
255
+ }
256
+ if (!item.container) {
257
+ return 'Custom mount missing "container" property';
258
+ }
259
+ if (item.readonly !== undefined && typeof item.readonly !== 'boolean') {
260
+ return '"readonly" must be a boolean';
261
+ }
262
+ } else {
263
+ return `Invalid mount: ${JSON.stringify(item)}. Use preset name or {host, container, readonly?}`;
264
+ }
265
+ }
266
+
267
+ return null;
268
+ }
269
+
270
+ export = {
271
+ MOUNT_PRESETS,
272
+ ENV_PRESETS,
273
+ PROVIDER_ENV_ONLY_PRESETS,
274
+ resolveMounts,
275
+ resolveEnvs,
276
+ expandEnvPatterns,
277
+ isUsableEnvValue,
278
+ isUsableHttpUrl,
279
+ validateMountConfig,
280
+ validateEnvPassthrough,
281
+ validateProviderEnvAuth,
282
+ };
@@ -0,0 +1,116 @@
1
+ import { URL } from 'url';
2
+
3
+ interface ProviderEnvAuth {
4
+ requireOneOf?: readonly string[];
5
+ requireTogether?: readonly (readonly string[])[];
6
+ requireUrl?: readonly string[];
7
+ }
8
+
9
+ interface ProviderMetadata {
10
+ docker?: {
11
+ envAuth?: ProviderEnvAuth;
12
+ };
13
+ }
14
+
15
+ interface ProviderNamesFacade {
16
+ getProviderMetadata(providerId: string): ProviderMetadata;
17
+ }
18
+
19
+ interface ProviderEnvAuthResult {
20
+ ok: boolean;
21
+ satisfiedOneOf: boolean;
22
+ malformed: string[];
23
+ message: string;
24
+ }
25
+
26
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
27
+ const providerNames: ProviderNamesFacade = require('./provider-names');
28
+
29
+ const ENV_SPEC_PATTERN = /^[A-Z_][A-Z0-9_]*(\*|=.*)?$/i;
30
+
31
+ function validateEnvPassthrough(value: unknown): string | null {
32
+ if (!Array.isArray(value)) {
33
+ return 'dockerEnvPassthrough must be an array';
34
+ }
35
+
36
+ for (const item of value) {
37
+ if (typeof item !== 'string') {
38
+ return `Invalid env var: ${JSON.stringify(item)}. Must be a string`;
39
+ }
40
+ if (!ENV_SPEC_PATTERN.test(item)) {
41
+ return `Invalid env var spec: "${item}". Use VAR, VAR_*, or VAR=value`;
42
+ }
43
+ }
44
+
45
+ return null;
46
+ }
47
+
48
+ function isUsableEnvValue(value: unknown): value is string {
49
+ return typeof value === 'string' && value.trim() !== '';
50
+ }
51
+
52
+ function isUsableHttpUrl(value: unknown): boolean {
53
+ if (!isUsableEnvValue(value)) {
54
+ return false;
55
+ }
56
+ let parsed: URL;
57
+ try {
58
+ parsed = new URL(value.trim());
59
+ } catch {
60
+ return false;
61
+ }
62
+ return parsed.protocol === 'http:' || parsed.protocol === 'https:';
63
+ }
64
+
65
+ function validateProviderEnvAuth(
66
+ providerId: string,
67
+ forwardedEnv: Readonly<Record<string, string | undefined>> | null | undefined
68
+ ): ProviderEnvAuthResult {
69
+ const metadata = providerNames.getProviderMetadata(providerId);
70
+ const envAuth = metadata.docker && metadata.docker.envAuth;
71
+ if (!envAuth) {
72
+ return { ok: true, satisfiedOneOf: true, malformed: [], message: '' };
73
+ }
74
+
75
+ const requireUrl = new Set(envAuth.requireUrl || []);
76
+ const valueOf = (name: string): string | undefined =>
77
+ forwardedEnv ? forwardedEnv[name] : undefined;
78
+ const isSet = (name: string): boolean =>
79
+ requireUrl.has(name) ? isUsableHttpUrl(valueOf(name)) : isUsableEnvValue(valueOf(name));
80
+
81
+ const requireOneOf = envAuth.requireOneOf || [];
82
+ const satisfiedOneOf = requireOneOf.length === 0 || requireOneOf.some(isSet);
83
+
84
+ const malformed: string[] = [];
85
+ for (const name of requireUrl) {
86
+ if (isUsableEnvValue(valueOf(name)) && !isUsableHttpUrl(valueOf(name))) {
87
+ malformed.push(`${name} is set but is not a usable http(s) URL`);
88
+ }
89
+ }
90
+
91
+ for (const group of envAuth.requireTogether || []) {
92
+ const missing = group.filter((name) => !isSet(name));
93
+ if (missing.length > 0 && missing.length < group.length) {
94
+ malformed.push(`${group.join(' + ')} must be set together (missing ${missing.join(', ')})`);
95
+ }
96
+ }
97
+
98
+ const reasons = [...malformed];
99
+ if (!satisfiedOneOf) {
100
+ reasons.push(`one of ${requireOneOf.join(', ')} must be set to a non-empty value`);
101
+ }
102
+
103
+ return {
104
+ ok: malformed.length === 0 && satisfiedOneOf,
105
+ satisfiedOneOf,
106
+ malformed,
107
+ message: reasons.join('; '),
108
+ };
109
+ }
110
+
111
+ export = {
112
+ isUsableEnvValue,
113
+ isUsableHttpUrl,
114
+ validateEnvPassthrough,
115
+ validateProviderEnvAuth,
116
+ };
@@ -0,0 +1,244 @@
1
+ /**
2
+ * Git remote URL parsing and provider detection.
3
+ * Automatically detects issue provider from git remote URL.
4
+ */
5
+
6
+ interface ExecSyncOptions {
7
+ cwd: string;
8
+ encoding: 'utf8';
9
+ stdio: 'pipe';
10
+ }
11
+
12
+ type ExecSync = (command: string, options: ExecSyncOptions) => string;
13
+
14
+ interface SafeExecFacade {
15
+ execSync: ExecSync;
16
+ }
17
+
18
+ interface HostedGitContext {
19
+ provider: 'github' | 'gitlab';
20
+ host: string;
21
+ org: string;
22
+ repo: string;
23
+ fullRepo: string;
24
+ }
25
+
26
+ interface AzureDevOpsGitContext {
27
+ provider: 'azure-devops';
28
+ host: string;
29
+ azureOrg: string;
30
+ azureProject: string;
31
+ repo: string;
32
+ }
33
+
34
+ type GitContext = HostedGitContext | AzureDevOpsGitContext;
35
+ type GitContextWithRemote = GitContext & { remote: string };
36
+
37
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
38
+ const safeExec: SafeExecFacade = require('../src/lib/safe-exec');
39
+ const { execSync } = safeExec;
40
+
41
+ function hasInvalidGitRefCharacter(value: string): boolean {
42
+ for (const character of value) {
43
+ const codePoint = character.codePointAt(0);
44
+ if (
45
+ codePoint === undefined ||
46
+ codePoint <= 0x20 ||
47
+ codePoint === 0x7f ||
48
+ '~^:?*[\\'.includes(character)
49
+ ) {
50
+ return true;
51
+ }
52
+ }
53
+ return false;
54
+ }
55
+
56
+ /**
57
+ * Normalize a Git remote name using the same ref-format rules Git applies to
58
+ * refs/remotes/<name>. Keeping this next to detection prevents a discovered
59
+ * remote from being rejected later by a narrower consumer-specific allowlist.
60
+ */
61
+ function normalizeGitRemoteName(value: unknown): string | null {
62
+ if (typeof value !== 'string') {
63
+ return null;
64
+ }
65
+
66
+ const name = value.trim();
67
+ if (
68
+ name.length === 0 ||
69
+ name.endsWith('.') ||
70
+ name.includes('..') ||
71
+ name.includes('@{') ||
72
+ hasInvalidGitRefCharacter(name)
73
+ ) {
74
+ return null;
75
+ }
76
+
77
+ const components = name.split('/');
78
+ if (
79
+ components.some(
80
+ (component) =>
81
+ component.length === 0 || component.startsWith('.') || component.endsWith('.lock')
82
+ )
83
+ ) {
84
+ return null;
85
+ }
86
+
87
+ return name;
88
+ }
89
+
90
+ /** Quote one argument for the POSIX shell snippets embedded in agent prompts. */
91
+ function quoteShellArgument(value: string): string {
92
+ return `'${value.replaceAll("'", `'"'"'`)}'`;
93
+ }
94
+
95
+ /**
96
+ * Parse git remote URL into structured provider context.
97
+ * Supports GitHub, GitLab, and Azure DevOps (cloud + self-hosted).
98
+ * Handles both HTTPS and SSH URL formats.
99
+ */
100
+ function parseGitRemoteUrl(remoteUrl: unknown): GitContext | null {
101
+ if (!remoteUrl || typeof remoteUrl !== 'string') {
102
+ return null;
103
+ }
104
+
105
+ const url = remoteUrl.trim();
106
+
107
+ // Normalize SSH URLs to HTTPS format for easier parsing
108
+ // git@host:path → https://host/path
109
+ let normalizedUrl = url;
110
+ const sshMatch = /^git@([^:]+):(.+)$/.exec(url);
111
+ if (sshMatch) {
112
+ const host = sshMatch[1];
113
+ const remotePath = sshMatch[2];
114
+ if (host !== undefined && remotePath !== undefined) {
115
+ normalizedUrl = `https://${host}/${remotePath}`;
116
+ }
117
+ }
118
+
119
+ // Remove .git suffix if present
120
+ normalizedUrl = normalizedUrl.replace(/\.git$/, '');
121
+
122
+ // Azure DevOps: https://dev.azure.com/org/project/_git/repo
123
+ // Azure Legacy: https://org.visualstudio.com/project/_git/repo
124
+ // Azure SSH: git@ssh.dev.azure.com:v3/org/project/repo
125
+ const azureMatch =
126
+ /https:\/\/dev\.azure\.com\/([^/]+)\/([^/]+)\/_git\/([^/]+)/.exec(normalizedUrl) ||
127
+ /https:\/\/([^.]+)\.visualstudio\.com\/([^/]+)\/_git\/([^/]+)/.exec(normalizedUrl) ||
128
+ /https:\/\/ssh\.dev\.azure\.com\/v3\/([^/]+)\/([^/]+)\/([^/]+)/.exec(normalizedUrl);
129
+
130
+ if (azureMatch) {
131
+ const orgPart = azureMatch[1];
132
+ const project = azureMatch[2];
133
+ const repo = azureMatch[3];
134
+ if (orgPart === undefined || project === undefined || repo === undefined) {
135
+ return null;
136
+ }
137
+ const isLegacy = normalizedUrl.includes('visualstudio.com');
138
+ const azureOrg = isLegacy
139
+ ? `https://${orgPart}.visualstudio.com`
140
+ : `https://dev.azure.com/${orgPart}`;
141
+
142
+ return {
143
+ provider: 'azure-devops',
144
+ host: isLegacy ? `${orgPart}.visualstudio.com` : 'dev.azure.com',
145
+ azureOrg,
146
+ azureProject: project,
147
+ repo,
148
+ };
149
+ }
150
+
151
+ // GitHub: https://github.com/org/repo
152
+ // GitLab: https://gitlab.com/org/repo (or self-hosted)
153
+ // Generic: https://host/org/repo
154
+ const httpsMatch = /https?:\/\/([^/]+)\/([^/]+)\/([^/]+)/.exec(normalizedUrl);
155
+ if (httpsMatch) {
156
+ const host = httpsMatch[1];
157
+ const org = httpsMatch[2];
158
+ const repo = httpsMatch[3];
159
+ if (host === undefined || org === undefined || repo === undefined) {
160
+ return null;
161
+ }
162
+
163
+ let provider: HostedGitContext['provider'];
164
+ if (host === 'github.com') {
165
+ provider = 'github';
166
+ } else if (host.includes('gitlab')) {
167
+ provider = 'gitlab';
168
+ } else {
169
+ return null;
170
+ }
171
+
172
+ return {
173
+ provider,
174
+ host,
175
+ org,
176
+ repo,
177
+ fullRepo: `${org}/${repo}`,
178
+ };
179
+ }
180
+
181
+ return null;
182
+ }
183
+
184
+ /**
185
+ * Detect git repository context from current working directory.
186
+ * Returns provider context extracted from git remote URL.
187
+ */
188
+ function detectGitContext(cwd = process.cwd()): GitContextWithRemote | null {
189
+ try {
190
+ execSync('git rev-parse --git-dir', {
191
+ cwd,
192
+ stdio: 'pipe',
193
+ encoding: 'utf8',
194
+ });
195
+ } catch {
196
+ return null;
197
+ }
198
+
199
+ try {
200
+ const remoteOutput = execSync('git remote -v', {
201
+ cwd,
202
+ stdio: 'pipe',
203
+ encoding: 'utf8',
204
+ });
205
+
206
+ const supportedRemotes = new Map<string, GitContextWithRemote>();
207
+ for (const line of remoteOutput.split(/\r?\n/)) {
208
+ const match = /^(\S+)\s+(.+)\s+\(fetch\)$/.exec(line);
209
+ if (!match) {
210
+ continue;
211
+ }
212
+
213
+ const remoteCandidate = match[1];
214
+ const remoteUrl = match[2];
215
+ const remote = normalizeGitRemoteName(remoteCandidate);
216
+ if (!remote || remoteUrl === undefined) {
217
+ continue;
218
+ }
219
+ const context = parseGitRemoteUrl(remoteUrl);
220
+ if (context && !supportedRemotes.has(remote)) {
221
+ supportedRemotes.set(remote, { ...context, remote });
222
+ }
223
+ }
224
+
225
+ if (supportedRemotes.has('origin')) {
226
+ return supportedRemotes.get('origin') ?? null;
227
+ }
228
+
229
+ if (supportedRemotes.size === 1) {
230
+ return supportedRemotes.values().next().value ?? null;
231
+ }
232
+
233
+ return null;
234
+ } catch {
235
+ return null;
236
+ }
237
+ }
238
+
239
+ export = {
240
+ normalizeGitRemoteName,
241
+ quoteShellArgument,
242
+ parseGitRemoteUrl,
243
+ detectGitContext,
244
+ };
@@ -0,0 +1,57 @@
1
+ /**
2
+ * ID Detector - Determines if an ID is a task or cluster
3
+ *
4
+ * Strategy:
5
+ * 1. Check if ID exists in cluster storage
6
+ * 2. If not, check if ID exists in task storage (SQLite)
7
+ * 3. Return type: 'cluster', 'task', or null
8
+ */
9
+
10
+ import path = require('path');
11
+ import fs = require('fs');
12
+ import os = require('os');
13
+ import Database = require('better-sqlite3');
14
+ import clustersRegistry = require('./clusters-registry');
15
+
16
+ type IdType = 'cluster' | 'task' | null;
17
+
18
+ function hasClusterId(clusters: unknown, id: string): boolean {
19
+ return Boolean(Reflect.get(Object(clusters), id));
20
+ }
21
+
22
+ /** Detect if an ID belongs to a cluster or task. */
23
+ function detectIdType(id: string): IdType {
24
+ const homeDir =
25
+ process.env.ZEROSHOT_HOME ||
26
+ process.env.HOME ||
27
+ process.env.USERPROFILE ||
28
+ os.homedir();
29
+ const storageDir = path.join(homeDir, '.zeroshot');
30
+ const taskDbFile = path.join(homeDir, '.claude-zeroshot', 'store.db');
31
+
32
+ try {
33
+ const clusters = clustersRegistry.readClustersFileSync(storageDir);
34
+ if (hasClusterId(clusters, id)) {
35
+ return 'cluster';
36
+ }
37
+ } catch {
38
+ // Ignore parse errors
39
+ }
40
+
41
+ if (fs.existsSync(taskDbFile)) {
42
+ try {
43
+ const db = new Database(taskDbFile, { readonly: true, timeout: 5000 });
44
+ const row: unknown = db.prepare('SELECT id FROM tasks WHERE id = ?').get(id);
45
+ db.close();
46
+ if (row) {
47
+ return 'task';
48
+ }
49
+ } catch {
50
+ // Ignore DB errors
51
+ }
52
+ }
53
+
54
+ return null;
55
+ }
56
+
57
+ export = { detectIdType };
@@ -0,0 +1,3 @@
1
+ declare module 'js-yaml' {
2
+ export function load(input: string): unknown;
3
+ }