@ulpi/cli 0.1.3 → 0.1.5

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 (57) hide show
  1. package/dist/{auth-KQCJ43U2.js → auth-BFFBUJUC.js} +1 -1
  2. package/dist/{chunk-YM2HV4IA.js → chunk-26LLDX2T.js} +50 -2
  3. package/dist/{chunk-QJ5GSMEC.js → chunk-5SCG7UYM.js} +2 -1
  4. package/dist/{chunk-5J6NLQUN.js → chunk-6OURRFP7.js} +8 -8
  5. package/dist/chunk-AV5RB3N2.js +173 -0
  6. package/dist/{chunk-7LXY5UVC.js → chunk-DDRLI6JU.js} +2 -1
  7. package/dist/{chunk-ZLYRPD7I.js → chunk-DOIKS6C5.js} +1 -1
  8. package/dist/{chunk-SPOI23SB.js → chunk-EIWYSP3A.js} +1 -1
  9. package/dist/{chunk-7AL4DOEJ.js → chunk-ELTGWMDE.js} +3 -3
  10. package/dist/{chunk-6OCEY7JY.js → chunk-IFATANHR.js} +34 -3
  11. package/dist/{chunk-2HEE5OKX.js → chunk-K4OVPFY2.js} +1 -1
  12. package/dist/{chunk-JGBXM5NC.js → chunk-L3PWNHSA.js} +2 -2
  13. package/dist/{chunk-2VYFVYJL.js → chunk-LD52XG3X.js} +24 -24
  14. package/dist/{chunk-F7OXF7Z3.js → chunk-P2RESJRN.js} +2 -2
  15. package/dist/{chunk-3SBPZRB5.js → chunk-RJIRWQJD.js} +1 -1
  16. package/dist/{chunk-2CLNOKPA.js → chunk-RSFJ6QSR.js} +18 -0
  17. package/dist/{chunk-PDR55ZNW.js → chunk-UCMT5OKP.js} +4 -4
  18. package/dist/{chunk-2MZER6ND.js → chunk-YYZOFYS6.js} +2 -2
  19. package/dist/ci-JQ56YIKC.js +756 -0
  20. package/dist/{codemap-RKSD4MIE.js → codemap-HMYBXJL2.js} +36 -36
  21. package/dist/{config-EGAXXCGL.js → config-YYWEN7U2.js} +1 -1
  22. package/dist/dist-2K7IEVTA.js +43 -0
  23. package/dist/{dist-UKMCJBB2.js → dist-4XTJ6HLM.js} +7 -7
  24. package/dist/{dist-QAU3LGJN.js → dist-5R4RYNQO.js} +3 -3
  25. package/dist/{dist-CB5D5LMO.js → dist-6MFVWIFF.js} +8 -8
  26. package/dist/{dist-GJYT2OQV.js → dist-7WLLPWWB.js} +8 -8
  27. package/dist/{dist-RKOGLK7R.js → dist-GWGTAHNM.js} +1 -1
  28. package/dist/{dist-CS2VKNYS.js → dist-U7ZIJMZD.js} +8 -8
  29. package/dist/{dist-YA2BWZB2.js → dist-WAMAQVPK.js} +2 -2
  30. package/dist/dist-XD4YI27T.js +26 -0
  31. package/dist/dist-XG2GG5SD.js +36 -0
  32. package/dist/{history-NFNA4HE5.js → history-RNUWO4JZ.js} +7 -7
  33. package/dist/hooks-installer-K2JXEBNN.js +19 -0
  34. package/dist/index.js +42 -42
  35. package/dist/{init-6CH4HV5T.js → init-NQWFZPKO.js} +11 -11
  36. package/dist/{launchd-LF2QMSKZ.js → launchd-OYXUAVW6.js} +2 -2
  37. package/dist/{mcp-installer-NQCGKQ23.js → mcp-installer-TOYDP77X.js} +1 -1
  38. package/dist/{memory-Y6OZTXJ2.js → memory-D6ZFFCI2.js} +17 -17
  39. package/dist/{openai-E7G2YAHU-UYY4ZWON.js → openai-E7G2YAHU-IG33BFYF.js} +2 -2
  40. package/dist/{projects-ATHDD3D6.js → projects-COUJP4ZC.js} +3 -3
  41. package/dist/{review-ADUPV3PN.js → review-KMGP2S25.js} +2 -2
  42. package/dist/{rules-E427DKYJ.js → rules-3OFGWHP4.js} +1 -1
  43. package/dist/server-USLHY6GH-F4JSXCWA.js +18 -0
  44. package/dist/server-X5P6WH2M-ULZF5WHZ.js +11 -0
  45. package/dist/{skills-CX73O3IV.js → skills-GY2CTPWN.js} +2 -2
  46. package/dist/{status-4DFHDJMN.js → status-SE43TIFJ.js} +2 -2
  47. package/dist/{templates-U7T6MARD.js → templates-O2XDKB5R.js} +5 -5
  48. package/dist/{ui-OWXZ3YSR.js → ui-4SM2SUI6.js} +13 -13
  49. package/dist/{ulpi-RMMCUAGP-JCJ273T6.js → ulpi-RMMCUAGP-EWYUE7RU.js} +1 -1
  50. package/dist/{uninstall-6SW35IK4.js → uninstall-KWGSGZTI.js} +3 -3
  51. package/dist/{update-WUITQX4Z.js → update-QYZA4D23.js} +3 -3
  52. package/dist/{version-checker-SMAYSN7Y.js → version-checker-MVB74DEX.js} +2 -2
  53. package/package.json +1 -1
  54. package/dist/chunk-G6SVZ4Q5.js +0 -122
  55. package/dist/ci-QM57ZCBW.js +0 -367
  56. package/dist/server-USLHY6GH-AEOJC5ST.js +0 -18
  57. package/dist/server-X5P6WH2M-7K2RY34N.js +0 -11
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  checkForUpdates
3
- } from "./chunk-F7OXF7Z3.js";
3
+ } from "./chunk-P2RESJRN.js";
4
4
  import {
5
5
  CLI_BIN_NAME,
6
6
  CLI_NPM_PACKAGE
7
- } from "./chunk-7LXY5UVC.js";
7
+ } from "./chunk-DDRLI6JU.js";
8
8
  import "./chunk-4VNS5WPM.js";
