@ulpi/cli 0.1.4 → 0.1.6
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.
- package/LICENSE +21 -0
- package/dist/{auth-PN7TMQHV-2W4ICG64.js → auth-FWM7MM4Q-VZC3U2XZ.js} +1 -1
- package/dist/{auth-ECQ3IB4E.js → auth-HDK7ECJL.js} +2 -1
- package/dist/{chunk-3SBPZRB5.js → chunk-3BCW6ABU.js} +402 -142
- package/dist/{chunk-JGBXM5NC.js → chunk-3WB5CXH4.js} +180 -5
- package/dist/{chunk-2HEE5OKX.js → chunk-4UCJIAOU.js} +2 -2
- package/dist/chunk-4XTHZVDS.js +109 -0
- package/dist/chunk-4ZPOZULQ.js +6522 -0
- package/dist/{chunk-SIAQVRKG.js → chunk-5MI5GIXM.js} +48 -2
- package/dist/{chunk-KLEASXUR.js → chunk-6ZL6NXMV.js} +1 -1
- package/dist/chunk-76D3BYJD.js +221 -0
- package/dist/{chunk-ZLYRPD7I.js → chunk-AWOSRA5F.js} +1 -1
- package/dist/{chunk-PDR55ZNW.js → chunk-BFEKZZHM.js} +274 -57
- package/dist/chunk-C7CLUQI6.js +1286 -0
- package/dist/{chunk-7AL4DOEJ.js → chunk-E3B5NROU.js} +7 -7
- package/dist/chunk-EJ7TW77N.js +1418 -0
- package/dist/{chunk-5J6NLQUN.js → chunk-IV6MWETF.js} +383 -168
- package/dist/chunk-IZPJHSPX.js +1478 -0
- package/dist/chunk-JLHNLM3C.js +228 -0
- package/dist/{chunk-BZL5H4YQ.js → chunk-KYYI23AQ.js} +2 -2
- package/dist/{chunk-2CLNOKPA.js → chunk-RSFJ6QSR.js} +18 -0
- package/dist/chunk-S6ANCSYO.js +1271 -0
- package/dist/chunk-SEU7WWNQ.js +1251 -0
- package/dist/chunk-SNQ7NAIS.js +453 -0
- package/dist/{ulpi-RMMCUAGP-JCJ273T6.js → chunk-TSLDGT5O.js} +73 -35
- package/dist/{chunk-SPOI23SB.js → chunk-UXHCHOWQ.js} +83 -62
- package/dist/chunk-V2H5D6Y3.js +146 -0
- package/dist/{chunk-QJ5GSMEC.js → chunk-VVEDXI7E.js} +2 -1
- package/dist/chunk-VXH5Y4FO.js +6761 -0
- package/dist/chunk-WED4LM5N.js +322 -0
- package/dist/{chunk-74WVVWJ4.js → chunk-YOKL7RB5.js} +184 -15
- package/dist/chunk-Z53CAR7G.js +298 -0
- package/dist/ci-X3U2W4HC.js +854 -0
- package/dist/cloud-2F3NLVHN.js +274 -0
- package/dist/{codemap-RKSD4MIE.js → codemap-XNGMAF3F.js} +37 -37
- package/dist/codex-MB5YTMRT.js +132 -0
- package/dist/{config-EGAXXCGL.js → config-OOELBYTH.js} +1 -1
- package/dist/dist-2BJYR5EI.js +59 -0
- package/dist/dist-2K7IEVTA.js +43 -0
- package/dist/dist-3EIQTZHT.js +1380 -0
- package/dist/{dist-YA2BWZB2.js → dist-4U5L2X2C.js} +2 -2
- package/dist/{dist-UKMCJBB2.js → dist-54KAMNLO.js} +16 -15
- package/dist/dist-6M4MZWZW.js +58 -0
- package/dist/dist-6X576SU2.js +27 -0
- package/dist/dist-7QOEYLFX.js +103 -0
- package/dist/dist-AYBGHEDY.js +2541 -0
- package/dist/dist-EK45QNEM.js +45 -0
- package/dist/{dist-CS2VKNYS.js → dist-FKFEJRPX.js} +16 -15
- package/dist/dist-GTEJUBBT.js +66 -0
- package/dist/dist-HA74OKJZ.js +40 -0
- package/dist/dist-HU5RZAON.js +48 -0
- package/dist/dist-IYE3OBRB.js +374 -0
- package/dist/{dist-GJYT2OQV.js → dist-JLU26AB6.js} +12 -9
- package/dist/{dist-6G7JC2RA.js → dist-KUCI6JFE.js} +49 -9
- package/dist/dist-NUEMFZFL.js +33 -0
- package/dist/{dist-RKOGLK7R.js → dist-NUXMDXZ3.js} +31 -3
- package/dist/{dist-QAU3LGJN.js → dist-YCNWHSLN.js} +15 -5
- package/dist/{dist-CB5D5LMO.js → dist-YFFG2ZD6.js} +9 -16
- package/dist/dist-ZG4OKCSR.js +15 -0
- package/dist/doctor-SI4LLLDZ.js +345 -0
- package/dist/{export-import-4A5MWLIA.js → export-import-JFQH4KSJ.js} +1 -1
- package/dist/{history-3MOBX4MA.js → history-5NE46ZAH.js} +7 -7
- package/dist/hooks-installer-UN5JZLDQ.js +19 -0
- package/dist/index.js +395 -619
- package/dist/{init-6CH4HV5T.js → init-5FK3VKRT.js} +79 -13
- package/dist/job-HIDMAFW2.js +376 -0
- package/dist/jobs.memory-PLMMSFHB-VBECCTHN.js +33 -0
- package/dist/kiro-VMUHDFGK.js +153 -0
- package/dist/{launchd-LF2QMSKZ.js → launchd-6AWT54HR.js} +9 -17
- package/dist/mcp-PDUD7SGP.js +249 -0
- package/dist/mcp-installer-PQU3XOGO.js +259 -0
- package/dist/mcp-setup-OA7IB3H3.js +263 -0
- package/dist/{memory-Y6OZTXJ2.js → memory-ZNAEAK3B.js} +17 -17
- package/dist/{ollama-3XCUZMZT-FYKHW4TZ.js → ollama-3XCUZMZT-4JMH6B7P.js} +1 -1
- package/dist/{openai-E7G2YAHU-UYY4ZWON.js → openai-E7G2YAHU-T3HMBPH7.js} +2 -2
- package/dist/portal-JYWVHXDU.js +210 -0
- package/dist/prd-Q4J5NVAR.js +408 -0
- package/dist/repos-WWZXNN3P.js +271 -0
- package/dist/review-integration-5WHEJU2A.js +14 -0
- package/dist/{rules-E427DKYJ.js → rules-Y4VSOY5Y.js} +3 -3
- package/dist/run-VPNXEIBY.js +687 -0
- package/dist/server-COL4AXKU-P7S7NNF6.js +11 -0
- package/dist/server-KKSETHDV-XSSLEENT.js +20 -0
- package/dist/{skills-CX73O3IV.js → skills-QEYU2N27.js} +4 -2
- package/dist/start-JYOEL7AJ.js +303 -0
- package/dist/{status-4DFHDJMN.js → status-BHQYYGAL.js} +2 -2
- package/dist/{templates-U7T6MARD.js → templates-CBRUJ66V.js} +4 -3
- package/dist/tui-DP7736EX.js +61 -0
- package/dist/ulpi-5EN6JCAS-LFE3WSL4.js +10 -0
- package/dist/{uninstall-6SW35IK4.js → uninstall-ICUV6DDV.js} +3 -3
- package/dist/{update-M6IBJNYP.js → update-7ZMAYRBH.js} +3 -3
- package/dist/{version-checker-Q6YTYAGP.js → version-checker-4ZFMZA7Y.js} +2 -2
- package/package.json +39 -31
- package/dist/chunk-2MZER6ND.js +0 -415
- package/dist/chunk-2VYFVYJL.js +0 -4273
- package/dist/chunk-6OCEY7JY.js +0 -422
- package/dist/chunk-7LXY5UVC.js +0 -330
- package/dist/chunk-B55DDP24.js +0 -136
- package/dist/chunk-JWUUVXIV.js +0 -13694
- package/dist/chunk-MIAQVCFW.js +0 -39
- package/dist/chunk-YM2HV4IA.js +0 -505
- package/dist/ci-STSL2LSP.js +0 -370
- package/dist/mcp-installer-NQCGKQ23.js +0 -124
- package/dist/projects-ATHDD3D6.js +0 -271
- package/dist/review-ADUPV3PN.js +0 -152
- package/dist/server-USLHY6GH-AEOJC5ST.js +0 -18
- package/dist/server-X5P6WH2M-7K2RY34N.js +0 -11
- package/dist/skills/ulpi-generate-guardian/SKILL.md +0 -750
- package/dist/skills/ulpi-generate-guardian/references/framework-rules.md +0 -849
- package/dist/skills/ulpi-generate-guardian/references/language-rules.md +0 -591
- package/dist/ui-OWXZ3YSR.js +0 -167
- package/dist/ui.html +0 -698
package/dist/ci-STSL2LSP.js
DELETED
|
@@ -1,370 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
buildPrompt
|
|
3
|
-
} from "./chunk-B55DDP24.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
|
-
// Host path — used for Docker bind mounts
|
|
100
|
-
localVolumeBaseDir: external_exports.string().optional()
|
|
101
|
-
// Container-local path — used for fs ops (defaults to volumeBaseDir)
|
|
102
|
-
});
|
|
103
|
-
var SecurityConfigSchema = external_exports.object({
|
|
104
|
-
requireWriteAccess: external_exports.boolean().default(true),
|
|
105
|
-
allowedRepos: external_exports.array(external_exports.string()).optional(),
|
|
106
|
-
allowedAuthors: external_exports.array(external_exports.string()).optional(),
|
|
107
|
-
allowedOrgs: external_exports.array(external_exports.string()).optional(),
|
|
108
|
-
apiToken: external_exports.string(),
|
|
109
|
-
rateLimitWebhook: external_exports.number().int().positive().default(60),
|
|
110
|
-
rateLimitApi: external_exports.number().int().positive().default(200)
|
|
111
|
-
});
|
|
112
|
-
var OrchestratorConfigSchema = external_exports.object({
|
|
113
|
-
github: GitHubAuthConfigSchema,
|
|
114
|
-
jira: JiraConfigSchema.optional(),
|
|
115
|
-
docker: DockerConfigSchema,
|
|
116
|
-
jobs: external_exports.object({
|
|
117
|
-
maxConcurrent: external_exports.number().int().positive().default(3),
|
|
118
|
-
timeoutMinutes: external_exports.number().int().positive().default(30),
|
|
119
|
-
retainCompletedHours: external_exports.number().int().positive().default(72)
|
|
120
|
-
}),
|
|
121
|
-
security: SecurityConfigSchema,
|
|
122
|
-
port: external_exports.number().int().positive().default(3e3),
|
|
123
|
-
host: external_exports.string().default("0.0.0.0")
|
|
124
|
-
});
|
|
125
|
-
var ClaudeCredentialsSchema = external_exports.object({
|
|
126
|
-
blob: external_exports.string(),
|
|
127
|
-
// base64-encoded credentials directory contents
|
|
128
|
-
createdAt: external_exports.string().datetime(),
|
|
129
|
-
expiresAt: external_exports.string().datetime().optional()
|
|
130
|
-
});
|
|
131
|
-
var WorkerInputSchema = external_exports.object({
|
|
132
|
-
jobId: external_exports.string(),
|
|
133
|
-
config: JobConfigSchema,
|
|
134
|
-
claudeModel: external_exports.string().optional()
|
|
135
|
-
});
|
|
136
|
-
var WorkerOutputSchema = external_exports.object({
|
|
137
|
-
jobId: external_exports.string(),
|
|
138
|
-
result: JobResultSchema
|
|
139
|
-
});
|
|
140
|
-
var WorkerProgressSchema = external_exports.object({
|
|
141
|
-
phase: external_exports.string(),
|
|
142
|
-
message: external_exports.string(),
|
|
143
|
-
timestamp: external_exports.string().datetime()
|
|
144
|
-
});
|
|
145
|
-
var JiraTicketSchema = external_exports.object({
|
|
146
|
-
key: external_exports.string(),
|
|
147
|
-
// e.g. "ABC-123"
|
|
148
|
-
summary: external_exports.string(),
|
|
149
|
-
description: external_exports.string().optional(),
|
|
150
|
-
status: external_exports.string(),
|
|
151
|
-
assignee: external_exports.string().optional(),
|
|
152
|
-
priority: external_exports.string().optional(),
|
|
153
|
-
labels: external_exports.array(external_exports.string()),
|
|
154
|
-
acceptanceCriteria: external_exports.string().optional()
|
|
155
|
-
});
|
|
156
|
-
var JiraReferenceSchema = external_exports.object({
|
|
157
|
-
key: external_exports.string(),
|
|
158
|
-
url: external_exports.string().url()
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// src/commands/ci.ts
|
|
162
|
-
async function runCi(args, projectDir) {
|
|
163
|
-
const subcommand = args[0];
|
|
164
|
-
switch (subcommand) {
|
|
165
|
-
case "run":
|
|
166
|
-
return runCiJob(args.slice(1));
|
|
167
|
-
default:
|
|
168
|
-
console.log(`
|
|
169
|
-
${chalk.bold("ulpi ci")} \u2014 CI/PR worker mode
|
|
170
|
-
|
|
171
|
-
Usage: ulpi ci <command>
|
|
172
|
-
|
|
173
|
-
Commands:
|
|
174
|
-
run Execute a CI job (used inside worker containers)
|
|
175
|
-
|
|
176
|
-
Options:
|
|
177
|
-
--job-id <id> Job identifier
|
|
178
|
-
--config <json> Job config (JSON string or from ULPI_JOB_CONFIG env)
|
|
179
|
-
--output <path> Output file path for results
|
|
180
|
-
--model <model> Claude model to use (default: claude-sonnet-4-20250514)
|
|
181
|
-
`.trim());
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
async function runCiJob(args) {
|
|
185
|
-
let jobId = "";
|
|
186
|
-
let configJson = "";
|
|
187
|
-
let outputPath = "";
|
|
188
|
-
let model = "claude-sonnet-4-20250514";
|
|
189
|
-
for (let i = 0; i < args.length; i++) {
|
|
190
|
-
switch (args[i]) {
|
|
191
|
-
case "--job-id":
|
|
192
|
-
jobId = args[++i] ?? "";
|
|
193
|
-
break;
|
|
194
|
-
case "--config":
|
|
195
|
-
configJson = args[++i] ?? "";
|
|
196
|
-
break;
|
|
197
|
-
case "--output":
|
|
198
|
-
outputPath = args[++i] ?? "";
|
|
199
|
-
break;
|
|
200
|
-
case "--model":
|
|
201
|
-
model = args[++i] ?? model;
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
jobId = jobId || process.env.ULPI_JOB_ID || "";
|
|
206
|
-
configJson = configJson || process.env.ULPI_JOB_CONFIG || "";
|
|
207
|
-
outputPath = outputPath || "/workspace/.ulpi-ci/output.json";
|
|
208
|
-
if (!jobId) {
|
|
209
|
-
console.error(chalk.red("Error: --job-id is required"));
|
|
210
|
-
process.exit(1);
|
|
211
|
-
}
|
|
212
|
-
if (!configJson) {
|
|
213
|
-
console.error(chalk.red("Error: --config is required (or set ULPI_JOB_CONFIG env)"));
|
|
214
|
-
process.exit(1);
|
|
215
|
-
}
|
|
216
|
-
let rawConfig;
|
|
217
|
-
try {
|
|
218
|
-
rawConfig = JSON.parse(configJson);
|
|
219
|
-
} catch {
|
|
220
|
-
console.error(chalk.red("Error: Invalid JSON in --config"));
|
|
221
|
-
process.exit(1);
|
|
222
|
-
}
|
|
223
|
-
const parseResult = JobConfigSchema.safeParse(rawConfig);
|
|
224
|
-
if (!parseResult.success) {
|
|
225
|
-
console.error(chalk.red("Error: Invalid job config:"));
|
|
226
|
-
console.error(parseResult.error.format());
|
|
227
|
-
process.exit(1);
|
|
228
|
-
}
|
|
229
|
-
const config = parseResult.data;
|
|
230
|
-
const startTime = Date.now();
|
|
231
|
-
console.log(chalk.blue(`[ulpi-ci] Job ${jobId} starting`));
|
|
232
|
-
console.log(chalk.blue(`[ulpi-ci] Instruction: ${config.instruction}`));
|
|
233
|
-
console.log(chalk.blue(`[ulpi-ci] Repo: ${config.repoFullName} PR#${config.prNumber}`));
|
|
234
|
-
const guardsPath = path.join(process.cwd(), ".ulpi", "guards.yml");
|
|
235
|
-
const hasGuards = fs.existsSync(guardsPath);
|
|
236
|
-
if (hasGuards) {
|
|
237
|
-
console.log(chalk.blue("[ulpi-ci] guards.yml found \u2014 rules will be enforced"));
|
|
238
|
-
}
|
|
239
|
-
const prompt = buildPrompt(config, {});
|
|
240
|
-
const claudePath = findClaudeBinary();
|
|
241
|
-
if (!claudePath) {
|
|
242
|
-
console.error(chalk.red("Error: claude binary not found in PATH"));
|
|
243
|
-
writeOutput(outputPath, {
|
|
244
|
-
jobId,
|
|
245
|
-
status: "failed",
|
|
246
|
-
filesChanged: [],
|
|
247
|
-
sessionEvents: 0,
|
|
248
|
-
durationMs: Date.now() - startTime,
|
|
249
|
-
error: "claude binary not found"
|
|
250
|
-
});
|
|
251
|
-
process.exit(1);
|
|
252
|
-
}
|
|
253
|
-
console.log(chalk.blue(`[ulpi-ci] Using claude at: ${claudePath}`));
|
|
254
|
-
const claudeArgs = [
|
|
255
|
-
"--print",
|
|
256
|
-
"--model",
|
|
257
|
-
model
|
|
258
|
-
];
|
|
259
|
-
console.log(chalk.blue("[ulpi-ci] Spawning Claude Code..."));
|
|
260
|
-
const result = await spawnClaude(claudePath, claudeArgs, prompt, config.timeoutMinutes * 60 * 1e3);
|
|
261
|
-
const baseBranch = config.baseBranch;
|
|
262
|
-
let diff = "";
|
|
263
|
-
let filesChanged = [];
|
|
264
|
-
try {
|
|
265
|
-
diff = execFileSync("git", ["diff", `origin/${baseBranch}...HEAD`], {
|
|
266
|
-
cwd: process.cwd(),
|
|
267
|
-
encoding: "utf-8",
|
|
268
|
-
timeout: 3e4,
|
|
269
|
-
maxBuffer: 10 * 1024 * 1024
|
|
270
|
-
});
|
|
271
|
-
} catch {
|
|
272
|
-
}
|
|
273
|
-
try {
|
|
274
|
-
const output = execFileSync("git", ["diff", "--name-only", `origin/${baseBranch}...HEAD`], {
|
|
275
|
-
cwd: process.cwd(),
|
|
276
|
-
encoding: "utf-8",
|
|
277
|
-
timeout: 3e4
|
|
278
|
-
});
|
|
279
|
-
filesChanged = output.trim().split("\n").filter(Boolean);
|
|
280
|
-
} catch {
|
|
281
|
-
}
|
|
282
|
-
const jobResult = {
|
|
283
|
-
jobId,
|
|
284
|
-
status: result.exitCode === 0 ? "completed" : "failed",
|
|
285
|
-
exitCode: result.exitCode,
|
|
286
|
-
diff: diff || void 0,
|
|
287
|
-
summary: result.output.slice(0, 5e3) || void 0,
|
|
288
|
-
filesChanged,
|
|
289
|
-
sessionEvents: 0,
|
|
290
|
-
durationMs: Date.now() - startTime,
|
|
291
|
-
error: result.exitCode !== 0 ? `Claude exited with code ${result.exitCode}` : void 0
|
|
292
|
-
};
|
|
293
|
-
writeOutput(outputPath, jobResult);
|
|
294
|
-
console.log(chalk.blue(`[ulpi-ci] Job ${jobId} ${jobResult.status} in ${formatDuration(jobResult.durationMs)}`));
|
|
295
|
-
console.log(chalk.blue(`[ulpi-ci] Files changed: ${filesChanged.length}`));
|
|
296
|
-
process.exit(result.exitCode === 0 ? 0 : 1);
|
|
297
|
-
}
|
|
298
|
-
function findClaudeBinary() {
|
|
299
|
-
try {
|
|
300
|
-
const result = execFileSync("which", ["claude"], { encoding: "utf-8", timeout: 5e3 });
|
|
301
|
-
return result.trim();
|
|
302
|
-
} catch {
|
|
303
|
-
}
|
|
304
|
-
const commonPaths = ["/usr/local/bin/claude", "/usr/bin/claude"];
|
|
305
|
-
for (const p of commonPaths) {
|
|
306
|
-
if (fs.existsSync(p)) return p;
|
|
307
|
-
}
|
|
308
|
-
return null;
|
|
309
|
-
}
|
|
310
|
-
function spawnClaude(claudePath, args, prompt, timeoutMs) {
|
|
311
|
-
return new Promise((resolve) => {
|
|
312
|
-
const proc = spawn(claudePath, args, {
|
|
313
|
-
cwd: process.cwd(),
|
|
314
|
-
env: process.env,
|
|
315
|
-
stdio: ["pipe", "pipe", "pipe"]
|
|
316
|
-
});
|
|
317
|
-
let stdout = "";
|
|
318
|
-
let stderr = "";
|
|
319
|
-
proc.stdout.on("data", (data) => {
|
|
320
|
-
const text = data.toString();
|
|
321
|
-
stdout += text;
|
|
322
|
-
process.stdout.write(text);
|
|
323
|
-
});
|
|
324
|
-
proc.stderr.on("data", (data) => {
|
|
325
|
-
const text = data.toString();
|
|
326
|
-
stderr += text;
|
|
327
|
-
process.stderr.write(text);
|
|
328
|
-
});
|
|
329
|
-
proc.stdin.write(prompt);
|
|
330
|
-
proc.stdin.end();
|
|
331
|
-
const timer = setTimeout(() => {
|
|
332
|
-
console.log(chalk.yellow("[ulpi-ci] Timeout reached, killing Claude process..."));
|
|
333
|
-
proc.kill("SIGTERM");
|
|
334
|
-
setTimeout(() => {
|
|
335
|
-
if (!proc.killed) proc.kill("SIGKILL");
|
|
336
|
-
}, 1e4);
|
|
337
|
-
}, timeoutMs);
|
|
338
|
-
proc.on("close", (code) => {
|
|
339
|
-
clearTimeout(timer);
|
|
340
|
-
resolve({ exitCode: code ?? 1, output: stdout });
|
|
341
|
-
});
|
|
342
|
-
const onSigterm = () => {
|
|
343
|
-
console.log(chalk.yellow("[ulpi-ci] Received SIGTERM, stopping Claude..."));
|
|
344
|
-
proc.kill("SIGTERM");
|
|
345
|
-
};
|
|
346
|
-
process.on("SIGTERM", onSigterm);
|
|
347
|
-
proc.on("close", () => {
|
|
348
|
-
process.removeListener("SIGTERM", onSigterm);
|
|
349
|
-
});
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
function writeOutput(outputPath, result) {
|
|
353
|
-
try {
|
|
354
|
-
const dir = path.dirname(outputPath);
|
|
355
|
-
fs.mkdirSync(dir, { recursive: true });
|
|
356
|
-
fs.writeFileSync(outputPath, JSON.stringify({ jobId: result.jobId, result }, null, 2), "utf-8");
|
|
357
|
-
} catch (err) {
|
|
358
|
-
console.error(chalk.red(`Error writing output: ${err instanceof Error ? err.message : String(err)}`));
|
|
359
|
-
}
|
|
360
|
-
}
|
|
361
|
-
function formatDuration(ms) {
|
|
362
|
-
const seconds = Math.floor(ms / 1e3);
|
|
363
|
-
if (seconds < 60) return `${seconds}s`;
|
|
364
|
-
const minutes = Math.floor(seconds / 60);
|
|
365
|
-
const remainingSeconds = seconds % 60;
|
|
366
|
-
return `${minutes}m ${remainingSeconds}s`;
|
|
367
|
-
}
|
|
368
|
-
export {
|
|
369
|
-
runCi
|
|
370
|
-
};
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getBinaryPath
|
|
3
|
-
} from "./chunk-7LXY5UVC.js";
|
|
4
|
-
import "./chunk-4VNS5WPM.js";
|
|
5
|
-
|
|
6
|
-
// src/mcp-installer.ts
|
|
7
|
-
import * as fs from "fs";
|
|
8
|
-
import * as path from "path";
|
|
9
|
-
function installMcpServer(projectDir) {
|
|
10
|
-
const settingsDir = path.join(projectDir, ".claude");
|
|
11
|
-
const settingsPath = path.join(settingsDir, "settings.local.json");
|
|
12
|
-
let settings = {};
|
|
13
|
-
if (fs.existsSync(settingsPath)) {
|
|
14
|
-
try {
|
|
15
|
-
settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
16
|
-
} catch {
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
const mcpServers = settings.mcpServers ?? {};
|
|
20
|
-
if (mcpServers["codemap"]) {
|
|
21
|
-
return { installed: false, message: "CodeMap MCP server already registered" };
|
|
22
|
-
}
|
|
23
|
-
const binary = getBinaryPath();
|
|
24
|
-
const parts = binary.split(" ");
|
|
25
|
-
const command = parts[0];
|
|
26
|
-
const baseArgs = parts.length > 1 ? [...parts.slice(1).map((a) => a.replace(/"/g, "")), "codemap", "serve"] : ["codemap", "serve"];
|
|
27
|
-
mcpServers["codemap"] = {
|
|
28
|
-
command,
|
|
29
|
-
args: baseArgs
|
|
30
|
-
};
|
|
31
|
-
settings.mcpServers = mcpServers;
|
|
32
|
-
fs.mkdirSync(settingsDir, { recursive: true });
|
|
33
|
-
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
34
|
-
return { installed: true, message: "CodeMap MCP server registered in .claude/settings.local.json" };
|
|
35
|
-
}
|
|
36
|
-
function uninstallMcpServer(projectDir) {
|
|
37
|
-
const settingsPath = path.join(projectDir, ".claude", "settings.local.json");
|
|
38
|
-
if (!fs.existsSync(settingsPath)) return;
|
|
39
|
-
try {
|
|
40
|
-
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
41
|
-
const mcpServers = settings.mcpServers;
|
|
42
|
-
if (mcpServers?.["codemap"]) {
|
|
43
|
-
delete mcpServers["codemap"];
|
|
44
|
-
if (Object.keys(mcpServers).length === 0) {
|
|
45
|
-
delete settings.mcpServers;
|
|
46
|
-
}
|
|
47
|
-
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
48
|
-
}
|
|
49
|
-
} catch {
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
function isMcpServerInstalled(projectDir) {
|
|
53
|
-
const settingsPath = path.join(projectDir, ".claude", "settings.local.json");
|
|
54
|
-
if (!fs.existsSync(settingsPath)) return false;
|
|
55
|
-
try {
|
|
56
|
-
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
57
|
-
const mcpServers = settings.mcpServers;
|
|
58
|
-
return !!mcpServers?.["codemap"];
|
|
59
|
-
} catch {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
function installMemoryMcpServer(projectDir) {
|
|
64
|
-
const settingsDir = path.join(projectDir, ".claude");
|
|
65
|
-
const settingsPath = path.join(settingsDir, "settings.local.json");
|
|
66
|
-
let settings = {};
|
|
67
|
-
if (fs.existsSync(settingsPath)) {
|
|
68
|
-
try {
|
|
69
|
-
settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
70
|
-
} catch {
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
const mcpServers = settings.mcpServers ?? {};
|
|
74
|
-
if (mcpServers["memory"]) {
|
|
75
|
-
return { installed: false, message: "Memory MCP server already registered" };
|
|
76
|
-
}
|
|
77
|
-
const binary = getBinaryPath();
|
|
78
|
-
const parts = binary.split(" ");
|
|
79
|
-
const command = parts[0];
|
|
80
|
-
const baseArgs = parts.length > 1 ? [...parts.slice(1).map((a) => a.replace(/"/g, "")), "memory", "serve"] : ["memory", "serve"];
|
|
81
|
-
mcpServers["memory"] = {
|
|
82
|
-
command,
|
|
83
|
-
args: baseArgs
|
|
84
|
-
};
|
|
85
|
-
settings.mcpServers = mcpServers;
|
|
86
|
-
fs.mkdirSync(settingsDir, { recursive: true });
|
|
87
|
-
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
88
|
-
return { installed: true, message: "Memory MCP server registered in .claude/settings.local.json" };
|
|
89
|
-
}
|
|
90
|
-
function uninstallMemoryMcpServer(projectDir) {
|
|
91
|
-
const settingsPath = path.join(projectDir, ".claude", "settings.local.json");
|
|
92
|
-
if (!fs.existsSync(settingsPath)) return;
|
|
93
|
-
try {
|
|
94
|
-
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
95
|
-
const mcpServers = settings.mcpServers;
|
|
96
|
-
if (mcpServers?.["memory"]) {
|
|
97
|
-
delete mcpServers["memory"];
|
|
98
|
-
if (Object.keys(mcpServers).length === 0) {
|
|
99
|
-
delete settings.mcpServers;
|
|
100
|
-
}
|
|
101
|
-
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + "\n", "utf-8");
|
|
102
|
-
}
|
|
103
|
-
} catch {
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
function isMemoryMcpServerInstalled(projectDir) {
|
|
107
|
-
const settingsPath = path.join(projectDir, ".claude", "settings.local.json");
|
|
108
|
-
if (!fs.existsSync(settingsPath)) return false;
|
|
109
|
-
try {
|
|
110
|
-
const settings = JSON.parse(fs.readFileSync(settingsPath, "utf-8"));
|
|
111
|
-
const mcpServers = settings.mcpServers;
|
|
112
|
-
return !!mcpServers?.["memory"];
|
|
113
|
-
} catch {
|
|
114
|
-
return false;
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
export {
|
|
118
|
-
installMcpServer,
|
|
119
|
-
installMemoryMcpServer,
|
|
120
|
-
isMcpServerInstalled,
|
|
121
|
-
isMemoryMcpServerInstalled,
|
|
122
|
-
uninstallMcpServer,
|
|
123
|
-
uninstallMemoryMcpServer
|
|
124
|
-
};
|