@the-open-engine/zeroshot 5.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (295) hide show
  1. package/CHANGELOG.md +539 -0
  2. package/LICENSE +21 -0
  3. package/README.md +508 -0
  4. package/cli/commands/inspect-render.js +135 -0
  5. package/cli/commands/inspect.js +294 -0
  6. package/cli/commands/providers.js +149 -0
  7. package/cli/index.js +5431 -0
  8. package/cli/lib/first-run.js +211 -0
  9. package/cli/lib/update-checker.js +281 -0
  10. package/cli/message-formatter-utils.js +75 -0
  11. package/cli/message-formatters-normal.js +275 -0
  12. package/cli/message-formatters-watch.js +185 -0
  13. package/cluster-templates/base-templates/debug-workflow.json +422 -0
  14. package/cluster-templates/base-templates/full-workflow.json +727 -0
  15. package/cluster-templates/base-templates/heavy-validation.json +272 -0
  16. package/cluster-templates/base-templates/quick-validation.json +285 -0
  17. package/cluster-templates/base-templates/single-worker.json +71 -0
  18. package/cluster-templates/base-templates/worker-validator.json +230 -0
  19. package/cluster-templates/conductor-bootstrap.json +130 -0
  20. package/docker/zeroshot-cluster/Dockerfile +153 -0
  21. package/docker/zeroshot-cluster/pre-baked-deps.json +28 -0
  22. package/lib/agent-cli-provider/adapters/claude-parser.d.ts +3 -0
  23. package/lib/agent-cli-provider/adapters/claude-parser.d.ts.map +1 -0
  24. package/lib/agent-cli-provider/adapters/claude-parser.js +122 -0
  25. package/lib/agent-cli-provider/adapters/claude-parser.js.map +1 -0
  26. package/lib/agent-cli-provider/adapters/claude-recovery.d.ts +15 -0
  27. package/lib/agent-cli-provider/adapters/claude-recovery.d.ts.map +1 -0
  28. package/lib/agent-cli-provider/adapters/claude-recovery.js +165 -0
  29. package/lib/agent-cli-provider/adapters/claude-recovery.js.map +1 -0
  30. package/lib/agent-cli-provider/adapters/claude.d.ts +3 -0
  31. package/lib/agent-cli-provider/adapters/claude.d.ts.map +1 -0
  32. package/lib/agent-cli-provider/adapters/claude.js +181 -0
  33. package/lib/agent-cli-provider/adapters/claude.js.map +1 -0
  34. package/lib/agent-cli-provider/adapters/codex-parser.d.ts +3 -0
  35. package/lib/agent-cli-provider/adapters/codex-parser.d.ts.map +1 -0
  36. package/lib/agent-cli-provider/adapters/codex-parser.js +192 -0
  37. package/lib/agent-cli-provider/adapters/codex-parser.js.map +1 -0
  38. package/lib/agent-cli-provider/adapters/codex.d.ts +3 -0
  39. package/lib/agent-cli-provider/adapters/codex.d.ts.map +1 -0
  40. package/lib/agent-cli-provider/adapters/codex.js +151 -0
  41. package/lib/agent-cli-provider/adapters/codex.js.map +1 -0
  42. package/lib/agent-cli-provider/adapters/common.d.ts +28 -0
  43. package/lib/agent-cli-provider/adapters/common.d.ts.map +1 -0
  44. package/lib/agent-cli-provider/adapters/common.js +71 -0
  45. package/lib/agent-cli-provider/adapters/common.js.map +1 -0
  46. package/lib/agent-cli-provider/adapters/gemini.d.ts +3 -0
  47. package/lib/agent-cli-provider/adapters/gemini.d.ts.map +1 -0
  48. package/lib/agent-cli-provider/adapters/gemini.js +176 -0
  49. package/lib/agent-cli-provider/adapters/gemini.js.map +1 -0
  50. package/lib/agent-cli-provider/adapters/index.d.ts +9 -0
  51. package/lib/agent-cli-provider/adapters/index.d.ts.map +1 -0
  52. package/lib/agent-cli-provider/adapters/index.js +95 -0
  53. package/lib/agent-cli-provider/adapters/index.js.map +1 -0
  54. package/lib/agent-cli-provider/adapters/opencode.d.ts +3 -0
  55. package/lib/agent-cli-provider/adapters/opencode.d.ts.map +1 -0
  56. package/lib/agent-cli-provider/adapters/opencode.js +228 -0
  57. package/lib/agent-cli-provider/adapters/opencode.js.map +1 -0
  58. package/lib/agent-cli-provider/contract-actions.d.ts +5 -0
  59. package/lib/agent-cli-provider/contract-actions.d.ts.map +1 -0
  60. package/lib/agent-cli-provider/contract-actions.js +140 -0
  61. package/lib/agent-cli-provider/contract-actions.js.map +1 -0
  62. package/lib/agent-cli-provider/contract-env.d.ts +11 -0
  63. package/lib/agent-cli-provider/contract-env.d.ts.map +1 -0
  64. package/lib/agent-cli-provider/contract-env.js +113 -0
  65. package/lib/agent-cli-provider/contract-env.js.map +1 -0
  66. package/lib/agent-cli-provider/contract-envelope.d.ts +49 -0
  67. package/lib/agent-cli-provider/contract-envelope.d.ts.map +1 -0
  68. package/lib/agent-cli-provider/contract-envelope.js +52 -0
  69. package/lib/agent-cli-provider/contract-envelope.js.map +1 -0
  70. package/lib/agent-cli-provider/contract-errors.d.ts +22 -0
  71. package/lib/agent-cli-provider/contract-errors.d.ts.map +1 -0
  72. package/lib/agent-cli-provider/contract-errors.js +71 -0
  73. package/lib/agent-cli-provider/contract-errors.js.map +1 -0
  74. package/lib/agent-cli-provider/contract-fallback.d.ts +7 -0
  75. package/lib/agent-cli-provider/contract-fallback.d.ts.map +1 -0
  76. package/lib/agent-cli-provider/contract-fallback.js +102 -0
  77. package/lib/agent-cli-provider/contract-fallback.js.map +1 -0
  78. package/lib/agent-cli-provider/contract-invoke.d.ts +5 -0
  79. package/lib/agent-cli-provider/contract-invoke.d.ts.map +1 -0
  80. package/lib/agent-cli-provider/contract-invoke.js +89 -0
  81. package/lib/agent-cli-provider/contract-invoke.js.map +1 -0
  82. package/lib/agent-cli-provider/contract-options.d.ts +3 -0
  83. package/lib/agent-cli-provider/contract-options.d.ts.map +1 -0
  84. package/lib/agent-cli-provider/contract-options.js +140 -0
  85. package/lib/agent-cli-provider/contract-options.js.map +1 -0
  86. package/lib/agent-cli-provider/contract-parse.d.ts +15 -0
  87. package/lib/agent-cli-provider/contract-parse.d.ts.map +1 -0
  88. package/lib/agent-cli-provider/contract-parse.js +81 -0
  89. package/lib/agent-cli-provider/contract-parse.js.map +1 -0
  90. package/lib/agent-cli-provider/contract-support.d.ts +18 -0
  91. package/lib/agent-cli-provider/contract-support.d.ts.map +1 -0
  92. package/lib/agent-cli-provider/contract-support.js +154 -0
  93. package/lib/agent-cli-provider/contract-support.js.map +1 -0
  94. package/lib/agent-cli-provider/contract.d.ts +13 -0
  95. package/lib/agent-cli-provider/contract.d.ts.map +1 -0
  96. package/lib/agent-cli-provider/contract.js +30 -0
  97. package/lib/agent-cli-provider/contract.js.map +1 -0
  98. package/lib/agent-cli-provider/env-safety.d.ts +11 -0
  99. package/lib/agent-cli-provider/env-safety.d.ts.map +1 -0
  100. package/lib/agent-cli-provider/env-safety.js +83 -0
  101. package/lib/agent-cli-provider/env-safety.js.map +1 -0
  102. package/lib/agent-cli-provider/errors.d.ts +5 -0
  103. package/lib/agent-cli-provider/errors.d.ts.map +1 -0
  104. package/lib/agent-cli-provider/errors.js +115 -0
  105. package/lib/agent-cli-provider/errors.js.map +1 -0
  106. package/lib/agent-cli-provider/executable.d.ts +3 -0
  107. package/lib/agent-cli-provider/executable.d.ts.map +1 -0
  108. package/lib/agent-cli-provider/executable.js +24 -0
  109. package/lib/agent-cli-provider/executable.js.map +1 -0
  110. package/lib/agent-cli-provider/index.d.ts +8 -0
  111. package/lib/agent-cli-provider/index.d.ts.map +1 -0
  112. package/lib/agent-cli-provider/index.js +31 -0
  113. package/lib/agent-cli-provider/index.js.map +1 -0
  114. package/lib/agent-cli-provider/invoke-evidence.d.ts +4 -0
  115. package/lib/agent-cli-provider/invoke-evidence.d.ts.map +1 -0
  116. package/lib/agent-cli-provider/invoke-evidence.js +17 -0
  117. package/lib/agent-cli-provider/invoke-evidence.js.map +1 -0
  118. package/lib/agent-cli-provider/json.d.ts +16 -0
  119. package/lib/agent-cli-provider/json.d.ts.map +1 -0
  120. package/lib/agent-cli-provider/json.js +110 -0
  121. package/lib/agent-cli-provider/json.js.map +1 -0
  122. package/lib/agent-cli-provider/log-prefix.d.ts +2 -0
  123. package/lib/agent-cli-provider/log-prefix.d.ts.map +1 -0
  124. package/lib/agent-cli-provider/log-prefix.js +22 -0
  125. package/lib/agent-cli-provider/log-prefix.js.map +1 -0
  126. package/lib/agent-cli-provider/process-runner.d.ts +17 -0
  127. package/lib/agent-cli-provider/process-runner.d.ts.map +1 -0
  128. package/lib/agent-cli-provider/process-runner.js +89 -0
  129. package/lib/agent-cli-provider/process-runner.js.map +1 -0
  130. package/lib/agent-cli-provider/redaction.d.ts +9 -0
  131. package/lib/agent-cli-provider/redaction.d.ts.map +1 -0
  132. package/lib/agent-cli-provider/redaction.js +227 -0
  133. package/lib/agent-cli-provider/redaction.js.map +1 -0
  134. package/lib/agent-cli-provider/schema.d.ts +5 -0
  135. package/lib/agent-cli-provider/schema.d.ts.map +1 -0
  136. package/lib/agent-cli-provider/schema.js +136 -0
  137. package/lib/agent-cli-provider/schema.js.map +1 -0
  138. package/lib/agent-cli-provider/single-agent-runtime.d.ts +15 -0
  139. package/lib/agent-cli-provider/single-agent-runtime.d.ts.map +1 -0
  140. package/lib/agent-cli-provider/single-agent-runtime.js +228 -0
  141. package/lib/agent-cli-provider/single-agent-runtime.js.map +1 -0
  142. package/lib/agent-cli-provider/types.d.ts +194 -0
  143. package/lib/agent-cli-provider/types.d.ts.map +1 -0
  144. package/lib/agent-cli-provider/types.js +12 -0
  145. package/lib/agent-cli-provider/types.js.map +1 -0
  146. package/lib/completion.js +174 -0
  147. package/lib/detached-startup.js +220 -0
  148. package/lib/docker-config.js +220 -0
  149. package/lib/git-remote-utils.js +165 -0
  150. package/lib/id-detector.js +55 -0
  151. package/lib/provider-defaults.js +62 -0
  152. package/lib/provider-detection.js +59 -0
  153. package/lib/provider-names.js +57 -0
  154. package/lib/repo-settings.js +69 -0
  155. package/lib/settings/claude-auth.js +78 -0
  156. package/lib/settings.js +542 -0
  157. package/lib/start-cluster.js +321 -0
  158. package/lib/stream-json-parser.js +67 -0
  159. package/package.json +162 -0
  160. package/scripts/fix-node-pty-permissions.js +75 -0
  161. package/scripts/record-demo.sh +279 -0
  162. package/scripts/setup-merge-queue.sh +170 -0
  163. package/scripts/test-install.sh +40 -0
  164. package/scripts/validate-templates.js +107 -0
  165. package/src/agent/agent-config.js +266 -0
  166. package/src/agent/agent-context-builder.js +189 -0
  167. package/src/agent/agent-context-sections.js +338 -0
  168. package/src/agent/agent-context-sources.js +147 -0
  169. package/src/agent/agent-hook-executor.js +721 -0
  170. package/src/agent/agent-input-injector.js +141 -0
  171. package/src/agent/agent-lifecycle.js +982 -0
  172. package/src/agent/agent-quality-gate-schema.js +93 -0
  173. package/src/agent/agent-quality-gates-context.js +51 -0
  174. package/src/agent/agent-stuck-detector.js +256 -0
  175. package/src/agent/agent-task-executor.js +2028 -0
  176. package/src/agent/agent-trigger-evaluator.js +67 -0
  177. package/src/agent/context-metrics.js +160 -0
  178. package/src/agent/context-pack-builder.js +367 -0
  179. package/src/agent/context-replay-policy.js +51 -0
  180. package/src/agent/guidance-queue.js +77 -0
  181. package/src/agent/output-extraction.js +367 -0
  182. package/src/agent/output-reformatter.js +175 -0
  183. package/src/agent/pr-verification.js +653 -0
  184. package/src/agent/rate-limit-backoff.js +82 -0
  185. package/src/agent/schema-utils.js +146 -0
  186. package/src/agent/validation-platform.js +35 -0
  187. package/src/agent-cli-provider/adapters/claude-parser.ts +133 -0
  188. package/src/agent-cli-provider/adapters/claude-recovery.ts +203 -0
  189. package/src/agent-cli-provider/adapters/claude.ts +247 -0
  190. package/src/agent-cli-provider/adapters/codex-parser.ts +211 -0
  191. package/src/agent-cli-provider/adapters/codex.ts +217 -0
  192. package/src/agent-cli-provider/adapters/common.ts +124 -0
  193. package/src/agent-cli-provider/adapters/gemini.ts +243 -0
  194. package/src/agent-cli-provider/adapters/index.ts +126 -0
  195. package/src/agent-cli-provider/adapters/opencode.ts +286 -0
  196. package/src/agent-cli-provider/contract-actions.ts +150 -0
  197. package/src/agent-cli-provider/contract-env.ts +111 -0
  198. package/src/agent-cli-provider/contract-envelope.ts +110 -0
  199. package/src/agent-cli-provider/contract-errors.ts +66 -0
  200. package/src/agent-cli-provider/contract-fallback.ts +121 -0
  201. package/src/agent-cli-provider/contract-invoke.ts +104 -0
  202. package/src/agent-cli-provider/contract-options.ts +173 -0
  203. package/src/agent-cli-provider/contract-parse.ts +94 -0
  204. package/src/agent-cli-provider/contract-support.ts +167 -0
  205. package/src/agent-cli-provider/contract.ts +56 -0
  206. package/src/agent-cli-provider/env-safety.ts +82 -0
  207. package/src/agent-cli-provider/errors.ts +122 -0
  208. package/src/agent-cli-provider/executable.ts +24 -0
  209. package/src/agent-cli-provider/index.ts +83 -0
  210. package/src/agent-cli-provider/invoke-evidence.ts +18 -0
  211. package/src/agent-cli-provider/json.ts +114 -0
  212. package/src/agent-cli-provider/log-prefix.ts +20 -0
  213. package/src/agent-cli-provider/process-runner.ts +145 -0
  214. package/src/agent-cli-provider/redaction.ts +282 -0
  215. package/src/agent-cli-provider/schema.ts +115 -0
  216. package/src/agent-cli-provider/single-agent-runtime.ts +311 -0
  217. package/src/agent-cli-provider/types.ts +237 -0
  218. package/src/agent-wrapper.js +615 -0
  219. package/src/agents/git-pusher-template.js +705 -0
  220. package/src/attach/attach-client.js +438 -0
  221. package/src/attach/attach-server.js +543 -0
  222. package/src/attach/index.js +37 -0
  223. package/src/attach/protocol.js +220 -0
  224. package/src/attach/ring-buffer.js +121 -0
  225. package/src/attach/send-input.js +88 -0
  226. package/src/attach/socket-discovery.js +267 -0
  227. package/src/claude-task-runner.js +661 -0
  228. package/src/config-router.js +89 -0
  229. package/src/config-validator.js +2202 -0
  230. package/src/copy-worker.js +43 -0
  231. package/src/guidance-topics.js +10 -0
  232. package/src/input-helpers.js +65 -0
  233. package/src/isolation-manager.js +1734 -0
  234. package/src/issue-providers/README.md +305 -0
  235. package/src/issue-providers/azure-devops-provider.js +307 -0
  236. package/src/issue-providers/base-provider.js +232 -0
  237. package/src/issue-providers/github-provider.js +210 -0
  238. package/src/issue-providers/gitlab-provider.js +262 -0
  239. package/src/issue-providers/index.js +196 -0
  240. package/src/issue-providers/jira-provider.js +260 -0
  241. package/src/ledger.js +692 -0
  242. package/src/lib/gc.js +232 -0
  243. package/src/lib/safe-exec.js +88 -0
  244. package/src/logic-engine.js +201 -0
  245. package/src/message-buffer.js +81 -0
  246. package/src/message-bus-bridge.js +144 -0
  247. package/src/message-bus.js +256 -0
  248. package/src/name-generator.js +232 -0
  249. package/src/orchestrator.js +3924 -0
  250. package/src/preflight.js +712 -0
  251. package/src/process-metrics.js +608 -0
  252. package/src/providers/anthropic/index.js +3 -0
  253. package/src/providers/base-provider.js +355 -0
  254. package/src/providers/capabilities.js +60 -0
  255. package/src/providers/google/index.js +3 -0
  256. package/src/providers/index.js +293 -0
  257. package/src/providers/openai/index.js +3 -0
  258. package/src/providers/opencode/index.js +3 -0
  259. package/src/quality-gates.js +143 -0
  260. package/src/schemas/sub-cluster.js +208 -0
  261. package/src/state-snapshot.js +398 -0
  262. package/src/state-snapshotter.js +142 -0
  263. package/src/status-footer.js +1026 -0
  264. package/src/sub-cluster-wrapper.js +693 -0
  265. package/src/task-runner.js +30 -0
  266. package/src/template-resolver.js +425 -0
  267. package/src/template-validation/index.js +338 -0
  268. package/src/template-validation/simulate-consensus-gates.js +324 -0
  269. package/src/template-validation/simulate-random-topology.js +541 -0
  270. package/src/template-validation/simulate-two-stage-validation.js +270 -0
  271. package/src/worktree-claude-config.js +135 -0
  272. package/src/worktree-tooling-env.js +150 -0
  273. package/task-lib/attachable-watcher.js +381 -0
  274. package/task-lib/commands/clean.js +50 -0
  275. package/task-lib/commands/episodes.js +105 -0
  276. package/task-lib/commands/get-log-path.js +23 -0
  277. package/task-lib/commands/kill.js +32 -0
  278. package/task-lib/commands/list.js +105 -0
  279. package/task-lib/commands/logs.js +439 -0
  280. package/task-lib/commands/resume.js +42 -0
  281. package/task-lib/commands/run.js +57 -0
  282. package/task-lib/commands/schedule.js +105 -0
  283. package/task-lib/commands/scheduler-cmd.js +96 -0
  284. package/task-lib/commands/schedules.js +148 -0
  285. package/task-lib/commands/status.js +44 -0
  286. package/task-lib/commands/unschedule.js +16 -0
  287. package/task-lib/completion.js +9 -0
  288. package/task-lib/config.js +11 -0
  289. package/task-lib/name-generator.js +230 -0
  290. package/task-lib/package.json +3 -0
  291. package/task-lib/provider-helper-runtime.js +29 -0
  292. package/task-lib/runner.js +190 -0
  293. package/task-lib/scheduler.js +252 -0
  294. package/task-lib/store.js +529 -0
  295. package/task-lib/watcher.js +305 -0
