@ob1-sg/horizon 0.1.10 → 0.1.11

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 (153) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +43 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/config.d.ts +10 -0
  6. package/dist/config.d.ts.map +1 -0
  7. package/dist/config.js +293 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/index.d.ts +4 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +629 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/lib/__tests__/attachment-downloader.test.d.ts +2 -0
  14. package/dist/lib/__tests__/attachment-downloader.test.d.ts.map +1 -0
  15. package/dist/lib/__tests__/attachment-downloader.test.js +163 -0
  16. package/dist/lib/__tests__/attachment-downloader.test.js.map +1 -0
  17. package/dist/lib/__tests__/cli-detection.test.d.ts +2 -0
  18. package/dist/lib/__tests__/cli-detection.test.d.ts.map +1 -0
  19. package/dist/lib/__tests__/cli-detection.test.js +119 -0
  20. package/dist/lib/__tests__/cli-detection.test.js.map +1 -0
  21. package/dist/lib/__tests__/config.test.d.ts +2 -0
  22. package/dist/lib/__tests__/config.test.d.ts.map +1 -0
  23. package/dist/lib/__tests__/config.test.js +291 -0
  24. package/dist/lib/__tests__/config.test.js.map +1 -0
  25. package/dist/lib/__tests__/gcp.test.d.ts +2 -0
  26. package/dist/lib/__tests__/gcp.test.d.ts.map +1 -0
  27. package/dist/lib/__tests__/gcp.test.js +104 -0
  28. package/dist/lib/__tests__/gcp.test.js.map +1 -0
  29. package/dist/lib/__tests__/git.test.d.ts +2 -0
  30. package/dist/lib/__tests__/git.test.d.ts.map +1 -0
  31. package/dist/lib/__tests__/git.test.js +62 -0
  32. package/dist/lib/__tests__/git.test.js.map +1 -0
  33. package/dist/lib/__tests__/linear-quick-check.test.d.ts +2 -0
  34. package/dist/lib/__tests__/linear-quick-check.test.d.ts.map +1 -0
  35. package/dist/lib/__tests__/linear-quick-check.test.js +152 -0
  36. package/dist/lib/__tests__/linear-quick-check.test.js.map +1 -0
  37. package/dist/lib/__tests__/loop-instance-name.test.d.ts +2 -0
  38. package/dist/lib/__tests__/loop-instance-name.test.d.ts.map +1 -0
  39. package/dist/lib/__tests__/loop-instance-name.test.js +90 -0
  40. package/dist/lib/__tests__/loop-instance-name.test.js.map +1 -0
  41. package/dist/lib/__tests__/output-logger.test.d.ts +2 -0
  42. package/dist/lib/__tests__/output-logger.test.d.ts.map +1 -0
  43. package/dist/lib/__tests__/output-logger.test.js +136 -0
  44. package/dist/lib/__tests__/output-logger.test.js.map +1 -0
  45. package/dist/lib/__tests__/prompts.test.d.ts +2 -0
  46. package/dist/lib/__tests__/prompts.test.d.ts.map +1 -0
  47. package/dist/lib/__tests__/prompts.test.js +70 -0
  48. package/dist/lib/__tests__/prompts.test.js.map +1 -0
  49. package/dist/lib/__tests__/provider.test.d.ts +2 -0
  50. package/dist/lib/__tests__/provider.test.d.ts.map +1 -0
  51. package/dist/lib/__tests__/provider.test.js +89 -0
  52. package/dist/lib/__tests__/provider.test.js.map +1 -0
  53. package/dist/lib/__tests__/rate-limit.test.d.ts +2 -0
  54. package/dist/lib/__tests__/rate-limit.test.d.ts.map +1 -0
  55. package/dist/lib/__tests__/rate-limit.test.js +275 -0
  56. package/dist/lib/__tests__/rate-limit.test.js.map +1 -0
  57. package/dist/lib/__tests__/readline.test.d.ts +2 -0
  58. package/dist/lib/__tests__/readline.test.d.ts.map +1 -0
  59. package/dist/lib/__tests__/readline.test.js +55 -0
  60. package/dist/lib/__tests__/readline.test.js.map +1 -0
  61. package/dist/lib/__tests__/stats-logger.test.d.ts +2 -0
  62. package/dist/lib/__tests__/stats-logger.test.d.ts.map +1 -0
  63. package/dist/lib/__tests__/stats-logger.test.js +297 -0
  64. package/dist/lib/__tests__/stats-logger.test.js.map +1 -0
  65. package/dist/lib/__tests__/update-checker.test.d.ts +2 -0
  66. package/dist/lib/__tests__/update-checker.test.d.ts.map +1 -0
  67. package/dist/lib/__tests__/update-checker.test.js +141 -0
  68. package/dist/lib/__tests__/update-checker.test.js.map +1 -0
  69. package/dist/lib/__tests__/version.test.d.ts +2 -0
  70. package/dist/lib/__tests__/version.test.d.ts.map +1 -0
  71. package/dist/lib/__tests__/version.test.js +51 -0
  72. package/dist/lib/__tests__/version.test.js.map +1 -0
  73. package/dist/lib/attachment-downloader.d.ts +26 -0
  74. package/dist/lib/attachment-downloader.d.ts.map +1 -0
  75. package/dist/lib/attachment-downloader.js +259 -0
  76. package/dist/lib/attachment-downloader.js.map +1 -0
  77. package/dist/lib/claude.d.ts +6 -0
  78. package/dist/lib/claude.d.ts.map +1 -0
  79. package/dist/lib/claude.js +358 -0
  80. package/dist/lib/claude.js.map +1 -0
  81. package/dist/lib/cli-detection.d.ts +25 -0
  82. package/dist/lib/cli-detection.d.ts.map +1 -0
  83. package/dist/lib/cli-detection.js +53 -0
  84. package/dist/lib/cli-detection.js.map +1 -0
  85. package/dist/lib/codex.d.ts +4 -0
  86. package/dist/lib/codex.d.ts.map +1 -0
  87. package/dist/lib/codex.js +285 -0
  88. package/dist/lib/codex.js.map +1 -0
  89. package/dist/lib/gcp.d.ts +21 -0
  90. package/dist/lib/gcp.d.ts.map +1 -0
  91. package/dist/lib/gcp.js +96 -0
  92. package/dist/lib/gcp.js.map +1 -0
  93. package/dist/lib/git.d.ts +3 -0
  94. package/dist/lib/git.d.ts.map +1 -0
  95. package/dist/lib/git.js +24 -0
  96. package/dist/lib/git.js.map +1 -0
  97. package/dist/lib/init-project.d.ts +13 -0
  98. package/dist/lib/init-project.d.ts.map +1 -0
  99. package/dist/lib/init-project.js +420 -0
  100. package/dist/lib/init-project.js.map +1 -0
  101. package/dist/lib/linear-api.d.ts +32 -0
  102. package/dist/lib/linear-api.d.ts.map +1 -0
  103. package/dist/lib/linear-api.js +267 -0
  104. package/dist/lib/linear-api.js.map +1 -0
  105. package/dist/lib/linear-quick-check.d.ts +13 -0
  106. package/dist/lib/linear-quick-check.d.ts.map +1 -0
  107. package/dist/lib/linear-quick-check.js +61 -0
  108. package/dist/lib/linear-quick-check.js.map +1 -0
  109. package/dist/lib/loop-instance-name.d.ts +29 -0
  110. package/dist/lib/loop-instance-name.d.ts.map +1 -0
  111. package/dist/lib/loop-instance-name.js +105 -0
  112. package/dist/lib/loop-instance-name.js.map +1 -0
  113. package/dist/lib/output-logger.d.ts +23 -0
  114. package/dist/lib/output-logger.d.ts.map +1 -0
  115. package/dist/lib/output-logger.js +104 -0
  116. package/dist/lib/output-logger.js.map +1 -0
  117. package/dist/lib/prompts.d.ts +17 -0
  118. package/dist/lib/prompts.d.ts.map +1 -0
  119. package/dist/lib/prompts.js +65 -0
  120. package/dist/lib/prompts.js.map +1 -0
  121. package/dist/lib/provider.d.ts +32 -0
  122. package/dist/lib/provider.d.ts.map +1 -0
  123. package/dist/lib/provider.js +27 -0
  124. package/dist/lib/provider.js.map +1 -0
  125. package/dist/lib/rate-limit.d.ts +14 -0
  126. package/dist/lib/rate-limit.d.ts.map +1 -0
  127. package/dist/lib/rate-limit.js +154 -0
  128. package/dist/lib/rate-limit.js.map +1 -0
  129. package/dist/lib/readline.d.ts +4 -0
  130. package/dist/lib/readline.d.ts.map +1 -0
  131. package/dist/lib/readline.js +39 -0
  132. package/dist/lib/readline.js.map +1 -0
  133. package/dist/lib/setup.d.ts +123 -0
  134. package/dist/lib/setup.d.ts.map +1 -0
  135. package/dist/lib/setup.js +492 -0
  136. package/dist/lib/setup.js.map +1 -0
  137. package/dist/lib/stats-logger.d.ts +92 -0
  138. package/dist/lib/stats-logger.d.ts.map +1 -0
  139. package/dist/lib/stats-logger.js +258 -0
  140. package/dist/lib/stats-logger.js.map +1 -0
  141. package/dist/lib/update-checker.d.ts +17 -0
  142. package/dist/lib/update-checker.d.ts.map +1 -0
  143. package/dist/lib/update-checker.js +140 -0
  144. package/dist/lib/update-checker.js.map +1 -0
  145. package/dist/lib/version.d.ts +10 -0
  146. package/dist/lib/version.d.ts.map +1 -0
  147. package/dist/lib/version.js +37 -0
  148. package/dist/lib/version.js.map +1 -0
  149. package/dist/types.d.ts +92 -0
  150. package/dist/types.d.ts.map +1 -0
  151. package/dist/types.js +3 -0
  152. package/dist/types.js.map +1 -0
  153. package/package.json +1 -1