9
9
 
10
10
  // src/commands/update.ts
@@ -36,7 +36,7 @@ Run '${CLI_BIN_NAME} update' to install the update.`));
36
36
  console.log(chalk.green(`
37
37
  \u2713 Updated to v${info.latest}`));
38
38
  try {
39
- const { isSupported, isLaunchAgentInstalled, needsLegacyMigration, installLaunchAgent, restartLaunchAgent } = await import("./launchd-LF2QMSKZ.js");
39
+ const { isSupported, isLaunchAgentInstalled, needsLegacyMigration, installLaunchAgent, restartLaunchAgent } = await import("./launchd-OYXUAVW6.js");
40
40
  if (isSupported()) {
41
41
  if (needsLegacyMigration()) {
42
42
  installLaunchAgent();
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  checkForUpdates,
3
3
  getCurrentVersion
4
- } from "./chunk-F7OXF7Z3.js";
5
- import "./chunk-7LXY5UVC.js";
4
+ } from "./chunk-P2RESJRN.js";
5
+ import "./chunk-DDRLI6JU.js";
6
6
  import "./chunk-4VNS5WPM.js";
7
7
  export {
8
8
  checkForUpdates,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ulpi/cli",
3
- "version": "0.1.3",
3
+ "version": "0.1.5",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "ulpi": "./dist/index.js"
@@ -1,122 +0,0 @@
1
- // ../../packages/ci-engine/dist/index.js
2
- import * as fs4 from "fs";
3
- import * as path3 from "path";
4
- import { execFileSync as execFileSync2 } from "child_process";
5
- function buildPrompt(config, context) {
6
- const sections = [];
7
- sections.push("# Task");
8
- sections.push("");
9
- sections.push(config.instruction);
10
- sections.push("");
11
- if (context.prTitle || context.prBody) {
12
- sections.push("# Pull Request Context");
13
- sections.push("");
14
- if (context.prTitle) sections.push(`**Title:** ${context.prTitle}`);
15
- if (context.prBody) {
16
- sections.push("");
17
- sections.push(context.prBody);
18
- }
19
- sections.push("");
20
- }
21
- sections.push("# Branch Info");
22
- sections.push("");
23
- sections.push(`- **Working branch:** ${config.ref}`);
24
- sections.push(`- **Base branch:** ${config.baseBranch}`);
25
- sections.push(`- **Repository:** ${config.repoFullName}`);
26
- sections.push("");
27
- if (config.jiraContext || context.jiraContext) {
28
- sections.push("# Jira Context");
29
- sections.push("");
30
- sections.push(config.jiraContext ?? context.jiraContext ?? "");
31
- sections.push("");
32
- }
33
- sections.push("# Important Instructions");
34
- sections.push("");
35
- sections.push(
36
- "- You are running in CI mode inside a worker container."
37
- );
38
- sections.push(
39
- "- Work on the existing branch \u2014 do NOT create new branches."
40
- );
41
- sections.push(
42
- "- Commit your changes with clear, descriptive commit messages."
43
- );
44
- sections.push("- Run tests if a test runner is configured.");
45
- sections.push(
46
- "- Do NOT push to the remote \u2014 the orchestrator will handle pushing."
47
- );
48
- sections.push("");
49
- return sections.join("\n");
50
- }
51
- function extractCredentials(claudeConfigDir) {
52
- const configDir = claudeConfigDir ?? path3.join(process.env.HOME ?? "", ".claude");
53
- if (!fs4.existsSync(configDir)) {
54
- throw new Error(
55
- `Claude config directory not found: ${configDir}`
56
- );
57
- }
58
- const tarOutput = execFileSync2(
59
- "tar",
60
- ["-czf", "-", "-C", configDir, "."],
61
- {
62
- encoding: "buffer",
63
- timeout: 3e4,
64
- maxBuffer: 50 * 1024 * 1024
65
- // 50MB limit
66
- }
67
- );
68
- return tarOutput.toString("base64");
69
- }
70
- function writeCredentials(blob, targetDir) {
71
- fs4.mkdirSync(targetDir, { recursive: true });
72
- const tarBuffer = Buffer.from(blob, "base64");
73
- execFileSync2("tar", ["-xzf", "-", "-C", targetDir], {
74
- input: tarBuffer,
75
- timeout: 3e4
76
- });
77
- }
78
- function validateCredentials(blob) {
79
- const tmpDir = fs4.mkdtempSync("/tmp/ulpi-claude-check-");
80
- try {
81
- writeCredentials(blob, tmpDir);
82
- const files = fs4.readdirSync(tmpDir);
83
- return files.length > 0;
84
- } catch {
85
- return false;
86
- } finally {
87
- try {
88
- fs4.rmSync(tmpDir, { recursive: true, force: true });
89
- } catch {
90
- }
91
- }
92
- }
93
- function getCredentialExpiry(blob) {
94
- const tmpDir = fs4.mkdtempSync("/tmp/ulpi-claude-expiry-");
95
- try {
96
- writeCredentials(blob, tmpDir);
97
- const authFile = path3.join(tmpDir, ".credentials.json");
98
- if (fs4.existsSync(authFile)) {
99
- try {
100
- const data = JSON.parse(
101
- fs4.readFileSync(authFile, "utf-8")
102
- );
103
- if (data.expiresAt) return data.expiresAt;
104
- if (data.expires_at) return data.expires_at;
105
- } catch {
106
- }
107
- }
108
- return void 0;
109
- } finally {
110
- try {
111
- fs4.rmSync(tmpDir, { recursive: true, force: true });
112
- } catch {
113
- }
114
- }
115
- }
116
-
117
- export {
118
- buildPrompt,
119
- extractCredentials,
120
- validateCredentials,
121
- getCredentialExpiry
122
- };
@@ -1,367 +0,0 @@
1
- import {
2
- buildPrompt
3
- } from "./chunk-G6SVZ4Q5.js";
4
- import {
5
- external_exports
6
- } from "./chunk-KIKPIH6N.js";
7
- import "./chunk-4VNS5WPM.js";
8
-
9
- // src/commands/ci.ts
10
- import * as fs from "fs";
11
- import * as path from "path";
12
- import { spawn, execFileSync } from "child_process";
13
- import chalk from "chalk";
14
-
15
- // ../../packages/contracts-ci/dist/index.js
16
- var CiCommandTypeSchema = external_exports.enum(["run", "cancel", "fork", "status"]);
17
- var CiCommandSchema = external_exports.object({
18
- type: CiCommandTypeSchema,
19
- instruction: external_exports.string().optional(),
20
- prNumber: external_exports.number().int().positive(),
21
- repoFullName: external_exports.string(),
22
- // "org/repo"
23
- commentId: external_exports.number().int().positive(),
24
- commentAuthor: external_exports.string(),
25
- forkName: external_exports.string().optional()
26
- });
27
- var JobStatusSchema = external_exports.enum([
28
- "queued",
29
- "provisioning",
30
- "running",
31
- "completing",
32
- "completed",
33
- "failed",
34
- "cancelled",
35
- "timed_out"
36
- ]);
37
- var JobConfigSchema = external_exports.object({
38
- repoUrl: external_exports.string().url(),
39
- ref: external_exports.string(),
40
- baseBranch: external_exports.string(),
41
- prNumber: external_exports.number().int().positive(),
42
- repoFullName: external_exports.string(),
43
- instruction: external_exports.string(),
44
- jiraContext: external_exports.string().optional(),
45
- timeoutMinutes: external_exports.number().int().positive().default(30),
46
- envVars: external_exports.record(external_exports.string()).optional()
47
- });
48
- var JobResultSchema = external_exports.object({
49
- jobId: external_exports.string(),
50
- status: JobStatusSchema,
51
- exitCode: external_exports.number().int().optional(),
52
- diff: external_exports.string().optional(),
53
- testOutput: external_exports.string().optional(),
54
- summary: external_exports.string().optional(),
55
- filesChanged: external_exports.array(external_exports.string()),
56
- sessionEvents: external_exports.number().int().default(0),
57
- durationMs: external_exports.number().int(),
58
- error: external_exports.string().optional()
59
- });
60
- var JobSchema = external_exports.object({
61
- id: external_exports.string(),
62
- config: JobConfigSchema,
63
- status: JobStatusSchema,
64
- result: JobResultSchema.optional(),
65
- containerId: external_exports.string().optional(),
66
- workspaceDir: external_exports.string().optional(),
67
- parentJobId: external_exports.string().optional(),
68
- createdAt: external_exports.string().datetime(),
69
- startedAt: external_exports.string().datetime().optional(),
70
- completedAt: external_exports.string().datetime().optional(),
71
- cancelledBy: external_exports.string().optional(),
72
- commentId: external_exports.number().int().positive(),
73
- commentAuthor: external_exports.string()
74
- });
75
- var GitHubAppAuthSchema = external_exports.object({
76
- appId: external_exports.string(),
77
- privateKeyPath: external_exports.string(),
78
- webhookSecret: external_exports.string(),
79
- installationId: external_exports.number().int().positive().optional()
80
- });
81
- var GitHubAuthConfigSchema = external_exports.discriminatedUnion("mode", [
82
- external_exports.object({ mode: external_exports.literal("app"), config: GitHubAppAuthSchema }),
83
- external_exports.object({ mode: external_exports.literal("pat"), token: external_exports.string() })
84
- ]);
85
- var JiraConfigSchema = external_exports.object({
86
- baseUrl: external_exports.string().url(),
87
- email: external_exports.string().email(),
88
- apiToken: external_exports.string(),
89
- defaultProject: external_exports.string().optional()
90
- });
91
- var DockerConfigSchema = external_exports.object({
92
- image: external_exports.string(),
93
- network: external_exports.string().optional(),
94
- memoryLimit: external_exports.string().optional(),
95
- // e.g. "4g"
96
- cpuLimit: external_exports.number().positive().optional(),
97
- // e.g. 2.0
98
- volumeBaseDir: external_exports.string()
99
- });
100
- var SecurityConfigSchema = external_exports.object({
101
- requireWriteAccess: external_exports.boolean().default(true),
102
- allowedRepos: external_exports.array(external_exports.string()).optional(),
103
- allowedAuthors: external_exports.array(external_exports.string()).optional(),
104
- allowedOrgs: external_exports.array(external_exports.string()).optional(),
105
- apiToken: external_exports.string(),
106
- rateLimitWebhook: external_exports.number().int().positive().default(60),
107
- rateLimitApi: external_exports.number().int().positive().default(200)
108
- });
109
- var OrchestratorConfigSchema = external_exports.object({
110
- github: GitHubAuthConfigSchema,
111
- jira: JiraConfigSchema.optional(),
112
- docker: DockerConfigSchema,
113
- jobs: external_exports.object({
114
- maxConcurrent: external_exports.number().int().positive().default(3),
115
- timeoutMinutes: external_exports.number().int().positive().default(30),
116
- retainCompletedHours: external_exports.number().int().positive().default(72)
117
- }),
118
- security: SecurityConfigSchema,
119
- port: external_exports.number().int().positive().default(3e3),
120
- host: external_exports.string().default("0.0.0.0")
121
- });
122
- var ClaudeCredentialsSchema = external_exports.object({
123
- blob: external_exports.string(),
124
- // base64-encoded credentials directory contents
125
- createdAt: external_exports.string().datetime(),
126
- expiresAt: external_exports.string().datetime().optional()
127
- });
128
- var WorkerInputSchema = external_exports.object({
129
- jobId: external_exports.string(),
130
- config: JobConfigSchema,
131
- claudeModel: external_exports.string().optional()
132
- });
133
- var WorkerOutputSchema = external_exports.object({
134
- jobId: external_exports.string(),
135
- result: JobResultSchema
136
- });
137
- var WorkerProgressSchema = external_exports.object({
138
- phase: external_exports.string(),
139
- message: external_exports.string(),
140
- timestamp: external_exports.string().datetime()
141
- });
142
- var JiraTicketSchema = external_exports.object({
143
- key: external_exports.string(),
144
- // e.g. "ABC-123"
145
- summary: external_exports.string(),
146
- description: external_exports.string().optional(),
147
- status: external_exports.string(),
148
- assignee: external_exports.string().optional(),
149
- priority: external_exports.string().optional(),
150
- labels: external_exports.array(external_exports.string()),
151
- acceptanceCriteria: external_exports.string().optional()
152
- });
153
- var JiraReferenceSchema = external_exports.object({
154
- key: external_exports.string(),
155
- url: external_exports.string().url()
156
- });
157
-
158
- // src/commands/ci.ts
159
- async function runCi(args, projectDir) {
160
- const subcommand = args[0];
161
- switch (subcommand) {
162
- case "run":
163
- return runCiJob(args.slice(1));
164
- default:
165
- console.log(`
166
- ${chalk.bold("ulpi ci")} \u2014 CI/PR worker mode
167
-
168
- Usage: ulpi ci <command>
169
-
170
- Commands:
171
- run Execute a CI job (used inside worker containers)
172
-
173
- Options:
174
- --job-id <id> Job identifier
175
- --config <json> Job config (JSON string or from ULPI_JOB_CONFIG env)
176
- --output <path> Output file path for results
177
- --model <model> Claude model to use (default: claude-sonnet-4-20250514)
178
- `.trim());
179
- }
180
- }
181
- async function runCiJob(args) {
182
- let jobId = "";
183
- let configJson = "";
184
- let outputPath = "";
185
- let model = "claude-sonnet-4-20250514";
186
- for (let i = 0; i < args.length; i++) {
187
- switch (args[i]) {
188
- case "--job-id":
189
- jobId = args[++i] ?? "";
190
- break;
191
- case "--config":
192
- configJson = args[++i] ?? "";
193
- break;
194
- case "--output":
195
- outputPath = args[++i] ?? "";
196
- break;
197
- case "--model":
198
- model = args[++i] ?? model;
199
- break;
200
- }
201
- }
202
- jobId = jobId || process.env.ULPI_JOB_ID || "";
203
- configJson = configJson || process.env.ULPI_JOB_CONFIG || "";
204
- outputPath = outputPath || "/workspace/.ulpi-ci/output.json";
205
- if (!jobId) {
206
- console.error(chalk.red("Error: --job-id is required"));
207
- process.exit(1);
208
- }
209
- if (!configJson) {
210
- console.error(chalk.red("Error: --config is required (or set ULPI_JOB_CONFIG env)"));
211
- process.exit(1);
212
- }
213
- let rawConfig;
214
- try {
215
- rawConfig = JSON.parse(configJson);
216
- } catch {
217
- console.error(chalk.red("Error: Invalid JSON in --config"));
218
- process.exit(1);
219
- }
220
- const parseResult = JobConfigSchema.safeParse(rawConfig);
221
- if (!parseResult.success) {
222
- console.error(chalk.red("Error: Invalid job config:"));
223
- console.error(parseResult.error.format());
224
- process.exit(1);
225
- }
226
- const config = parseResult.data;
227
- const startTime = Date.now();
228
- console.log(chalk.blue(`[ulpi-ci] Job ${jobId} starting`));
229
- console.log(chalk.blue(`[ulpi-ci] Instruction: ${config.instruction}`));
230
- console.log(chalk.blue(`[ulpi-ci] Repo: ${config.repoFullName} PR#${config.prNumber}`));
231
- const guardsPath = path.join(process.cwd(), ".ulpi", "guards.yml");
232
- const hasGuards = fs.existsSync(guardsPath);
233
- if (hasGuards) {
234
- console.log(chalk.blue("[ulpi-ci] guards.yml found \u2014 rules will be enforced"));
235
- }
236
- const prompt = buildPrompt(config, {});
237
- const claudePath = findClaudeBinary();
238
- if (!claudePath) {
239
- console.error(chalk.red("Error: claude binary not found in PATH"));
240
- writeOutput(outputPath, {
241
- jobId,
242
- status: "failed",
243
- filesChanged: [],
244
- sessionEvents: 0,
245
- durationMs: Date.now() - startTime,
246
- error: "claude binary not found"
247
- });
248
- process.exit(1);
249
- }
250
- console.log(chalk.blue(`[ulpi-ci] Using claude at: ${claudePath}`));
251
- const claudeArgs = [
252
- "--print",
253
- "--model",
254
- model
255
- ];
256
- console.log(chalk.blue("[ulpi-ci] Spawning Claude Code..."));
257
- const result = await spawnClaude(claudePath, claudeArgs, prompt, config.timeoutMinutes * 60 * 1e3);
258
- const baseBranch = config.baseBranch;
259
- let diff = "";
260
- let filesChanged = [];
261
- try {
262
- diff = execFileSync("git", ["diff", `origin/${baseBranch}...HEAD`], {
263
- cwd: process.cwd(),
264
- encoding: "utf-8",
265
- timeout: 3e4,
266
- maxBuffer: 10 * 1024 * 1024
267
- });
268
- } catch {
269
- }
270
- try {
271
- const output = execFileSync("git", ["diff", "--name-only", `origin/${baseBranch}...HEAD`], {
272
- cwd: process.cwd(),
273
- encoding: "utf-8",
274
- timeout: 3e4
275
- });
276
- filesChanged = output.trim().split("\n").filter(Boolean);
277
- } catch {
278
- }
279
- const jobResult = {
280
- jobId,
281
- status: result.exitCode === 0 ? "completed" : "failed",
282
- exitCode: result.exitCode,
283
- diff: diff || void 0,
284
- summary: result.output.slice(0, 5e3) || void 0,
285
- filesChanged,
286
- sessionEvents: 0,
287
- durationMs: Date.now() - startTime,
288
- error: result.exitCode !== 0 ? `Claude exited with code ${result.exitCode}` : void 0
289
- };
290
- writeOutput(outputPath, jobResult);
291
- console.log(chalk.blue(`[ulpi-ci] Job ${jobId} ${jobResult.status} in ${formatDuration(jobResult.durationMs)}`));
292
- console.log(chalk.blue(`[ulpi-ci] Files changed: ${filesChanged.length}`));
293
- process.exit(result.exitCode === 0 ? 0 : 1);
294
- }
295
- function findClaudeBinary() {
296
- try {
297
- const result = execFileSync("which", ["claude"], { encoding: "utf-8", timeout: 5e3 });
298
- return result.trim();
299
- } catch {
300
- }
301
- const commonPaths = ["/usr/local/bin/claude", "/usr/bin/claude"];
302
- for (const p of commonPaths) {
303
- if (fs.existsSync(p)) return p;
304
- }
305
- return null;
306
- }
307
- function spawnClaude(claudePath, args, prompt, timeoutMs) {
308
- return new Promise((resolve) => {
309
- const proc = spawn(claudePath, args, {
310
- cwd: process.cwd(),
311
- env: process.env,
312
- stdio: ["pipe", "pipe", "pipe"]
313
- });
314
- let stdout = "";
315
- let stderr = "";
316
- proc.stdout.on("data", (data) => {
317
- const text = data.toString();
318
- stdout += text;
319
- process.stdout.write(text);
320
- });
321
- proc.stderr.on("data", (data) => {
322
- const text = data.toString();
323
- stderr += text;
324
- process.stderr.write(text);
325
- });
326
- proc.stdin.write(prompt);
327
- proc.stdin.end();
328
- const timer = setTimeout(() => {
329
- console.log(chalk.yellow("[ulpi-ci] Timeout reached, killing Claude process..."));
330
- proc.kill("SIGTERM");
331
- setTimeout(() => {
332
- if (!proc.killed) proc.kill("SIGKILL");
333
- }, 1e4);
334
- }, timeoutMs);
335
- proc.on("close", (code) => {
336
- clearTimeout(timer);
337
- resolve({ exitCode: code ?? 1, output: stdout });
338
- });
339
- const onSigterm = () => {
340
- console.log(chalk.yellow("[ulpi-ci] Received SIGTERM, stopping Claude..."));
341
- proc.kill("SIGTERM");
342
- };
343
- process.on("SIGTERM", onSigterm);
344
- proc.on("close", () => {
345
- process.removeListener("SIGTERM", onSigterm);
346
- });
347
- });
348
- }
349
- function writeOutput(outputPath, result) {
350
- try {
351
- const dir = path.dirname(outputPath);
352
- fs.mkdirSync(dir, { recursive: true });
353
- fs.writeFileSync(outputPath, JSON.stringify({ jobId: result.jobId, result }, null, 2), "utf-8");
354
- } catch (err) {
355
- console.error(chalk.red(`Error writing output: ${err instanceof Error ? err.message : String(err)}`));
356
- }
357
- }
358
- function formatDuration(ms) {
359
- const seconds = Math.floor(ms / 1e3);
360
- if (seconds < 60) return `${seconds}s`;
361
- const minutes = Math.floor(seconds / 60);
362
- const remainingSeconds = seconds % 60;
363
- return `${minutes}m ${remainingSeconds}s`;
364
- }
365
- export {
366
- runCi
367
- };
@@ -1,18 +0,0 @@
1
- import {
2
- createApiServer
3
- } from "./chunk-2VYFVYJL.js";
4
- import "./chunk-MIAQVCFW.js";
5
- import "./chunk-2MZER6ND.js";
6
- import "./chunk-3SBPZRB5.js";
7
- import "./chunk-2CLNOKPA.js";
8
- import "./chunk-SPOI23SB.js";
9
- import "./chunk-6OCEY7JY.js";
10
- import "./chunk-SIAQVRKG.js";
11
- import "./chunk-JGBXM5NC.js";
12
- import "./chunk-YM2HV4IA.js";
13
- import "./chunk-KIKPIH6N.js";
14
- import "./chunk-7LXY5UVC.js";
15
- import "./chunk-4VNS5WPM.js";
16
- export {
17
- createApiServer
18
- };
@@ -1,11 +0,0 @@
1
- import {
2
- attachWebSocket
3
- } from "./chunk-7AL4DOEJ.js";
4
- import "./chunk-MIAQVCFW.js";
5
- import "./chunk-SPOI23SB.js";
6
- import "./chunk-YM2HV4IA.js";
7
- import "./chunk-7LXY5UVC.js";
8
- import "./chunk-4VNS5WPM.js";
9
- export {
10
- attachWebSocket
11
- };