@dungle-scrubs/harness-cli-normalizer 0.5.7 → 0.6.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/README.md +25 -8
- package/dist/cli/args.d.ts +9 -1
- package/dist/cli/args.d.ts.map +1 -1
- package/dist/cli/args.js +31 -26
- package/dist/cli/args.js.map +1 -1
- package/dist/cli/check.d.ts +14 -0
- package/dist/cli/check.d.ts.map +1 -1
- package/dist/cli/check.js +10 -3
- package/dist/cli/check.js.map +1 -1
- package/dist/cli/config.d.ts +4 -4
- package/dist/cli/config.d.ts.map +1 -1
- package/dist/cli/config.js +6 -6
- package/dist/cli/config.js.map +1 -1
- package/dist/cli/exit-codes.d.ts +0 -1
- package/dist/cli/exit-codes.d.ts.map +1 -1
- package/dist/cli/exit-codes.js +0 -1
- package/dist/cli/exit-codes.js.map +1 -1
- package/dist/cli/help.d.ts +3 -3
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +9 -2
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +3 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/inspect.d.ts.map +1 -1
- package/dist/cli/inspect.js +84 -265
- package/dist/cli/inspect.js.map +1 -1
- package/dist/cli/plan-turn.d.ts +68 -0
- package/dist/cli/plan-turn.d.ts.map +1 -0
- package/dist/cli/plan-turn.js +266 -0
- package/dist/cli/plan-turn.js.map +1 -0
- package/dist/cli/refuse.d.ts.map +1 -1
- package/dist/cli/refuse.js +2 -1
- package/dist/cli/refuse.js.map +1 -1
- package/dist/cli/resolve-harness.d.ts.map +1 -1
- package/dist/cli/resolve-harness.js +2 -3
- package/dist/cli/resolve-harness.js.map +1 -1
- package/dist/cli/run.d.ts.map +1 -1
- package/dist/cli/run.js +33 -367
- package/dist/cli/run.js.map +1 -1
- package/dist/cli/session-json.d.ts +1 -1
- package/dist/cli/session-json.d.ts.map +1 -1
- package/dist/cli/session-json.js +1 -3
- package/dist/cli/session-json.js.map +1 -1
- package/dist/cli/session.d.ts.map +1 -1
- package/dist/cli/session.js +27 -45
- package/dist/cli/session.js.map +1 -1
- package/dist/cli/skills-root.d.ts +1 -1
- package/dist/cli/skills-root.d.ts.map +1 -1
- package/dist/cli/skills-root.js +1 -1
- package/dist/cli/skills-root.js.map +1 -1
- package/dist/execution/decode.d.ts.map +1 -1
- package/dist/execution/decode.js +11 -36
- package/dist/execution/decode.js.map +1 -1
- package/dist/execution/events.d.ts +4 -1
- package/dist/execution/events.d.ts.map +1 -1
- package/dist/execution/events.js.map +1 -1
- package/dist/execution/failure.d.ts +3 -1
- package/dist/execution/failure.d.ts.map +1 -1
- package/dist/execution/failure.js +14 -11
- package/dist/execution/failure.js.map +1 -1
- package/dist/execution/open-session.d.ts +6 -1
- package/dist/execution/open-session.d.ts.map +1 -1
- package/dist/execution/open-session.js +151 -223
- package/dist/execution/open-session.js.map +1 -1
- package/dist/execution/stream-turn.d.ts +9 -14
- package/dist/execution/stream-turn.d.ts.map +1 -1
- package/dist/execution/stream-turn.js +85 -188
- package/dist/execution/stream-turn.js.map +1 -1
- package/dist/execution/supervisor.d.ts +71 -0
- package/dist/execution/supervisor.d.ts.map +1 -0
- package/dist/execution/supervisor.js +127 -0
- package/dist/execution/supervisor.js.map +1 -0
- package/dist/interpretation/argv.d.ts +44 -12
- package/dist/interpretation/argv.d.ts.map +1 -1
- package/dist/interpretation/argv.js +38 -24
- package/dist/interpretation/argv.js.map +1 -1
- package/dist/interpretation/content.d.ts +10 -1
- package/dist/interpretation/content.d.ts.map +1 -1
- package/dist/interpretation/content.js +20 -11
- package/dist/interpretation/content.js.map +1 -1
- package/dist/interpretation/hints.d.ts +1 -1
- package/dist/interpretation/hints.d.ts.map +1 -1
- package/dist/interpretation/hints.js +10 -11
- package/dist/interpretation/hints.js.map +1 -1
- package/dist/interpretation/index.d.ts +0 -1
- package/dist/interpretation/index.d.ts.map +1 -1
- package/dist/interpretation/index.js +0 -1
- package/dist/interpretation/index.js.map +1 -1
- package/dist/interpretation/limits.d.ts +2 -5
- package/dist/interpretation/limits.d.ts.map +1 -1
- package/dist/interpretation/limits.js +8 -62
- package/dist/interpretation/limits.js.map +1 -1
- package/dist/interpretation/question.d.ts +27 -0
- package/dist/interpretation/question.d.ts.map +1 -1
- package/dist/interpretation/question.js +28 -0
- package/dist/interpretation/question.js.map +1 -1
- package/dist/interpretation/refusal.d.ts +10 -5
- package/dist/interpretation/refusal.d.ts.map +1 -1
- package/dist/interpretation/refusal.js +24 -15
- package/dist/interpretation/refusal.js.map +1 -1
- package/dist/interpretation/resolve-options.d.ts +36 -2
- package/dist/interpretation/resolve-options.d.ts.map +1 -1
- package/dist/interpretation/resolve-options.js +38 -21
- package/dist/interpretation/resolve-options.js.map +1 -1
- package/dist/interpretation/session-input.d.ts +44 -1
- package/dist/interpretation/session-input.d.ts.map +1 -1
- package/dist/interpretation/session-input.js +59 -4
- package/dist/interpretation/session-input.js.map +1 -1
- package/dist/interpretation/shape.d.ts +1 -0
- package/dist/interpretation/shape.d.ts.map +1 -1
- package/dist/interpretation/shape.js +10 -0
- package/dist/interpretation/shape.js.map +1 -1
- package/dist/interpretation/skills-selection.d.ts +25 -33
- package/dist/interpretation/skills-selection.d.ts.map +1 -1
- package/dist/interpretation/skills-selection.js +41 -48
- package/dist/interpretation/skills-selection.js.map +1 -1
- package/dist/interpretation/support.d.ts.map +1 -1
- package/dist/interpretation/support.js +23 -8
- package/dist/interpretation/support.js.map +1 -1
- package/dist/interpretation/tool-selection.d.ts +7 -6
- package/dist/interpretation/tool-selection.d.ts.map +1 -1
- package/dist/interpretation/tool-selection.js +54 -116
- package/dist/interpretation/tool-selection.js.map +1 -1
- package/dist/interpretation/tool-vocabulary.d.ts +31 -12
- package/dist/interpretation/tool-vocabulary.d.ts.map +1 -1
- package/dist/interpretation/tool-vocabulary.js +19 -41
- package/dist/interpretation/tool-vocabulary.js.map +1 -1
- package/dist/interpretation/turn-options.d.ts +4 -0
- package/dist/interpretation/turn-options.d.ts.map +1 -1
- package/dist/interpretation/turn-options.js +105 -241
- package/dist/interpretation/turn-options.js.map +1 -1
- package/dist/interpretation/vocabulary.d.ts +8 -6
- package/dist/interpretation/vocabulary.d.ts.map +1 -1
- package/dist/interpretation/vocabulary.js +22 -9
- package/dist/interpretation/vocabulary.js.map +1 -1
- package/dist/knowledge/claude-code.js +3 -3
- package/dist/knowledge/claude-code.js.map +1 -1
- package/dist/knowledge/codex.d.ts.map +1 -1
- package/dist/knowledge/codex.js +31 -7
- package/dist/knowledge/codex.js.map +1 -1
- package/dist/knowledge/descriptor.d.ts +67 -36
- package/dist/knowledge/descriptor.d.ts.map +1 -1
- package/dist/knowledge/descriptor.js +49 -15
- package/dist/knowledge/descriptor.js.map +1 -1
- package/dist/knowledge/matchers.d.ts +12 -0
- package/dist/knowledge/matchers.d.ts.map +1 -1
- package/dist/knowledge/matchers.js +34 -0
- package/dist/knowledge/matchers.js.map +1 -1
- package/dist/knowledge/muse.d.ts.map +1 -1
- package/dist/knowledge/muse.js +7 -5
- package/dist/knowledge/muse.js.map +1 -1
- package/dist/knowledge/overrides.d.ts.map +1 -1
- package/dist/knowledge/overrides.js +9 -20
- package/dist/knowledge/overrides.js.map +1 -1
- package/dist/knowledge/pi.d.ts.map +1 -1
- package/dist/knowledge/pi.js +8 -6
- package/dist/knowledge/pi.js.map +1 -1
- package/dist/knowledge/profile.d.ts +1 -0
- package/dist/knowledge/profile.d.ts.map +1 -1
- package/dist/knowledge/profile.js +1 -0
- package/dist/knowledge/profile.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/args.ts +35 -27
- package/src/cli/check.ts +10 -3
- package/src/cli/config.ts +12 -11
- package/src/cli/exit-codes.ts +0 -2
- package/src/cli/help.ts +9 -2
- package/src/cli/index.ts +3 -1
- package/src/cli/inspect.ts +88 -269
- package/src/cli/plan-turn.ts +346 -0
- package/src/cli/refuse.ts +2 -1
- package/src/cli/resolve-harness.ts +4 -5
- package/src/cli/run.ts +36 -399
- package/src/cli/session-json.ts +1 -6
- package/src/cli/session.ts +36 -45
- package/src/cli/skills-root.ts +1 -4
- package/src/execution/decode.ts +10 -36
- package/src/execution/events.ts +4 -1
- package/src/execution/failure.ts +18 -11
- package/src/execution/open-session.ts +160 -228
- package/src/execution/stream-turn.ts +90 -193
- package/src/execution/supervisor.ts +199 -0
- package/src/interpretation/argv.ts +86 -38
- package/src/interpretation/content.ts +30 -13
- package/src/interpretation/hints.ts +2 -12
- package/src/interpretation/index.ts +0 -1
- package/src/interpretation/limits.ts +14 -75
- package/src/interpretation/question.ts +46 -0
- package/src/interpretation/refusal.ts +28 -18
- package/src/interpretation/resolve-options.ts +85 -32
- package/src/interpretation/session-input.ts +88 -5
- package/src/interpretation/shape.ts +10 -0
- package/src/interpretation/skills-selection.ts +70 -74
- package/src/interpretation/support.ts +19 -6
- package/src/interpretation/tool-selection.ts +67 -122
- package/src/interpretation/tool-vocabulary.ts +48 -53
- package/src/interpretation/turn-options.ts +123 -220
- package/src/interpretation/vocabulary.ts +15 -10
- package/src/knowledge/claude-code.ts +3 -3
- package/src/knowledge/codex.ts +31 -7
- package/src/knowledge/descriptor.ts +105 -49
- package/src/knowledge/matchers.ts +35 -0
- package/src/knowledge/muse.ts +7 -5
- package/src/knowledge/overrides.ts +17 -32
- package/src/knowledge/pi.ts +8 -6
- package/src/knowledge/profile.ts +1 -0
- package/dist/interpretation/dimensions.d.ts +0 -11
- package/dist/interpretation/dimensions.d.ts.map +0 -1
- package/dist/interpretation/dimensions.js +0 -4
- package/dist/interpretation/dimensions.js.map +0 -1
- package/src/interpretation/dimensions.ts +0 -14
package/src/cli/config.ts
CHANGED
|
@@ -20,8 +20,9 @@ import { existsSync, readFileSync } from "node:fs";
|
|
|
20
20
|
import { homedir } from "node:os";
|
|
21
21
|
import { dirname, join, resolve } from "node:path";
|
|
22
22
|
import type { TurnOptions } from "../interpretation/argv.js";
|
|
23
|
-
import {
|
|
24
|
-
import {
|
|
23
|
+
import { isQuestionMode, QUESTION_MODES } from "../interpretation/question.js";
|
|
24
|
+
import type { ConfigTier } from "../interpretation/resolve-options.js";
|
|
25
|
+
import { CLEAN_SELECTOR, validateAccess } from "../interpretation/vocabulary.js";
|
|
25
26
|
import { HARNESS_NAMES } from "../knowledge/descriptor.js";
|
|
26
27
|
import { defaultDescriptors } from "../knowledge/overrides.js";
|
|
27
28
|
|
|
@@ -68,6 +69,7 @@ const KNOWN_KEYS = new Set([
|
|
|
68
69
|
"model",
|
|
69
70
|
"provider",
|
|
70
71
|
"sandbox",
|
|
72
|
+
"contextWindow",
|
|
71
73
|
"tools",
|
|
72
74
|
"excludeTools",
|
|
73
75
|
"autonomy",
|
|
@@ -88,11 +90,10 @@ const KNOWN_KEYS = new Set([
|
|
|
88
90
|
|
|
89
91
|
const LIST_KEYS = new Set(["tools", "excludeTools"]);
|
|
90
92
|
const BOOL_KEYS = new Set(["autonomy", "write", "shell"]);
|
|
91
|
-
const QUESTIONS_VALUES = new Set(["ask", "assume", "none"]);
|
|
92
93
|
|
|
93
94
|
/** Parse + validate config text. Throws ConfigError with the offending key
|
|
94
95
|
* named on any violation - never warns and continues. */
|
|
95
|
-
export const parseUserConfig = (text: string):
|
|
96
|
+
export const parseUserConfig = (text: string): ConfigTier => {
|
|
96
97
|
let raw: unknown;
|
|
97
98
|
try {
|
|
98
99
|
raw = JSON.parse(text);
|
|
@@ -126,7 +127,7 @@ export const parseUserConfig = (text: string): Partial<TurnOptions> => {
|
|
|
126
127
|
);
|
|
127
128
|
}
|
|
128
129
|
const toolMapObj = value as Record<string, unknown>;
|
|
129
|
-
const SEL =
|
|
130
|
+
const SEL = CLEAN_SELECTOR;
|
|
130
131
|
const descSet = defaultDescriptors();
|
|
131
132
|
const harnessNames = HARNESS_NAMES as readonly string[];
|
|
132
133
|
for (const [harness, inner] of Object.entries(toolMapObj)) {
|
|
@@ -228,9 +229,9 @@ export const parseUserConfig = (text: string): Partial<TurnOptions> => {
|
|
|
228
229
|
continue;
|
|
229
230
|
}
|
|
230
231
|
if (key === "questions") {
|
|
231
|
-
if (typeof value !== "string" || !
|
|
232
|
+
if (typeof value !== "string" || !isQuestionMode(value)) {
|
|
232
233
|
throw new ConfigError(
|
|
233
|
-
`config key ${JSON.stringify(key)} must be one of ${
|
|
234
|
+
`config key ${JSON.stringify(key)} must be one of ${QUESTION_MODES.join(", ")}`,
|
|
234
235
|
);
|
|
235
236
|
}
|
|
236
237
|
(out as Record<string, unknown>).questions = value;
|
|
@@ -250,24 +251,24 @@ export const parseUserConfig = (text: string): Partial<TurnOptions> => {
|
|
|
250
251
|
}
|
|
251
252
|
(out as Record<string, unknown>)[key] = value;
|
|
252
253
|
}
|
|
253
|
-
return out as
|
|
254
|
+
return out as ConfigTier;
|
|
254
255
|
};
|
|
255
256
|
|
|
256
257
|
/** Load the user config if the file exists; absent file is an empty config
|
|
257
258
|
* (no tiers engaged), unreadable or invalid file is a hard error. */
|
|
258
|
-
export const loadUserConfig = (): { config:
|
|
259
|
+
export const loadUserConfig = (): { config: ConfigTier; path: string } | null =>
|
|
259
260
|
loadConfigAt(userConfigPath());
|
|
260
261
|
|
|
261
262
|
/** Load the project config (git-root auto-discovery, ratified A). */
|
|
262
263
|
export const loadProjectConfig = (
|
|
263
264
|
startDir?: string,
|
|
264
|
-
): { config:
|
|
265
|
+
): { config: ConfigTier; path: string } | null => {
|
|
265
266
|
const path = projectConfigPath(startDir);
|
|
266
267
|
if (path === null) return null;
|
|
267
268
|
return loadConfigAt(path);
|
|
268
269
|
};
|
|
269
270
|
|
|
270
|
-
const loadConfigAt = (path: string): { config:
|
|
271
|
+
const loadConfigAt = (path: string): { config: ConfigTier; path: string } | null => {
|
|
271
272
|
let text: string;
|
|
272
273
|
try {
|
|
273
274
|
text = readFileSync(path, "utf8");
|
package/src/cli/exit-codes.ts
CHANGED
package/src/cli/help.ts
CHANGED
|
@@ -31,6 +31,8 @@ Options:
|
|
|
31
31
|
--model <id> Model id (validated per harness)
|
|
32
32
|
--effort <value> Effort level (validated per harness/model)
|
|
33
33
|
--sandbox <value> Sandbox mode (codex only)
|
|
34
|
+
--context-window <tokens> Context window (codex, integer 1-272000;
|
|
35
|
+
launch default 272000; config: contextWindow)
|
|
34
36
|
--provider <value> Provider (pi only)
|
|
35
37
|
--tools <a,b> Tool grant allowlist - canonical names (read, write,
|
|
36
38
|
edit, shell, grep, glob, list, web-fetch,
|
|
@@ -74,7 +76,7 @@ Options:
|
|
|
74
76
|
--no-instruction-files Disable instructionFiles discovery facet
|
|
75
77
|
--no-extensions Disable extensions discovery facet
|
|
76
78
|
--skills <a,b> Skill allowlist (names resolved against $HCN_SKILLS_ROOT
|
|
77
|
-
or ~/.agents/skills; pi loads, claude
|
|
79
|
+
or ~/.agents/skills; pi loads, claude and codex narrow)
|
|
78
80
|
--no-skills Disable skills discovery facet
|
|
79
81
|
--cwd <path> Working directory for spawn
|
|
80
82
|
--env KEY=VAL Environment (repeatable; KEY= deletes)
|
|
@@ -99,7 +101,8 @@ Defaults with no flags:
|
|
|
99
101
|
git root) > user config (~/.config/hcn/config.json) > built-in profile
|
|
100
102
|
> harness default. The profile pins: effort medium, sandbox
|
|
101
103
|
workspace-write (codex only; other harnesses report divergence),
|
|
102
|
-
|
|
104
|
+
context window 272000 (codex only; divergence elsewhere), discovery on,
|
|
105
|
+
autonomy off, write/shell on. timeout, max-steps and
|
|
103
106
|
access have no default; harness default applies (access write emits
|
|
104
107
|
nothing on claude/pi/muse, --sandbox workspace-write on codex via
|
|
105
108
|
profile). toolMap is config-only (no flag) - canonical -> native
|
|
@@ -132,6 +135,9 @@ Options:
|
|
|
132
135
|
(default: no limit)
|
|
133
136
|
--provider <value> Provider (pi only)
|
|
134
137
|
--model <id> Model for the session
|
|
138
|
+
--effort <value> Effort level for the session spawn (validated
|
|
139
|
+
per harness/model; no default - the harness's
|
|
140
|
+
own effort applies without the flag)
|
|
135
141
|
--resume <uuid> Resume session id (UUID). Continues the
|
|
136
142
|
conversation where it left off. --session-id
|
|
137
143
|
is an alias (mutually exclusive with --resume).
|
|
@@ -168,6 +174,7 @@ Options:
|
|
|
168
174
|
--model <id> Model
|
|
169
175
|
--effort <value> Effort
|
|
170
176
|
--sandbox <value> Sandbox
|
|
177
|
+
--context-window <tokens> Context window (codex, integer 1-272000)
|
|
171
178
|
--provider <value> Provider
|
|
172
179
|
--tools <a,b> Tools - canonical names (read, write, edit,
|
|
173
180
|
shell, grep, glob, list, web-fetch,
|
package/src/cli/index.ts
CHANGED
|
@@ -2,10 +2,12 @@
|
|
|
2
2
|
import { realpathSync } from "node:fs";
|
|
3
3
|
import { resolve } from "node:path";
|
|
4
4
|
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { HARNESS_NAMES } from "../knowledge/descriptor.js";
|
|
5
6
|
import { TOP_LEVEL_HELP } from "./help.js";
|
|
6
7
|
import { getVersion } from "./version.js";
|
|
7
8
|
|
|
8
|
-
|
|
9
|
+
/** The one harness list, read from the descriptor vocabulary. */
|
|
10
|
+
const SUPPORTED: readonly string[] = HARNESS_NAMES;
|
|
9
11
|
|
|
10
12
|
// Prevent EPIPE crashes when piped to head/grep -q (e.g., hcn ls | head, hcn run --json | head)
|
|
11
13
|
process.stdout.on("error", (err) => {
|
package/src/cli/inspect.ts
CHANGED
|
@@ -1,69 +1,63 @@
|
|
|
1
|
-
import { redactArgv } from "../execution/stream-turn.js";
|
|
2
|
-
import { buildLaunchArgv } from "../interpretation/argv.js";
|
|
3
1
|
import { capabilitiesOf } from "../interpretation/capabilities.js";
|
|
4
|
-
import { ArgvRefusalError } from "../interpretation/refusal.js";
|
|
5
|
-
import { FloorExceededError, resolveEffectiveOptions } from "../interpretation/resolve-options.js";
|
|
6
2
|
import { canonicalTable, mergeToolMaps } from "../interpretation/tool-vocabulary.js";
|
|
7
|
-
import type
|
|
3
|
+
import { HARNESS_MODES, type HarnessMode } from "../knowledge/descriptor.js";
|
|
8
4
|
import { defaultDescriptors } from "../knowledge/overrides.js";
|
|
9
|
-
import {
|
|
5
|
+
import { splitPassthrough } from "./args.js";
|
|
10
6
|
import { ConfigError, loadProjectConfig, loadUserConfig } from "./config.js";
|
|
11
7
|
import { EXIT_REFUSAL } from "./exit-codes.js";
|
|
12
|
-
import {
|
|
8
|
+
import { planTurn, writePlanDiagnostics } from "./plan-turn.js";
|
|
9
|
+
import { refuse } from "./refuse.js";
|
|
13
10
|
import { resolveHarness } from "./resolve-harness.js";
|
|
14
11
|
|
|
15
|
-
const HARNESS_MODES = ["headless-turn", "headless-session", "interactive"] as const;
|
|
16
|
-
|
|
17
12
|
export const inspect = async (harnessName: string, rawArgs: string[]): Promise<void> => {
|
|
18
13
|
const h = resolveHarness(harnessName);
|
|
14
|
+
const { normalized } = splitPassthrough(rawArgs);
|
|
19
15
|
|
|
20
|
-
|
|
21
|
-
if (rawArgs.includes("--help") || rawArgs.includes("-h")) {
|
|
16
|
+
if (normalized.includes("--help") || normalized.includes("-h")) {
|
|
22
17
|
const { INSPECT_HELP } = await import("./help.js");
|
|
23
18
|
process.stdout.write(INSPECT_HELP);
|
|
24
19
|
return;
|
|
25
20
|
}
|
|
26
21
|
|
|
27
|
-
//
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
process.stderr.write(`supported: prompt must not start with '-'\n`);
|
|
40
|
-
process.exitCode = 2;
|
|
22
|
+
// --argv: the preview is the plan the run command would spawn from, so
|
|
23
|
+
// the two agree by construction (RFC-02 change 10). Refusals go through
|
|
24
|
+
// the shared refuse path like every other command's.
|
|
25
|
+
if (normalized.includes("--argv")) {
|
|
26
|
+
if (normalized.includes("--capabilities")) {
|
|
27
|
+
process.stderr.write(`--capabilities and --argv are mutually exclusive; pick one\n`);
|
|
28
|
+
process.exitCode = EXIT_REFUSAL;
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const outcome = await planTurn(h, rawArgs, { command: "inspect" });
|
|
32
|
+
if (outcome.kind === "refusal") {
|
|
33
|
+
refuse(outcome.refusal, false);
|
|
41
34
|
return;
|
|
42
35
|
}
|
|
36
|
+
writePlanDiagnostics(h, outcome.plan, "argv");
|
|
37
|
+
process.stdout.write(`${JSON.stringify(outcome.plan.redactedArgv)}\n`);
|
|
38
|
+
return;
|
|
43
39
|
}
|
|
44
40
|
|
|
45
|
-
//
|
|
41
|
+
// --capabilities path: pure capability record, no spawn, no config, no prompt
|
|
42
|
+
const { parseCommonFlags } = await import("./args.js");
|
|
46
43
|
let parsed: ReturnType<typeof parseCommonFlags>;
|
|
47
44
|
try {
|
|
48
45
|
parsed = parseCommonFlags(rawArgs);
|
|
49
46
|
} catch (err) {
|
|
50
47
|
const message = err instanceof Error ? err.message : String(err);
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
48
|
+
refuse(
|
|
49
|
+
{
|
|
50
|
+
message: `unknown flag: ${message}`,
|
|
51
|
+
issue: "invalid-option-value",
|
|
52
|
+
trailer: ["Run 'hcn inspect --help' for usage."],
|
|
53
|
+
},
|
|
54
|
+
false,
|
|
55
|
+
);
|
|
54
56
|
return;
|
|
55
57
|
}
|
|
56
|
-
|
|
57
58
|
const values = parsed.values as Record<string, unknown>;
|
|
58
|
-
const wantArgv = values.argv === true;
|
|
59
59
|
|
|
60
|
-
// --capabilities path: pure capability record, no spawn, no config, no prompt
|
|
61
60
|
if (values.capabilities === true) {
|
|
62
|
-
if (wantArgv) {
|
|
63
|
-
process.stderr.write(`--capabilities and --argv are mutually exclusive; pick one\n`);
|
|
64
|
-
process.exitCode = EXIT_REFUSAL;
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
61
|
const mode = values.mode === undefined ? "headless-turn" : String(values.mode);
|
|
68
62
|
if (!(HARNESS_MODES as readonly string[]).includes(mode)) {
|
|
69
63
|
process.stderr.write(
|
|
@@ -78,247 +72,72 @@ export const inspect = async (harnessName: string, rawArgs: string[]): Promise<v
|
|
|
78
72
|
return;
|
|
79
73
|
}
|
|
80
74
|
|
|
81
|
-
//
|
|
82
|
-
|
|
83
|
-
let
|
|
84
|
-
let
|
|
85
|
-
user?: import("../interpretation/argv.js").TurnOptions;
|
|
86
|
-
project?: import("../interpretation/argv.js").TurnOptions;
|
|
87
|
-
} = {};
|
|
75
|
+
// The descriptor dump, with the tool vocabulary slice the config tiers
|
|
76
|
+
// extend.
|
|
77
|
+
let userMap: ReturnType<typeof loadUserConfig> = null;
|
|
78
|
+
let projectMap: ReturnType<typeof loadProjectConfig> = null;
|
|
88
79
|
try {
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
?.toolMap;
|
|
92
|
-
if (u) loadedTiers = { ...loadedTiers, user: u.config as never };
|
|
93
|
-
const p = loadProjectConfig();
|
|
94
|
-
rawProjectMap = (p?.config as { toolMap?: Record<string, Record<string, string>> } | undefined)
|
|
95
|
-
?.toolMap;
|
|
96
|
-
if (p) loadedTiers = { ...loadedTiers, project: p.config as never };
|
|
80
|
+
userMap = loadUserConfig();
|
|
81
|
+
projectMap = loadProjectConfig();
|
|
97
82
|
} catch (e) {
|
|
98
83
|
if (e instanceof ConfigError) {
|
|
99
|
-
|
|
100
|
-
process.exitCode = 2;
|
|
84
|
+
refuse({ message: `config error: ${e.message}`, issue: "invalid-option-value" }, false);
|
|
101
85
|
return;
|
|
102
86
|
}
|
|
103
87
|
throw e;
|
|
104
88
|
}
|
|
105
|
-
const merged = mergeToolMaps({
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
} else {
|
|
127
|
-
slice[canonical] = { native: null, source: "none" };
|
|
128
|
-
}
|
|
89
|
+
const merged = mergeToolMaps({
|
|
90
|
+
user: userMap?.config.toolMap,
|
|
91
|
+
project: projectMap?.config.toolMap,
|
|
92
|
+
});
|
|
93
|
+
const table = canonicalTable(defaultDescriptors());
|
|
94
|
+
const slice: Record<string, unknown> = {};
|
|
95
|
+
const allCanonicalForInspect = [
|
|
96
|
+
...new Set([...Object.keys(table), ...Object.keys(merged[h.name] ?? {})]),
|
|
97
|
+
].sort();
|
|
98
|
+
for (const canonical of allCanonicalForInspect) {
|
|
99
|
+
const v = table[canonical]?.[h.name];
|
|
100
|
+
const mapped = merged[h.name]?.[canonical];
|
|
101
|
+
if (mapped !== undefined) {
|
|
102
|
+
slice[canonical] = { native: mapped.native, source: mapped.tier };
|
|
103
|
+
} else if (v !== undefined) {
|
|
104
|
+
slice[canonical] =
|
|
105
|
+
v.kind === "builtin"
|
|
106
|
+
? { native: v.native, source: "descriptor" }
|
|
107
|
+
: { ...v, source: "descriptor" };
|
|
108
|
+
} else {
|
|
109
|
+
slice[canonical] = { native: null, source: "none" };
|
|
129
110
|
}
|
|
130
|
-
const out = {
|
|
131
|
-
name: h.name,
|
|
132
|
-
bin: h.bin,
|
|
133
|
-
verifiedAgainst: h.verifiedAgainst,
|
|
134
|
-
versionSource: h.versionSource,
|
|
135
|
-
launch: {
|
|
136
|
-
baseFlags: h.launch.baseFlags,
|
|
137
|
-
subcommands: h.launch.subcommands,
|
|
138
|
-
streamFlags: h.launch.streamFlags,
|
|
139
|
-
promptStyle: h.launch.promptStyle,
|
|
140
|
-
toolsFlag: h.launch.toolsFlag,
|
|
141
|
-
idFlag: h.launch.idFlag,
|
|
142
|
-
},
|
|
143
|
-
resume: h.resume,
|
|
144
|
-
sessionMode: h.sessionMode,
|
|
145
|
-
vocabulary: {
|
|
146
|
-
models: h.vocabulary.models,
|
|
147
|
-
aliases: h.vocabulary.aliases,
|
|
148
|
-
efforts: h.vocabulary.efforts,
|
|
149
|
-
effortsByModel: (h.vocabulary as { effortsByModel?: unknown }).effortsByModel,
|
|
150
|
-
extensible: h.vocabulary.extensible,
|
|
151
|
-
modelFlag: h.vocabulary.modelFlag,
|
|
152
|
-
},
|
|
153
|
-
turnOptions: h.turnOptions,
|
|
154
|
-
limitMatchers: h.limitMatchers,
|
|
155
|
-
authMatchers: h.authMatchers,
|
|
156
|
-
toolVocabulary: slice,
|
|
157
|
-
};
|
|
158
|
-
process.stdout.write(`${JSON.stringify(out, null, 2)}\n`);
|
|
159
|
-
return;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
// --argv preview path: need prompt + turn options
|
|
163
|
-
const positional = parsed.positionals as string[];
|
|
164
|
-
// positional[0] would be harness already consumed, but we passed rawArgs without harness - check: caller passes remaining after harness
|
|
165
|
-
// So positionals are potential prompt positional if not using --prompt
|
|
166
|
-
const positionalPrompt = positional.length > 0 ? positional[0] : undefined;
|
|
167
|
-
if (positional.length > 1) {
|
|
168
|
-
process.stderr.write(`too many positionals for inspect --argv\n`);
|
|
169
|
-
process.exitCode = 2;
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
let prompt: string;
|
|
174
|
-
let promptSource: string;
|
|
175
|
-
try {
|
|
176
|
-
const resolved = await resolvePromptAsync({
|
|
177
|
-
positionalPrompt,
|
|
178
|
-
promptFlag: values.prompt as string | undefined,
|
|
179
|
-
promptFile: values["prompt-file"] as string | undefined,
|
|
180
|
-
});
|
|
181
|
-
prompt = resolved.prompt;
|
|
182
|
-
promptSource = resolved.source;
|
|
183
|
-
} catch (err) {
|
|
184
|
-
if (err instanceof ArgvRefusalError) {
|
|
185
|
-
process.stderr.write(`${err.message}\n`);
|
|
186
|
-
if (err.supported.length) process.stderr.write(`supported: ${err.supported.join(", ")}\n`);
|
|
187
|
-
process.exitCode = 2;
|
|
188
|
-
return;
|
|
189
|
-
}
|
|
190
|
-
throw err;
|
|
191
111
|
}
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
(turnOpts as unknown as Record<string, unknown>).skills = resolvedSkills;
|
|
222
|
-
(turnOpts as unknown as Record<string, unknown>).__skillTokens = skillTokens;
|
|
223
|
-
} catch (err) {
|
|
224
|
-
if (err instanceof ArgvRefusalError) {
|
|
225
|
-
process.stderr.write(`${err.message}\n`);
|
|
226
|
-
if (err.supported.length) process.stderr.write(`supported: ${err.supported.join(", ")}\n`);
|
|
227
|
-
process.exitCode = 2;
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
throw err;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Resume previews from unresolved options, mirroring run.ts launch-only rule (F-15)
|
|
235
|
-
if (values.resume !== undefined || values["session-id"] !== undefined) {
|
|
236
|
-
if (values.resume !== undefined && values["session-id"] !== undefined) {
|
|
237
|
-
const err = new ArgvRefusalError({
|
|
238
|
-
issue: "mutually-exclusive-options",
|
|
239
|
-
harness: h.name,
|
|
240
|
-
supported: ["--resume or --session-id, not both (--session-id is an alias for --resume)"],
|
|
241
|
-
detail: "both --resume and --session-id given",
|
|
242
|
-
});
|
|
243
|
-
process.stderr.write(`${err.message}\n`);
|
|
244
|
-
if (err.supported.length) process.stderr.write(`supported: ${err.supported.join(", ")}\n`);
|
|
245
|
-
process.exitCode = 2;
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
const { buildResumeArgv } = await import("../interpretation/argv.js");
|
|
249
|
-
const resumeId = String(values.resume ?? values["session-id"]);
|
|
250
|
-
try {
|
|
251
|
-
const resumeOpts = {
|
|
252
|
-
...(turnOpts as object),
|
|
253
|
-
prompt,
|
|
254
|
-
sessionId: resumeId,
|
|
255
|
-
...(promptSource !== "positional" ? { __explicitPrompt: true as const } : {}),
|
|
256
|
-
} as Parameters<typeof buildResumeArgv>[1];
|
|
257
|
-
const resumeArgv = buildResumeArgv(h, resumeOpts);
|
|
258
|
-
const redactedResume = redactArgv(resumeArgv, prompt);
|
|
259
|
-
process.stdout.write(`${JSON.stringify(redactedResume)}\n`);
|
|
260
|
-
process.stderr.write(`argv: ${redactedResume.join(" ")}\n`);
|
|
261
|
-
return;
|
|
262
|
-
} catch (err) {
|
|
263
|
-
if (err instanceof ArgvRefusalError) {
|
|
264
|
-
process.stderr.write(`${err.message}\n`);
|
|
265
|
-
if (err.supported.length) process.stderr.write(`supported: ${err.supported.join(", ")}\n`);
|
|
266
|
-
process.exitCode = 2;
|
|
267
|
-
return;
|
|
268
|
-
}
|
|
269
|
-
throw err;
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
// Reuse already-loaded config for argv preview
|
|
274
|
-
const tiers: {
|
|
275
|
-
user?: Partial<ReturnType<typeof parseTurnOptions>>;
|
|
276
|
-
project?: Partial<ReturnType<typeof parseTurnOptions>>;
|
|
277
|
-
} = {};
|
|
278
|
-
if (loadedTiers.user) tiers.user = loadedTiers.user as never;
|
|
279
|
-
if (loadedTiers.project) tiers.project = loadedTiers.project as never;
|
|
280
|
-
let resolved: ReturnType<typeof resolveEffectiveOptions>;
|
|
281
|
-
try {
|
|
282
|
-
resolved = resolveEffectiveOptions(h, { ...turnOpts, prompt } as never, tiers);
|
|
283
|
-
} catch (resErr) {
|
|
284
|
-
if (resErr instanceof FloorExceededError) {
|
|
285
|
-
process.stderr.write(`${(resErr as Error).message}\n`);
|
|
286
|
-
process.exitCode = 2;
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
if (resErr instanceof ArgvRefusalError) {
|
|
290
|
-
refuse(refusalOf(resErr as ArgvRefusalError), false);
|
|
291
|
-
return;
|
|
292
|
-
}
|
|
293
|
-
throw resErr;
|
|
294
|
-
}
|
|
295
|
-
const { writeProvenance } = await import("./provenance.js");
|
|
296
|
-
writeProvenance(h.name, resolved.provenance, resolved.unrenderable);
|
|
297
|
-
const { prompt: _p, ...effectiveRest } = resolved.options as { prompt: string };
|
|
298
|
-
const fullOpts = {
|
|
299
|
-
...(effectiveRest as object),
|
|
300
|
-
prompt,
|
|
301
|
-
...(promptSource !== "positional" ? { __explicitPrompt: true as const } : {}),
|
|
302
|
-
} as Parameters<typeof buildLaunchArgv>[1];
|
|
303
|
-
|
|
304
|
-
let argv: string[];
|
|
305
|
-
try {
|
|
306
|
-
argv = buildLaunchArgv(h, fullOpts);
|
|
307
|
-
const skillTokens = (effectiveRest as unknown as { __skillTokens?: string[] }).__skillTokens;
|
|
308
|
-
if (skillTokens !== undefined && skillTokens.length > 0) argv.push(...skillTokens);
|
|
309
|
-
} catch (err) {
|
|
310
|
-
if (err instanceof ArgvRefusalError) {
|
|
311
|
-
refuse(refusalOf(err as ArgvRefusalError), false);
|
|
312
|
-
return;
|
|
313
|
-
}
|
|
314
|
-
throw err;
|
|
315
|
-
}
|
|
316
|
-
|
|
317
|
-
// Redact prompt for display, but keep structure
|
|
318
|
-
const redacted = redactArgv(argv, prompt);
|
|
319
|
-
|
|
320
|
-
process.stdout.write(`${JSON.stringify(redacted)}\n`);
|
|
321
|
-
process.stderr.write(`argv: ${redacted.join(" ")}\n`);
|
|
112
|
+
const out = {
|
|
113
|
+
name: h.name,
|
|
114
|
+
bin: h.bin,
|
|
115
|
+
verifiedAgainst: h.verifiedAgainst,
|
|
116
|
+
versionSource: h.versionSource,
|
|
117
|
+
launch: {
|
|
118
|
+
baseFlags: h.launch.baseFlags,
|
|
119
|
+
subcommands: h.launch.subcommands,
|
|
120
|
+
streamFlags: h.launch.streamFlags,
|
|
121
|
+
promptStyle: h.launch.promptStyle,
|
|
122
|
+
toolsFlag: h.tools.includeFlag,
|
|
123
|
+
idFlag: h.launch.idFlag,
|
|
124
|
+
},
|
|
125
|
+
resume: h.resume,
|
|
126
|
+
sessionMode: h.sessionMode,
|
|
127
|
+
vocabulary: {
|
|
128
|
+
models: h.vocabulary.models,
|
|
129
|
+
aliases: h.vocabulary.aliases,
|
|
130
|
+
efforts: h.vocabulary.efforts,
|
|
131
|
+
effortsByModel: h.vocabulary.effortsByModel,
|
|
132
|
+
extensible: h.vocabulary.extensible,
|
|
133
|
+
modelFlag: h.vocabulary.modelFlag,
|
|
134
|
+
},
|
|
135
|
+
turnOptions: h.turnOptions,
|
|
136
|
+
limitMatchers: h.limitMatchers,
|
|
137
|
+
authMatchers: h.authMatchers,
|
|
138
|
+
toolVocabulary: slice,
|
|
139
|
+
};
|
|
140
|
+
process.stdout.write(`${JSON.stringify(out, null, 2)}\n`);
|
|
322
141
|
};
|
|
323
142
|
|
|
324
143
|
export const inspectCommand = inspect;
|