@@ -0,0 +1,196 @@
1
+ /**
2
+ * Issue Provider Registry
3
+ *
4
+ * Manages issue provider registration and auto-detection
5
+ */
6
+
7
+ const GitHubProvider = require('./github-provider');
8
+ const GitLabProvider = require('./gitlab-provider');
9
+ const JiraProvider = require('./jira-provider');
10
+ const AzureDevOpsProvider = require('./azure-devops-provider');
11
+ const { detectGitContext } = require('../../lib/git-remote-utils');
12
+
13
+ /** @type {Map<string, typeof IssueProvider>} */
14
+ const providers = new Map();
15
+
16
+ /**
17
+ * Register a provider class
18
+ * @param {typeof IssueProvider} ProviderClass
19
+ */
20
+ function registerProvider(ProviderClass) {
21
+ if (!ProviderClass.id) {
22
+ throw new Error(`Provider ${ProviderClass.name} must define static id property`);
23
+ }
24
+ providers.set(ProviderClass.id, ProviderClass);
25
+ }
26
+
27
+ /**
28
+ * Detect which provider matches the input
29
+ * Automatically detects provider from git remote when in a git repository
30
+ *
31
+ * @param {string} input - User input (URL, issue key, number)
32
+ * @param {Object} settings - User settings
33
+ * @param {string|null} forceProvider - Force specific provider (from CLI flag)
34
+ * @param {Object|null|undefined} [gitContextOverride] - Override git context (for testing)
35
+ * - undefined: auto-detect from git remote (default)
36
+ * - null: explicitly no git context
37
+ * - object: use provided git context
38
+ * @returns {typeof IssueProvider|null}
39
+ */
40
+ function detectProvider(input, settings, forceProvider = null, gitContextOverride = undefined) {
41
+ // Force flag takes precedence
42
+ if (forceProvider) {
43
+ return providers.get(forceProvider) || null;
44
+ }
45
+
46
+ // Use provided gitContext or auto-detect
47
+ const gitContext = gitContextOverride === undefined ? detectGitContext() : gitContextOverride;
48
+
49
+ // Auto-detect by checking each provider's detectIdentifier
50
+ for (const ProviderClass of providers.values()) {
51
+ if (ProviderClass.detectIdentifier(input, settings, gitContext)) {
52
+ return ProviderClass;
53
+ }
54
+ }
55
+
56
+ return null;
57
+ }
58
+
59
+ /**
60
+ * Get provider class by ID
61
+ * @param {string} providerId - Provider identifier
62
+ * @returns {typeof IssueProvider|null}
63
+ */
64
+ function getProvider(providerId) {
65
+ return providers.get(providerId) || null;
66
+ }
67
+
68
+ /**
69
+ * List all registered provider IDs
70
+ * @returns {string[]}
71
+ */
72
+ function listProviders() {
73
+ return Array.from(providers.keys());
74
+ }
75
+
76
+ /**
77
+ * List providers that support PR/MR creation
78
+ * @returns {string[]}
79
+ */
80
+ function listPRProviders() {
81
+ return Array.from(providers.values())
82
+ .filter((p) => p.supportsPR())
83
+ .map((p) => p.id);
84
+ }
85
+
86
+ /**
87
+ * Determine which git platform to create PR/MR on.
88
+ * ALWAYS uses git remote context, NEVER the issue provider.
89
+ *
90
+ * This is the unified replacement for platform-detector.js
91
+ *
92
+ * @param {string} [cwd=process.cwd()] - Working directory
93
+ * @returns {string} Platform ID ('github', 'gitlab', 'azure-devops')
94
+ * @throws {Error} If platform cannot be determined or doesn't support PRs
95
+ *
96
+ * @example
97
+ * // In a GitHub repo
98
+ * getPlatformForPR() // → 'github'
99
+ *
100
+ * @example
101
+ * // In a GitLab repo with Jira issue
102
+ * getPlatformForPR() // → 'gitlab' (creates GitLab MR, not related to Jira)
103
+ */
104
+ function getPlatformForPR(cwd = process.cwd()) {
105
+ const gitContext = detectGitContext(cwd);
106
+
107
+ if (!gitContext?.provider) {
108
+ throw new Error(
109
+ 'Cannot determine git platform for --pr mode. ' +
110
+ 'Ensure you are in a git repository with a remote URL from GitHub, GitLab, or Azure DevOps.'
111
+ );
112
+ }
113
+
114
+ const platform = gitContext.provider;
115
+ const ProviderClass = providers.get(platform);
116
+
117
+ if (!ProviderClass || !ProviderClass.supportsPR()) {
118
+ const supported = listPRProviders().join(', ');
119
+ throw new Error(
120
+ `Platform '${platform}' does not support --pr mode. Supported platforms: ${supported}`
121
+ );
122
+ }
123
+
124
+ return platform;
125
+ }
126
+
127
+ /**
128
+ * Get PR tool info for a platform
129
+ * @param {string} platform - Platform ID
130
+ * @returns {{ name: string, checkCmd: string, installHint: string, displayName: string }|null}
131
+ */
132
+ function getPRToolForPlatform(platform) {
133
+ const ProviderClass = providers.get(platform);
134
+ return ProviderClass?.getPRTool() || null;
135
+ }
136
+
137
+ /**
138
+ * Get aggregated settings schema from all issue providers
139
+ * @returns {Object.<string, Object>} Combined settings schema
140
+ */
141
+ function getIssueProviderSettingsSchema() {
142
+ const schema = {};
143
+ for (const ProviderClass of providers.values()) {
144
+ Object.assign(schema, ProviderClass.getSettingsSchema());
145
+ }
146
+ return schema;
147
+ }
148
+
149
+ /**
150
+ * Get default values for all issue provider settings
151
+ * @returns {Object.<string, any>} Default values keyed by setting name
152
+ */
153
+ function getIssueProviderSettingsDefaults() {
154
+ const defaults = {};
155
+ const schema = getIssueProviderSettingsSchema();
156
+ for (const [key, config] of Object.entries(schema)) {
157
+ defaults[key] = config.default;
158
+ }
159
+ return defaults;
160
+ }
161
+
162
+ /**
163
+ * Validate an issue provider setting
164
+ * Delegates to the appropriate provider's validateSetting method
165
+ * @param {string} key - Setting key
166
+ * @param {any} value - Setting value
167
+ * @returns {string|null|undefined} Error message if invalid, null if valid, undefined if not an issue provider setting
168
+ */
169
+ function validateIssueProviderSetting(key, value) {
170
+ for (const ProviderClass of providers.values()) {
171
+ const result = ProviderClass.validateSetting(key, value);
172
+ if (result !== undefined) {
173
+ return result;
174
+ }
175
+ }
176
+ return undefined; // Not an issue provider setting
177
+ }
178
+
179
+ // Auto-register providers on module load
180
+ registerProvider(GitHubProvider);
181
+ registerProvider(GitLabProvider);
182
+ registerProvider(JiraProvider);
183
+ registerProvider(AzureDevOpsProvider);
184
+
185
+ module.exports = {
186
+ registerProvider,
187
+ detectProvider,
188
+ getProvider,
189
+ listProviders,
190
+ listPRProviders,
191
+ getPlatformForPR,
192
+ getPRToolForPlatform,
193
+ getIssueProviderSettingsSchema,
194
+ getIssueProviderSettingsDefaults,
195
+ validateIssueProviderSetting,
196
+ };
@@ -0,0 +1,260 @@
1
+ /**
2
+ * Jira Provider - Fetch issues from Jira via jira CLI (go-jira)
3
+ * Supports both Jira Cloud (*.atlassian.net) and self-hosted (Server/Data Center)
4
+ */
5
+
6
+ const IssueProvider = require('./base-provider');
7
+ const { execSync } = require('../lib/safe-exec');
8
+
9
+ const AUTH_CHECK_TIMEOUT_MS = 2000;
10
+
11
+ class JiraProvider extends IssueProvider {
12
+ static id = 'jira';
13
+ static displayName = 'Jira';
14
+
15
+ /**
16
+ * Detect Jira issue keys and URLs
17
+ * Matches:
18
+ * - Jira Cloud URLs (*.atlassian.net)
19
+ * - Self-hosted Jira URLs (via jiraInstance setting)
20
+ * - Jira issue keys (KEY-123 format)
21
+ * - Bare numbers when defaultIssueSource=jira (requires jiraProject setting)
22
+ *
23
+ * Note: Jira doesn't use git context since it's not a git hosting platform.
24
+ * Git context will never match 'jira', so this provider only activates via
25
+ * explicit Jira URLs, Jira issue keys, or settings.
26
+ *
27
+ * @param {string} input - Issue identifier (URL, key, or number)
28
+ * @param {Object} settings - User settings
29
+ * @param {Object|null} gitContext - Git context (unused for Jira, but kept for API consistency)
30
+ * @returns {boolean} True if this provider should handle the input
31
+ */
32
+ static detectIdentifier(input, settings, gitContext = null) {
33
+ // Jira Cloud URLs
34
+ if (/atlassian\.net\/browse\/[A-Z][A-Z0-9]+-\d+/.test(input)) {
35
+ return true;
36
+ }
37
+
38
+ // Self-hosted Jira URLs
39
+ if (
40
+ settings.jiraInstance &&
41
+ input.includes(settings.jiraInstance) &&
42
+ /\/browse\/[A-Z][A-Z0-9]+-\d+/.test(input)
43
+ ) {
44
+ return true;
45
+ }
46
+
47
+ // Jira issue key pattern (KEY-123)
48
+ if (/^[A-Z][A-Z0-9]+-\d+$/.test(input)) {
49
+ return true;
50
+ }
51
+
52
+ // Bare numbers - use shared priority cascade logic
53
+ // Jira requires jiraProject setting to convert bare numbers to issue keys
54
+ // Note: gitContext check will never match 'jira' since Jira isn't a git host
55
+ return IssueProvider.detectBareNumber(input, settings, gitContext, 'jira', {
56
+ requiredSettings: ['jiraProject'],
57
+ });
58
+ }
59
+
60
+ static getRequiredTool() {
61
+ return {
62
+ name: 'jira',
63
+ checkCmd: 'jira version',
64
+ installHint: 'Install jira-cli: brew install go-jira (or https://github.com/go-jira/jira)',
65
+ };
66
+ }
67
+
68
+ /**
69
+ * Check jira CLI authentication
70
+ * go-jira uses config files (~/.jira.d/) rather than explicit auth commands
71
+ */
72
+ static checkAuth() {
73
+ try {
74
+ // go-jira uses 'jira session' to verify authentication
75
+ // If not configured, it fails with endpoint/login errors
76
+ execSync('jira session', { encoding: 'utf8', stdio: 'pipe', timeout: AUTH_CHECK_TIMEOUT_MS });
77
+ return { authenticated: true, error: null, recovery: [] };
78
+ } catch (err) {
79
+ const stderr = err.stderr || err.message || '';
80
+
81
+ if (err.code === 'ENOENT' || stderr.includes('command not found')) {
82
+ return {
83
+ authenticated: false,
84
+ error: 'Jira CLI not installed',
85
+ recovery: [
86
+ 'Install jira CLI: https://github.com/go-jira/jira',
87
+ 'Then verify: jira version',
88
+ ],
89
+ };
90
+ }
91
+
92
+ if (stderr.includes('Command timed out')) {
93
+ return {
94
+ authenticated: false,
95
+ error: 'jira session timed out',
96
+ recovery: ['Retry: jira session', 'Check ~/.jira.d/config.yml for endpoint/login'],
97
+ };
98
+ }
99
+
100
+ // go-jira has various error patterns for auth issues
101
+ if (
102
+ stderr.includes('endpoint') ||
103
+ stderr.includes('login') ||
104
+ stderr.includes('authentication') ||
105
+ stderr.includes('401')
106
+ ) {
107
+ return {
108
+ authenticated: false,
109
+ error: 'Jira CLI not configured',
110
+ recovery: [
111
+ 'Create ~/.jira.d/config.yml with your Jira endpoint',
112
+ 'See: https://github.com/go-jira/jira#configuration',
113
+ 'Example config:\n endpoint: https://yourcompany.atlassian.net\n login: your-email@company.com',
114
+ 'Then verify: jira session',
115
+ ],
116
+ };
117
+ }
118
+
119
+ // If command just doesn't exist or times out, it's likely not configured
120
+ if (stderr.includes('command not found') || stderr.includes('ETIMEDOUT')) {
121
+ return {
122
+ authenticated: false,
123
+ error: 'Jira CLI not configured',
124
+ recovery: [
125
+ 'Configure ~/.jira.d/config.yml',
126
+ 'See: https://github.com/go-jira/jira#configuration',
127
+ ],
128
+ };
129
+ }
130
+
131
+ // Default: assume not authenticated
132
+ return {
133
+ authenticated: false,
134
+ error: stderr.trim() || 'Jira CLI not configured or authentication failed',
135
+ recovery: [
136
+ 'Create ~/.jira.d/config.yml with your Jira endpoint',
137
+ 'See: https://github.com/go-jira/jira#configuration',
138
+ ],
139
+ };
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Jira-specific settings schema
145
+ */
146
+ static getSettingsSchema() {
147
+ return {
148
+ jiraInstance: {
149
+ type: 'string',
150
+ nullable: true,
151
+ default: null,
152
+ description: "Self-hosted Jira URL (e.g., 'jira.company.com')",
153
+ },
154
+ jiraProject: {
155
+ type: 'string',
156
+ nullable: true,
157
+ default: null,
158
+ description: "Default Jira project key for bare numbers (e.g., 'PROJ')",
159
+ pattern: /^[A-Z][A-Z0-9]*$/,
160
+ patternMsg: 'jiraProject must be a valid Jira project key (e.g., PROJ, ABC)',
161
+ },
162
+ };
163
+ }
164
+
165
+ fetchIssue(identifier, settings) {
166
+ try {
167
+ const issueKey = this._extractIssueKey(identifier, settings);
168
+
169
+ // Fetch issue using jira CLI
170
+ const cmd = `jira issue view ${issueKey} --template json`;
171
+ const output = execSync(cmd, { encoding: 'utf8' });
172
+ const issue = JSON.parse(output);
173
+
174
+ return this._parseIssue(issue);
175
+ } catch (error) {
176
+ throw new Error(`Failed to fetch Jira issue: ${error.message}`);
177
+ }
178
+ }
179
+
180
+ /**
181
+ * Extract Jira issue key from URL or return as-is
182
+ * @private
183
+ */
184
+ _extractIssueKey(identifier, settings) {
185
+ // URL format: https://company.atlassian.net/browse/KEY-123
186
+ const urlMatch = identifier.match(/\/browse\/([A-Z][A-Z0-9]+-\d+)/);
187
+ if (urlMatch) {
188
+ return urlMatch[1];
189
+ }
190
+
191
+ // Bare number: construct from jiraProject setting
192
+ if (/^\d+$/.test(identifier) && settings.jiraProject) {
193
+ return `${settings.jiraProject}-${identifier}`;
194
+ }
195
+
196
+ // Assume it's already a key
197
+ return identifier;
198
+ }
199
+
200
+ /**
201
+ * Parse Jira issue into standardized InputData format
202
+ * @private
203
+ */
204
+ _parseIssue(issue) {
205
+ const fields = issue.fields || {};
206
+ const key = issue.key;
207
+ const summary = fields.summary || '';
208
+ const description = fields.description || '';
209
+ const labels = fields.labels || [];
210
+ const comments = fields.comment?.comments || [];
211
+
212
+ let context = `# Jira Issue ${key}\n\n`;
213
+ context += `## Title\n${summary}\n\n`;
214
+
215
+ if (description) {
216
+ context += `## Description\n${description}\n\n`;
217
+ }
218
+
219
+ if (labels.length > 0) {
220
+ context += `## Labels\n`;
221
+ context += labels.map((l) => `- ${l}`).join('\n');
222
+ context += '\n\n';
223
+ }
224
+
225
+ if (comments.length > 0) {
226
+ context += `## Comments\n\n`;
227
+ for (const comment of comments) {
228
+ const author = comment.author?.displayName || comment.author?.name || 'unknown';
229
+ context += `### ${author} (${comment.created})\n`;
230
+ context += `${comment.body}\n\n`;
231
+ }
232
+ }
233
+
234
+ // Map Jira labels to GitHub format
235
+ const mappedLabels = labels.map((name) => ({ name }));
236
+
237
+ // Map Jira comments to GitHub format
238
+ const mappedComments = comments.map((comment) => ({
239
+ author: { login: comment.author?.displayName || comment.author?.name || 'unknown' },
240
+ createdAt: comment.created,
241
+ body: comment.body,
242
+ }));
243
+
244
+ // Extract issue number from key (KEY-123 → 123)
245
+ const numberMatch = key.match(/-(\d+)$/);
246
+ const number = numberMatch ? parseInt(numberMatch[1], 10) : null;
247
+
248
+ return {
249
+ number,
250
+ title: summary,
251
+ body: description,
252
+ labels: mappedLabels,
253
+ comments: mappedComments,
254
+ url: fields.self || null,
255
+ context,
256
+ };
257
+ }
258
+ }
259
+
260
+ module.exports = JiraProvider;