@claudexor/cli 3.1.1 → 3.2.0
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.map +1 -1
- package/dist/accounts-projection.d.ts +8 -1
- package/dist/accounts-projection.d.ts.map +1 -1
- package/dist/accounts-projection.js +33 -20
- package/dist/accounts-projection.js.map +1 -1
- package/dist/accounts-services.d.ts +206 -0
- package/dist/accounts-services.d.ts.map +1 -0
- package/dist/accounts-services.js +71 -0
- package/dist/accounts-services.js.map +1 -0
- package/dist/acp-surface-runner.d.ts +39 -0
- package/dist/acp-surface-runner.d.ts.map +1 -1
- package/dist/acp-surface-runner.js +104 -30
- package/dist/acp-surface-runner.js.map +1 -1
- package/dist/attachment-upload.d.ts +5 -0
- package/dist/attachment-upload.d.ts.map +1 -0
- package/dist/attachment-upload.js +64 -0
- package/dist/attachment-upload.js.map +1 -0
- package/dist/belt-bridge.d.ts +2 -0
- package/dist/belt-bridge.d.ts.map +1 -0
- package/dist/belt-bridge.js +31 -0
- package/dist/belt-bridge.js.map +1 -0
- package/dist/bridge-serve.d.ts +1 -9
- package/dist/bridge-serve.d.ts.map +1 -1
- package/dist/bridge-serve.js +5 -22
- package/dist/bridge-serve.js.map +1 -1
- package/dist/capabilities.d.ts.map +1 -1
- package/dist/capabilities.js +8 -1
- package/dist/capabilities.js.map +1 -1
- package/dist/choice-input.d.ts +7 -0
- package/dist/choice-input.d.ts.map +1 -0
- package/dist/choice-input.js +17 -0
- package/dist/choice-input.js.map +1 -0
- package/dist/claude-oauth-usage.js.map +1 -1
- package/dist/claudexord-entry.d.ts +11 -0
- package/dist/claudexord-entry.d.ts.map +1 -0
- package/dist/claudexord-entry.js +42 -0
- package/dist/claudexord-entry.js.map +1 -0
- package/dist/claudexord.d.ts +2 -17
- package/dist/claudexord.d.ts.map +1 -1
- package/dist/claudexord.js +60 -93
- package/dist/claudexord.js.map +1 -1
- package/dist/cli-error.d.ts.map +1 -1
- package/dist/cli-error.js +21 -11
- package/dist/cli-error.js.map +1 -1
- package/dist/cli.js +149 -170
- package/dist/cli.js.map +1 -1
- package/dist/codex-device-login.js.map +1 -1
- package/dist/codex-quota-source.js.map +1 -1
- package/dist/command-flags.d.ts +16 -1
- package/dist/command-flags.d.ts.map +1 -1
- package/dist/command-flags.js +41 -19
- package/dist/command-flags.js.map +1 -1
- package/dist/command-registry.d.ts +21 -8
- package/dist/command-registry.d.ts.map +1 -1
- package/dist/command-registry.js +59 -116
- package/dist/command-registry.js.map +1 -1
- package/dist/command-scope.d.ts +13 -0
- package/dist/command-scope.d.ts.map +1 -0
- package/dist/command-scope.js +61 -0
- package/dist/command-scope.js.map +1 -0
- package/dist/control-services.d.ts +1622 -982
- package/dist/control-services.d.ts.map +1 -1
- package/dist/control-services.js +39 -68
- package/dist/control-services.js.map +1 -1
- package/dist/credential-commands.d.ts.map +1 -1
- package/dist/credential-commands.js +13 -3
- package/dist/credential-commands.js.map +1 -1
- package/dist/daemon-lifecycle.d.ts.map +1 -1
- package/dist/daemon-outcome.d.ts +3 -5
- package/dist/daemon-outcome.d.ts.map +1 -1
- package/dist/daemon-outcome.js +7 -19
- package/dist/daemon-outcome.js.map +1 -1
- package/dist/daemon-run.d.ts +26 -29
- package/dist/daemon-run.d.ts.map +1 -1
- package/dist/daemon-run.js +89 -97
- package/dist/daemon-run.js.map +1 -1
- package/dist/daemon-runtime-shutdown.d.ts +7 -0
- package/dist/daemon-runtime-shutdown.d.ts.map +1 -1
- package/dist/daemon-runtime-shutdown.js +29 -0
- package/dist/daemon-runtime-shutdown.js.map +1 -1
- package/dist/delegation-belt-descriptor.d.ts +20 -36
- package/dist/delegation-belt-descriptor.d.ts.map +1 -1
- package/dist/delegation-belt-descriptor.js +48 -51
- package/dist/delegation-belt-descriptor.js.map +1 -1
- package/dist/delegation-capability.d.ts +4 -0
- package/dist/delegation-capability.d.ts.map +1 -0
- package/dist/delegation-capability.js +29 -0
- package/dist/delegation-capability.js.map +1 -0
- package/dist/delegation-daemon-binding.d.ts +8 -0
- package/dist/delegation-daemon-binding.d.ts.map +1 -0
- package/dist/delegation-daemon-binding.js +18 -0
- package/dist/delegation-daemon-binding.js.map +1 -0
- package/dist/delegation-output.d.ts +18 -0
- package/dist/delegation-output.d.ts.map +1 -0
- package/dist/delegation-output.js +47 -0
- package/dist/delegation-output.js.map +1 -0
- package/dist/harness-command.d.ts +13 -0
- package/dist/harness-command.d.ts.map +1 -0
- package/dist/harness-command.js +35 -0
- package/dist/harness-command.js.map +1 -0
- package/dist/harness-installer.d.ts +79 -0
- package/dist/harness-installer.d.ts.map +1 -0
- package/dist/harness-installer.js +256 -0
- package/dist/harness-installer.js.map +1 -0
- package/dist/interaction-prompt.d.ts +19 -0
- package/dist/interaction-prompt.d.ts.map +1 -0
- package/dist/interaction-prompt.js +114 -0
- package/dist/interaction-prompt.js.map +1 -0
- package/dist/live.d.ts +2 -6
- package/dist/live.d.ts.map +1 -1
- package/dist/live.js +92 -75
- package/dist/live.js.map +1 -1
- package/dist/mcp-daemon-unavailable.d.ts +6 -0
- package/dist/mcp-daemon-unavailable.d.ts.map +1 -0
- package/dist/mcp-daemon-unavailable.js +16 -0
- package/dist/mcp-daemon-unavailable.js.map +1 -0
- package/dist/mcp-run-projections.d.ts +42 -0
- package/dist/mcp-run-projections.d.ts.map +1 -0
- package/dist/mcp-run-projections.js +74 -0
- package/dist/mcp-run-projections.js.map +1 -0
- package/dist/mcp-runner.d.ts +19 -1
- package/dist/mcp-runner.d.ts.map +1 -1
- package/dist/mcp-runner.js +121 -115
- package/dist/mcp-runner.js.map +1 -1
- package/dist/native-login.js.map +1 -1
- package/dist/ops-command-specs.d.ts +64 -0
- package/dist/ops-command-specs.d.ts.map +1 -0
- package/dist/ops-command-specs.js +146 -0
- package/dist/ops-command-specs.js.map +1 -0
- package/dist/ops-commands.d.ts.map +1 -1
- package/dist/ops-commands.js +23 -5
- package/dist/ops-commands.js.map +1 -1
- package/dist/orphan-reaper.js.map +1 -1
- package/dist/output-mode.d.ts +11 -0
- package/dist/output-mode.d.ts.map +1 -0
- package/dist/output-mode.js +28 -0
- package/dist/output-mode.js.map +1 -0
- package/dist/plan-question-loop.d.ts.map +1 -1
- package/dist/plan-question-loop.js +16 -13
- package/dist/plan-question-loop.js.map +1 -1
- package/dist/plugins.js +1 -1
- package/dist/plugins.js.map +1 -1
- package/dist/primary-output.d.ts +9 -4
- package/dist/primary-output.d.ts.map +1 -1
- package/dist/primary-output.js +50 -2
- package/dist/primary-output.js.map +1 -1
- package/dist/quota-subject-universe.d.ts +6 -0
- package/dist/quota-subject-universe.d.ts.map +1 -0
- package/dist/quota-subject-universe.js +31 -0
- package/dist/quota-subject-universe.js.map +1 -0
- package/dist/registry.js.map +1 -1
- package/dist/release-command.d.ts +1 -1
- package/dist/release-command.js +2 -2
- package/dist/remote-command-specs.d.ts +45 -0
- package/dist/remote-command-specs.d.ts.map +1 -0
- package/dist/remote-command-specs.js +29 -0
- package/dist/remote-command-specs.js.map +1 -0
- package/dist/remote-command.d.ts +11 -0
- package/dist/remote-command.d.ts.map +1 -0
- package/dist/remote-command.js +262 -0
- package/dist/remote-command.js.map +1 -0
- package/dist/remote-filesystem.d.ts +33 -0
- package/dist/remote-filesystem.d.ts.map +1 -0
- package/dist/remote-filesystem.js +280 -0
- package/dist/remote-filesystem.js.map +1 -0
- package/dist/repo-asset-authority.js.map +1 -1
- package/dist/request-preflight.d.ts +11 -2
- package/dist/request-preflight.d.ts.map +1 -1
- package/dist/request-preflight.js +36 -13
- package/dist/request-preflight.js.map +1 -1
- package/dist/retry-command-specs.d.ts.map +1 -1
- package/dist/retry-command-specs.js +2 -0
- package/dist/retry-command-specs.js.map +1 -1
- package/dist/run-applicability.d.ts +74 -0
- package/dist/run-applicability.d.ts.map +1 -0
- package/dist/run-applicability.js +72 -0
- package/dist/run-applicability.js.map +1 -0
- package/dist/run-detail-projections.d.ts +39 -0
- package/dist/run-detail-projections.d.ts.map +1 -0
- package/dist/run-detail-projections.js +64 -0
- package/dist/run-detail-projections.js.map +1 -0
- package/dist/run-detail-response.d.ts +7 -0
- package/dist/run-detail-response.d.ts.map +1 -0
- package/dist/run-detail-response.js +23 -0
- package/dist/run-detail-response.js.map +1 -0
- package/dist/run-facts-projection.d.ts +22 -0
- package/dist/run-facts-projection.d.ts.map +1 -0
- package/dist/run-facts-projection.js +86 -0
- package/dist/run-facts-projection.js.map +1 -0
- package/dist/runtime-replacement-stop.d.ts +25 -0
- package/dist/runtime-replacement-stop.d.ts.map +1 -0
- package/dist/runtime-replacement-stop.js +145 -0
- package/dist/runtime-replacement-stop.js.map +1 -0
- package/dist/settings-command.d.ts +1 -0
- package/dist/settings-command.d.ts.map +1 -1
- package/dist/settings-command.js +27 -21
- package/dist/settings-command.js.map +1 -1
- package/dist/settings-service.d.ts +7 -7
- package/dist/settings-service.d.ts.map +1 -1
- package/dist/settings-service.js +3 -3
- package/dist/settings-service.js.map +1 -1
- package/dist/setup-client-pty.d.ts +14 -0
- package/dist/setup-client-pty.d.ts.map +1 -0
- package/dist/setup-client-pty.js +61 -0
- package/dist/setup-client-pty.js.map +1 -0
- package/dist/setup-device-code-disclosure.d.ts +15 -0
- package/dist/setup-device-code-disclosure.d.ts.map +1 -0
- package/dist/setup-device-code-disclosure.js +52 -0
- package/dist/setup-device-code-disclosure.js.map +1 -0
- package/dist/setup-job-reducer.d.ts.map +1 -1
- package/dist/setup-job-reducer.js +1 -0
- package/dist/setup-job-reducer.js.map +1 -1
- package/dist/setup-job-store.d.ts +275 -75
- package/dist/setup-job-store.d.ts.map +1 -1
- package/dist/setup-job-store.js.map +1 -1
- package/dist/setup-job-support.js.map +1 -1
- package/dist/setup-jobs.d.ts +517 -137
- package/dist/setup-jobs.d.ts.map +1 -1
- package/dist/setup-jobs.js +68 -118
- package/dist/setup-jobs.js.map +1 -1
- package/dist/setup-lifecycle-binding.d.ts +7 -0
- package/dist/setup-lifecycle-binding.d.ts.map +1 -1
- package/dist/setup-lifecycle-binding.js +6 -0
- package/dist/setup-lifecycle-binding.js.map +1 -1
- package/dist/setup-login-child-lifecycle.d.ts +13 -0
- package/dist/setup-login-child-lifecycle.d.ts.map +1 -0
- package/dist/setup-login-child-lifecycle.js +45 -0
- package/dist/setup-login-child-lifecycle.js.map +1 -0
- package/dist/setup-login-inline.d.ts +11 -12
- package/dist/setup-login-inline.d.ts.map +1 -1
- package/dist/setup-login-inline.js +26 -15
- package/dist/setup-login-inline.js.map +1 -1
- package/dist/setup-login-permit.d.ts +10 -0
- package/dist/setup-login-permit.d.ts.map +1 -0
- package/dist/setup-login-permit.js +52 -0
- package/dist/setup-login-permit.js.map +1 -0
- package/dist/setup-login-protocol.d.ts.map +1 -1
- package/dist/setup-login-protocol.js +9 -2
- package/dist/setup-login-protocol.js.map +1 -1
- package/dist/setup-login-runner.d.ts +1 -0
- package/dist/setup-login-runner.d.ts.map +1 -1
- package/dist/setup-login-runner.js +20 -31
- package/dist/setup-login-runner.js.map +1 -1
- package/dist/setup-supervisor.d.ts.map +1 -1
- package/dist/setup-supervisor.js.map +1 -1
- package/dist/terminal-run-output.d.ts +12 -0
- package/dist/terminal-run-output.d.ts.map +1 -0
- package/dist/terminal-run-output.js +33 -0
- package/dist/terminal-run-output.js.map +1 -0
- package/dist/thread-delivery.d.ts.map +1 -1
- package/dist/thread-delivery.js +4 -3
- package/dist/thread-delivery.js.map +1 -1
- package/dist/thread-execution-workspace.d.ts +15 -0
- package/dist/thread-execution-workspace.d.ts.map +1 -1
- package/dist/thread-execution-workspace.js +39 -5
- package/dist/thread-execution-workspace.js.map +1 -1
- package/dist/thread-turn-services.d.ts +104 -0
- package/dist/thread-turn-services.d.ts.map +1 -0
- package/dist/thread-turn-services.js +27 -0
- package/dist/thread-turn-services.js.map +1 -0
- package/package.json +23 -23
package/dist/cli.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import process from "node:process";
|
|
3
|
-
import {
|
|
4
|
-
import { createHash } from "node:crypto";
|
|
5
|
-
import { Readable, Transform } from "node:stream";
|
|
3
|
+
import { existsSync, lstatSync, readFileSync, readdirSync } from "node:fs";
|
|
6
4
|
import { dirname, join, relative, resolve, sep } from "node:path";
|
|
7
5
|
import { ArtifactStore } from "@claudexor/artifact-store";
|
|
8
6
|
import { CLAUDEXOR_VERSION, noProjectRepoRoot, readTextSafe, userConfigDir } from "@claudexor/util";
|
|
@@ -10,13 +8,15 @@ import { releaseCommand } from "./release-command.js";
|
|
|
10
8
|
import { serveBeltBridge, serveMcpBridge } from "./bridge-serve.js";
|
|
11
9
|
import { dispatchAcpCommand } from "./acp-auth-command.js";
|
|
12
10
|
import { initProjectConfig } from "@claudexor/config";
|
|
13
|
-
import { DecisionRecord, EFFORT_HINT_HELP, EffortHint, ExternalContextPolicy, ModeKind as ModeKindSchema, RoutingGoal, ControlThreadListResponse, RunTelemetry, StructuredOutputConformance, TaskContract, runOutcomeLabel, } from "@claudexor/schema";
|
|
11
|
+
import { DecisionRecord, EFFORT_HINT_HELP, EffortHint, ExternalContextPolicy, ModeKind as ModeKindSchema, RoutingGoal, ControlThreadListResponse, RunFailure, RunTelemetry, StructuredOutputConformance, TaskContract, runOutcomeLabel, } from "@claudexor/schema";
|
|
14
12
|
import { flagBool, flagStr, flagStringList, flagValues, parseArgs, requiredStringFlagError, } from "./args.js";
|
|
15
13
|
import { print, printJson, printJsonLine, printUsageError, statusGlyph } from "./cli-io.js";
|
|
16
14
|
import { controlProblemError, minIntError, renderCliFailure, usageError } from "./cli-error.js";
|
|
15
|
+
import { cliOutputMode, outputModeIsMachine, outputModeIsStream, renderOutputFailure, renderOutputUsageFailure, } from "./output-mode.js";
|
|
17
16
|
import { handleHelpRequest } from "./command-help.js";
|
|
18
17
|
import { pickResumableThread } from "./thread-select.js";
|
|
19
|
-
import { KNOWN_FLAGS, VALUE_FLAGS,
|
|
18
|
+
import { KNOWN_FLAGS, VALUE_FLAGS, helpJson, renderHelp } from "./command-registry.js";
|
|
19
|
+
import { commandFlagScopeError, commandPositionalError, runModeFlagScopeError, } from "./command-scope.js";
|
|
20
20
|
import { buildAgentCapabilityCatalog } from "./capabilities.js";
|
|
21
21
|
import { aboutJson, renderAbout } from "./about-command.js";
|
|
22
22
|
import { dispatchOpsCommand } from "./ops-commands.js";
|
|
@@ -24,17 +24,22 @@ import { reviewCommand } from "./review-command.js";
|
|
|
24
24
|
import { controlApiFetch, followRun } from "./live.js";
|
|
25
25
|
import { retryCommand, runAgainCommand } from "./retry-command.js";
|
|
26
26
|
import { assertCliRunParamsHaveNoInlineSecrets } from "./run-secret-scan.js";
|
|
27
|
-
import {
|
|
28
|
-
import {
|
|
27
|
+
import { resolveLocalAttachment } from "./local-attachment.js";
|
|
28
|
+
import { uploadLocalAttachment } from "./attachment-upload.js";
|
|
29
|
+
import { connectDaemonIfRunning, daemonOutcomeSummary, ensureDaemon, enqueueAndAwait, exitCodeForState, fetchApplyEligibility, fetchCouncil, fetchRunDetail, fetchRunOutcomeFacts, projectOutcomeBanner, projectRunOutcomeFacts, mergeDaemonRunOutcome, } from "./daemon-run.js";
|
|
30
|
+
import { inspectDelegationLines, projectDelegation, terminalDelegationLines, } from "./delegation-output.js";
|
|
31
|
+
import { readRunFactsArtifact } from "./run-facts-projection.js";
|
|
32
|
+
import { projectTerminalRunOutput, terminalRunRequiredActionLines } from "./terminal-run-output.js";
|
|
29
33
|
import { runPlanQuestionLoop } from "./plan-question-loop.js";
|
|
30
34
|
import { resolveDecisionBody } from "./decision.js";
|
|
31
35
|
import { primaryOutputForCli } from "./primary-output.js";
|
|
32
36
|
import { PLUGIN_TARGETS, PLUGIN_VERBS, formatPluginResult, pluginCommandErrorResult, runPluginCommand, } from "./plugins.js";
|
|
33
|
-
import { buildRegistry } from "./registry.js";
|
|
34
37
|
import { settingsCommand } from "./settings-command.js";
|
|
35
38
|
import { quotaCommand } from "./quota-command.js";
|
|
36
39
|
import { trustCommand } from "./trust-command.js";
|
|
37
40
|
import { projectCommand } from "./project-command.js";
|
|
41
|
+
import { remoteCommand, setupCommand } from "./remote-command.js";
|
|
42
|
+
import { harnessCommand } from "./harness-command.js";
|
|
38
43
|
import { runRepl } from "./repl.js";
|
|
39
44
|
import { parseProtectedPathApprovalFlags, parseTestCommandFlags, parseReviewerEffortFlags, parseReviewerModelFlags, parseReviewerPanelFlags, } from "./run-options.js";
|
|
40
45
|
const CLI_VERSION = CLAUDEXOR_VERSION;
|
|
@@ -159,55 +164,6 @@ function attachmentInputs(args) {
|
|
|
159
164
|
const out = attachmentPaths(args).map(({ path, forceImage }) => resolveLocalAttachment(path, forceImage));
|
|
160
165
|
return out.length > 0 ? out : undefined;
|
|
161
166
|
}
|
|
162
|
-
async function uploadLocalAttachment(addr, attachment) {
|
|
163
|
-
const created = (await controlJson(addr, "/uploads", {
|
|
164
|
-
method: "POST",
|
|
165
|
-
headers: { "content-type": "application/json" },
|
|
166
|
-
body: JSON.stringify({
|
|
167
|
-
kind: attachment.kind,
|
|
168
|
-
mime: attachment.mime,
|
|
169
|
-
name: attachment.name,
|
|
170
|
-
sizeBytes: attachment.sizeBytes,
|
|
171
|
-
}),
|
|
172
|
-
}));
|
|
173
|
-
try {
|
|
174
|
-
const source = createReadStream(attachment.path, {
|
|
175
|
-
fd: openLocalAttachment(attachment),
|
|
176
|
-
autoClose: true,
|
|
177
|
-
});
|
|
178
|
-
const hash = createHash("sha256");
|
|
179
|
-
const hashingStream = new Transform({
|
|
180
|
-
transform(chunk, _encoding, callback) {
|
|
181
|
-
hash.update(chunk);
|
|
182
|
-
callback(null, chunk);
|
|
183
|
-
},
|
|
184
|
-
});
|
|
185
|
-
source.pipe(hashingStream);
|
|
186
|
-
const response = await controlApiFetch(addr, `/uploads/${encodeURIComponent(created.uploadId)}/bytes`, {
|
|
187
|
-
method: "PUT",
|
|
188
|
-
headers: { "content-type": "application/octet-stream" },
|
|
189
|
-
body: Readable.toWeb(hashingStream),
|
|
190
|
-
duplex: "half",
|
|
191
|
-
});
|
|
192
|
-
if (!response.ok) {
|
|
193
|
-
const detail = (await response.json().catch(() => ({})));
|
|
194
|
-
throw new Error(String(detail["message"] ?? detail["error"] ?? `HTTP ${response.status}`));
|
|
195
|
-
}
|
|
196
|
-
const expectedSha256 = `sha256:${hash.digest("hex")}`;
|
|
197
|
-
const resource = (await controlJson(addr, `/uploads/${encodeURIComponent(created.uploadId)}/finalize`, {
|
|
198
|
-
method: "POST",
|
|
199
|
-
headers: { "content-type": "application/json" },
|
|
200
|
-
body: JSON.stringify({ expectedSha256 }),
|
|
201
|
-
}));
|
|
202
|
-
return { resourceId: resource.resourceId };
|
|
203
|
-
}
|
|
204
|
-
catch (error) {
|
|
205
|
-
await controlApiFetch(addr, `/uploads/${encodeURIComponent(created.uploadId)}`, {
|
|
206
|
-
method: "DELETE",
|
|
207
|
-
}).catch(() => undefined);
|
|
208
|
-
throw error;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
167
|
/** Per-family reviewer model map from `--reviewer-model "openai=gpt-4o-mini,anthropic=claude-haiku"`. Fails loudly on malformed input. */
|
|
212
168
|
function reviewerModels(args) {
|
|
213
169
|
return parseReviewerModelFlags(flagValues(args, "reviewer-model"));
|
|
@@ -220,7 +176,7 @@ function reviewerEfforts(args) {
|
|
|
220
176
|
function reviewerPanel(args) {
|
|
221
177
|
return parseReviewerPanelFlags(flagValues(args, "reviewer-panel"));
|
|
222
178
|
}
|
|
223
|
-
async function orchestrate(args, mode,
|
|
179
|
+
async function orchestrate(args, mode, outputMode, forced = {}) {
|
|
224
180
|
let rawPrompt = args._.slice(1).join(" ").trim();
|
|
225
181
|
// Headless prompt sources (W13): `-` reads the prompt from stdin; a file
|
|
226
182
|
// beats retyping. Exactly ONE source — ambiguity is a usage error, never a
|
|
@@ -228,34 +184,34 @@ async function orchestrate(args, mode, json, forced = {}) {
|
|
|
228
184
|
const promptFile = flagStr(args, "prompt-file");
|
|
229
185
|
if (promptFile !== undefined) {
|
|
230
186
|
if (rawPrompt && rawPrompt !== "-") {
|
|
231
|
-
return
|
|
187
|
+
return renderOutputUsageFailure(outputMode, "claudexor: pass either an inline prompt or --prompt-file, not both");
|
|
232
188
|
}
|
|
233
189
|
try {
|
|
234
190
|
rawPrompt = readFileSync(promptFile, "utf8").trim();
|
|
235
191
|
}
|
|
236
192
|
catch (err) {
|
|
237
|
-
return
|
|
193
|
+
return renderOutputUsageFailure(outputMode, `claudexor: --prompt-file: cannot read ${promptFile}: ${err instanceof Error ? err.message : String(err)}`);
|
|
238
194
|
}
|
|
239
195
|
}
|
|
240
196
|
else if (rawPrompt === "-") {
|
|
241
197
|
rawPrompt = readFileSync(0, "utf8").trim();
|
|
242
198
|
if (!rawPrompt) {
|
|
243
|
-
return
|
|
199
|
+
return renderOutputUsageFailure(outputMode, "claudexor: stdin prompt (`-`) was empty");
|
|
244
200
|
}
|
|
245
201
|
}
|
|
246
202
|
const prompt = rawPrompt;
|
|
247
203
|
if (!prompt) {
|
|
248
|
-
return
|
|
204
|
+
return renderOutputUsageFailure(outputMode, "claudexor: missing prompt");
|
|
249
205
|
}
|
|
250
206
|
const portfolioRaw = flagStr(args, "portfolio");
|
|
251
207
|
if (portfolioRaw !== undefined) {
|
|
252
|
-
return
|
|
208
|
+
return renderOutputUsageFailure(outputMode, "claudexor: --portfolio was removed in v2; use --routing-goal auto|quality|economy");
|
|
253
209
|
}
|
|
254
210
|
const credentialProfileId = flagStr(args, "profile");
|
|
255
211
|
const routingGoalRaw = flagStr(args, "routing-goal");
|
|
256
212
|
const routingGoal = routingGoalRaw !== undefined ? RoutingGoal.safeParse(routingGoalRaw) : null;
|
|
257
213
|
if (routingGoalRaw !== undefined && !routingGoal?.success) {
|
|
258
|
-
return
|
|
214
|
+
return renderOutputUsageFailure(outputMode, `claudexor: unknown --routing-goal '${routingGoalRaw}'`);
|
|
259
215
|
}
|
|
260
216
|
let reviewerEffortOverrides;
|
|
261
217
|
let resolvedReviewerModels;
|
|
@@ -332,7 +288,10 @@ async function orchestrate(args, mode, json, forced = {}) {
|
|
|
332
288
|
}
|
|
333
289
|
catch (err) {
|
|
334
290
|
// Projector: typed field errors / domain codes survive; a plain flag-parse Error is usage (exit 2).
|
|
335
|
-
return
|
|
291
|
+
return renderOutputFailure(outputMode, err, {
|
|
292
|
+
defaultCategory: "usage",
|
|
293
|
+
messagePrefix: "claudexor:",
|
|
294
|
+
});
|
|
336
295
|
}
|
|
337
296
|
let tests;
|
|
338
297
|
try {
|
|
@@ -361,15 +320,18 @@ async function orchestrate(args, mode, json, forced = {}) {
|
|
|
361
320
|
}
|
|
362
321
|
catch (err) {
|
|
363
322
|
// Preserves the typed `inline_secret_rejected` code (never echoing the token).
|
|
364
|
-
return
|
|
323
|
+
return renderOutputFailure(outputMode, err, {
|
|
324
|
+
defaultCategory: "usage",
|
|
325
|
+
messagePrefix: "claudexor:",
|
|
326
|
+
});
|
|
365
327
|
}
|
|
366
328
|
if (delegate && mode !== "agent") {
|
|
367
|
-
return
|
|
329
|
+
return renderOutputUsageFailure(outputMode, `claudexor: --delegate is an agent strategy (got mode '${mode}')`);
|
|
368
330
|
}
|
|
369
331
|
if (council && mode !== "plan") {
|
|
370
|
-
return
|
|
332
|
+
return renderOutputUsageFailure(outputMode, `claudexor: --council is a plan strategy (got mode '${mode}')`);
|
|
371
333
|
}
|
|
372
|
-
return daemonRun(args,
|
|
334
|
+
return daemonRun(args, outputMode, {
|
|
373
335
|
mode,
|
|
374
336
|
delegate,
|
|
375
337
|
council,
|
|
@@ -404,12 +366,10 @@ async function orchestrate(args, mode, json, forced = {}) {
|
|
|
404
366
|
* All five product modes enter through the managed daemon and control API.
|
|
405
367
|
* `--json` prints one stable `{ runId, runDir, status }` machine envelope.
|
|
406
368
|
*/
|
|
407
|
-
async function daemonRun(args,
|
|
369
|
+
async function daemonRun(args, outputMode, p) {
|
|
408
370
|
const inPlace = flagBool(args, "in-place");
|
|
409
|
-
const
|
|
410
|
-
|
|
411
|
-
return printUsageError(json, "claudexor: --json prints exactly one object and --json-stream prints NDJSON; pass one, not both");
|
|
412
|
-
}
|
|
371
|
+
const json = outputModeIsMachine(outputMode);
|
|
372
|
+
const jsonStream = outputModeIsStream(outputMode);
|
|
413
373
|
let client;
|
|
414
374
|
let addr;
|
|
415
375
|
try {
|
|
@@ -503,6 +463,10 @@ async function daemonRun(args, json, p) {
|
|
|
503
463
|
...(p.reviewerModels ? { reviewerModels: p.reviewerModels } : {}),
|
|
504
464
|
...(p.reviewerEfforts ? { reviewerEfforts: p.reviewerEfforts } : {}),
|
|
505
465
|
};
|
|
466
|
+
// The last run id this command bound, threaded into the failure envelope as
|
|
467
|
+
// a per-command extra: a run that DID start (or finish) must keep its handle
|
|
468
|
+
// even when a post-terminal read raises (e.g. 500 run_facts_invalid).
|
|
469
|
+
let terminalRunId = "";
|
|
506
470
|
try {
|
|
507
471
|
if (jsonStream) {
|
|
508
472
|
// NDJSON machine surface (W13): an EARLY runId frame first, every run
|
|
@@ -512,18 +476,10 @@ async function daemonRun(args, json, p) {
|
|
|
512
476
|
const started = await enqueueAndAwait(client, addr, body, { waitForTerminal: false });
|
|
513
477
|
if (!started.runId) {
|
|
514
478
|
// Even the early-failure path stays valid NDJSON (compact, one line).
|
|
515
|
-
printJsonLine({
|
|
516
|
-
frame: "run.terminal",
|
|
517
|
-
runId: "",
|
|
518
|
-
runDir: started.runDir,
|
|
519
|
-
status: started.status,
|
|
520
|
-
jobId: started.jobId,
|
|
521
|
-
mode: p.mode,
|
|
522
|
-
...(started.error ? { error: started.error } : {}),
|
|
523
|
-
...daemonOutcomeProblemFields(started),
|
|
524
|
-
});
|
|
479
|
+
printJsonLine(projectTerminalRunOutput(started, p.mode, null, { frame: "run.terminal" }));
|
|
525
480
|
return exitCodeForState(started.status);
|
|
526
481
|
}
|
|
482
|
+
terminalRunId = started.runId;
|
|
527
483
|
printJsonLine({
|
|
528
484
|
frame: "run.started",
|
|
529
485
|
runId: started.runId,
|
|
@@ -537,50 +493,31 @@ async function daemonRun(args, json, p) {
|
|
|
537
493
|
const final = started.jobId ? await client.status(started.jobId) : null;
|
|
538
494
|
const out = mergeDaemonRunOutcome(started, final);
|
|
539
495
|
const status = out.status;
|
|
540
|
-
const reason = daemonOutcomeSummary({ ...started, status, error: out.error });
|
|
541
|
-
// ONE GET /runs/:id feeds all three terminal projections (INV-120/122).
|
|
542
496
|
const detail = await fetchRunDetail(addr, out.runId);
|
|
543
|
-
const
|
|
544
|
-
const
|
|
545
|
-
printJsonLine({
|
|
497
|
+
const facts = projectRunOutcomeFacts(detail);
|
|
498
|
+
const reason = daemonOutcomeSummary({ ...out, outcomeFacts: facts ?? undefined });
|
|
499
|
+
printJsonLine(projectTerminalRunOutput(out, p.mode, detail, {
|
|
546
500
|
frame: "run.terminal",
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
status: out.status,
|
|
550
|
-
jobId: out.jobId,
|
|
551
|
-
mode: p.mode,
|
|
552
|
-
...(out.error ? { error: out.error } : {}),
|
|
553
|
-
...daemonOutcomeProblemFields(out),
|
|
554
|
-
...(reason ? { summary: reason } : {}),
|
|
555
|
-
...(outcomeBanner ? { outcomeBanner } : {}),
|
|
556
|
-
...(applyEligibility ? { applyEligibility } : {}),
|
|
557
|
-
});
|
|
501
|
+
summary: reason,
|
|
502
|
+
}));
|
|
558
503
|
return exitCodeForState(status, projectRunOutcomeFacts(detail));
|
|
559
504
|
}
|
|
560
505
|
if (json) {
|
|
561
506
|
// Pure machine surface: await the terminal outcome and print one JSON object.
|
|
562
507
|
const out = await enqueueAndAwait(client, addr, body, { waitForTerminal: true });
|
|
563
|
-
|
|
564
|
-
const reason = daemonOutcomeSummary(out);
|
|
508
|
+
terminalRunId = out.runId;
|
|
565
509
|
// ADD-ONLY key (bench contract keeps {runId,runDir,status}): the derived
|
|
566
510
|
// apply-gate verdict, so machine callers act on truth instead of
|
|
567
511
|
// re-implying eligibility from status. ONE GET /runs/:id feeds all three
|
|
568
512
|
// terminal projections (INV-120/122).
|
|
569
513
|
const detail = await fetchRunDetail(addr, out.runId);
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
status: out.status,
|
|
576
|
-
jobId: out.jobId,
|
|
577
|
-
mode: p.mode,
|
|
578
|
-
...(out.error ? { error: out.error } : {}),
|
|
579
|
-
...daemonOutcomeProblemFields(out),
|
|
580
|
-
...(reason ? { summary: reason } : {}),
|
|
581
|
-
...(outcomeBanner ? { outcomeBanner } : {}),
|
|
582
|
-
...(applyEligibility ? { applyEligibility } : {}),
|
|
514
|
+
// Preserve bench keys while deriving the human summary from the same
|
|
515
|
+
// canonical receipt that feeds the machine terminal fields.
|
|
516
|
+
const reason = daemonOutcomeSummary({
|
|
517
|
+
...out,
|
|
518
|
+
outcomeFacts: projectRunOutcomeFacts(detail) ?? undefined,
|
|
583
519
|
});
|
|
520
|
+
printJson(projectTerminalRunOutput(out, p.mode, detail, { summary: reason }));
|
|
584
521
|
return exitCodeForState(out.status, projectRunOutcomeFacts(detail));
|
|
585
522
|
}
|
|
586
523
|
// Text mode: enqueue, then live-stream the run through the shared follow
|
|
@@ -589,19 +526,30 @@ async function daemonRun(args, json, p) {
|
|
|
589
526
|
const started = await enqueueAndAwait(client, addr, body, { waitForTerminal: false });
|
|
590
527
|
if (!started.runId) {
|
|
591
528
|
print(`run did not start: ${started.status}${started.error ? ` — ${started.error}` : ""}`);
|
|
529
|
+
for (const line of terminalRunRequiredActionLines(started))
|
|
530
|
+
print(line);
|
|
592
531
|
return exitCodeForState(started.status);
|
|
593
532
|
}
|
|
533
|
+
terminalRunId = started.runId;
|
|
594
534
|
await followRun(started.runId, false);
|
|
595
535
|
const final = started.jobId ? await client.status(started.jobId) : null;
|
|
596
|
-
const
|
|
536
|
+
const out = mergeDaemonRunOutcome(started, final);
|
|
537
|
+
const status = out.status;
|
|
597
538
|
const publicStatus = status;
|
|
598
539
|
print("");
|
|
599
540
|
print(`run ${started.runId} [${publicStatus}]`);
|
|
600
541
|
// Server-owned outcome headline (D18), printed verbatim above any output.
|
|
601
|
-
const
|
|
542
|
+
const terminalDetail = await fetchRunDetail(addr, started.runId);
|
|
543
|
+
const terminalBanner = projectOutcomeBanner(terminalDetail);
|
|
602
544
|
if (terminalBanner)
|
|
603
545
|
print(` ${terminalBanner}`);
|
|
604
|
-
|
|
546
|
+
for (const line of terminalDelegationLines(projectDelegation(terminalDetail)))
|
|
547
|
+
print(line);
|
|
548
|
+
print(` artifacts: ${out.runDir}`);
|
|
549
|
+
if (out.error)
|
|
550
|
+
print(` error: ${out.error}`);
|
|
551
|
+
for (const line of terminalRunRequiredActionLines(out))
|
|
552
|
+
print(line);
|
|
605
553
|
// A succeeded lifecycle exits 0 — INCLUDING a "Done · needs review" run
|
|
606
554
|
// (review blocked / checks failed). The apply-eligibility verdict (state
|
|
607
555
|
// needs_review) is the ONE source for the unblock guidance (D8).
|
|
@@ -629,6 +577,7 @@ async function daemonRun(args, json, p) {
|
|
|
629
577
|
runId: started.runId,
|
|
630
578
|
interactive: !json && !jsonStream, // TTY plan turns answer inline
|
|
631
579
|
});
|
|
580
|
+
terminalRunId = effectiveRunId;
|
|
632
581
|
}
|
|
633
582
|
// Offer apply only after a positive gate; otherwise print inspect/unblock guidance.
|
|
634
583
|
const eligibility = await fetchApplyEligibility(addr, effectiveRunId);
|
|
@@ -650,9 +599,11 @@ async function daemonRun(args, json, p) {
|
|
|
650
599
|
catch (err) {
|
|
651
600
|
// D-7 projector: a typed control problem (code/retryable/context) survives
|
|
652
601
|
// intact; --json-stream stays valid NDJSON via the compact-line stream option.
|
|
602
|
+
// A run that already started keeps its handle in the envelope (extras).
|
|
653
603
|
return renderCliFailure(json || jsonStream, err, {
|
|
654
604
|
messagePrefix: "claudexor:",
|
|
655
605
|
stream: jsonStream,
|
|
606
|
+
...(terminalRunId ? { extras: { runId: terminalRunId } } : {}),
|
|
656
607
|
});
|
|
657
608
|
}
|
|
658
609
|
}
|
|
@@ -761,21 +712,12 @@ async function resolveRunStore(runId) {
|
|
|
761
712
|
}
|
|
762
713
|
return null;
|
|
763
714
|
}
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
const text = await response.text();
|
|
767
|
-
const body = text ? JSON.parse(text) : {};
|
|
768
|
-
if (response.ok)
|
|
769
|
-
return body;
|
|
770
|
-
const detail = body && typeof body === "object" ? body : {};
|
|
771
|
-
throw new Error(String(detail["message"] ?? detail["error"] ?? `HTTP ${response.status}`));
|
|
772
|
-
}
|
|
773
|
-
function printPreflightError(args, json, error) {
|
|
774
|
-
if (json && (args._[0] ?? "help") === "plugin") {
|
|
715
|
+
function printPreflightError(args, outputMode, error) {
|
|
716
|
+
if (outputMode === "json" && (args._[0] ?? "help") === "plugin") {
|
|
775
717
|
printJson(pluginCommandErrorResult(args._[1], args._[2], flagBool(args, "dry-run"), 2, error));
|
|
776
718
|
return 2;
|
|
777
719
|
}
|
|
778
|
-
return
|
|
720
|
+
return renderOutputUsageFailure(outputMode, error);
|
|
779
721
|
}
|
|
780
722
|
function listCliArtifacts(root) {
|
|
781
723
|
if (!existsSync(root))
|
|
@@ -797,8 +739,12 @@ function listCliArtifacts(root) {
|
|
|
797
739
|
// KNOWN_FLAGS / VALUE_FLAGS (imported above) and the per-command scope check
|
|
798
740
|
// are projections of the command registry. Unknown flags FAIL LOUDLY: `--harnes
|
|
799
741
|
// codex` must never silently run all harnesses.
|
|
800
|
-
async function dispatch(args,
|
|
742
|
+
async function dispatch(args, outputMode) {
|
|
801
743
|
const cmd = args._[0] ?? "help";
|
|
744
|
+
if (outputMode === "conflict") {
|
|
745
|
+
return renderOutputUsageFailure(outputMode, "claudexor: --json prints exactly one object and --json-stream prints NDJSON; pass one, not both");
|
|
746
|
+
}
|
|
747
|
+
const json = outputModeIsMachine(outputMode);
|
|
802
748
|
// `--help` resolves the COMMAND first (QA-057): scoped usage for a known verb,
|
|
803
749
|
// global help for a bare/`help` verb, a usage error (exit 2) for a typo.
|
|
804
750
|
if (flagBool(args, "help"))
|
|
@@ -806,18 +752,21 @@ async function dispatch(args, json) {
|
|
|
806
752
|
const unknownFlags = Object.keys(args.flags).filter((f) => !KNOWN_FLAGS.has(f));
|
|
807
753
|
if (unknownFlags.length > 0) {
|
|
808
754
|
const error = `claudexor: unknown flag(s): ${unknownFlags.map((f) => `--${f}`).join(", ")} (see \`claudexor help\`)`;
|
|
809
|
-
return printPreflightError(args,
|
|
755
|
+
return printPreflightError(args, outputMode, error);
|
|
810
756
|
}
|
|
811
757
|
const valueFlagError = requiredStringFlagError(args, VALUE_FLAGS);
|
|
812
758
|
if (valueFlagError)
|
|
813
|
-
return printPreflightError(args,
|
|
759
|
+
return printPreflightError(args, outputMode, valueFlagError);
|
|
814
760
|
// Registry-enforced per-command flag scope: a KNOWN flag outside the
|
|
815
761
|
// command's declared set (e.g. `plan --create`, `ask --force`) fails loudly
|
|
816
762
|
// instead of being silently ignored. Data-driven from CLI_COMMANDS for
|
|
817
763
|
// every verb (this replaced the old hand-listed plugin/--force special cases).
|
|
818
764
|
const scopeError = commandFlagScopeError(cmd, Object.keys(args.flags));
|
|
819
765
|
if (scopeError)
|
|
820
|
-
return printPreflightError(args,
|
|
766
|
+
return printPreflightError(args, outputMode, scopeError);
|
|
767
|
+
const positionalError = commandPositionalError(cmd, args._.slice(1));
|
|
768
|
+
if (positionalError)
|
|
769
|
+
return printPreflightError(args, outputMode, positionalError);
|
|
821
770
|
// No arguments at all = the interactive REPL: a thread of turns over the
|
|
822
771
|
// current project with native session continuity (chat is the normal loop).
|
|
823
772
|
if (args._.length === 0 && process.stdin.isTTY) {
|
|
@@ -838,21 +787,28 @@ async function dispatch(args, json) {
|
|
|
838
787
|
}
|
|
839
788
|
case "project":
|
|
840
789
|
return projectCommand(args, json);
|
|
790
|
+
case "remote":
|
|
791
|
+
return remoteCommand(args, json);
|
|
792
|
+
case "setup":
|
|
793
|
+
return setupCommand(args, json);
|
|
841
794
|
case "agent": {
|
|
842
795
|
const modeStr = flagStr(args, "mode");
|
|
843
796
|
if (modeStr !== undefined) {
|
|
844
797
|
const mode = normalizeMode(modeStr);
|
|
845
798
|
if (!MODES.has(mode)) {
|
|
846
|
-
return
|
|
799
|
+
return renderOutputUsageFailure(outputMode, `claudexor: unknown --mode '${modeStr}'. valid: ${[...MODES].join(", ")}`);
|
|
847
800
|
}
|
|
848
|
-
|
|
801
|
+
const modeScopeError = runModeFlagScopeError(mode, Object.keys(args.flags));
|
|
802
|
+
if (modeScopeError)
|
|
803
|
+
return printPreflightError(args, outputMode, modeScopeError);
|
|
804
|
+
return orchestrate(args, mode, outputMode);
|
|
849
805
|
}
|
|
850
|
-
return orchestrate(args, "agent",
|
|
806
|
+
return orchestrate(args, "agent", outputMode);
|
|
851
807
|
}
|
|
852
808
|
case "ask":
|
|
853
|
-
return orchestrate(args, "ask",
|
|
809
|
+
return orchestrate(args, "ask", outputMode);
|
|
854
810
|
case "best-of":
|
|
855
|
-
return orchestrate(args, "agent",
|
|
811
|
+
return orchestrate(args, "agent", outputMode, { race: true });
|
|
856
812
|
// RETIRED verb spellings hard-error with the new spelling — no silent
|
|
857
813
|
// aliases (same doctrine as retired mode ids: stale scripts fail loudly).
|
|
858
814
|
case "run":
|
|
@@ -871,12 +827,12 @@ async function dispatch(args, json) {
|
|
|
871
827
|
: cmd === "spec"
|
|
872
828
|
? "claudexor plan <prompt> then Implement (the plan lifecycle surfaces open questions and freezes the plan on implement)"
|
|
873
829
|
: "claudexor ask --deep-scan <prompt>";
|
|
874
|
-
return printPreflightError(args,
|
|
830
|
+
return printPreflightError(args, outputMode, `claudexor: the '${cmd}' verb was retired; use ${replacement}`);
|
|
875
831
|
}
|
|
876
832
|
case "plan":
|
|
877
|
-
return orchestrate(args, "plan",
|
|
833
|
+
return orchestrate(args, "plan", outputMode);
|
|
878
834
|
case "create":
|
|
879
|
-
return orchestrate(args, "agent",
|
|
835
|
+
return orchestrate(args, "agent", outputMode, { create: true });
|
|
880
836
|
case "settings":
|
|
881
837
|
return settingsCommand(args, json);
|
|
882
838
|
case "quota":
|
|
@@ -925,12 +881,23 @@ async function dispatch(args, json) {
|
|
|
925
881
|
const decision = store.readYaml(join(paths.arbitrationDir, "decision.yaml"));
|
|
926
882
|
const workProduct = store.readYaml(join(paths.finalDir, "work_product.yaml"));
|
|
927
883
|
const contract = TaskContract.safeParse(store.readYaml(join(paths.contextDir, "task.yaml")));
|
|
928
|
-
const
|
|
884
|
+
const parsedFailure = RunFailure.safeParse(store.readYaml(join(paths.finalDir, "failure.yaml")));
|
|
885
|
+
const failure = parsedFailure.success ? parsedFailure.data : null;
|
|
929
886
|
// The CLI projects the orchestrator-owned telemetry artifact and NEVER
|
|
930
887
|
// recomputes evidence from raw events (single-owner rule); a missing
|
|
931
888
|
// artifact (legacy run) renders "telemetry unavailable".
|
|
932
889
|
const parsedTelemetry = RunTelemetry.safeParse(store.readYaml(join(paths.finalDir, "telemetry.yaml")));
|
|
933
890
|
const telemetry = parsedTelemetry.success ? parsedTelemetry.data : null;
|
|
891
|
+
// GH #29: inspect reads the same immutable receipt as GET and terminal JSON.
|
|
892
|
+
const runFacts = readRunFactsArtifact(store, paths.finalDir, {
|
|
893
|
+
runId,
|
|
894
|
+
...(contract.success ? { taskId: contract.data.task_id } : {}),
|
|
895
|
+
});
|
|
896
|
+
const primary = primaryOutputForCli(paths.root, contract.success ? contract.data.mode.kind : undefined, {
|
|
897
|
+
failure,
|
|
898
|
+
lifecycle: runFacts?.outcome.lifecycle,
|
|
899
|
+
...(runFacts?.presentation ? { presentation: runFacts.presentation } : {}),
|
|
900
|
+
});
|
|
934
901
|
const toolErrors = telemetry
|
|
935
902
|
? telemetry.attempts.flatMap((a) => a.tool_errors
|
|
936
903
|
.filter((e) => !e.recovered && e.kind === "web")
|
|
@@ -952,22 +919,26 @@ async function dispatch(args, json) {
|
|
|
952
919
|
})))
|
|
953
920
|
: [];
|
|
954
921
|
const artifacts = listCliArtifacts(paths.root).filter((p) => !p.endsWith("/"));
|
|
955
|
-
const outputReadyState =
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
922
|
+
const outputReadyState = runFacts?.presentation?.state ??
|
|
923
|
+
(primary?.kind === "diagnostic"
|
|
924
|
+
? "diagnostic"
|
|
925
|
+
: primary?.text.trim()
|
|
926
|
+
? "ready"
|
|
927
|
+
: (failure ?? readTextSafe(join(paths.finalDir, "failure.yaml")))
|
|
928
|
+
? "diagnostic"
|
|
929
|
+
: "finalizing");
|
|
962
930
|
const parsedDecision = DecisionRecord.safeParse(decision);
|
|
963
931
|
const summary = readTextSafe(join(paths.finalDir, "summary.md"));
|
|
964
932
|
if (json) {
|
|
965
933
|
printJson({
|
|
966
934
|
runId,
|
|
967
935
|
runDir: paths.root,
|
|
936
|
+
lifecycle: runFacts?.outcome.lifecycle ?? null,
|
|
968
937
|
outputReadyState,
|
|
969
938
|
contract: contract.success ? contract.data : null,
|
|
970
939
|
telemetry,
|
|
940
|
+
runFacts,
|
|
941
|
+
failure,
|
|
971
942
|
toolErrors,
|
|
972
943
|
toolWarnings,
|
|
973
944
|
primaryOutput: primary,
|
|
@@ -979,10 +950,14 @@ async function dispatch(args, json) {
|
|
|
979
950
|
return summary || primary ? 0 : 1;
|
|
980
951
|
}
|
|
981
952
|
print(`run ${runId} @ ${paths.root}`);
|
|
953
|
+
if (runFacts)
|
|
954
|
+
print(`lifecycle: ${runFacts.outcome.lifecycle}`);
|
|
982
955
|
if (contract.success) {
|
|
983
956
|
print(`mode: ${contract.data.mode.kind}`);
|
|
984
957
|
print(`access: requested=${contract.data.access.requested_profile} effective=${contract.data.access.effective_profile}`);
|
|
985
958
|
}
|
|
959
|
+
for (const line of inspectDelegationLines(telemetry?.delegation ?? null))
|
|
960
|
+
print(line);
|
|
986
961
|
if (telemetry) {
|
|
987
962
|
print(`web: policy=${telemetry.external_context_policy} effective=${telemetry.effective_web_mode} required=${telemetry.web_required} evidence=${telemetry.web.status}`);
|
|
988
963
|
for (const requirement of telemetry.request_requirements.filter((item) => item.requested)) {
|
|
@@ -993,6 +968,12 @@ async function dispatch(args, json) {
|
|
|
993
968
|
print(`web: policy=${contract.data.external_context.policy} required=${contract.data.external_context.web_required} evidence=unavailable (no telemetry.yaml)`);
|
|
994
969
|
}
|
|
995
970
|
print(`output: ${outputReadyState}${primary ? ` ${primary.path}` : ""}`);
|
|
971
|
+
if (failure) {
|
|
972
|
+
print(`failure: ${failure.category}${failure.code ? `/${failure.code}` : ""} phase=${failure.phase}${failure.harnessId ? ` harness=${failure.harnessId}` : ""}`);
|
|
973
|
+
print(`failure message: ${failure.safeMessage}`);
|
|
974
|
+
for (const action of failure.nextActions)
|
|
975
|
+
print(`next action: ${action}`);
|
|
976
|
+
}
|
|
996
977
|
{
|
|
997
978
|
// Structured-output contract receipt (only present when the run was
|
|
998
979
|
// started with --output-schema); projected, never re-validated here.
|
|
@@ -1149,20 +1130,8 @@ async function dispatch(args, json) {
|
|
|
1149
1130
|
throw err;
|
|
1150
1131
|
}
|
|
1151
1132
|
}
|
|
1152
|
-
case "harness":
|
|
1153
|
-
|
|
1154
|
-
if (sub === "list") {
|
|
1155
|
-
// Fakes are test fixtures, not real harnesses; `--all` reveals them.
|
|
1156
|
-
const includeFakes = flagBool(args, "all");
|
|
1157
|
-
const ids = [...buildRegistry({ includeFakes }).keys()];
|
|
1158
|
-
if (json)
|
|
1159
|
-
printJson({ harnesses: ids });
|
|
1160
|
-
else
|
|
1161
|
-
ids.forEach((id) => print(id));
|
|
1162
|
-
return 0;
|
|
1163
|
-
}
|
|
1164
|
-
return printUsageError(json, "usage: claudexor harness list [--all]");
|
|
1165
|
-
}
|
|
1133
|
+
case "harness":
|
|
1134
|
+
return harnessCommand(args, json);
|
|
1166
1135
|
case "capabilities": {
|
|
1167
1136
|
// The derived AgentCapabilityCatalog — same composer as the daemon's
|
|
1168
1137
|
// GET /agent-capabilities and the MCP claudexor_capabilities tool.
|
|
@@ -1172,6 +1141,7 @@ async function dispatch(args, json) {
|
|
|
1172
1141
|
else {
|
|
1173
1142
|
print(`claudexor ${catalog.version} — capability catalog`);
|
|
1174
1143
|
print(`modes: ${catalog.modes.join(", ")}`);
|
|
1144
|
+
print(`git: ${catalog.git.status}${catalog.git.version ? ` (${catalog.git.version})` : ""}${catalog.git.remediation ? ` — ${catalog.git.remediation}` : ""}`);
|
|
1175
1145
|
print(`available harnesses: ${catalog.availableHarnesses.join(", ") || "(none)"}`);
|
|
1176
1146
|
for (const h of catalog.harnesses) {
|
|
1177
1147
|
const model = h.configuredModel
|
|
@@ -1208,7 +1178,7 @@ async function dispatch(args, json) {
|
|
|
1208
1178
|
// callers get the ONE projector envelope (with message/code shape, no
|
|
1209
1179
|
// longer a partial {ok,exitCode,error}); text mode prints the full help.
|
|
1210
1180
|
if (json) {
|
|
1211
|
-
return
|
|
1181
|
+
return renderOutputFailure(outputMode, usageError(`claudexor: unknown command '${cmd}' (see \`claudexor help --json\`)`), {});
|
|
1212
1182
|
}
|
|
1213
1183
|
process.stderr.write(`claudexor: unknown command '${cmd}'\n\n${HELP}\n`);
|
|
1214
1184
|
return 2;
|
|
@@ -1224,18 +1194,27 @@ async function main() {
|
|
|
1224
1194
|
process.stdout.write(`${CLI_VERSION}\n`);
|
|
1225
1195
|
return 0;
|
|
1226
1196
|
}
|
|
1227
|
-
const
|
|
1197
|
+
const outputMode = cliOutputMode(args);
|
|
1228
1198
|
try {
|
|
1229
|
-
return await dispatch(args,
|
|
1199
|
+
return await dispatch(args, outputMode);
|
|
1230
1200
|
}
|
|
1231
1201
|
catch (err) {
|
|
1232
|
-
return
|
|
1202
|
+
return renderOutputFailure(outputMode, err);
|
|
1233
1203
|
}
|
|
1234
1204
|
}
|
|
1235
1205
|
main()
|
|
1236
1206
|
.then((code) => process.exit(code))
|
|
1237
1207
|
.catch((err) => {
|
|
1238
|
-
// Last-resort projector:
|
|
1239
|
-
process.
|
|
1208
|
+
// Last-resort projector: infer the complete mode even if parsing itself threw.
|
|
1209
|
+
const json = process.argv.includes("--json");
|
|
1210
|
+
const stream = process.argv.includes("--json-stream");
|
|
1211
|
+
const outputMode = json
|
|
1212
|
+
? stream
|
|
1213
|
+
? "conflict"
|
|
1214
|
+
: "json"
|
|
1215
|
+
: stream
|
|
1216
|
+
? "json-stream"
|
|
1217
|
+
: "human";
|
|
1218
|
+
process.exit(renderOutputFailure(outputMode, err));
|
|
1240
1219
|
});
|
|
1241
1220
|
//# sourceMappingURL=cli.js.map
|