@nk070281sjv/cli 2.3.5 → 2.3.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/dist/index.js +150 -14
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -30779,7 +30779,7 @@ ${hint}
|
|
|
30779
30779
|
}
|
|
30780
30780
|
|
|
30781
30781
|
// src/lib/version.ts
|
|
30782
|
-
var CLI_VERSION = true ? "2.3.
|
|
30782
|
+
var CLI_VERSION = true ? "2.3.6" : createRequire(import.meta.url)("../../package.json").version;
|
|
30783
30783
|
|
|
30784
30784
|
// src/lib/deps.ts
|
|
30785
30785
|
init_src();
|
|
@@ -37516,6 +37516,9 @@ function buildOpenCodeRunArgs(input) {
|
|
|
37516
37516
|
if (input.attachUrl) {
|
|
37517
37517
|
base.push("--attach", input.attachUrl, "--dir", input.cwd);
|
|
37518
37518
|
}
|
|
37519
|
+
if (input.pure) {
|
|
37520
|
+
base.push("--pure");
|
|
37521
|
+
}
|
|
37519
37522
|
const limit = input.promptArgvLimit ?? DEFAULT_PROMPT_ARGV_LIMIT;
|
|
37520
37523
|
if (input.prompt.length <= limit) {
|
|
37521
37524
|
return [...base, input.prompt];
|
|
@@ -37534,15 +37537,25 @@ function parseOpenCodeJsonEvents(stdout) {
|
|
|
37534
37537
|
}
|
|
37535
37538
|
return events;
|
|
37536
37539
|
}
|
|
37540
|
+
function extractOpenCodeText(events) {
|
|
37541
|
+
return events.map((event) => {
|
|
37542
|
+
if (!isRecord(event)) return "";
|
|
37543
|
+
const part = event.part;
|
|
37544
|
+
if (!isRecord(part) || part.type !== "text") return "";
|
|
37545
|
+
return typeof part.text === "string" ? part.text : "";
|
|
37546
|
+
}).join("").trimStart();
|
|
37547
|
+
}
|
|
37537
37548
|
var OpenCodeProcessRunner = class {
|
|
37538
37549
|
spawn;
|
|
37539
37550
|
promptArgvLimit;
|
|
37540
37551
|
serveReadyTimeoutMs;
|
|
37552
|
+
pure;
|
|
37541
37553
|
server;
|
|
37542
37554
|
constructor(options = {}) {
|
|
37543
37555
|
this.spawn = options.spawn ?? spawnBinary;
|
|
37544
37556
|
this.promptArgvLimit = options.promptArgvLimit ?? DEFAULT_PROMPT_ARGV_LIMIT;
|
|
37545
37557
|
this.serveReadyTimeoutMs = options.serveReadyTimeoutMs ?? 15e3;
|
|
37558
|
+
this.pure = options.pure ?? true;
|
|
37546
37559
|
}
|
|
37547
37560
|
async run(request, signal) {
|
|
37548
37561
|
const prompt = await readFile2(request.promptPath, "utf-8");
|
|
@@ -37555,7 +37568,8 @@ var OpenCodeProcessRunner = class {
|
|
|
37555
37568
|
exitCode: -1,
|
|
37556
37569
|
stdout: "",
|
|
37557
37570
|
stderr: error instanceof Error ? error.message : "Failed to start OpenCode server.",
|
|
37558
|
-
ndjsonEvents: []
|
|
37571
|
+
ndjsonEvents: [],
|
|
37572
|
+
outputText: ""
|
|
37559
37573
|
};
|
|
37560
37574
|
}
|
|
37561
37575
|
const args = buildOpenCodeRunArgs({
|
|
@@ -37565,6 +37579,7 @@ var OpenCodeProcessRunner = class {
|
|
|
37565
37579
|
promptPath: request.promptPath,
|
|
37566
37580
|
cwd: request.cwd,
|
|
37567
37581
|
attachUrl,
|
|
37582
|
+
pure: this.pure,
|
|
37568
37583
|
promptArgvLimit: this.promptArgvLimit
|
|
37569
37584
|
});
|
|
37570
37585
|
return new Promise((resolve4) => {
|
|
@@ -37574,7 +37589,8 @@ var OpenCodeProcessRunner = class {
|
|
|
37574
37589
|
exitCode: -1,
|
|
37575
37590
|
stdout: "",
|
|
37576
37591
|
stderr: "OpenCode process aborted before spawn.",
|
|
37577
|
-
ndjsonEvents: []
|
|
37592
|
+
ndjsonEvents: [],
|
|
37593
|
+
outputText: ""
|
|
37578
37594
|
});
|
|
37579
37595
|
return;
|
|
37580
37596
|
}
|
|
@@ -37604,21 +37620,25 @@ var OpenCodeProcessRunner = class {
|
|
|
37604
37620
|
stderr += chunk;
|
|
37605
37621
|
});
|
|
37606
37622
|
child.on("error", (err) => {
|
|
37623
|
+
const ndjsonEvents = parseOpenCodeJsonEvents(stdout);
|
|
37607
37624
|
settle({
|
|
37608
37625
|
id: request.id,
|
|
37609
37626
|
exitCode: -1,
|
|
37610
37627
|
stdout,
|
|
37611
37628
|
stderr: stderr || err.message,
|
|
37612
|
-
ndjsonEvents
|
|
37629
|
+
ndjsonEvents,
|
|
37630
|
+
outputText: extractOpenCodeText(ndjsonEvents)
|
|
37613
37631
|
});
|
|
37614
37632
|
});
|
|
37615
37633
|
child.on("close", (code) => {
|
|
37634
|
+
const ndjsonEvents = parseOpenCodeJsonEvents(stdout);
|
|
37616
37635
|
settle({
|
|
37617
37636
|
id: request.id,
|
|
37618
37637
|
exitCode: code ?? -1,
|
|
37619
37638
|
stdout,
|
|
37620
37639
|
stderr,
|
|
37621
|
-
ndjsonEvents
|
|
37640
|
+
ndjsonEvents,
|
|
37641
|
+
outputText: extractOpenCodeText(ndjsonEvents)
|
|
37622
37642
|
});
|
|
37623
37643
|
});
|
|
37624
37644
|
});
|
|
@@ -37656,7 +37676,14 @@ var OpenCodeProcessRunner = class {
|
|
|
37656
37676
|
}
|
|
37657
37677
|
const child = this.spawn(
|
|
37658
37678
|
"opencode",
|
|
37659
|
-
[
|
|
37679
|
+
[
|
|
37680
|
+
"serve",
|
|
37681
|
+
"--hostname",
|
|
37682
|
+
"127.0.0.1",
|
|
37683
|
+
"--port",
|
|
37684
|
+
"0",
|
|
37685
|
+
...this.pure ? ["--pure"] : []
|
|
37686
|
+
],
|
|
37660
37687
|
{
|
|
37661
37688
|
cwd,
|
|
37662
37689
|
stdio: ["ignore", "pipe", "pipe"]
|
|
@@ -37731,6 +37758,9 @@ ${server.stderr}`);
|
|
|
37731
37758
|
function parseServeUrl(output) {
|
|
37732
37759
|
return output.match(/opencode server listening on (https?:\/\/\S+)/)?.[1];
|
|
37733
37760
|
}
|
|
37761
|
+
function isRecord(value) {
|
|
37762
|
+
return typeof value === "object" && value !== null;
|
|
37763
|
+
}
|
|
37734
37764
|
|
|
37735
37765
|
// src/lib/agent-orchestrator/prompt-writer.ts
|
|
37736
37766
|
import { mkdir as mkdir3, writeFile as writeFile3 } from "node:fs/promises";
|
|
@@ -37889,6 +37919,7 @@ function schemaHint(stage) {
|
|
|
37889
37919
|
// src/lib/agent-orchestrator/review-orchestrator.ts
|
|
37890
37920
|
async function runReviewerPhase(input) {
|
|
37891
37921
|
const journal = input.journal ?? new NoopAgentLifecycleJournal();
|
|
37922
|
+
const emit = input.emit ?? (() => void 0);
|
|
37892
37923
|
const controller = new AbortController();
|
|
37893
37924
|
const reviewerRequests = input.resolvedTeam.reviewers.map((reviewer) => {
|
|
37894
37925
|
if (!reviewer.model.trim()) {
|
|
@@ -37917,7 +37948,26 @@ async function runReviewerPhase(input) {
|
|
|
37917
37948
|
phase: "reviews"
|
|
37918
37949
|
});
|
|
37919
37950
|
await journal.beat(agentSessionId);
|
|
37951
|
+
const startLogPaths = await writeProcessStartLog(input.context.roundDir, request);
|
|
37952
|
+
emit({
|
|
37953
|
+
event: "agent:start",
|
|
37954
|
+
phase: "reviews",
|
|
37955
|
+
id: request.id,
|
|
37956
|
+
model: request.model,
|
|
37957
|
+
prompt_path: request.promptPath,
|
|
37958
|
+
meta_log: startLogPaths.meta
|
|
37959
|
+
});
|
|
37920
37960
|
const result = await input.runner.run(request, controller.signal);
|
|
37961
|
+
const logPaths = await writeProcessLogs(input.context.roundDir, request, result);
|
|
37962
|
+
emit({
|
|
37963
|
+
event: "agent:complete",
|
|
37964
|
+
phase: "reviews",
|
|
37965
|
+
id: request.id,
|
|
37966
|
+
exit_code: result.exitCode,
|
|
37967
|
+
stdout_log: logPaths.stdout,
|
|
37968
|
+
stderr_log: logPaths.stderr,
|
|
37969
|
+
meta_log: logPaths.meta
|
|
37970
|
+
});
|
|
37921
37971
|
const vendorId = extractVendorSessionId(result.ndjsonEvents);
|
|
37922
37972
|
if (vendorId) await journal.bindVendorId(agentSessionId, vendorId);
|
|
37923
37973
|
await journal.endInstance(agentSessionId, {
|
|
@@ -37988,7 +38038,7 @@ async function runReviewerPhase(input) {
|
|
|
37988
38038
|
for (const result of sortResults(results, requests)) {
|
|
37989
38039
|
const reviewer = byId.get(result.id);
|
|
37990
38040
|
if (!reviewer) continue;
|
|
37991
|
-
await writeRoundArtifact(input.context.roundDir, reviewer.reviewPath, result
|
|
38041
|
+
await writeRoundArtifact(input.context.roundDir, reviewer.reviewPath, processOutput(result));
|
|
37992
38042
|
}
|
|
37993
38043
|
return { ok: true, results: sortResults(results, requests) };
|
|
37994
38044
|
}
|
|
@@ -38021,7 +38071,8 @@ async function runOpenCodeProcessAgentReview(input) {
|
|
|
38021
38071
|
resolvedTeam: snapshot.resolvedTeam,
|
|
38022
38072
|
cwd: input.cwd,
|
|
38023
38073
|
runner,
|
|
38024
|
-
journal
|
|
38074
|
+
journal,
|
|
38075
|
+
emit
|
|
38025
38076
|
});
|
|
38026
38077
|
if (!reviewerResult.ok) {
|
|
38027
38078
|
emit({
|
|
@@ -38042,7 +38093,8 @@ async function runOpenCodeProcessAgentReview(input) {
|
|
|
38042
38093
|
resolvedTeam: snapshot.resolvedTeam,
|
|
38043
38094
|
cwd: input.cwd,
|
|
38044
38095
|
runner,
|
|
38045
|
-
journal
|
|
38096
|
+
journal,
|
|
38097
|
+
emit
|
|
38046
38098
|
});
|
|
38047
38099
|
if (!pipelineResult.ok) {
|
|
38048
38100
|
emit({
|
|
@@ -38069,6 +38121,7 @@ async function runOpenCodeProcessAgentReview(input) {
|
|
|
38069
38121
|
}
|
|
38070
38122
|
async function runPipelineStages(input) {
|
|
38071
38123
|
const journal = input.journal ?? new NoopAgentLifecycleJournal();
|
|
38124
|
+
const emit = input.emit ?? (() => void 0);
|
|
38072
38125
|
const missingReviews = input.resolvedTeam.reviewers.map((reviewer) => reviewer.reviewPath).filter((reviewPath) => !isNonEmptyFile(join27(input.context.roundDir, reviewPath)));
|
|
38073
38126
|
if (missingReviews.length > 0) {
|
|
38074
38127
|
return {
|
|
@@ -38097,7 +38150,26 @@ async function runPipelineStages(input) {
|
|
|
38097
38150
|
cwd: input.cwd,
|
|
38098
38151
|
phase: stage
|
|
38099
38152
|
};
|
|
38153
|
+
const startLogPaths = await writeProcessStartLog(input.context.roundDir, request);
|
|
38154
|
+
emit({
|
|
38155
|
+
event: "agent:start",
|
|
38156
|
+
phase: stage,
|
|
38157
|
+
id: request.id,
|
|
38158
|
+
model: request.model,
|
|
38159
|
+
prompt_path: request.promptPath,
|
|
38160
|
+
meta_log: startLogPaths.meta
|
|
38161
|
+
});
|
|
38100
38162
|
const result = await input.runner.run(request, new AbortController().signal);
|
|
38163
|
+
const logPaths = await writeProcessLogs(input.context.roundDir, request, result);
|
|
38164
|
+
emit({
|
|
38165
|
+
event: "agent:complete",
|
|
38166
|
+
phase: stage,
|
|
38167
|
+
id: request.id,
|
|
38168
|
+
exit_code: result.exitCode,
|
|
38169
|
+
stdout_log: logPaths.stdout,
|
|
38170
|
+
stderr_log: logPaths.stderr,
|
|
38171
|
+
meta_log: logPaths.meta
|
|
38172
|
+
});
|
|
38101
38173
|
results.push(result);
|
|
38102
38174
|
const vendorId = extractVendorSessionId(result.ndjsonEvents);
|
|
38103
38175
|
if (vendorId) await journal.bindVendorId(agentSessionId, vendorId);
|
|
@@ -38123,7 +38195,7 @@ async function runPipelineStages(input) {
|
|
|
38123
38195
|
results
|
|
38124
38196
|
};
|
|
38125
38197
|
}
|
|
38126
|
-
await writeRoundArtifact(input.context.roundDir, ref.artifactPath, result
|
|
38198
|
+
await writeRoundArtifact(input.context.roundDir, ref.artifactPath, processOutput(result));
|
|
38127
38199
|
const validationErrors = validateStageArtifact(input.context.roundDir, stage, ref.artifactPath);
|
|
38128
38200
|
if (validationErrors.length > 0) {
|
|
38129
38201
|
await journal.endInstance(agentSessionId, {
|
|
@@ -38156,6 +38228,70 @@ function validateStageArtifact(roundDir, stage, artifactPath) {
|
|
|
38156
38228
|
function isNonEmptyFile(path2) {
|
|
38157
38229
|
return existsSync22(path2) && statSync5(path2).isFile() && statSync5(path2).size > 0;
|
|
38158
38230
|
}
|
|
38231
|
+
async function writeProcessStartLog(roundDir, request) {
|
|
38232
|
+
const metaPath = `process-logs/${request.id}.meta.json`;
|
|
38233
|
+
await writeRoundArtifact(
|
|
38234
|
+
roundDir,
|
|
38235
|
+
metaPath,
|
|
38236
|
+
JSON.stringify(
|
|
38237
|
+
{
|
|
38238
|
+
schema_version: 1,
|
|
38239
|
+
id: request.id,
|
|
38240
|
+
phase: request.phase,
|
|
38241
|
+
model: request.model,
|
|
38242
|
+
prompt_path: request.promptPath,
|
|
38243
|
+
status: "running",
|
|
38244
|
+
started_at: (/* @__PURE__ */ new Date()).toISOString()
|
|
38245
|
+
},
|
|
38246
|
+
null,
|
|
38247
|
+
2
|
|
38248
|
+
)
|
|
38249
|
+
);
|
|
38250
|
+
return { meta: metaPath };
|
|
38251
|
+
}
|
|
38252
|
+
async function writeProcessLogs(roundDir, request, result) {
|
|
38253
|
+
const prefix = `process-logs/${request.id}`;
|
|
38254
|
+
const stdoutPath = `${prefix}.stdout.ndjson`;
|
|
38255
|
+
const stderrPath = `${prefix}.stderr.log`;
|
|
38256
|
+
const metaPath = `${prefix}.meta.json`;
|
|
38257
|
+
await writeRoundArtifact(roundDir, stdoutPath, result.stdout);
|
|
38258
|
+
await writeRoundArtifact(roundDir, stderrPath, result.stderr);
|
|
38259
|
+
await writeRoundArtifact(
|
|
38260
|
+
roundDir,
|
|
38261
|
+
metaPath,
|
|
38262
|
+
JSON.stringify(
|
|
38263
|
+
{
|
|
38264
|
+
schema_version: 1,
|
|
38265
|
+
id: request.id,
|
|
38266
|
+
phase: request.phase,
|
|
38267
|
+
model: request.model,
|
|
38268
|
+
prompt_path: request.promptPath,
|
|
38269
|
+
status: "completed",
|
|
38270
|
+
completed_at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
38271
|
+
exit_code: result.exitCode,
|
|
38272
|
+
output_text_bytes: Buffer.byteLength(processOutput(result), "utf-8"),
|
|
38273
|
+
stdout_bytes: Buffer.byteLength(result.stdout, "utf-8"),
|
|
38274
|
+
stderr_bytes: Buffer.byteLength(result.stderr, "utf-8"),
|
|
38275
|
+
opencode_session_ids: extractUniqueSessionIds(result.ndjsonEvents)
|
|
38276
|
+
},
|
|
38277
|
+
null,
|
|
38278
|
+
2
|
|
38279
|
+
)
|
|
38280
|
+
);
|
|
38281
|
+
return { stdout: stdoutPath, stderr: stderrPath, meta: metaPath };
|
|
38282
|
+
}
|
|
38283
|
+
function processOutput(result) {
|
|
38284
|
+
return result.outputText ?? result.stdout;
|
|
38285
|
+
}
|
|
38286
|
+
function extractUniqueSessionIds(events) {
|
|
38287
|
+
const ids = /* @__PURE__ */ new Set();
|
|
38288
|
+
for (const event of events) {
|
|
38289
|
+
if (!isRecord2(event)) continue;
|
|
38290
|
+
const sessionID = event.sessionID;
|
|
38291
|
+
if (typeof sessionID === "string") ids.add(sessionID);
|
|
38292
|
+
}
|
|
38293
|
+
return [...ids];
|
|
38294
|
+
}
|
|
38159
38295
|
async function writePipelineFailure(roundDir, stage, result, results, validationErrors = [], diagnostic = buildFailureDiagnostic(result)) {
|
|
38160
38296
|
await writeRoundArtifact(
|
|
38161
38297
|
roundDir,
|
|
@@ -38217,11 +38353,11 @@ function buildFailureDiagnostic(result, request) {
|
|
|
38217
38353
|
}
|
|
38218
38354
|
function extractOpenCodeErrorMessage(events) {
|
|
38219
38355
|
for (const event of events) {
|
|
38220
|
-
if (!
|
|
38356
|
+
if (!isRecord2(event) || event.type !== "error") continue;
|
|
38221
38357
|
const error = event.error;
|
|
38222
|
-
if (!
|
|
38358
|
+
if (!isRecord2(error)) continue;
|
|
38223
38359
|
const data = error.data;
|
|
38224
|
-
if (
|
|
38360
|
+
if (isRecord2(data) && typeof data.message === "string") return data.message;
|
|
38225
38361
|
if (typeof error.message === "string") return error.message;
|
|
38226
38362
|
}
|
|
38227
38363
|
return void 0;
|
|
@@ -38234,7 +38370,7 @@ function excerpt(value, limit = 1200) {
|
|
|
38234
38370
|
function stripAnsi2(value) {
|
|
38235
38371
|
return value.replace(/\u001b\[[0-9;]*m/g, "");
|
|
38236
38372
|
}
|
|
38237
|
-
function
|
|
38373
|
+
function isRecord2(value) {
|
|
38238
38374
|
return typeof value === "object" && value !== null;
|
|
38239
38375
|
}
|
|
38240
38376
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nk070281sjv/cli",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.6",
|
|
4
4
|
"description": "CLI for Open Code Review - Multi-environment setup and progress tracking",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@inquirer/prompts": "^7.2.0",
|
|
40
|
-
"@nk070281sjv/agents": "2.3.
|
|
40
|
+
"@nk070281sjv/agents": "2.3.6",
|
|
41
41
|
"chalk": "^5.4.1",
|
|
42
42
|
"chokidar": "^4.0.3",
|
|
43
43
|
"commander": "^13.0.0",
|