@claudexor/cli 3.0.4 → 3.1.1
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/about-command.d.ts +32 -0
- package/dist/about-command.d.ts.map +1 -0
- package/dist/about-command.js +40 -0
- package/dist/about-command.js.map +1 -0
- package/dist/acp-auth-command.d.ts +3 -0
- package/dist/acp-auth-command.d.ts.map +1 -0
- package/dist/acp-auth-command.js +18 -0
- package/dist/acp-auth-command.js.map +1 -0
- package/dist/acp-auth.d.ts +13 -0
- package/dist/acp-auth.d.ts.map +1 -0
- package/dist/acp-auth.js +47 -0
- package/dist/acp-auth.js.map +1 -0
- package/dist/acp-surface-runner.d.ts +12 -0
- package/dist/acp-surface-runner.d.ts.map +1 -1
- package/dist/acp-surface-runner.js +113 -11
- package/dist/acp-surface-runner.js.map +1 -1
- package/dist/bridge-serve.d.ts.map +1 -1
- package/dist/bridge-serve.js +2 -0
- package/dist/bridge-serve.js.map +1 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +2 -1
- package/dist/capabilities.js.map +1 -1
- package/dist/claudexord.d.ts +21 -0
- package/dist/claudexord.d.ts.map +1 -1
- package/dist/claudexord.js +105 -21
- package/dist/claudexord.js.map +1 -1
- package/dist/cli-error.d.ts +97 -0
- package/dist/cli-error.d.ts.map +1 -0
- package/dist/cli-error.js +308 -0
- package/dist/cli-error.js.map +1 -0
- package/dist/cli-io.d.ts +9 -0
- package/dist/cli-io.d.ts.map +1 -1
- package/dist/cli-io.js +10 -1
- package/dist/cli-io.js.map +1 -1
- package/dist/cli.js +110 -116
- package/dist/cli.js.map +1 -1
- package/dist/codex-device-login.d.ts +117 -0
- package/dist/codex-device-login.d.ts.map +1 -0
- package/dist/codex-device-login.js +227 -0
- package/dist/codex-device-login.js.map +1 -0
- package/dist/command-flags.d.ts +0 -6
- package/dist/command-flags.d.ts.map +1 -1
- package/dist/command-flags.js +12 -4
- package/dist/command-flags.js.map +1 -1
- package/dist/command-help.d.ts +46 -0
- package/dist/command-help.d.ts.map +1 -0
- package/dist/command-help.js +92 -0
- package/dist/command-help.js.map +1 -0
- package/dist/command-registry.d.ts +2 -0
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +14 -7
- package/dist/command-registry.js.map +1 -1
- package/dist/control-services.d.ts +54 -27
- package/dist/control-services.d.ts.map +1 -1
- package/dist/control-services.js +56 -30
- package/dist/control-services.js.map +1 -1
- package/dist/credential-commands.d.ts.map +1 -1
- package/dist/credential-commands.js +44 -1
- package/dist/credential-commands.js.map +1 -1
- package/dist/daemon-outcome.d.ts +24 -0
- package/dist/daemon-outcome.d.ts.map +1 -0
- package/dist/daemon-outcome.js +59 -0
- package/dist/daemon-outcome.js.map +1 -0
- package/dist/daemon-run.d.ts +23 -4
- package/dist/daemon-run.d.ts.map +1 -1
- package/dist/daemon-run.js +66 -27
- package/dist/daemon-run.js.map +1 -1
- package/dist/delegation-belt-descriptor.d.ts +31 -13
- package/dist/delegation-belt-descriptor.d.ts.map +1 -1
- package/dist/delegation-belt-descriptor.js +43 -15
- package/dist/delegation-belt-descriptor.js.map +1 -1
- package/dist/live.d.ts +13 -1
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +56 -7
- package/dist/live.js.map +1 -1
- package/dist/mcp-runner.d.ts.map +1 -1
- package/dist/mcp-runner.js +60 -6
- package/dist/mcp-runner.js.map +1 -1
- package/dist/native-login.d.ts +10 -1
- package/dist/native-login.d.ts.map +1 -1
- package/dist/native-login.js +32 -10
- package/dist/native-login.js.map +1 -1
- package/dist/ops-commands.d.ts +5 -1
- package/dist/ops-commands.d.ts.map +1 -1
- package/dist/ops-commands.js +45 -52
- package/dist/ops-commands.js.map +1 -1
- package/dist/plan-implement-readiness.d.ts +32 -0
- package/dist/plan-implement-readiness.d.ts.map +1 -0
- package/dist/plan-implement-readiness.js +51 -0
- package/dist/plan-implement-readiness.js.map +1 -0
- package/dist/plugins.d.ts.map +1 -1
- package/dist/plugins.js +73 -20
- package/dist/plugins.js.map +1 -1
- package/dist/project-command.d.ts +15 -0
- package/dist/project-command.d.ts.map +1 -1
- package/dist/project-command.js +75 -20
- package/dist/project-command.js.map +1 -1
- package/dist/quota-command.d.ts.map +1 -1
- package/dist/quota-command.js +2 -6
- package/dist/quota-command.js.map +1 -1
- package/dist/release-command.d.ts.map +1 -1
- package/dist/release-command.js +31 -6
- package/dist/release-command.js.map +1 -1
- package/dist/release.d.ts +41 -10
- package/dist/release.d.ts.map +1 -1
- package/dist/release.js +70 -48
- package/dist/release.js.map +1 -1
- package/dist/repo-asset-authority.d.ts +89 -0
- package/dist/repo-asset-authority.d.ts.map +1 -0
- package/dist/repo-asset-authority.js +175 -0
- package/dist/repo-asset-authority.js.map +1 -0
- package/dist/retry-command.d.ts +15 -0
- package/dist/retry-command.d.ts.map +1 -1
- package/dist/retry-command.js +7 -4
- package/dist/retry-command.js.map +1 -1
- package/dist/review-command.d.ts.map +1 -1
- package/dist/review-command.js +2 -6
- package/dist/review-command.js.map +1 -1
- package/dist/reviewer-options.d.ts +11 -1
- package/dist/reviewer-options.d.ts.map +1 -1
- package/dist/reviewer-options.js +24 -9
- package/dist/reviewer-options.js.map +1 -1
- package/dist/run-options.d.ts.map +1 -1
- package/dist/run-options.js +13 -1
- package/dist/run-options.js.map +1 -1
- package/dist/settings-command.d.ts.map +1 -1
- package/dist/settings-command.js +2 -6
- package/dist/settings-command.js.map +1 -1
- package/dist/settings-service.d.ts +101 -10
- package/dist/settings-service.d.ts.map +1 -1
- package/dist/settings-service.js +201 -12
- package/dist/settings-service.js.map +1 -1
- package/dist/setup-job-store.d.ts +16 -5
- package/dist/setup-job-store.d.ts.map +1 -1
- package/dist/setup-job-store.js +24 -4
- package/dist/setup-job-store.js.map +1 -1
- package/dist/setup-jobs.d.ts +14 -4
- package/dist/setup-jobs.d.ts.map +1 -1
- package/dist/setup-jobs.js +204 -23
- package/dist/setup-jobs.js.map +1 -1
- package/dist/setup-login-inline.d.ts +71 -0
- package/dist/setup-login-inline.d.ts.map +1 -0
- package/dist/setup-login-inline.js +207 -0
- package/dist/setup-login-inline.js.map +1 -0
- package/dist/setup-login-protocol.d.ts +3 -2
- package/dist/setup-login-protocol.d.ts.map +1 -1
- package/dist/setup-login-protocol.js +16 -1
- package/dist/setup-login-protocol.js.map +1 -1
- package/dist/setup-login-runner.d.ts +9 -0
- package/dist/setup-login-runner.d.ts.map +1 -1
- package/dist/setup-login-runner.js +212 -5
- package/dist/setup-login-runner.js.map +1 -1
- package/dist/thread-delivery.d.ts.map +1 -1
- package/dist/thread-delivery.js +3 -1
- package/dist/thread-delivery.js.map +1 -1
- package/dist/thread-execution-workspace.d.ts +22 -0
- package/dist/thread-execution-workspace.d.ts.map +1 -0
- package/dist/thread-execution-workspace.js +21 -0
- package/dist/thread-execution-workspace.js.map +1 -0
- package/package.json +23 -23
package/dist/cli.js
CHANGED
|
@@ -7,21 +7,25 @@ import { dirname, join, relative, resolve, sep } from "node:path";
|
|
|
7
7
|
import { ArtifactStore } from "@claudexor/artifact-store";
|
|
8
8
|
import { CLAUDEXOR_VERSION, noProjectRepoRoot, readTextSafe, userConfigDir } from "@claudexor/util";
|
|
9
9
|
import { releaseCommand } from "./release-command.js";
|
|
10
|
-
import {
|
|
10
|
+
import { serveBeltBridge, serveMcpBridge } from "./bridge-serve.js";
|
|
11
|
+
import { dispatchAcpCommand } from "./acp-auth-command.js";
|
|
11
12
|
import { initProjectConfig } from "@claudexor/config";
|
|
12
|
-
import { DecisionRecord, EffortHint, ExternalContextPolicy, ModeKind as ModeKindSchema, RoutingGoal, ControlThreadListResponse, RunTelemetry, StructuredOutputConformance, TaskContract, runOutcomeLabel, } from "@claudexor/schema";
|
|
13
|
+
import { DecisionRecord, EFFORT_HINT_HELP, EffortHint, ExternalContextPolicy, ModeKind as ModeKindSchema, RoutingGoal, ControlThreadListResponse, RunTelemetry, StructuredOutputConformance, TaskContract, runOutcomeLabel, } from "@claudexor/schema";
|
|
13
14
|
import { flagBool, flagStr, flagStringList, flagValues, parseArgs, requiredStringFlagError, } from "./args.js";
|
|
14
15
|
import { print, printJson, printJsonLine, printUsageError, statusGlyph } from "./cli-io.js";
|
|
16
|
+
import { controlProblemError, minIntError, renderCliFailure, usageError } from "./cli-error.js";
|
|
17
|
+
import { handleHelpRequest } from "./command-help.js";
|
|
15
18
|
import { pickResumableThread } from "./thread-select.js";
|
|
16
19
|
import { KNOWN_FLAGS, VALUE_FLAGS, commandFlagScopeError, helpJson, renderHelp, } from "./command-registry.js";
|
|
17
20
|
import { buildAgentCapabilityCatalog } from "./capabilities.js";
|
|
21
|
+
import { aboutJson, renderAbout } from "./about-command.js";
|
|
18
22
|
import { dispatchOpsCommand } from "./ops-commands.js";
|
|
19
23
|
import { reviewCommand } from "./review-command.js";
|
|
20
24
|
import { controlApiFetch, followRun } from "./live.js";
|
|
21
25
|
import { retryCommand, runAgainCommand } from "./retry-command.js";
|
|
22
26
|
import { assertCliRunParamsHaveNoInlineSecrets } from "./run-secret-scan.js";
|
|
23
27
|
import { openLocalAttachment, resolveLocalAttachment, } from "./local-attachment.js";
|
|
24
|
-
import { connectDaemonIfRunning, daemonOutcomeSummary, ensureDaemon, enqueueAndAwait, exitCodeForState, fetchApplyEligibility, fetchCouncil, fetchOutcomeBanner, } from "./daemon-run.js";
|
|
28
|
+
import { connectDaemonIfRunning, daemonOutcomeProblemFields, daemonOutcomeSummary, ensureDaemon, enqueueAndAwait, exitCodeForState, fetchApplyEligibility, fetchCouncil, fetchOutcomeBanner, fetchRunDetail, fetchRunOutcomeFacts, projectApplyEligibility, projectOutcomeBanner, projectRunOutcomeFacts, mergeDaemonRunOutcome, } from "./daemon-run.js";
|
|
25
29
|
import { runPlanQuestionLoop } from "./plan-question-loop.js";
|
|
26
30
|
import { resolveDecisionBody } from "./decision.js";
|
|
27
31
|
import { primaryOutputForCli } from "./primary-output.js";
|
|
@@ -119,7 +123,7 @@ function effortHint(args) {
|
|
|
119
123
|
return undefined;
|
|
120
124
|
const parsed = EffortHint.safeParse(v);
|
|
121
125
|
if (!parsed.success)
|
|
122
|
-
throw new Error(`invalid --effort '${v}' (expected
|
|
126
|
+
throw new Error(`invalid --effort '${v}' (expected a ${EFFORT_HINT_HELP})`);
|
|
123
127
|
return parsed.data;
|
|
124
128
|
}
|
|
125
129
|
function synthesisMode(args) {
|
|
@@ -288,7 +292,12 @@ async function orchestrate(args, mode, json, forced = {}) {
|
|
|
288
292
|
const maxUsd = floatFlag(args, "max-usd");
|
|
289
293
|
paidBudget = maxUsd === undefined ? undefined : { kind: "finite", maxUsd };
|
|
290
294
|
nFlag = intFlag(args, "n");
|
|
295
|
+
// Structured min-value validation (GH #28): `--n 0` is a usage field error, not a Zod dump.
|
|
296
|
+
if (nFlag !== undefined && nFlag < 1)
|
|
297
|
+
throw minIntError("n", 1);
|
|
291
298
|
attemptsFlag = intFlag(args, "attempts");
|
|
299
|
+
if (attemptsFlag !== undefined && attemptsFlag < 1)
|
|
300
|
+
throw minIntError("attempts", 1);
|
|
292
301
|
delegate = flagBool(args, "delegate") ? true : undefined;
|
|
293
302
|
council = flagBool(args, "council") ? true : undefined;
|
|
294
303
|
resolvedSynthesis = synthesisMode(args);
|
|
@@ -322,7 +331,8 @@ async function orchestrate(args, mode, json, forced = {}) {
|
|
|
322
331
|
}
|
|
323
332
|
}
|
|
324
333
|
catch (err) {
|
|
325
|
-
|
|
334
|
+
// Projector: typed field errors / domain codes survive; a plain flag-parse Error is usage (exit 2).
|
|
335
|
+
return renderCliFailure(json, err, { defaultCategory: "usage", messagePrefix: "claudexor:" });
|
|
326
336
|
}
|
|
327
337
|
let tests;
|
|
328
338
|
try {
|
|
@@ -350,7 +360,8 @@ async function orchestrate(args, mode, json, forced = {}) {
|
|
|
350
360
|
});
|
|
351
361
|
}
|
|
352
362
|
catch (err) {
|
|
353
|
-
|
|
363
|
+
// Preserves the typed `inline_secret_rejected` code (never echoing the token).
|
|
364
|
+
return renderCliFailure(json, err, { defaultCategory: "usage", messagePrefix: "claudexor:" });
|
|
354
365
|
}
|
|
355
366
|
if (delegate && mode !== "agent") {
|
|
356
367
|
return printUsageError(json, `claudexor: --delegate is an agent strategy (got mode '${mode}')`);
|
|
@@ -405,15 +416,13 @@ async function daemonRun(args, json, p) {
|
|
|
405
416
|
({ client, addr } = await ensureDaemon());
|
|
406
417
|
}
|
|
407
418
|
catch (err) {
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
process.stderr.write(`claudexor: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
416
|
-
return 1;
|
|
419
|
+
// D-7 projector: one failure envelope with message/code (never a legacy
|
|
420
|
+
// partial {ok,exitCode,error}). --json-stream stays valid NDJSON via the
|
|
421
|
+
// compact-line stream option.
|
|
422
|
+
return renderCliFailure(json || jsonStream, err, {
|
|
423
|
+
messagePrefix: "claudexor:",
|
|
424
|
+
stream: jsonStream,
|
|
425
|
+
});
|
|
417
426
|
}
|
|
418
427
|
// Thread continuation (W13/D10): --thread <id> targets a thread explicitly;
|
|
419
428
|
// --resume picks the most recently updated one. When a threadId is present
|
|
@@ -435,28 +444,17 @@ async function daemonRun(args, json, p) {
|
|
|
435
444
|
// another project's threads.
|
|
436
445
|
const newest = pickResumableThread(list.threads, process.cwd());
|
|
437
446
|
if (!newest) {
|
|
438
|
-
//
|
|
447
|
+
// D-7 projector on the active surface: NDJSON stream keeps compact
|
|
439
448
|
// lines; --json prints its one object; text goes to stderr.
|
|
440
|
-
|
|
441
|
-
if (jsonStream)
|
|
442
|
-
printJsonLine({ ok: false, exitCode: 1, error: message });
|
|
443
|
-
else if (json)
|
|
444
|
-
printJson({ ok: false, exitCode: 1, error: message });
|
|
445
|
-
else
|
|
446
|
-
process.stderr.write(`${message}\n`);
|
|
447
|
-
return 1;
|
|
449
|
+
return renderCliFailure(json || jsonStream, new Error("--resume found no threads to continue in this project"), { messagePrefix: "claudexor:", stream: jsonStream });
|
|
448
450
|
}
|
|
449
451
|
threadId = newest.id;
|
|
450
452
|
}
|
|
451
453
|
catch (err) {
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
printJson({ ok: false, exitCode: 1, error: message });
|
|
457
|
-
else
|
|
458
|
-
process.stderr.write(`${message}\n`);
|
|
459
|
-
return 1;
|
|
454
|
+
// Flatten any cause (transport error, a malformed-threads Zod parse) into a
|
|
455
|
+
// single operational message so the exit code stays 1 and no raw Zod field
|
|
456
|
+
// dump leaks; the projector owns the envelope on every surface.
|
|
457
|
+
return renderCliFailure(json || jsonStream, new Error(`--resume could not list threads: ${err instanceof Error ? err.message : String(err)}`), { messagePrefix: "claudexor:", stream: jsonStream });
|
|
460
458
|
}
|
|
461
459
|
}
|
|
462
460
|
let attachmentRefs;
|
|
@@ -466,15 +464,9 @@ async function daemonRun(args, json, p) {
|
|
|
466
464
|
: undefined;
|
|
467
465
|
}
|
|
468
466
|
catch (err) {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
exitCode: 1,
|
|
473
|
-
error: `claudexor: attachment upload failed: ${err instanceof Error ? err.message : String(err)}`,
|
|
474
|
-
});
|
|
475
|
-
else
|
|
476
|
-
process.stderr.write(`claudexor: attachment upload failed: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
477
|
-
return 1;
|
|
467
|
+
// D-7 projector: message/code envelope, NDJSON-safe. (Previously this branch
|
|
468
|
+
// ignored --json-stream and fell through to a stderr line.)
|
|
469
|
+
return renderCliFailure(json || jsonStream, new Error(`attachment upload failed: ${err instanceof Error ? err.message : String(err)}`), { messagePrefix: "claudexor:", stream: jsonStream });
|
|
478
470
|
}
|
|
479
471
|
const body = {
|
|
480
472
|
prompt: p.prompt,
|
|
@@ -528,6 +520,7 @@ async function daemonRun(args, json, p) {
|
|
|
528
520
|
jobId: started.jobId,
|
|
529
521
|
mode: p.mode,
|
|
530
522
|
...(started.error ? { error: started.error } : {}),
|
|
523
|
+
...daemonOutcomeProblemFields(started),
|
|
531
524
|
});
|
|
532
525
|
return exitCodeForState(started.status);
|
|
533
526
|
}
|
|
@@ -542,17 +535,13 @@ async function daemonRun(args, json, p) {
|
|
|
542
535
|
// per event via print(JSON.stringify(ev)).
|
|
543
536
|
await followRun(started.runId, true);
|
|
544
537
|
const final = started.jobId ? await client.status(started.jobId) : null;
|
|
545
|
-
const
|
|
546
|
-
const
|
|
547
|
-
runId: started.runId,
|
|
548
|
-
runDir: final?.runDir ?? started.runDir,
|
|
549
|
-
status: status,
|
|
550
|
-
jobId: started.jobId,
|
|
551
|
-
error: final?.error ?? started.error,
|
|
552
|
-
};
|
|
538
|
+
const out = mergeDaemonRunOutcome(started, final);
|
|
539
|
+
const status = out.status;
|
|
553
540
|
const reason = daemonOutcomeSummary({ ...started, status, error: out.error });
|
|
554
|
-
|
|
555
|
-
const
|
|
541
|
+
// ONE GET /runs/:id feeds all three terminal projections (INV-120/122).
|
|
542
|
+
const detail = await fetchRunDetail(addr, out.runId);
|
|
543
|
+
const applyEligibility = projectApplyEligibility(detail);
|
|
544
|
+
const outcomeBanner = projectOutcomeBanner(detail);
|
|
556
545
|
printJsonLine({
|
|
557
546
|
frame: "run.terminal",
|
|
558
547
|
runId: out.runId,
|
|
@@ -561,11 +550,12 @@ async function daemonRun(args, json, p) {
|
|
|
561
550
|
jobId: out.jobId,
|
|
562
551
|
mode: p.mode,
|
|
563
552
|
...(out.error ? { error: out.error } : {}),
|
|
553
|
+
...daemonOutcomeProblemFields(out),
|
|
564
554
|
...(reason ? { summary: reason } : {}),
|
|
565
555
|
...(outcomeBanner ? { outcomeBanner } : {}),
|
|
566
556
|
...(applyEligibility ? { applyEligibility } : {}),
|
|
567
557
|
});
|
|
568
|
-
return exitCodeForState(status);
|
|
558
|
+
return exitCodeForState(status, projectRunOutcomeFacts(detail));
|
|
569
559
|
}
|
|
570
560
|
if (json) {
|
|
571
561
|
// Pure machine surface: await the terminal outcome and print one JSON object.
|
|
@@ -574,9 +564,11 @@ async function daemonRun(args, json, p) {
|
|
|
574
564
|
const reason = daemonOutcomeSummary(out);
|
|
575
565
|
// ADD-ONLY key (bench contract keeps {runId,runDir,status}): the derived
|
|
576
566
|
// apply-gate verdict, so machine callers act on truth instead of
|
|
577
|
-
// re-implying eligibility from status.
|
|
578
|
-
|
|
579
|
-
const
|
|
567
|
+
// re-implying eligibility from status. ONE GET /runs/:id feeds all three
|
|
568
|
+
// terminal projections (INV-120/122).
|
|
569
|
+
const detail = await fetchRunDetail(addr, out.runId);
|
|
570
|
+
const applyEligibility = projectApplyEligibility(detail);
|
|
571
|
+
const outcomeBanner = projectOutcomeBanner(detail);
|
|
580
572
|
printJson({
|
|
581
573
|
runId: out.runId,
|
|
582
574
|
runDir: out.runDir,
|
|
@@ -584,11 +576,12 @@ async function daemonRun(args, json, p) {
|
|
|
584
576
|
jobId: out.jobId,
|
|
585
577
|
mode: p.mode,
|
|
586
578
|
...(out.error ? { error: out.error } : {}),
|
|
579
|
+
...daemonOutcomeProblemFields(out),
|
|
587
580
|
...(reason ? { summary: reason } : {}),
|
|
588
581
|
...(outcomeBanner ? { outcomeBanner } : {}),
|
|
589
582
|
...(applyEligibility ? { applyEligibility } : {}),
|
|
590
583
|
});
|
|
591
|
-
return exitCodeForState(out.status);
|
|
584
|
+
return exitCodeForState(out.status, projectRunOutcomeFacts(detail));
|
|
592
585
|
}
|
|
593
586
|
// Text mode: enqueue, then live-stream the run through the shared follow
|
|
594
587
|
// pipeline (replay + push + interactive TTY question answering), then print
|
|
@@ -652,18 +645,15 @@ async function daemonRun(args, json, p) {
|
|
|
652
645
|
print(` inspect with: claudexor inspect ${effectiveRunId}`);
|
|
653
646
|
}
|
|
654
647
|
}
|
|
655
|
-
return exitCodeForState(status);
|
|
648
|
+
return exitCodeForState(status, await fetchRunOutcomeFacts(addr, effectiveRunId));
|
|
656
649
|
}
|
|
657
650
|
catch (err) {
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
else
|
|
665
|
-
process.stderr.write(`claudexor: ${err instanceof Error ? err.message : String(err)}\n`);
|
|
666
|
-
return 1;
|
|
651
|
+
// D-7 projector: a typed control problem (code/retryable/context) survives
|
|
652
|
+
// intact; --json-stream stays valid NDJSON via the compact-line stream option.
|
|
653
|
+
return renderCliFailure(json || jsonStream, err, {
|
|
654
|
+
messagePrefix: "claudexor:",
|
|
655
|
+
stream: jsonStream,
|
|
656
|
+
});
|
|
667
657
|
}
|
|
668
658
|
}
|
|
669
659
|
/**
|
|
@@ -692,19 +682,9 @@ async function decisionCommand(args, json) {
|
|
|
692
682
|
const text = await res.text();
|
|
693
683
|
const data = text ? JSON.parse(text) : {};
|
|
694
684
|
if (!res.ok) {
|
|
695
|
-
// A typed decision rejection (
|
|
696
|
-
//
|
|
697
|
-
|
|
698
|
-
const msg = typeof data["error"] === "string"
|
|
699
|
-
? data["error"]
|
|
700
|
-
: typeof data["message"] === "string"
|
|
701
|
-
? data["message"]
|
|
702
|
-
: `decision failed (HTTP ${res.status})`;
|
|
703
|
-
if (json)
|
|
704
|
-
printJson({ accepted: false, status: "rejected", message: msg });
|
|
705
|
-
else
|
|
706
|
-
process.stderr.write(`claudexor decision: ${msg}\n`);
|
|
707
|
-
return 1;
|
|
685
|
+
// A typed decision rejection (revert_refused: tree diverged) rides through
|
|
686
|
+
// the projector with its code/retryable/bounded git-stderr context intact.
|
|
687
|
+
return renderCliFailure(json, controlProblemError(res.status, data, `decision failed (HTTP ${res.status})`), { messagePrefix: "claudexor decision:" });
|
|
708
688
|
}
|
|
709
689
|
if (json) {
|
|
710
690
|
printJson(data);
|
|
@@ -720,8 +700,7 @@ async function decisionCommand(args, json) {
|
|
|
720
700
|
return data["accepted"] === true ? 0 : 1;
|
|
721
701
|
}
|
|
722
702
|
catch (err) {
|
|
723
|
-
|
|
724
|
-
return 1;
|
|
703
|
+
return renderCliFailure(json, err, { messagePrefix: "claudexor decision:" });
|
|
725
704
|
}
|
|
726
705
|
}
|
|
727
706
|
/**
|
|
@@ -818,19 +797,12 @@ function listCliArtifacts(root) {
|
|
|
818
797
|
// KNOWN_FLAGS / VALUE_FLAGS (imported above) and the per-command scope check
|
|
819
798
|
// are projections of the command registry. Unknown flags FAIL LOUDLY: `--harnes
|
|
820
799
|
// codex` must never silently run all harnesses.
|
|
821
|
-
async function
|
|
822
|
-
const args = parseArgs(process.argv.slice(2));
|
|
823
|
-
// --version / --help are standard CLI affordances, not unknown flags.
|
|
824
|
-
if (flagBool(args, "version")) {
|
|
825
|
-
process.stdout.write(`${CLI_VERSION}\n`);
|
|
826
|
-
return 0;
|
|
827
|
-
}
|
|
828
|
-
if (flagBool(args, "help")) {
|
|
829
|
-
process.stdout.write(HELP);
|
|
830
|
-
return 0;
|
|
831
|
-
}
|
|
832
|
-
const json = flagBool(args, "json");
|
|
800
|
+
async function dispatch(args, json) {
|
|
833
801
|
const cmd = args._[0] ?? "help";
|
|
802
|
+
// `--help` resolves the COMMAND first (QA-057): scoped usage for a known verb,
|
|
803
|
+
// global help for a bare/`help` verb, a usage error (exit 2) for a typo.
|
|
804
|
+
if (flagBool(args, "help"))
|
|
805
|
+
return handleHelpRequest(cmd, args._.length, json, CLI_VERSION);
|
|
834
806
|
const unknownFlags = Object.keys(args.flags).filter((f) => !KNOWN_FLAGS.has(f));
|
|
835
807
|
if (unknownFlags.length > 0) {
|
|
836
808
|
const error = `claudexor: unknown flag(s): ${unknownFlags.map((f) => `--${f}`).join(", ")} (see \`claudexor help\`)`;
|
|
@@ -921,9 +893,7 @@ async function main() {
|
|
|
921
893
|
return printUsageError(json, "usage: claudexor mcp serve");
|
|
922
894
|
}
|
|
923
895
|
case "acp": {
|
|
924
|
-
|
|
925
|
-
return serveAcpBridge();
|
|
926
|
-
return printUsageError(json, "usage: claudexor acp serve");
|
|
896
|
+
return dispatchAcpCommand(args, json);
|
|
927
897
|
}
|
|
928
898
|
case "follow": {
|
|
929
899
|
const runId = args._[1];
|
|
@@ -947,11 +917,8 @@ async function main() {
|
|
|
947
917
|
// store, or a daemon-tracked run that started in another project.
|
|
948
918
|
const resolved = await resolveRunStore(runId);
|
|
949
919
|
if (!resolved) {
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
else
|
|
953
|
-
print(`no such run ${runId}`);
|
|
954
|
-
return 1;
|
|
920
|
+
// D-7 projector: canonical envelope, run id as a per-command extra.
|
|
921
|
+
return renderCliFailure(json, new Error(`no such run ${runId}`), { extras: { runId } });
|
|
955
922
|
}
|
|
956
923
|
const store = resolved.store;
|
|
957
924
|
const paths = store.runPaths(runId);
|
|
@@ -1090,11 +1057,10 @@ async function main() {
|
|
|
1090
1057
|
}
|
|
1091
1058
|
const rawMode = flagStr(args, "mode") ?? "apply";
|
|
1092
1059
|
if (!["apply", "commit", "branch", "pr"].includes(rawMode)) {
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
return 2;
|
|
1060
|
+
// D-7 projector: a usage failure (exit 2) with the run id as extra.
|
|
1061
|
+
return renderCliFailure(json, usageError(`unsupported apply mode: ${rawMode}`), {
|
|
1062
|
+
extras: { runId },
|
|
1063
|
+
});
|
|
1098
1064
|
}
|
|
1099
1065
|
const { addr } = await ensureDaemon();
|
|
1100
1066
|
const dryRun = flagBool(args, "dry-run");
|
|
@@ -1116,9 +1082,14 @@ async function main() {
|
|
|
1116
1082
|
else if (!response.ok)
|
|
1117
1083
|
print(String(result["message"] ?? result["error"] ?? text));
|
|
1118
1084
|
else if (dryRun)
|
|
1119
|
-
print(result["
|
|
1085
|
+
print(result["alreadyApplied"] === true
|
|
1086
|
+
? "already applied; nothing would change"
|
|
1087
|
+
: result["ok"] === true
|
|
1088
|
+
? "patch applies cleanly"
|
|
1089
|
+
: "patch does not apply");
|
|
1120
1090
|
else
|
|
1121
1091
|
print(`${String(result["mode"] ?? rawMode)}: applied=${String(result["applied"] ?? false)}` +
|
|
1092
|
+
(result["alreadyApplied"] === true ? " (already applied; no files changed)" : "") +
|
|
1122
1093
|
(typeof result["commit"] === "string"
|
|
1123
1094
|
? ` commit=${result["commit"].slice(0, 8)}`
|
|
1124
1095
|
: "") +
|
|
@@ -1214,6 +1185,15 @@ async function main() {
|
|
|
1214
1185
|
}
|
|
1215
1186
|
return 0;
|
|
1216
1187
|
}
|
|
1188
|
+
case "about":
|
|
1189
|
+
// Product identity (version + author + license + owner links, D-11).
|
|
1190
|
+
// `--json` is a small stable envelope; the Swift About panel and the
|
|
1191
|
+
// packed npm-manifest assertion consume the same facts.
|
|
1192
|
+
if (json)
|
|
1193
|
+
printJson(aboutJson(CLI_VERSION));
|
|
1194
|
+
else
|
|
1195
|
+
print(renderAbout(CLI_VERSION));
|
|
1196
|
+
return 0;
|
|
1217
1197
|
case "help":
|
|
1218
1198
|
// `help --json` is the machine-readable command catalog (agents parse
|
|
1219
1199
|
// it instead of scraping the text help).
|
|
@@ -1225,23 +1205,37 @@ async function main() {
|
|
|
1225
1205
|
default:
|
|
1226
1206
|
// Unknown command is an ERROR (exit 2), not a silent help print with
|
|
1227
1207
|
// exit 0 — scripts must not mistake a typo'd verb for success. --json
|
|
1228
|
-
// callers get the
|
|
1208
|
+
// callers get the ONE projector envelope (with message/code shape, no
|
|
1209
|
+
// longer a partial {ok,exitCode,error}); text mode prints the full help.
|
|
1229
1210
|
if (json) {
|
|
1230
|
-
|
|
1231
|
-
ok: false,
|
|
1232
|
-
exitCode: 2,
|
|
1233
|
-
error: `claudexor: unknown command '${cmd}' (see \`claudexor help --json\`)`,
|
|
1234
|
-
});
|
|
1235
|
-
return 2;
|
|
1211
|
+
return renderCliFailure(true, usageError(`claudexor: unknown command '${cmd}' (see \`claudexor help --json\`)`), {});
|
|
1236
1212
|
}
|
|
1237
1213
|
process.stderr.write(`claudexor: unknown command '${cmd}'\n\n${HELP}\n`);
|
|
1238
1214
|
return 2;
|
|
1239
1215
|
}
|
|
1240
1216
|
}
|
|
1217
|
+
// The ONE top-level result/error projector (D-7, GH #28): any throw from any
|
|
1218
|
+
// command path is rendered by renderCliFailure (see cli-error.ts) into exactly
|
|
1219
|
+
// one JSON envelope or one stderr line, via the central category->exit-code
|
|
1220
|
+
// table. Commands that already print and return a code are unaffected.
|
|
1221
|
+
async function main() {
|
|
1222
|
+
const args = parseArgs(process.argv.slice(2));
|
|
1223
|
+
if (flagBool(args, "version")) {
|
|
1224
|
+
process.stdout.write(`${CLI_VERSION}\n`);
|
|
1225
|
+
return 0;
|
|
1226
|
+
}
|
|
1227
|
+
const json = flagBool(args, "json");
|
|
1228
|
+
try {
|
|
1229
|
+
return await dispatch(args, json);
|
|
1230
|
+
}
|
|
1231
|
+
catch (err) {
|
|
1232
|
+
return renderCliFailure(json, err);
|
|
1233
|
+
}
|
|
1234
|
+
}
|
|
1241
1235
|
main()
|
|
1242
1236
|
.then((code) => process.exit(code))
|
|
1243
1237
|
.catch((err) => {
|
|
1244
|
-
|
|
1245
|
-
process.exit(
|
|
1238
|
+
// Last-resort projector: still emit ONE envelope if the parse threw before json was known.
|
|
1239
|
+
process.exit(renderCliFailure(process.argv.includes("--json"), err));
|
|
1246
1240
|
});
|
|
1247
1241
|
//# sourceMappingURL=cli.js.map
|