@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
@@ -0,0 +1,25 @@
1
+ export interface CliAvailability {
2
+ claude: boolean;
3
+ codex: boolean;
4
+ }
5
+ /**
6
+ * Checks if Claude Code CLI is installed.
7
+ * Uses `claude --version` to verify the binary exists.
8
+ */
9
+ export declare function isClaudeCliInstalled(): boolean;
10
+ /**
11
+ * Checks if Codex CLI is installed.
12
+ * Uses `codex --version` to verify the binary exists.
13
+ */
14
+ export declare function isCodexCliInstalled(): boolean;
15
+ /**
16
+ * Detects which coding CLIs are available on the system.
17
+ * Returns an object indicating availability of each CLI.
18
+ */
19
+ export declare function detectAvailableClis(): CliAvailability;
20
+ /**
21
+ * Checks if at least one coding CLI is available.
22
+ * Returns true if either Claude or Codex CLI is installed.
23
+ */
24
+ export declare function hasAnyCli(availability: CliAvailability): boolean;
25
+ //# sourceMappingURL=cli-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-detection.d.ts","sourceRoot":"","sources":["../../src/lib/cli-detection.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,OAAO,CAAC;IAChB,KAAK,EAAE,OAAO,CAAC;CAChB;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,OAAO,CAW9C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAW7C;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,eAAe,CAKrD;AAED;;;GAGG;AACH,wBAAgB,SAAS,CAAC,YAAY,EAAE,eAAe,GAAG,OAAO,CAEhE"}
@@ -0,0 +1,53 @@
1
+ import { execSync } from 'child_process';
2
+ /**
3
+ * Checks if Claude Code CLI is installed.
4
+ * Uses `claude --version` to verify the binary exists.
5
+ */
6
+ export function isClaudeCliInstalled() {
7
+ try {
8
+ execSync('claude --version', {
9
+ encoding: 'utf-8',
10
+ timeout: 5000,
11
+ stdio: ['pipe', 'pipe', 'pipe'],
12
+ });
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ /**
20
+ * Checks if Codex CLI is installed.
21
+ * Uses `codex --version` to verify the binary exists.
22
+ */
23
+ export function isCodexCliInstalled() {
24
+ try {
25
+ execSync('codex --version', {
26
+ encoding: 'utf-8',
27
+ timeout: 5000,
28
+ stdio: ['pipe', 'pipe', 'pipe'],
29
+ });
30
+ return true;
31
+ }
32
+ catch {
33
+ return false;
34
+ }
35
+ }
36
+ /**
37
+ * Detects which coding CLIs are available on the system.
38
+ * Returns an object indicating availability of each CLI.
39
+ */
40
+ export function detectAvailableClis() {
41
+ return {
42
+ claude: isClaudeCliInstalled(),
43
+ codex: isCodexCliInstalled(),
44
+ };
45
+ }
46
+ /**
47
+ * Checks if at least one coding CLI is available.
48
+ * Returns true if either Claude or Codex CLI is installed.
49
+ */
50
+ export function hasAnyCli(availability) {
51
+ return availability.claude || availability.codex;
52
+ }
53
+ //# sourceMappingURL=cli-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-detection.js","sourceRoot":"","sources":["../../src/lib/cli-detection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAQzC;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAClC,IAAI,CAAC;QACH,QAAQ,CAAC,kBAAkB,EAAE;YAC3B,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,IAAI,CAAC;QACH,QAAQ,CAAC,iBAAiB,EAAE;YAC1B,QAAQ,EAAE,OAAO;YACjB,OAAO,EAAE,IAAI;YACb,KAAK,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC;SAChC,CAAC,CAAC;QACH,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO;QACL,MAAM,EAAE,oBAAoB,EAAE;QAC9B,KAAK,EAAE,mBAAmB,EAAE;KAC7B,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,YAA6B;IACrD,OAAO,YAAY,CAAC,MAAM,IAAI,YAAY,CAAC,KAAK,CAAC;AACnD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { LLMProvider } from './provider.js';
2
+ export declare function createCodexProvider(): LLMProvider;
3
+ export declare function checkCodexLinearMcpConfigured(): boolean;
4
+ //# sourceMappingURL=codex.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.d.ts","sourceRoot":"","sources":["../../src/lib/codex.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,WAAW,EAAgF,MAAM,eAAe,CAAC;AA0V1H,wBAAgB,mBAAmB,IAAI,WAAW,CAEjD;AAGD,wBAAgB,6BAA6B,IAAI,OAAO,CAOvD"}
@@ -0,0 +1,285 @@
1
+ import { spawn, execSync } from 'child_process';
2
+ import { getConfig } from '../config.js';
3
+ import { logAgentOutput, logTerminalOutput } from './output-logger.js';
4
+ import { registerCodexProvider } from './provider.js';
5
+ import { isRateLimitError } from './rate-limit.js';
6
+ // ANSI color codes
7
+ const BOLD = '\x1b[1m';
8
+ const DIM = '\x1b[2m';
9
+ const YELLOW = '\x1b[33m';
10
+ const RESET = '\x1b[0m';
11
+ // Codex pricing per 1M tokens (approximate, based on OpenAI pricing)
12
+ // These are estimates and may need updating
13
+ const CODEX_PRICING = {
14
+ 'gpt-5.2-codex': { input: 2.00, output: 8.00 },
15
+ 'gpt-5-codex': { input: 2.00, output: 8.00 },
16
+ 'gpt-4-codex': { input: 1.50, output: 6.00 },
17
+ 'default': { input: 2.00, output: 8.00 },
18
+ };
19
+ // Helper: Clean up file paths for display
20
+ function cleanPath(path) {
21
+ return path
22
+ .replace(/\/home\/ubuntu\/repos\/[^/]+\//g, '')
23
+ .replace(/\/Users\/[^/]+\/repos\/[^/]+\//g, '');
24
+ }
25
+ // Helper: Clean up command for display
26
+ function cleanCommand(cmd) {
27
+ return cmd
28
+ .replace(/^\/bin\/zsh -lc /, '')
29
+ .replace(/^\/bin\/bash -lc /, '')
30
+ .replace(/^['"]|['"]$/g, '');
31
+ }
32
+ // Helper: Truncate string to max length (default 120 for better visibility)
33
+ function truncate(str, maxLen = 120) {
34
+ if (str.length <= maxLen)
35
+ return str;
36
+ return str.substring(0, maxLen) + '...';
37
+ }
38
+ // Format a single Codex JSON event for terminal display
39
+ function formatCodexEvent(event) {
40
+ if (event.type === 'item.completed') {
41
+ const itemEvent = event;
42
+ const item = itemEvent.item;
43
+ switch (item.type) {
44
+ case 'command_execution': {
45
+ const cmd = cleanCommand(item.command || '');
46
+ const shortCmd = truncate(cmd.replace(/\n/g, ' '));
47
+ const exitCode = item.exit_code ?? 0;
48
+ if (exitCode === 0) {
49
+ return `${DIM}🔧 [codex] ${shortCmd}${RESET}`;
50
+ }
51
+ else {
52
+ let output = `${YELLOW}⚠️ [codex] ${shortCmd} (exit ${exitCode})${RESET}`;
53
+ if (item.aggregated_output) {
54
+ const shortOutput = truncate(item.aggregated_output);
55
+ output += `\n${DIM}↳ [codex] ${shortOutput}${RESET}`;
56
+ }
57
+ return output;
58
+ }
59
+ }
60
+ case 'file_change': {
61
+ if (item.changes && item.changes.length > 0) {
62
+ return item.changes
63
+ .map(change => `${DIM}📝 [codex] ${change.kind || 'update'} ${cleanPath(change.path)}${RESET}`)
64
+ .join('\n');
65
+ }
66
+ return `${DIM}📝 [codex] file_change${RESET}`;
67
+ }
68
+ case 'reasoning': {
69
+ // Extract first line of reasoning (often a header like **Planning**)
70
+ const text = item.text || '';
71
+ const firstLine = text.split('\n')[0] || '';
72
+ const cleanLine = firstLine.replace(/^\*\*|\*\*$/g, '').trim();
73
+ // Dim reasoning like other events for visual consistency
74
+ return `${DIM}💭 [codex] ${cleanLine}${RESET}`;
75
+ }
76
+ case 'agent_message': {
77
+ return `${BOLD}💬 [codex] ${item.text || ''}${RESET}`;
78
+ }
79
+ case 'mcp_tool_call': {
80
+ // Codex uses server + tool fields for MCP calls
81
+ const server = item.server || '';
82
+ const tool = item.tool || 'unknown';
83
+ const toolDisplay = server ? `${server}:${tool}` : tool;
84
+ // Show tool name and a preview of arguments if present
85
+ let display = `🔌 [codex] ${toolDisplay}`;
86
+ if (item.arguments && Object.keys(item.arguments).length > 0) {
87
+ const argPreview = truncate(JSON.stringify(item.arguments), 80);
88
+ display += ` ${argPreview}`;
89
+ }
90
+ return `${DIM}${display}${RESET}`;
91
+ }
92
+ case 'web_search': {
93
+ const query = item.query || item.text || 'search';
94
+ return `${DIM}🔍 [codex] web search: ${truncate(query, 100)}${RESET}`;
95
+ }
96
+ case 'plan_update': {
97
+ const text = item.text || 'plan updated';
98
+ const firstLine = text.split('\n')[0] || '';
99
+ return `${DIM}📋 [codex] ${truncate(firstLine, 100)}${RESET}`;
100
+ }
101
+ default:
102
+ return null;
103
+ }
104
+ }
105
+ if (event.type === 'error') {
106
+ const errorEvent = event;
107
+ const message = errorEvent.message || errorEvent.error || 'error';
108
+ return `${YELLOW}⚠️ [codex] ERROR: ${message}${RESET}`;
109
+ }
110
+ return null;
111
+ }
112
+ // Estimate cost based on token usage and model
113
+ function estimateCost(tokenUsage, model) {
114
+ const pricing = CODEX_PRICING[model] || CODEX_PRICING['default'];
115
+ // Input tokens (non-cached) - cached tokens are typically free or discounted
116
+ const inputCost = ((tokenUsage.input - tokenUsage.cached) / 1_000_000) * pricing.input;
117
+ const outputCost = (tokenUsage.output / 1_000_000) * pricing.output;
118
+ return inputCost + outputCost;
119
+ }
120
+ // Extract final text output from Codex streaming JSON
121
+ function extractCodexFinalOutput(streamOutput) {
122
+ const lines = streamOutput.split('\n');
123
+ let lastAgentMessage = '';
124
+ for (const line of lines) {
125
+ if (!line.trim())
126
+ continue;
127
+ try {
128
+ const json = JSON.parse(line);
129
+ if (json.type === 'item.completed' && json.item?.type === 'agent_message') {
130
+ lastAgentMessage = json.item.text || '';
131
+ }
132
+ }
133
+ catch {
134
+ // Not JSON, ignore
135
+ }
136
+ }
137
+ return lastAgentMessage;
138
+ }
139
+ // Codex provider implementation
140
+ class CodexProvider {
141
+ name = 'codex';
142
+ async spawn(options, agentNumber) {
143
+ const config = getConfig();
144
+ const model = options.model || config.codexModel;
145
+ const reasoningEffort = options.reasoningEffort || config.codexReasoningEffort;
146
+ return new Promise((resolve, reject) => {
147
+ const args = [
148
+ 'exec',
149
+ '--dangerously-bypass-approvals-and-sandbox',
150
+ '--json',
151
+ '--model', model,
152
+ '-c', `model_reasoning_effort="${reasoningEffort}"`,
153
+ ];
154
+ const spawnMsg = `${BOLD}Spawning: codex ${args.join(' ')}${RESET}`;
155
+ const cwdMsg = `${DIM} Working directory: ${config.workingDirectory}${RESET}`;
156
+ console.log(spawnMsg);
157
+ console.log(cwdMsg);
158
+ // Log spawn info to terminal log
159
+ if (agentNumber !== undefined) {
160
+ logTerminalOutput(agentNumber, spawnMsg).catch(() => { });
161
+ logTerminalOutput(agentNumber, cwdMsg).catch(() => { });
162
+ }
163
+ const proc = spawn('codex', args, {
164
+ stdio: ['pipe', 'pipe', 'pipe'],
165
+ cwd: config.workingDirectory,
166
+ env: { ...process.env },
167
+ });
168
+ // Feed prompt via stdin
169
+ proc.stdin.write(options.prompt);
170
+ proc.stdin.end();
171
+ let output = '';
172
+ let rateLimited = false;
173
+ let retryAfterMs;
174
+ const startTime = Date.now();
175
+ // Token tracking
176
+ const tokenUsage = { input: 0, output: 0, cached: 0 };
177
+ proc.stdout.on('data', (chunk) => {
178
+ const text = chunk.toString();
179
+ output += text;
180
+ // Parse streaming JSON output line by line
181
+ for (const line of text.split('\n')) {
182
+ if (!line.trim())
183
+ continue;
184
+ // Skip non-JSON lines (like "Reading prompt from stdin...")
185
+ if (!line.startsWith('{'))
186
+ continue;
187
+ // Persist raw line to output log file
188
+ if (agentNumber !== undefined) {
189
+ logAgentOutput(agentNumber, line).catch(() => { });
190
+ }
191
+ try {
192
+ const json = JSON.parse(line);
193
+ // Track token usage from turn.completed events
194
+ if (json.type === 'turn.completed') {
195
+ const turnEvent = json;
196
+ tokenUsage.input += turnEvent.usage.input_tokens || 0;
197
+ tokenUsage.output += turnEvent.usage.output_tokens || 0;
198
+ tokenUsage.cached += turnEvent.usage.cached_input_tokens || 0;
199
+ }
200
+ // Check for rate limits in error events
201
+ if (json.type === 'error') {
202
+ const errorEvent = json;
203
+ const errorText = errorEvent.message || errorEvent.error || '';
204
+ if (isRateLimitError(errorText)) {
205
+ rateLimited = true;
206
+ // Default wait time for Codex rate limits (5 minutes)
207
+ retryAfterMs = 5 * 60 * 1000;
208
+ }
209
+ }
210
+ // Format and display the event
211
+ const formatted = formatCodexEvent(json);
212
+ if (formatted) {
213
+ console.log(formatted);
214
+ if (agentNumber !== undefined) {
215
+ logTerminalOutput(agentNumber, formatted).catch(() => { });
216
+ }
217
+ }
218
+ }
219
+ catch {
220
+ // Not valid JSON, ignore
221
+ }
222
+ }
223
+ });
224
+ proc.stderr.on('data', (chunk) => {
225
+ const text = chunk.toString().trim();
226
+ if (text && !text.includes('Reading prompt from stdin')) {
227
+ const stderrMsg = `${DIM}stderr: ${text}${RESET}`;
228
+ console.error(stderrMsg);
229
+ if (agentNumber !== undefined) {
230
+ logTerminalOutput(agentNumber, stderrMsg).catch(() => { });
231
+ }
232
+ }
233
+ });
234
+ proc.on('close', (code) => {
235
+ const duration = Date.now() - startTime;
236
+ const cost = estimateCost(tokenUsage, model);
237
+ // Format session end summary
238
+ const sessionEnd = `${BOLD}📊 CODEX SESSION END
239
+ Tokens: in=${tokenUsage.input.toLocaleString()} cached=${tokenUsage.cached.toLocaleString()} out=${tokenUsage.output.toLocaleString()}
240
+ Duration: ${Math.floor(duration / 1000)}s
241
+ Cost: ~$${cost.toFixed(4)} (estimated)${RESET}`;
242
+ console.log(sessionEnd);
243
+ if (agentNumber !== undefined) {
244
+ logTerminalOutput(agentNumber, sessionEnd).catch(() => { });
245
+ }
246
+ resolve({
247
+ output,
248
+ finalOutput: extractCodexFinalOutput(output),
249
+ rateLimited,
250
+ retryAfterMs,
251
+ cost,
252
+ costEstimated: true, // Codex cost is always estimated
253
+ duration,
254
+ exitCode: code || 0,
255
+ tokenUsage,
256
+ });
257
+ });
258
+ proc.on('error', (err) => {
259
+ if (err.message.includes('ENOENT')) {
260
+ reject(new Error('Codex CLI not found. Install from https://github.com/openai/codex'));
261
+ }
262
+ else {
263
+ reject(new Error(`Failed to spawn codex: ${err.message}`));
264
+ }
265
+ });
266
+ });
267
+ }
268
+ }
269
+ // Factory function
270
+ export function createCodexProvider() {
271
+ return new CodexProvider();
272
+ }
273
+ // Check if Linear MCP is configured in Codex
274
+ export function checkCodexLinearMcpConfigured() {
275
+ try {
276
+ const result = execSync('codex mcp list', { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
277
+ return result.toLowerCase().includes('linear');
278
+ }
279
+ catch {
280
+ return false;
281
+ }
282
+ }
283
+ // Register the Codex provider
284
+ registerCodexProvider(createCodexProvider);
285
+ //# sourceMappingURL=codex.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"codex.js","sourceRoot":"","sources":["../../src/lib/codex.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * GCP (Google Cloud Platform) utilities for detecting if running on a VM
3
+ * and for auto-stopping the instance when work is complete.
4
+ */
5
+ /**
6
+ * Detect if we're running inside a Google Cloud VM by querying the metadata server.
7
+ * The metadata server is only available from within GCP VMs and responds with
8
+ * `Metadata-Flavor: Google` header.
9
+ */
10
+ export declare function isRunningOnGcp(): Promise<boolean>;
11
+ /**
12
+ * Stop the current GCP VM instance.
13
+ * This will shut down the VM, saving compute costs.
14
+ *
15
+ * Uses `gcloud compute instances stop` which is available on all GCP VMs.
16
+ * The VM must have IAM permissions to stop itself (compute.instances.stop).
17
+ *
18
+ * @returns true if stop command was issued successfully, false otherwise
19
+ */
20
+ export declare function stopGcpInstance(): Promise<boolean>;
21
+ //# sourceMappingURL=gcp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp.d.ts","sourceRoot":"","sources":["../../src/lib/gcp.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAOH;;;;GAIG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,OAAO,CAAC,CAgBvD;AAqCD;;;;;;;;GAQG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAyBxD"}
@@ -0,0 +1,96 @@
1
+ /**
2
+ * GCP (Google Cloud Platform) utilities for detecting if running on a VM
3
+ * and for auto-stopping the instance when work is complete.
4
+ */
5
+ import { execSync } from 'child_process';
6
+ const GCP_METADATA_URL = 'http://metadata.google.internal/computeMetadata/v1/';
7
+ const GCP_METADATA_FLAVOR = 'Metadata-Flavor: Google';
8
+ /**
9
+ * Detect if we're running inside a Google Cloud VM by querying the metadata server.
10
+ * The metadata server is only available from within GCP VMs and responds with
11
+ * `Metadata-Flavor: Google` header.
12
+ */
13
+ export async function isRunningOnGcp() {
14
+ try {
15
+ // Use a short timeout since this should respond instantly if on GCP
16
+ const response = await fetch(GCP_METADATA_URL, {
17
+ method: 'GET',
18
+ headers: { 'Metadata-Flavor': 'Google' },
19
+ signal: AbortSignal.timeout(2000), // 2 second timeout
20
+ });
21
+ // Check for the GCP metadata flavor header in response
22
+ const flavor = response.headers.get('Metadata-Flavor');
23
+ return flavor === 'Google';
24
+ }
25
+ catch {
26
+ // If fetch fails (timeout, network error, etc.), we're not on GCP
27
+ return false;
28
+ }
29
+ }
30
+ /**
31
+ * Get the current VM's instance name from GCP metadata.
32
+ */
33
+ async function getInstanceName() {
34
+ try {
35
+ const response = await fetch(`${GCP_METADATA_URL}instance/name`, {
36
+ headers: { 'Metadata-Flavor': 'Google' },
37
+ signal: AbortSignal.timeout(2000),
38
+ });
39
+ if (!response.ok)
40
+ return null;
41
+ return (await response.text()).trim();
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ }
47
+ /**
48
+ * Get the current VM's zone from GCP metadata.
49
+ * Returns just the zone name (e.g., 'us-central1-a'), not the full path.
50
+ */
51
+ async function getInstanceZone() {
52
+ try {
53
+ const response = await fetch(`${GCP_METADATA_URL}instance/zone`, {
54
+ headers: { 'Metadata-Flavor': 'Google' },
55
+ signal: AbortSignal.timeout(2000),
56
+ });
57
+ if (!response.ok)
58
+ return null;
59
+ // Response is like 'projects/123456/zones/us-central1-a'
60
+ const fullZone = (await response.text()).trim();
61
+ return fullZone.split('/').pop() || null;
62
+ }
63
+ catch {
64
+ return null;
65
+ }
66
+ }
67
+ /**
68
+ * Stop the current GCP VM instance.
69
+ * This will shut down the VM, saving compute costs.
70
+ *
71
+ * Uses `gcloud compute instances stop` which is available on all GCP VMs.
72
+ * The VM must have IAM permissions to stop itself (compute.instances.stop).
73
+ *
74
+ * @returns true if stop command was issued successfully, false otherwise
75
+ */
76
+ export async function stopGcpInstance() {
77
+ try {
78
+ const instanceName = await getInstanceName();
79
+ const zone = await getInstanceZone();
80
+ if (!instanceName || !zone) {
81
+ console.error('GCP auto-stop: Could not determine instance name or zone');
82
+ return false;
83
+ }
84
+ console.log(`GCP auto-stop: Stopping instance ${instanceName} in zone ${zone}...`);
85
+ // Use gcloud to stop the instance
86
+ // --quiet suppresses confirmation prompts
87
+ // Running async so the process doesn't wait for the stop to complete
88
+ execSync(`gcloud compute instances stop "${instanceName}" --zone="${zone}" --quiet &`, { stdio: 'inherit', shell: '/bin/bash' });
89
+ return true;
90
+ }
91
+ catch (error) {
92
+ console.error('GCP auto-stop: Failed to stop instance:', error);
93
+ return false;
94
+ }
95
+ }
96
+ //# sourceMappingURL=gcp.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gcp.js","sourceRoot":"","sources":["../../src/lib/gcp.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function gitPull(): boolean;
2
+ export declare function getCurrentBranch(): string;
3
+ //# sourceMappingURL=git.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.d.ts","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"AAIA,wBAAgB,OAAO,IAAI,OAAO,CAQjC;AAGD,wBAAgB,gBAAgB,IAAI,MAAM,CAOzC"}
@@ -0,0 +1,24 @@
1
+ import { execSync } from 'child_process';
2
+ import { getConfig } from '../config.js';
3
+ // Pull latest changes from remote
4
+ export function gitPull() {
5
+ const config = getConfig();
6
+ try {
7
+ execSync('git pull origin main', { stdio: 'pipe', cwd: config.workingDirectory });
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ }
14
+ // Get current branch
15
+ export function getCurrentBranch() {
16
+ const config = getConfig();
17
+ try {
18
+ return execSync('git branch --show-current', { encoding: 'utf-8', cwd: config.workingDirectory }).trim();
19
+ }
20
+ catch {
21
+ return 'unknown';
22
+ }
23
+ }
24
+ //# sourceMappingURL=git.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"git.js","sourceRoot":"","sources":["../../src/lib/git.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzC,kCAAkC;AAClC,MAAM,UAAU,OAAO;IACrB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,QAAQ,CAAC,sBAAsB,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC;QAClF,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,qBAAqB;AACrB,MAAM,UAAU,gBAAgB;IAC9B,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAC3B,IAAI,CAAC;QACH,OAAO,QAAQ,CAAC,2BAA2B,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,CAAC,gBAAgB,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Horizon configuration wizard (`horizon config`).
3
+ * Shows all current values and allows user to change them with "Enter to keep" UX.
4
+ */
5
+ /**
6
+ * Main configuration wizard for `horizon config`.
7
+ */
8
+ export declare function configProject(): Promise<void>;
9
+ /**
10
+ * Removes Horizon from the current project (`horizon uninstall`).
11
+ */
12
+ export declare function uninstallProject(): Promise<void>;
13
+ //# sourceMappingURL=init-project.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"init-project.d.ts","sourceRoot":"","sources":["../../src/lib/init-project.ts"],"names":[],"mappings":"AAAA;;;GAGG;AA6CH;;GAEG;AACH,wBAAsB,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CA6SnD;AAED;;GAEG;AACH,wBAAsB,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC,CAsJtD"}