@the-open-engine/zeroshot 6.38.0 → 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 (381) 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/agent-cli-provider/adapters/codex.d.ts.map +1 -1
  13. package/lib/agent-cli-provider/adapters/codex.js +3 -1
  14. package/lib/agent-cli-provider/adapters/codex.js.map +1 -1
  15. package/lib/cluster/generated/protocol-schema.cjs +1 -1
  16. package/lib/cluster/generated/protocol-schema.mjs +1 -1
  17. package/lib/cluster/generated/protocol.d.cts +8 -0
  18. package/lib/cluster/generated/protocol.d.mts +8 -0
  19. package/lib/cluster/generated/protocol.d.ts +8 -0
  20. package/lib/clusters-registry.d.ts +23 -0
  21. package/lib/clusters-registry.js +17 -29
  22. package/lib/completion.d.ts +12 -0
  23. package/lib/completion.js +84 -94
  24. package/lib/compose-utils.d.ts +32 -0
  25. package/lib/compose-utils.js +57 -72
  26. package/lib/detached-startup.d.ts +83 -0
  27. package/lib/detached-startup.js +231 -302
  28. package/lib/docker-config.d.ts +43 -0
  29. package/lib/docker-config.js +150 -325
  30. package/lib/docker-env-auth.d.ts +17 -0
  31. package/lib/docker-env-auth.js +75 -0
  32. package/lib/git-remote-utils.d.ts +48 -0
  33. package/lib/git-remote-utils.js +147 -213
  34. package/lib/id-detector.d.ts +15 -0
  35. package/lib/id-detector.js +37 -41
  36. package/lib/path-check.d.ts +30 -0
  37. package/lib/path-check.js +42 -45
  38. package/lib/process-liveness.d.ts +16 -0
  39. package/lib/process-liveness.js +19 -12
  40. package/lib/provider-credential-path.d.ts +16 -0
  41. package/lib/provider-credential-path.js +31 -29
  42. package/lib/provider-defaults.d.ts +30 -0
  43. package/lib/provider-defaults.js +47 -42
  44. package/lib/provider-detection.d.ts +11 -0
  45. package/lib/provider-detection.js +91 -54
  46. package/lib/provider-names.d.ts +38 -0
  47. package/lib/provider-names.js +56 -64
  48. package/lib/repo-settings.d.ts +28 -0
  49. package/lib/repo-settings.js +83 -59
  50. package/lib/run-mode.d.ts +21 -0
  51. package/lib/run-mode.js +21 -20
  52. package/lib/run-plan.d.ts +28 -0
  53. package/lib/run-plan.js +17 -16
  54. package/lib/settings/claude-auth.d.ts +35 -0
  55. package/lib/settings/claude-auth.js +30 -47
  56. package/lib/settings-defaults.d.ts +20 -0
  57. package/lib/settings-defaults.js +149 -0
  58. package/lib/settings-error.d.ts +7 -0
  59. package/lib/settings-error.js +8 -0
  60. package/lib/settings-issue-providers.d.ts +10 -0
  61. package/lib/settings-issue-providers.js +12 -0
  62. package/lib/settings-models.d.ts +22 -0
  63. package/lib/settings-models.js +93 -0
  64. package/lib/settings-storage.d.ts +23 -0
  65. package/lib/settings-storage.js +205 -0
  66. package/lib/settings-validation.d.ts +7 -0
  67. package/lib/settings-validation.js +182 -0
  68. package/lib/settings.d.ts +29 -0
  69. package/lib/settings.js +41 -736
  70. package/lib/setup-apply-types.d.ts +66 -0
  71. package/lib/setup-apply-types.js +2 -0
  72. package/lib/setup-apply.d.ts +39 -0
  73. package/lib/setup-apply.js +267 -264
  74. package/lib/setup-journal.d.ts +41 -0
  75. package/lib/setup-journal.js +119 -76
  76. package/lib/setup-plan-types.d.ts +102 -0
  77. package/lib/setup-plan-types.js +2 -0
  78. package/lib/setup-plan.d.ts +30 -0
  79. package/lib/setup-plan.js +300 -324
  80. package/lib/setup-undo.d.ts +44 -0
  81. package/lib/setup-undo.js +61 -74
  82. package/lib/start-cluster-config.d.ts +26 -0
  83. package/lib/start-cluster-config.js +56 -0
  84. package/lib/start-cluster-environment.d.ts +40 -0
  85. package/lib/start-cluster-environment.js +134 -0
  86. package/lib/start-cluster-run-options.d.ts +53 -0
  87. package/lib/start-cluster-run-options.js +147 -0
  88. package/lib/start-cluster.d.ts +64 -0
  89. package/lib/start-cluster.js +98 -454
  90. package/lib/stream-json-parser.d.ts +17 -0
  91. package/lib/stream-json-parser.js +51 -52
  92. package/npm-shrinkwrap.json +2 -2
  93. package/package.json +12 -6
  94. package/scripts/postinstall.js +27 -0
  95. package/scripts/rust-distribution.js +23 -14
  96. package/src/agent/agent-command-proofs-context.js +35 -45
  97. package/src/agent/agent-command-proofs-context.ts +87 -0
  98. package/src/agent/agent-config-settings.js +19 -0
  99. package/src/agent/agent-config-settings.ts +41 -0
  100. package/src/agent/agent-config.js +122 -231
  101. package/src/agent/agent-config.ts +285 -0
  102. package/src/agent/agent-context-builder.js +38 -273
  103. package/src/agent/agent-context-builder.ts +51 -0
  104. package/src/agent/agent-context-environment-sections.js +105 -0
  105. package/src/agent/agent-context-environment-sections.ts +134 -0
  106. package/src/agent/agent-context-packs.js +165 -0
  107. package/src/agent/agent-context-packs.ts +296 -0
  108. package/src/agent/agent-context-prompt-sections.js +100 -0
  109. package/src/agent/agent-context-prompt-sections.ts +148 -0
  110. package/src/agent/agent-context-sections.js +25 -334
  111. package/src/agent/agent-context-sections.ts +36 -0
  112. package/src/agent/agent-context-sources.js +96 -149
  113. package/src/agent/agent-context-sources.ts +253 -0
  114. package/src/agent/agent-context-types.js +2 -0
  115. package/src/agent/agent-context-types.ts +132 -0
  116. package/src/agent/agent-context-validation-sections.js +73 -0
  117. package/src/agent/agent-context-validation-sections.ts +129 -0
  118. package/src/agent/agent-input-injector.js +99 -118
  119. package/src/agent/agent-input-injector.ts +195 -0
  120. package/src/agent/agent-liveness-poll.js +74 -78
  121. package/src/agent/agent-liveness-poll.ts +163 -0
  122. package/src/agent/agent-quality-gate-schema.js +77 -86
  123. package/src/agent/agent-quality-gate-schema.ts +135 -0
  124. package/src/agent/agent-quality-gates-context.js +44 -50
  125. package/src/agent/agent-quality-gates-context.ts +91 -0
  126. package/src/agent/agent-stuck-detector.js +171 -239
  127. package/src/agent/agent-stuck-detector.ts +288 -0
  128. package/src/agent/agent-trigger-evaluator.js +29 -46
  129. package/src/agent/agent-trigger-evaluator.ts +98 -0
  130. package/src/agent/context-metrics.js +110 -141
  131. package/src/agent/context-metrics.ts +261 -0
  132. package/src/agent/context-pack-builder.js +72 -358
  133. package/src/agent/context-pack-builder.ts +105 -0
  134. package/src/agent/context-pack-core.js +70 -0
  135. package/src/agent/context-pack-core.ts +96 -0
  136. package/src/agent/context-pack-selection.js +119 -0
  137. package/src/agent/context-pack-selection.ts +187 -0
  138. package/src/agent/context-pack-truncation.js +139 -0
  139. package/src/agent/context-pack-truncation.ts +208 -0
  140. package/src/agent/context-pack-types.js +2 -0
  141. package/src/agent/context-pack-types.ts +98 -0
  142. package/src/agent/context-replay-policy.js +30 -39
  143. package/src/agent/context-replay-policy.ts +71 -0
  144. package/src/agent/critical-agent-policy.js +6 -10
  145. package/src/agent/critical-agent-policy.ts +20 -0
  146. package/src/agent/guidance-queue.js +74 -87
  147. package/src/agent/guidance-queue.ts +166 -0
  148. package/src/agent/output-extraction-error-detail.js +45 -0
  149. package/src/agent/output-extraction-error-detail.ts +49 -0
  150. package/src/agent/output-extraction-failures.js +125 -0
  151. package/src/agent/output-extraction-failures.ts +149 -0
  152. package/src/agent/output-extraction-json.js +234 -0
  153. package/src/agent/output-extraction-json.ts +235 -0
  154. package/src/agent/output-extraction-pi.js +124 -0
  155. package/src/agent/output-extraction-pi.ts +137 -0
  156. package/src/agent/output-extraction-types.js +2 -0
  157. package/src/agent/output-extraction-types.ts +49 -0
  158. package/src/agent/output-extraction.js +17 -617
  159. package/src/agent/output-extraction.ts +30 -0
  160. package/src/agent/output-reformatter-errors.js +83 -0
  161. package/src/agent/output-reformatter-errors.ts +106 -0
  162. package/src/agent/output-reformatter-types.js +2 -0
  163. package/src/agent/output-reformatter-types.ts +86 -0
  164. package/src/agent/output-reformatter.js +140 -185
  165. package/src/agent/output-reformatter.ts +238 -0
  166. package/src/agent/pi-terminal-lifecycle-types.js +2 -0
  167. package/src/agent/pi-terminal-lifecycle-types.ts +41 -0
  168. package/src/agent/pi-terminal-lifecycle.js +186 -206
  169. package/src/agent/pi-terminal-lifecycle.ts +297 -0
  170. package/src/agent/provider-control-plane.js +22 -21
  171. package/src/agent/provider-control-plane.ts +52 -0
  172. package/src/agent/provider-terminal-failure-types.js +2 -0
  173. package/src/agent/provider-terminal-failure-types.ts +60 -0
  174. package/src/agent/provider-terminal-failure.js +194 -191
  175. package/src/agent/provider-terminal-failure.ts +262 -0
  176. package/src/agent/rate-limit-backoff.js +31 -74
  177. package/src/agent/rate-limit-backoff.ts +71 -0
  178. package/src/agent/schema-utils.js +85 -125
  179. package/src/agent/schema-utils.ts +148 -0
  180. package/src/agent/structured-output-error.js +34 -33
  181. package/src/agent/structured-output-error.ts +105 -0
  182. package/src/agent/validation-platform.js +27 -27
  183. package/src/agent/validation-platform.ts +49 -0
  184. package/src/agent-cli-provider/adapters/codex.ts +3 -1
  185. package/src/attach/attach-client.js +232 -405
  186. package/src/attach/attach-client.ts +300 -0
  187. package/src/attach/attach-server-cleanup.js +43 -0
  188. package/src/attach/attach-server-cleanup.ts +39 -0
  189. package/src/attach/attach-server-clients.js +117 -0
  190. package/src/attach/attach-server-clients.ts +122 -0
  191. package/src/attach/attach-server-events.js +38 -0
  192. package/src/attach/attach-server-events.ts +36 -0
  193. package/src/attach/attach-server-pty.js +45 -0
  194. package/src/attach/attach-server-pty.ts +64 -0
  195. package/src/attach/attach-server-runtime.js +73 -0
  196. package/src/attach/attach-server-runtime.ts +62 -0
  197. package/src/attach/attach-server-socket.js +28 -0
  198. package/src/attach/attach-server-socket.ts +23 -0
  199. package/src/attach/attach-server-types.js +2 -0
  200. package/src/attach/attach-server-types.ts +82 -0
  201. package/src/attach/attach-server.js +106 -523
  202. package/src/attach/attach-server.ts +158 -0
  203. package/src/attach/index.js +18 -35
  204. package/src/attach/index.ts +18 -0
  205. package/src/attach/protocol.js +95 -184
  206. package/src/attach/protocol.ts +181 -0
  207. package/src/attach/ring-buffer.js +76 -102
  208. package/src/attach/ring-buffer.ts +109 -0
  209. package/src/attach/send-input.js +64 -75
  210. package/src/attach/send-input.ts +94 -0
  211. package/src/attach/socket-discovery.js +164 -218
  212. package/src/attach/socket-discovery.ts +230 -0
  213. package/src/attach/socket-paths.js +42 -61
  214. package/src/attach/socket-paths.ts +81 -0
  215. package/src/claude-credentials.js +51 -54
  216. package/src/claude-credentials.ts +89 -0
  217. package/src/cluster/generated/protocol-schema.ts +1 -1
  218. package/src/cluster/generated/protocol.ts +2 -1
  219. package/src/command-proofs.js +110 -141
  220. package/src/command-proofs.ts +216 -0
  221. package/src/config-router.js +81 -73
  222. package/src/config-router.ts +131 -0
  223. package/src/copy-worker.js +53 -29
  224. package/src/copy-worker.ts +75 -0
  225. package/src/darwin-keychain-boundary.js +80 -111
  226. package/src/darwin-keychain-boundary.ts +148 -0
  227. package/src/guidance-topics.js +4 -5
  228. package/src/guidance-topics.ts +10 -0
  229. package/src/input-helpers.js +33 -54
  230. package/src/input-helpers.ts +58 -0
  231. package/src/ledger-sequence.js +45 -48
  232. package/src/ledger-sequence.ts +63 -0
  233. package/src/legacy-lib/clusters-registry.ts +40 -0
  234. package/src/legacy-lib/completion.ts +148 -0
  235. package/src/legacy-lib/compose-utils.ts +102 -0
  236. package/src/legacy-lib/detached-startup.ts +449 -0
  237. package/src/legacy-lib/docker-config.ts +282 -0
  238. package/src/legacy-lib/docker-env-auth.ts +116 -0
  239. package/src/legacy-lib/git-remote-utils.ts +244 -0
  240. package/src/legacy-lib/id-detector.ts +57 -0
  241. package/src/legacy-lib/js-yaml.d.ts +3 -0
  242. package/src/legacy-lib/omelette.d.ts +15 -0
  243. package/src/legacy-lib/path-check.ts +89 -0
  244. package/src/legacy-lib/process-liveness.ts +36 -0
  245. package/src/legacy-lib/provider-credential-path.ts +57 -0
  246. package/src/legacy-lib/provider-defaults.ts +114 -0
  247. package/src/legacy-lib/provider-detection.ts +67 -0
  248. package/src/legacy-lib/provider-names.ts +126 -0
  249. package/src/legacy-lib/repo-settings.ts +88 -0
  250. package/src/legacy-lib/run-mode.ts +58 -0
  251. package/src/legacy-lib/run-plan.ts +49 -0
  252. package/src/legacy-lib/settings/claude-auth.ts +80 -0
  253. package/src/legacy-lib/settings-defaults.ts +212 -0
  254. package/src/legacy-lib/settings-error.ts +8 -0
  255. package/src/legacy-lib/settings-issue-providers.ts +18 -0
  256. package/src/legacy-lib/settings-models.ts +124 -0
  257. package/src/legacy-lib/settings-storage.ts +277 -0
  258. package/src/legacy-lib/settings-validation.ts +220 -0
  259. package/src/legacy-lib/settings.ts +87 -0
  260. package/src/legacy-lib/setup-apply-types.ts +70 -0
  261. package/src/legacy-lib/setup-apply.ts +456 -0
  262. package/src/legacy-lib/setup-journal.ts +185 -0
  263. package/src/legacy-lib/setup-plan-types.ts +96 -0
  264. package/src/legacy-lib/setup-plan.ts +500 -0
  265. package/src/legacy-lib/setup-undo.ts +142 -0
  266. package/src/legacy-lib/start-cluster-config.ts +124 -0
  267. package/src/legacy-lib/start-cluster-environment.ts +165 -0
  268. package/src/legacy-lib/start-cluster-run-options.ts +279 -0
  269. package/src/legacy-lib/start-cluster.ts +237 -0
  270. package/src/legacy-lib/stream-json-parser.ts +88 -0
  271. package/src/message-buffer.js +55 -71
  272. package/src/message-buffer.ts +107 -0
  273. package/src/message-bus-bridge.js +92 -133
  274. package/src/message-bus-bridge.ts +149 -0
  275. package/src/name-generator-shared.js +220 -0
  276. package/src/name-generator-shared.ts +231 -0
  277. package/src/name-generator.js +8 -217
  278. package/src/name-generator.ts +27 -0
  279. package/src/omp-blob-root.js +83 -64
  280. package/src/omp-blob-root.ts +116 -0
  281. package/src/omp-config-overlay.js +65 -38
  282. package/src/omp-config-overlay.ts +110 -0
  283. package/src/omp-execution-fingerprint.js +38 -43
  284. package/src/omp-execution-fingerprint.ts +92 -0
  285. package/src/omp-session-limits.js +10 -15
  286. package/src/omp-session-limits.ts +53 -0
  287. package/src/omp-session-partition.js +2 -2
  288. package/src/omp-session-verifier.js +1 -1
  289. package/src/orchestrator.js +19 -4
  290. package/src/providers/anthropic/index.js +3 -1
  291. package/src/providers/anthropic/index.ts +13 -0
  292. package/src/providers/capabilities.js +19 -27
  293. package/src/providers/capabilities.ts +44 -0
  294. package/src/providers/google/index.js +3 -1
  295. package/src/providers/google/index.ts +13 -0
  296. package/src/providers/openai/index.js +3 -1
  297. package/src/providers/openai/index.ts +13 -0
  298. package/src/providers/opencode/index.js +3 -1
  299. package/src/providers/opencode/index.ts +13 -0
  300. package/src/quality-gates.js +67 -127
  301. package/src/quality-gates.ts +149 -0
  302. package/src/repo-settings-access.js +40 -0
  303. package/src/repo-settings-access.ts +64 -0
  304. package/src/schemas/sub-cluster.js +127 -183
  305. package/src/schemas/sub-cluster.ts +238 -0
  306. package/src/state-snapshot-normalization.js +224 -0
  307. package/src/state-snapshot-normalization.ts +222 -0
  308. package/src/state-snapshot.js +192 -359
  309. package/src/state-snapshot.ts +291 -0
  310. package/src/state-snapshotter.js +118 -130
  311. package/src/state-snapshotter.ts +167 -0
  312. package/src/sub-cluster-wrapper.js +4 -13
  313. package/src/task-run-model-args.js +87 -124
  314. package/src/task-run-model-args.ts +204 -0
  315. package/src/task-runner.js +5 -25
  316. package/src/task-runner.ts +28 -0
  317. package/src/task-startup-error.js +73 -58
  318. package/src/task-startup-error.ts +126 -0
  319. package/src/template-validation/consensus-gate-contracts.js +2 -0
  320. package/src/template-validation/consensus-gate-contracts.ts +70 -0
  321. package/src/template-validation/consensus-gate-scenarios.js +76 -0
  322. package/src/template-validation/consensus-gate-scenarios.ts +130 -0
  323. package/src/template-validation/consensus-gate-stage.js +34 -0
  324. package/src/template-validation/consensus-gate-stage.ts +56 -0
  325. package/src/template-validation/random-topology-contracts.js +2 -0
  326. package/src/template-validation/random-topology-contracts.ts +54 -0
  327. package/src/template-validation/random-topology-dispatch.js +25 -0
  328. package/src/template-validation/random-topology-dispatch.ts +33 -0
  329. package/src/template-validation/random-topology-message-loop.js +53 -0
  330. package/src/template-validation/random-topology-message-loop.ts +73 -0
  331. package/src/template-validation/random-topology-operations.js +79 -0
  332. package/src/template-validation/random-topology-operations.ts +101 -0
  333. package/src/template-validation/random-topology-runtime.js +25 -0
  334. package/src/template-validation/random-topology-runtime.ts +43 -0
  335. package/src/template-validation/random-topology-scenario.js +52 -0
  336. package/src/template-validation/random-topology-scenario.ts +57 -0
  337. package/src/template-validation/random-topology-schema.js +159 -0
  338. package/src/template-validation/random-topology-schema.ts +190 -0
  339. package/src/template-validation/random-topology-state.js +28 -0
  340. package/src/template-validation/random-topology-state.ts +30 -0
  341. package/src/template-validation/random-topology-trigger-evaluation.js +45 -0
  342. package/src/template-validation/random-topology-trigger-evaluation.ts +65 -0
  343. package/src/template-validation/random-topology-trigger.js +75 -0
  344. package/src/template-validation/random-topology-trigger.ts +88 -0
  345. package/src/template-validation/report-formatter.js +40 -46
  346. package/src/template-validation/report-formatter.ts +101 -0
  347. package/src/template-validation/simulate-consensus-gates.js +111 -302
  348. package/src/template-validation/simulate-consensus-gates.ts +196 -0
  349. package/src/template-validation/simulate-random-topology.js +26 -519
  350. package/src/template-validation/simulate-random-topology.ts +57 -0
  351. package/src/template-validation/simulate-two-stage-validation.js +41 -265
  352. package/src/template-validation/simulate-two-stage-validation.ts +55 -0
  353. package/src/template-validation/simulation-agent-runtime.js +25 -0
  354. package/src/template-validation/simulation-agent-runtime.ts +40 -0
  355. package/src/template-validation/simulation-agent.js +29 -0
  356. package/src/template-validation/simulation-agent.ts +73 -0
  357. package/src/template-validation/simulation-runtime.js +34 -0
  358. package/src/template-validation/simulation-runtime.ts +72 -0
  359. package/src/template-validation/two-stage-contracts.js +2 -0
  360. package/src/template-validation/two-stage-contracts.ts +41 -0
  361. package/src/template-validation/two-stage-inputs.js +21 -0
  362. package/src/template-validation/two-stage-inputs.ts +29 -0
  363. package/src/template-validation/two-stage-results.js +30 -0
  364. package/src/template-validation/two-stage-results.ts +40 -0
  365. package/src/template-validation/two-stage-scenario.js +86 -0
  366. package/src/template-validation/two-stage-scenario.ts +120 -0
  367. package/src/worktree-claude-config.js +182 -220
  368. package/src/worktree-claude-config.ts +272 -0
  369. package/src/worktree-tooling-env.js +103 -125
  370. package/src/worktree-tooling-env.ts +142 -0
  371. package/task-lib/completion.js +2 -3
  372. package/task-lib/completion.ts +9 -0
  373. package/task-lib/config.js +1 -4
  374. package/task-lib/config.ts +11 -0
  375. package/task-lib/name-generator.js +4 -226
  376. package/task-lib/name-generator.ts +11 -0
  377. package/task-lib/omp-session-cleanup.js +1 -1
  378. package/task-lib/omp-storage-root.js +8 -12
  379. package/task-lib/omp-storage-root.ts +62 -0
  380. package/task-lib/process-termination.js +143 -166
  381. 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
+ }