@the-open-engine/zeroshot 6.38.1 → 6.39.1

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