package/dist/index.js ADDED
@@ -0,0 +1,629 @@
1
+ import { getConfig, isGitRepository } from './config.js';
2
+ import { sleep, executeWithRateLimitRetry } from './lib/rate-limit.js';
3
+ import { loadPrompt } from './lib/prompts.js';
4
+ import { getCurrentBranch } from './lib/git.js';
5
+ import { generatePodName } from './lib/loop-instance-name.js';
6
+ import { initLoopLogger, getCurrentOutputDir } from './lib/output-logger.js';
7
+ import { initLoopStats, logAgentStats, finalizeLoopStats } from './lib/stats-logger.js';
8
+ import { createProvider } from './lib/provider.js';
9
+ import { extractLinearUrls, downloadIssueAttachments } from './lib/attachment-downloader.js';
10
+ import { createLinearClientWithSignedUrls, getIssueDescription } from './lib/linear-api.js';
11
+ import { isRunningOnGcp, stopGcpInstance } from './lib/gcp.js';
12
+ import { checkForUncompletedTickets } from './lib/linear-quick-check.js';
13
+ import { getVersion } from './lib/version.js';
14
+ import { checkForUpdates, displayUpdateNotification } from './lib/update-checker.js';
15
+ import { ensureHorizonDir, ensureHorizonDocsDir, ensureGitignore, loadExistingConfig, saveEnvConfig, saveMcpConfig, copyPromptsToProject, checkAndDisplayCliAvailability, autoSelectProvider, validateLinearKey, fetchLinearTeams, checkLinearStatuses, createLinearStatuses, checkCodexLinearMcp, createPromptInterface, promptSecret, promptSelect, } from './lib/setup.js';
16
+ // Import providers to register them
17
+ import './lib/claude.js';
18
+ import './lib/codex.js';
19
+ /**
20
+ * Extracts the issue identifier (e.g., RSK-39) from Agent 1's output.
21
+ * Agent 1 outputs this in the format "**Identifier**: RSK-39" or similar.
22
+ */
23
+ function extractIssueIdentifier(agent1Output) {
24
+ // Try various patterns Agent 1 might use
25
+ const patterns = [
26
+ /\*\*Identifier\*\*:\s*([A-Z]+-\d+)/i,
27
+ /\*\*Issue Identifier\*\*:\s*([A-Z]+-\d+)/i,
28
+ /Issue ID[^:]*:\s*[^\n]*\n[^*]*\*\*Identifier\*\*:\s*([A-Z]+-\d+)/i,
29
+ /Identifier:\s*([A-Z]+-\d+)/i,
30
+ /Branch:\s*horizon\/([A-Z]+-\d+)/i,
31
+ /\b([A-Z]+-\d+)\b/, // Fallback: any ticket-like pattern
32
+ ];
33
+ for (const pattern of patterns) {
34
+ const match = agent1Output.match(pattern);
35
+ if (match) {
36
+ return match[1];
37
+ }
38
+ }
39
+ return null;
40
+ }
41
+ async function runLoop(podName, iteration) {
42
+ const config = getConfig();
43
+ // Initialize output logger for this loop iteration
44
+ // Pod name persists across all loops in this Horizon session
45
+ initLoopLogger(podName, iteration);
46
+ // Initialize stats tracking for this loop iteration
47
+ initLoopStats(podName, iteration);
48
+ console.log(`\n${'='.repeat(24)} LOOP ${iteration} ${'='.repeat(24)}`);
49
+ console.log(`Pod: ${podName}`);
50
+ console.log(`Provider: ${config.provider}`);
51
+ if (config.provider === 'codex') {
52
+ console.log(`Codex Model: ${config.codexModel}`);
53
+ console.log(`Agent Reasoning: A1=${config.codexAgentReasoning.agent1}, A2=${config.codexAgentReasoning.agent2}, A3=${config.codexAgentReasoning.agent3}`);
54
+ }
55
+ else {
56
+ console.log(`Claude Model: ${config.claudeModel}`);
57
+ }
58
+ console.log(`Output Dir: ${getCurrentOutputDir()}\n`);
59
+ const loopStart = Date.now();
60
+ // ═══════════════════════════════════════════════════════════════════════════
61
+ // AGENT 1: Linear Reader (uses configured provider)
62
+ // ═══════════════════════════════════════════════════════════════════════════
63
+ console.log('Agent 1: Linear Reader starting...');
64
+ const agent1Provider = createProvider(config.provider);
65
+ const agent1BasePrompt = await loadPrompt('agent1-linear-reader');
66
+ const agent1Prompt = `## Agent Instance
67
+
68
+ You are part of pod: **${podName}** / Loop ${iteration} / Agent 1 (Linear Reader)
69
+
70
+ This identifier format is: Pod Name / Loop Number / Agent Number (Role).
71
+ - **Pod Name**: ${podName} - persists for this entire Horizon session
72
+ - **Loop Number**: ${iteration} - increments each time Horizon processes a new ticket
73
+ - **Agent**: Agent 1 (Linear Reader) - your role in this loop
74
+
75
+ ## Linear Team Configuration
76
+
77
+ **Team Key**: ${config.linearTeamId}
78
+
79
+ Use this team key for all Linear MCP tool calls (list_issues, list_issue_statuses, update_issue, create_comment, etc.). Do NOT use any other team key.
80
+
81
+ ---
82
+
83
+ ${agent1BasePrompt}`;
84
+ // Select model based on provider
85
+ const agent1Model = config.provider === 'codex' ? config.codexModel : 'opus';
86
+ // Rate limit retry config - uses configured max retries
87
+ const retryConfig = { maxRetries: config.rateLimitMaxRetries };
88
+ // Agent 1 with rate limit retry
89
+ const agent1Result = await executeWithRateLimitRetry(() => agent1Provider.spawn({
90
+ prompt: agent1Prompt,
91
+ model: agent1Model,
92
+ allowedTools: ['mcp__linear__*'],
93
+ reasoningEffort: config.provider === 'codex' ? config.codexAgentReasoning.agent1 : undefined,
94
+ }, 1), retryConfig, 'Agent 1 (Linear Reader)');
95
+ // If still rate limited after max retries, skip this iteration
96
+ if (agent1Result.rateLimited) {
97
+ console.log('Agent 1 still rate limited after max retries. Skipping iteration.');
98
+ return;
99
+ }
100
+ // Log Agent 1 stats
101
+ await logAgentStats(1, config.provider, agent1Model, {
102
+ tokenUsage: agent1Result.tokenUsage,
103
+ cost: agent1Result.cost,
104
+ costEstimated: agent1Result.costEstimated,
105
+ duration: agent1Result.duration,
106
+ exitCode: agent1Result.exitCode,
107
+ rateLimited: agent1Result.rateLimited,
108
+ output: agent1Result.output,
109
+ });
110
+ // Extract the text output from agent 1
111
+ const agent1Output = agent1Result.finalOutput;
112
+ // Check if there's no work (look for the signal in the output)
113
+ if (agent1Output.includes('no_work: true') || agent1Output.includes('NO_WORK')) {
114
+ console.log('No work available.');
115
+ // If GCP auto-stop is enabled, check if we're on GCP and stop the instance
116
+ if (config.gcpAutoStop) {
117
+ console.log('GCP auto-stop is enabled. Checking if running on GCP...');
118
+ const onGcp = await isRunningOnGcp();
119
+ if (onGcp) {
120
+ console.log('Running on GCP VM. Initiating instance stop...');
121
+ const stopped = await stopGcpInstance();
122
+ if (stopped) {
123
+ console.log('Instance stop command issued. VM will shut down shortly.');
124
+ // Give the stop command time to take effect
125
+ await sleep(10000);
126
+ process.exit(0);
127
+ }
128
+ else {
129
+ console.log('Failed to stop GCP instance. Falling back to quick check.');
130
+ }
131
+ }
132
+ else {
133
+ console.log('Not running on GCP VM. Falling back to pulse check.');
134
+ }
135
+ }
136
+ // Two-tier polling: pulse check loop with fallback
137
+ const fullCheckIntervalMs = config.fullCheckIntervalMinutes * 60 * 1000;
138
+ const pulseCheckIntervalMs = config.quickCheckIntervalMinutes * 60 * 1000;
139
+ let lastFullCheck = Date.now(); // Agent 1 just ran
140
+ while (true) {
141
+ console.log(`\n[Pulse Check] Sleeping ${config.quickCheckIntervalMinutes} minutes...`);
142
+ await sleep(pulseCheckIntervalMs);
143
+ // Check if fallback is due
144
+ const timeSinceFullCheck = Date.now() - lastFullCheck;
145
+ const fallbackDue = timeSinceFullCheck >= fullCheckIntervalMs;
146
+ if (fallbackDue) {
147
+ console.log('[Pulse Check] Full check interval reached. Running full Agent 1 check.');
148
+ return; // Exit to let main loop run Agent 1
149
+ }
150
+ // Perform pulse check
151
+ if (!config.linearApiKey || !config.linearTeamId) {
152
+ console.log('[Pulse Check] Missing Linear credentials. Falling back to Agent 1.');
153
+ return;
154
+ }
155
+ console.log('[Pulse Check] Checking for ready-to-work tickets...');
156
+ const result = await checkForUncompletedTickets(config.linearApiKey, config.linearTeamId);
157
+ if (result.error) {
158
+ console.log(`[Pulse Check] Error: ${result.error}. Falling back to Agent 1.`);
159
+ return; // Error - let Agent 1 handle it
160
+ }
161
+ // Display status category stats
162
+ const { statusCounts } = result;
163
+ const statsLine = `[Pulse Check] Status: ${statusCounts.completed} done, ${statusCounts.started} in progress, ${statusCounts.unstarted} todo, ${statusCounts.backlog} backlog, ${statusCounts.canceled} canceled`;
164
+ console.log(statsLine);
165
+ if (result.hasWork) {
166
+ console.log(`[Pulse Check] Found ${result.ticketCount} ready-to-work ticket(s). Initiating next loop.`);
167
+ return; // Work found - run Agent 1
168
+ }
169
+ // No work found - continue pulse check loop
170
+ const minutesUntilFallback = Math.round((fullCheckIntervalMs - timeSinceFullCheck) / 60000);
171
+ console.log(`[Pulse Check] No ready-to-work tickets. Checking again in ${config.quickCheckIntervalMinutes} minutes (full check in ${minutesUntilFallback} minutes).`);
172
+ }
173
+ }
174
+ // ═══════════════════════════════════════════════════════════════════════════
175
+ // ATTACHMENT DOWNLOAD: Download any attached images/files from the Linear issue
176
+ // ═══════════════════════════════════════════════════════════════════════════
177
+ let attachmentPaths = [];
178
+ const issueIdentifier = extractIssueIdentifier(agent1Output);
179
+ if (issueIdentifier && config.linearApiKey) {
180
+ console.log('\nDownloading attachments from Linear...');
181
+ try {
182
+ // Fetch fresh description from Linear API with signed URLs
183
+ // The public-file-urls-expire-in header makes Linear return pre-signed URLs (1 hour expiry)
184
+ const linearClient = createLinearClientWithSignedUrls(config.linearApiKey, 3600);
185
+ const freshDescription = await getIssueDescription(linearClient, issueIdentifier);
186
+ if (freshDescription) {
187
+ // Extract URLs from the fresh description (has valid signatures)
188
+ const attachments = extractLinearUrls(freshDescription);
189
+ if (attachments.length > 0) {
190
+ const result = await downloadIssueAttachments(config.linearApiKey, issueIdentifier, attachments);
191
+ attachmentPaths = result.attachments.map(a => a.localPath);
192
+ }
193
+ }
194
+ if (attachmentPaths.length > 0) {
195
+ console.log(`Downloaded ${attachmentPaths.length} attachment(s)`);
196
+ }
197
+ else {
198
+ console.log('No attachments found in issue');
199
+ }
200
+ }
201
+ catch (error) {
202
+ console.log('Failed to download attachments (continuing without them):', error);
203
+ }
204
+ }
205
+ // ═══════════════════════════════════════════════════════════════════════════
206
+ // AGENT 2: Worker (uses configured provider - Claude or Codex)
207
+ // ═══════════════════════════════════════════════════════════════════════════
208
+ console.log('\nAgent 2: Worker starting...');
209
+ // Use configured provider for Agent 2
210
+ const agent2Provider = createProvider(config.provider);
211
+ // Build attachment context section if we have downloaded files
212
+ const attachmentSection = attachmentPaths.length > 0
213
+ ? `
214
+
215
+ ## Downloaded Attachments
216
+
217
+ The following files have been downloaded locally from the Linear issue. You can read/view these files using the Read tool:
218
+
219
+ ${attachmentPaths.map(p => `- ${p}`).join('\n')}
220
+
221
+ `
222
+ : '';
223
+ // Build worker prompt by combining the base prompt with agent 1's output
224
+ const workerBasePrompt = await loadPrompt('agent2-worker');
225
+ const workerPrompt = `## Agent Instance
226
+
227
+ You are part of pod: **${podName}** / Loop ${iteration} / Agent 2 (Worker)
228
+
229
+ This identifier format is: Pod Name / Loop Number / Agent Number (Role).
230
+ - **Pod Name**: ${podName} - persists for this entire Horizon session
231
+ - **Loop Number**: ${iteration} - increments each time Horizon processes a new ticket
232
+ - **Agent**: Agent 2 (Worker) - your role in this loop
233
+
234
+ ## Linear Team Configuration
235
+
236
+ **Team Key**: ${config.linearTeamId}
237
+
238
+ This team key is used for all Linear MCP tool calls. While you don't make Linear calls directly, this context may be passed to other agents.
239
+
240
+ ---
241
+
242
+ ## Context from Linear (gathered by Agent 1)
243
+
244
+ ${agent1Output}
245
+ ${attachmentSection}
246
+ ---
247
+
248
+ ${workerBasePrompt}`;
249
+ // Agent 2 with rate limit retry
250
+ let agent2Result;
251
+ if (config.provider === 'codex') {
252
+ agent2Result = await executeWithRateLimitRetry(() => agent2Provider.spawn({
253
+ prompt: workerPrompt,
254
+ model: config.codexModel,
255
+ reasoningEffort: config.codexReasoningEffort,
256
+ }, 2), retryConfig, 'Agent 2 (Worker)');
257
+ }
258
+ else {
259
+ agent2Result = await executeWithRateLimitRetry(() => agent2Provider.spawn({
260
+ prompt: workerPrompt,
261
+ model: config.claudeModel,
262
+ }, 2), retryConfig, 'Agent 2 (Worker)');
263
+ }
264
+ // Note: Agent 2 rate limits are logged but we continue to Agent 3 regardless
265
+ if (agent2Result.rateLimited) {
266
+ console.log('Agent 2 still rate limited after max retries. Continuing to Agent 3 to log status.');
267
+ }
268
+ // Log Agent 2 stats
269
+ const agent2Model = config.provider === 'codex' ? config.codexModel : config.claudeModel;
270
+ await logAgentStats(2, config.provider, agent2Model, {
271
+ tokenUsage: agent2Result.tokenUsage,
272
+ cost: agent2Result.cost,
273
+ costEstimated: agent2Result.costEstimated,
274
+ duration: agent2Result.duration,
275
+ exitCode: agent2Result.exitCode,
276
+ rateLimited: agent2Result.rateLimited,
277
+ output: agent2Result.output,
278
+ });
279
+ const agent2Output = agent2Result.finalOutput;
280
+ // ═══════════════════════════════════════════════════════════════════════════
281
+ // AGENT 3: Linear Writer (uses configured provider)
282
+ // ═══════════════════════════════════════════════════════════════════════════
283
+ console.log('\nAgent 3: Linear Writer starting...');
284
+ const agent3Provider = createProvider(config.provider);
285
+ const writerBasePrompt = await loadPrompt('agent3-linear-writer');
286
+ // Format cost strings with estimated marker for Codex
287
+ const agent1CostStr = agent1Result.costEstimated
288
+ ? `~$${agent1Result.cost.toFixed(4)} (estimated)`
289
+ : `$${agent1Result.cost.toFixed(4)}`;
290
+ const agent2CostStr = agent2Result.costEstimated
291
+ ? `~$${agent2Result.cost.toFixed(4)} (estimated)`
292
+ : `$${agent2Result.cost.toFixed(4)}`;
293
+ const writerPrompt = `## Agent Instance
294
+
295
+ You are part of pod: **${podName}** / Loop ${iteration} / Agent 3 (Linear Writer)
296
+
297
+ This identifier format is: Pod Name / Loop Number / Agent Number (Role).
298
+ - **Pod Name**: ${podName} - persists for this entire Horizon session
299
+ - **Loop Number**: ${iteration} - increments each time Horizon processes a new ticket
300
+ - **Agent**: Agent 3 (Linear Writer) - your role in this loop
301
+
302
+ **IMPORTANT**: Include the pod name (${podName}) in all comments you post to Linear so that when multiple pods work in parallel, we can identify which one made which comment.
303
+
304
+ ## Linear Team Configuration
305
+
306
+ **Team Key**: ${config.linearTeamId}
307
+
308
+ Use this team key for all Linear MCP tool calls (update_issue, create_comment, create_issue for sub-issues, etc.). Do NOT use any other team key.
309
+
310
+ ---
311
+
312
+ ## Context from Agent 1 (Linear issue details)
313
+
314
+ ${agent1Output}
315
+
316
+ ---
317
+
318
+ ## Results from Agent 2 (Work performed)
319
+
320
+ ${agent2Output}
321
+
322
+ ---
323
+
324
+ ## Session Stats
325
+
326
+ - Pod: ${podName}
327
+ - Loop: ${iteration}
328
+
329
+ ### Agent 1 (Linear Reader)
330
+ - Provider: ${config.provider}
331
+ - Model: ${agent1Model}
332
+ - Cost: ${agent1CostStr}
333
+ - Duration: ${Math.round(agent1Result.duration / 1000)}s
334
+ - Tokens: in=${agent1Result.tokenUsage.input.toLocaleString()} out=${agent1Result.tokenUsage.output.toLocaleString()} cached=${agent1Result.tokenUsage.cached.toLocaleString()}
335
+
336
+ ### Agent 2 (Worker)
337
+ - Provider: ${config.provider}
338
+ - Model: ${agent2Model}
339
+ - Cost: ${agent2CostStr}
340
+ - Duration: ${Math.round(agent2Result.duration / 1000)}s
341
+ - Tokens: in=${agent2Result.tokenUsage.input.toLocaleString()} out=${agent2Result.tokenUsage.output.toLocaleString()} cached=${agent2Result.tokenUsage.cached.toLocaleString()}
342
+ - Exit code: ${agent2Result.exitCode}
343
+ - Rate limited: ${agent2Result.rateLimited}
344
+
345
+ ### Loop Totals (Agent 1 + Agent 2)
346
+ - Total Cost: $${(agent1Result.cost + agent2Result.cost).toFixed(4)}${(agent1Result.costEstimated || agent2Result.costEstimated) ? ' (includes estimate)' : ''}
347
+ - Total Duration: ${Math.round((agent1Result.duration + agent2Result.duration) / 1000)}s
348
+ - Total Tokens: in=${(agent1Result.tokenUsage.input + agent2Result.tokenUsage.input).toLocaleString()} out=${(agent1Result.tokenUsage.output + agent2Result.tokenUsage.output).toLocaleString()} cached=${(agent1Result.tokenUsage.cached + agent2Result.tokenUsage.cached).toLocaleString()}
349
+
350
+ ---
351
+
352
+ ${writerBasePrompt}`;
353
+ // Agent 3 with rate limit retry
354
+ const agent3Model = config.provider === 'codex' ? config.codexModel : 'sonnet';
355
+ const agent3Result = await executeWithRateLimitRetry(() => agent3Provider.spawn({
356
+ prompt: writerPrompt,
357
+ model: agent3Model,
358
+ allowedTools: ['mcp__linear__*'],
359
+ reasoningEffort: config.provider === 'codex' ? config.codexAgentReasoning.agent3 : undefined,
360
+ }, 3), retryConfig, 'Agent 3 (Linear Writer)');
361
+ if (agent3Result.rateLimited) {
362
+ console.log('Agent 3 still rate limited after max retries.');
363
+ }
364
+ // Log Agent 3 stats
365
+ await logAgentStats(3, config.provider, agent3Model, {
366
+ tokenUsage: agent3Result.tokenUsage,
367
+ cost: agent3Result.cost,
368
+ costEstimated: agent3Result.costEstimated,
369
+ duration: agent3Result.duration,
370
+ exitCode: agent3Result.exitCode,
371
+ rateLimited: agent3Result.rateLimited,
372
+ output: agent3Result.output,
373
+ });
374
+ // Finalize loop stats
375
+ await finalizeLoopStats();
376
+ // Loop stats
377
+ const duration = Math.round((Date.now() - loopStart) / 1000);
378
+ const minutes = Math.floor(duration / 60);
379
+ const seconds = duration % 60;
380
+ console.log(`\nLoop ${iteration} complete in ${minutes}m ${seconds}s`);
381
+ }
382
+ /**
383
+ * Displays the Horizon startup banner with ASCII art.
384
+ * Futuristic/sci-fi themed, ~10 lines.
385
+ */
386
+ function displayBanner() {
387
+ const version = getVersion();
388
+ const banner = `
389
+ ██╗ ██╗ ██████╗ ██████╗ ██╗███████╗ ██████╗ ███╗ ██╗
390
+ ██║ ██║██╔═══██╗██╔══██╗██║╚══███╔╝██╔═══██╗████╗ ██║
391
+ ███████║██║ ██║██████╔╝██║ ███╔╝ ██║ ██║██╔██╗ ██║
392
+ ██╔══██║██║ ██║██╔══██╗██║ ███╔╝ ██║ ██║██║╚██╗██║
393
+ ██║ ██║╚██████╔╝██║ ██║██║███████╗╚██████╔╝██║ ╚████║
394
+ ╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚═╝╚═╝╚══════╝ ╚═════╝ ╚═╝ ╚═══╝
395
+
396
+ ⚡ Autonomous Product Development System ⚡ v${version}
397
+ ════════════════════════════════════════════════════════════════`;
398
+ console.log(banner);
399
+ }
400
+ /**
401
+ * Displays a safety warning about AI coding agents.
402
+ */
403
+ function displaySafetyWarning() {
404
+ console.log(`
405
+ ┌─────────────────────────────────────────────────────────────────┐
406
+ │ ⚠️ SAFETY WARNING │
407
+ ├─────────────────────────────────────────────────────────────────┤
408
+ │ Horizon uses AI coding agents (Claude Code, Codex) that are │
409
+ │ granted permissions to read, write, and execute code. │
410
+ │ │
411
+ │ • Coding agents may make mistakes │
412
+ │ • They may take actions that could be harmful to your system │
413
+ │ • Always review changes before merging to production │
414
+ │ │
415
+ │ We recommend running Horizon in a sandboxed environment or │
416
+ │ virtual machine for added safety. │
417
+ └─────────────────────────────────────────────────────────────────┘
418
+ `);
419
+ }
420
+ /**
421
+ * Runs minimal first-run setup if credentials are missing.
422
+ * Prompts only for essentials (API key, team), uses defaults for everything else.
423
+ * Returns true if setup completed successfully, false if user cancelled.
424
+ */
425
+ async function runMinimalSetup(cliAvailability) {
426
+ console.log('\n⚠️ Linear credentials not configured.\n');
427
+ const rl = createPromptInterface();
428
+ try {
429
+ // Load any existing config
430
+ const existingConfig = loadExistingConfig();
431
+ // ─── API Key ───
432
+ console.log('To get your API key:');
433
+ console.log(' 1. Go to: https://linear.app/settings/account/security/api-keys/new');
434
+ console.log(' 2. Enter a label (e.g., "Horizon")');
435
+ console.log(' 3. Click "Create key"');
436
+ console.log('');
437
+ let apiKey = await promptSecret(rl, 'Enter your Linear API key');
438
+ if (!apiKey) {
439
+ console.log('\nLinear API key is required.');
440
+ return false;
441
+ }
442
+ // Validate API key
443
+ console.log('Validating...');
444
+ const isValid = await validateLinearKey(apiKey);
445
+ if (!isValid) {
446
+ console.log('Invalid API key. Please check and try again.');
447
+ return false;
448
+ }
449
+ console.log('✓ Valid\n');
450
+ // ─── Team Selection ───
451
+ console.log('Fetching teams...');
452
+ const teams = await fetchLinearTeams(apiKey);
453
+ if (teams.length === 0) {
454
+ console.log('No teams found in your Linear workspace.');
455
+ return false;
456
+ }
457
+ let teamKey;
458
+ if (teams.length === 1) {
459
+ teamKey = teams[0].key;
460
+ console.log(`Found team: ${teams[0].name} (${teams[0].key})`);
461
+ console.log('Auto-selecting as it\'s the only team.\n');
462
+ }
463
+ else {
464
+ console.log('Select team:');
465
+ const teamOptions = teams.map((team) => ({
466
+ value: team.key,
467
+ label: `${team.name} (${team.key})`,
468
+ }));
469
+ teamKey = await promptSelect(rl, teamOptions, 0);
470
+ const selectedTeam = teams.find((t) => t.key === teamKey);
471
+ console.log(`Selected: ${selectedTeam.name}\n`);
472
+ }
473
+ // Auto-select provider based on CLI availability
474
+ const provider = autoSelectProvider(cliAvailability);
475
+ console.log(`Using provider: ${provider}\n`);
476
+ // ─── Merge Mode ───
477
+ console.log('When work completes:');
478
+ const mergeModeOptions = [
479
+ { value: 'auto', label: 'auto', description: 'Agent decides: merge directly or create PR (recommended)' },
480
+ { value: 'merge', label: 'merge', description: 'Merge directly to main' },
481
+ { value: 'pr', label: 'pr', description: 'Create PR for review' },
482
+ ];
483
+ const mergeMode = await promptSelect(rl, mergeModeOptions, 0);
484
+ // Save configuration
485
+ const newConfig = {
486
+ linearApiKey: apiKey,
487
+ linearTeamKey: teamKey,
488
+ provider,
489
+ claudeModel: existingConfig.claudeModel || 'opus',
490
+ codexModel: existingConfig.codexModel || 'gpt-5.2',
491
+ codexReasoningEffort: existingConfig.codexReasoningEffort || 'high',
492
+ maxIterations: existingConfig.maxIterations ?? 0,
493
+ mergeMode,
494
+ };
495
+ saveEnvConfig(newConfig);
496
+ saveMcpConfig(apiKey);
497
+ ensureGitignore();
498
+ // Update process.env so config picks up new values
499
+ process.env.LINEAR_API_KEY = apiKey;
500
+ process.env.LINEAR_TEAM_KEY = teamKey;
501
+ process.env.HORIZON_PROVIDER = provider;
502
+ process.env.HORIZON_MERGE_MODE = mergeMode;
503
+ console.log('\n✓ Configuration saved!\n');
504
+ return true;
505
+ }
506
+ finally {
507
+ rl.close();
508
+ }
509
+ }
510
+ export async function main() {
511
+ displayBanner();
512
+ displaySafetyWarning();
513
+ // Check for updates (non-blocking, cached for 24 hours)
514
+ const updateResult = await checkForUpdates();
515
+ displayUpdateNotification(updateResult);
516
+ // Check for git repository first - Horizon requires git
517
+ if (!isGitRepository()) {
518
+ console.log('\n❌ Error: Not a git repository');
519
+ console.log('');
520
+ console.log(' Horizon requires a git repository to operate. It uses git for:');
521
+ console.log(' - Creating feature branches');
522
+ console.log(' - Committing changes');
523
+ console.log(' - Creating pull requests');
524
+ console.log('');
525
+ console.log(' To initialize a git repository, run:');
526
+ console.log(' git init');
527
+ console.log('');
528
+ process.exit(1);
529
+ }
530
+ // Ensure directories exist (silent)
531
+ ensureHorizonDir();
532
+ ensureHorizonDocsDir();
533
+ ensureGitignore();
534
+ // Check for coding CLI availability - at least one must be installed
535
+ const cliAvailability = checkAndDisplayCliAvailability();
536
+ if (!cliAvailability) {
537
+ // Error message already displayed by checkAndDisplayCliAvailability
538
+ process.exit(1);
539
+ }
540
+ // Sync prompts from package to .horizon/prompts/ (ensures they're always up-to-date)
541
+ copyPromptsToProject();
542
+ let config = getConfig();
543
+ // Check if Linear credentials are configured
544
+ if (!config.linearApiKey || !config.linearTeamId) {
545
+ const setupSuccess = await runMinimalSetup(cliAvailability);
546
+ if (!setupSuccess) {
547
+ console.log('\nCannot start Horizon without Linear configuration.');
548
+ console.log('Run `horizon config` for full configuration options.\n');
549
+ process.exit(1);
550
+ }
551
+ // Reload config after setup (rebuild from updated process.env)
552
+ config = getConfig(true);
553
+ }
554
+ // Display config summary
555
+ console.log(` Working directory: ${config.workingDirectory}`);
556
+ console.log(` Branch: ${getCurrentBranch()}`);
557
+ console.log(` Provider: ${config.provider}`);
558
+ if (config.provider === 'codex') {
559
+ console.log(` Codex Model: ${config.codexModel}`);
560
+ console.log(` Reasoning Effort (default): ${config.codexReasoningEffort}`);
561
+ console.log(` Agent Reasoning: A1=${config.codexAgentReasoning.agent1}, A2=${config.codexAgentReasoning.agent2}, A3=${config.codexAgentReasoning.agent3}`);
562
+ }
563
+ else {
564
+ console.log(` Claude Model: ${config.claudeModel}`);
565
+ }
566
+ if (config.maxIterations > 0) {
567
+ console.log(` Max Iterations: ${config.maxIterations}`);
568
+ }
569
+ if (config.gcpAutoStop) {
570
+ console.log(` GCP Auto-Stop: enabled`);
571
+ }
572
+ console.log(` Merge Mode: ${config.mergeMode}`);
573
+ // Check if ∞ statuses exist in Linear, create if needed
574
+ const statusesExist = await checkLinearStatuses(config.linearApiKey, config.linearTeamId);
575
+ if (!statusesExist) {
576
+ console.log('\n Creating ∞ workflow statuses in Linear...');
577
+ const result = await createLinearStatuses(config.linearApiKey, config.linearTeamId);
578
+ if (!result.success) {
579
+ console.log('\n❌ Failed to create ∞ statuses. Please check Linear permissions.');
580
+ if (result.errors.length > 0) {
581
+ result.errors.forEach((err) => console.log(` - ${err}`));
582
+ }
583
+ process.exit(1);
584
+ }
585
+ // Show status creation summary
586
+ if (result.created.length > 0) {
587
+ console.log(` Created ${result.created.length} status(es)`);
588
+ }
589
+ if (result.existing.length > 0) {
590
+ console.log(` Found ${result.existing.length} existing status(es)`);
591
+ }
592
+ }
593
+ console.log(' Linear Team: ' + config.linearTeamId);
594
+ console.log(' ∞ Statuses: ✓ configured');
595
+ // Check Codex Linear MCP if using Codex provider
596
+ if (config.provider === 'codex') {
597
+ const hasLinearMcp = checkCodexLinearMcp();
598
+ if (!hasLinearMcp) {
599
+ console.log('\n⚠️ Linear MCP not configured for Codex.');
600
+ console.log(' Run: horizon config');
601
+ process.exit(1);
602
+ }
603
+ console.log(' Codex Linear MCP: ✓ configured');
604
+ }
605
+ // Generate pod name once at startup - persists for entire Horizon session
606
+ const podName = generatePodName();
607
+ console.log(` Pod: ${podName}`);
608
+ let iteration = 0;
609
+ while (config.maxIterations === 0 || iteration < config.maxIterations) {
610
+ try {
611
+ await runLoop(podName, iteration);
612
+ iteration++;
613
+ }
614
+ catch (error) {
615
+ console.error(`\nLoop ${iteration} error:`, error);
616
+ console.log(`Sleeping ${config.errorSleepMinutes} minute(s) before retry...`);
617
+ await sleep(config.errorSleepMinutes * 60 * 1000);
618
+ }
619
+ }
620
+ if (config.maxIterations > 0) {
621
+ console.log(`\nReached max iterations: ${config.maxIterations}`);
622
+ }
623
+ }
624
+ // Run main when executed directly
625
+ // When used as CLI via cli.ts, main() is imported and called there
626
+ if (import.meta.url === `file://${process.argv[1]}`) {
627
+ main().catch(console.error);
628
+ }
629
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}