@agentworkforce/cli 0.15.1 → 0.17.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/CHANGELOG.md +16 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +187 -14
- package/dist/cli.js.map +1 -1
- package/dist/cli.test.js +18 -0
- package/dist/cli.test.js.map +1 -1
- package/dist/local-personas.d.ts +6 -0
- package/dist/local-personas.d.ts.map +1 -1
- package/dist/local-personas.js +10 -0
- package/dist/local-personas.js.map +1 -1
- package/dist/local-personas.test.js +105 -0
- package/dist/local-personas.test.js.map +1 -1
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,22 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [0.17.0] - 2026-05-08
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Add optional defaultTier to PersonaSpec**
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- Agent: consult routingProfiles before defaultTier on no-@<tier>
|
|
19
|
+
|
|
20
|
+
## [0.16.0] - 2026-05-08
|
|
21
|
+
|
|
22
|
+
### Added
|
|
23
|
+
|
|
24
|
+
- **Add --dry-run flag to agentworkforce agent**
|
|
25
|
+
|
|
10
26
|
## [0.15.1] - 2026-05-08
|
|
11
27
|
|
|
12
28
|
### Added
|
package/dist/cli.d.ts
CHANGED
package/dist/cli.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AAkBA,OAAO,EAUL,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,gBAAgB,EAIrB,KAAK,aAAa,EACnB,MAAM,iCAAiC,CAAC;AA6BzC,OAAO,EAAe,KAAK,aAAa,EAAmB,MAAM,qBAAqB,CAAC;AA8JvF,eAAO,MAAM,WAAW,QAAuB,CAAC;AAChD,eAAO,MAAM,eAAe,uBAAuB,CAAC;AAiHpD;;;;;;;;;;GAUG;AACH,wBAAgB,+BAA+B,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAExF;AAyJD;;;;;;;;;;;;GAYG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,CAUhE;AAED;;;;;;GAMG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAe5D;AAED;;;kDAGkD;AAClD,eAAO,MAAM,sBAAsB,gFAUzB,CAAC;AAEX;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,2JAiBjC,CAAC;AAEX,MAAM,WAAW,sBAAsB;IACrC,eAAe,EAAE,MAAM,EAAE,CAAC;IAC1B,gBAAgB,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE;IACjD,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,YAAY,CAAC;IACrB,eAAe,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC,GAAG,sBAAsB,CAqBzB;AAED;;;;;;;;GAQG;AACH,wBAAgB,yBAAyB,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,MAAM,CAU7E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,SAAS,MAAM,EAAE,GAAG,IAAI,CAuCxF;AAED;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B,iFAAiF;IACjF,SAAS,EAAE,WAAW,GAAG,WAAW,CAAC;IACrC,uFAAuF;IACvF,cAAc,EAAE,MAAM,CAAC;IACvB,IAAI,EAAE,aAAa,CAAC;CACrB;AAED;;;;;;;GAOG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,gBAAgB,GAC1B;IAAE,OAAO,CAAC,EAAE,eAAe,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAyDjD;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,eAAe,EACxB,UAAU,EAAE,MAAM,GACjB,MAAM,CAkBR;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,OAAO,EAChB,aAAa,UAAQ,GACpB;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,CAKvB;AAizBD,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,kBAAkB,CA+B5E;AAwnBD;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,EAAE,CAmBrD;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAC7B,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE;IACJ,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAChC,IAAI,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;CAC5B,GACL,OAAO,CAWT;AAiGD,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAiE1C;AAED,MAAM,WAAW,UAAU;IACzB,aAAa,EAAE,OAAO,CAAC;IACvB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,MAAM,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,cAAc,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IACvD,KAAK,EAAE,UAAU,CAAC;IAClB,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB,CAoCA;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG;IACxD,KAAK,EAAE,WAAW,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACrC,CA6EA"}
|
package/dist/cli.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { spawn, spawnSync } from 'node:child_process';
|
|
3
3
|
import { randomBytes } from 'node:crypto';
|
|
4
|
-
import { appendFileSync, existsSync, mkdirSync, readFileSync, readSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
5
|
-
import { constants, homedir } from 'node:os';
|
|
4
|
+
import { appendFileSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readSync, rmSync, statSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { constants, homedir, tmpdir } from 'node:os';
|
|
6
6
|
import { dirname, isAbsolute, join, resolve as resolvePath } from 'node:path';
|
|
7
7
|
import { pathToFileURL } from 'node:url';
|
|
8
|
-
import { HARNESS_VALUES, PERSONA_TAGS, PERSONA_TIERS, listBuiltInPersonas, personaCatalog, resolveSidecar, routingProfiles, useSelection } from '@agentworkforce/workload-router';
|
|
8
|
+
import { HARNESS_VALUES, materializeSkills, PERSONA_TAGS, PERSONA_TIERS, listBuiltInPersonas, personaCatalog, resolveSidecar, routingProfiles, useSelection } from '@agentworkforce/workload-router';
|
|
9
9
|
import { buildInteractiveSpec, detectHarnesses, formatDropWarnings, MissingPersonaInputError, renderPersonaInputs, resolvePersonaInputs, resolveMcpServersLenient, resolveStringMapLenient } from '@agentworkforce/harness-kit';
|
|
10
10
|
import { launchOnMount, readAgentDotfiles } from '@relayfile/local-mount';
|
|
11
11
|
import ora from 'ora';
|
|
@@ -34,9 +34,11 @@ Commands:
|
|
|
34
34
|
--no-launch-metadata
|
|
35
35
|
Same behavior as agent.
|
|
36
36
|
agent [flags] <persona>[@<tier>]
|
|
37
|
-
Run a persona. Tier one of: ${PERSONA_TIERS.join(' | ')}
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
Run a persona. Tier one of: ${PERSONA_TIERS.join(' | ')}.
|
|
38
|
+
With no @<tier>, the resolution order is:
|
|
39
|
+
routingProfiles.default.intents (built-in personas only)
|
|
40
|
+
→ persona.defaultTier (when set) → best-value. Drops into
|
|
41
|
+
an interactive harness session.
|
|
40
42
|
|
|
41
43
|
Flags:
|
|
42
44
|
--install-in-repo Disengage the sandbox mount and
|
|
@@ -57,6 +59,26 @@ Commands:
|
|
|
57
59
|
Disable launch metadata recording.
|
|
58
60
|
Also disabled by
|
|
59
61
|
AGENTWORKFORCE_LAUNCH_METADATA=0.
|
|
62
|
+
--dry-run Validate the persona without
|
|
63
|
+
spawning the harness or burning
|
|
64
|
+
tier-model tokens. Three checks:
|
|
65
|
+
(1) sidecar — claudeMd / agentsMd
|
|
66
|
+
filename refs are readable;
|
|
67
|
+
(2) harness spec — permissions /
|
|
68
|
+
mcpServers / harness-settings
|
|
69
|
+
shape is accepted by the harness
|
|
70
|
+
translator; (3) skills — each
|
|
71
|
+
\`skills[].source\` is run through
|
|
72
|
+
its real installer (npx skills
|
|
73
|
+
add / npx prpm install) inside a
|
|
74
|
+
fresh temp dir, with per-skill
|
|
75
|
+
pass/fail reporting. Use this in
|
|
76
|
+
the persona-author loop to catch
|
|
77
|
+
hallucinated skill names and
|
|
78
|
+
malformed config before a persona
|
|
79
|
+
ships. Temp dir is removed on
|
|
80
|
+
success, kept on failure for
|
|
81
|
+
inspection.
|
|
60
82
|
list [flags] List available personas from the cascade (cwd →
|
|
61
83
|
configured persona dirs → library). By default shows
|
|
62
84
|
one row per persona at the recommended tier for its
|
|
@@ -212,14 +234,22 @@ function parseSelector(sel) {
|
|
|
212
234
|
const tierRaw = at === -1 ? undefined : sel.slice(at + 1);
|
|
213
235
|
if (!key)
|
|
214
236
|
die('Missing persona name before "@"');
|
|
215
|
-
|
|
216
|
-
if (tierRaw !== undefined && !PERSONA_TIERS.includes(tier)) {
|
|
237
|
+
if (tierRaw !== undefined && !PERSONA_TIERS.includes(tierRaw)) {
|
|
217
238
|
die(`Invalid tier "${tierRaw}". Must be one of: ${PERSONA_TIERS.join(', ')}`);
|
|
218
239
|
}
|
|
219
240
|
const result = resolveSpec(key);
|
|
220
241
|
if ('error' in result)
|
|
221
242
|
die(result.error, false);
|
|
222
243
|
const kind = local.byId.has(key) ? 'local' : 'repo';
|
|
244
|
+
// Resolution order when no @<tier> is given: routingProfiles default for the
|
|
245
|
+
// persona's intent (built-ins only — local personas with custom intents miss
|
|
246
|
+
// the lookup and fall through), then the persona's own defaultTier, then
|
|
247
|
+
// 'best-value'. Mirrors `resolveShowTarget` and the `list` recommended-tier
|
|
248
|
+
// filter so all three commands agree on what "no tier" means.
|
|
249
|
+
const profileRule = kind === 'repo'
|
|
250
|
+
? routingProfiles.default.intents[result.intent]
|
|
251
|
+
: undefined;
|
|
252
|
+
const tier = (tierRaw ?? profileRule?.tier ?? result.defaultTier ?? 'best-value');
|
|
223
253
|
if (kind === 'local') {
|
|
224
254
|
return { kind, source: local.sources.get(result.id) ?? 'cwd', spec: result, tier };
|
|
225
255
|
}
|
|
@@ -677,6 +707,128 @@ export function decideCleanMode(harness, installInRepo = false) {
|
|
|
677
707
|
}
|
|
678
708
|
return { useClean: false };
|
|
679
709
|
}
|
|
710
|
+
/**
|
|
711
|
+
* Persona authoring dry-run. Used by persona authors to verify a persona
|
|
712
|
+
* actually launches before it ships, without spawning the harness or
|
|
713
|
+
* running the agent's tier model. Three checks, in order:
|
|
714
|
+
*
|
|
715
|
+
* 1. Sidecar resolution — `claudeMd` / `agentsMd` filename references
|
|
716
|
+
* that point at unreadable files would brick the launch silently
|
|
717
|
+
* today (lenient warning); dry-run promotes them to failures.
|
|
718
|
+
* 2. Interactive spec build — runs `buildInteractiveSpec` on the
|
|
719
|
+
* resolved selection. Catches malformed `permissions` patterns,
|
|
720
|
+
* `mcpServers` shape errors, and missing required harness fields.
|
|
721
|
+
* Pure / no side effects.
|
|
722
|
+
* 3. Skill install — runs each `skills[].source` through its real
|
|
723
|
+
* installer (`npx skills add` / `npx prpm install`) inside a fresh
|
|
724
|
+
* temp dir and reports per-skill pass/fail.
|
|
725
|
+
*
|
|
726
|
+
* Temp dir is deleted on success so dry-run leaves no trace; on a skill
|
|
727
|
+
* failure it is left in place and its path printed so the author can
|
|
728
|
+
* inspect the installer's output. Checks 1 and 2 run before any temp
|
|
729
|
+
* dir is created so an early failure doesn't litter `/tmp`.
|
|
730
|
+
*/
|
|
731
|
+
function runDryRun(selection) {
|
|
732
|
+
const inputResolution = resolvePersonaInputs(selection.inputs, selection.inputValues, process.env);
|
|
733
|
+
const renderedSystemPrompt = renderPersonaInputs(selection.runtime.systemPrompt, inputResolution.values);
|
|
734
|
+
const renderedClaudeContent = selection.claudeMdContent !== undefined
|
|
735
|
+
? renderPersonaInputs(selection.claudeMdContent, inputResolution.values)
|
|
736
|
+
: undefined;
|
|
737
|
+
const renderedAgentsContent = selection.agentsMdContent !== undefined
|
|
738
|
+
? renderPersonaInputs(selection.agentsMdContent, inputResolution.values)
|
|
739
|
+
: undefined;
|
|
740
|
+
const effectiveSelection = {
|
|
741
|
+
...selection,
|
|
742
|
+
runtime: { ...selection.runtime, systemPrompt: renderedSystemPrompt },
|
|
743
|
+
...(renderedClaudeContent !== undefined ? { claudeMdContent: renderedClaudeContent } : {}),
|
|
744
|
+
...(renderedAgentsContent !== undefined ? { agentsMdContent: renderedAgentsContent } : {})
|
|
745
|
+
};
|
|
746
|
+
const { runtime, personaId, tier } = effectiveSelection;
|
|
747
|
+
process.stderr.write(`→ ${personaId} [${tier}] via ${runtime.harness} (${runtime.model}) [DRY-RUN]\n`);
|
|
748
|
+
// Check 1: sidecar resolution. A loadSidecarForSelection warning means
|
|
749
|
+
// the persona points `claudeMd` / `agentsMd` at a file we couldn't
|
|
750
|
+
// read; the launch path degrades to a warning today, which silently
|
|
751
|
+
// drops the persona's operating spec. In dry-run that's a failure.
|
|
752
|
+
const sidecarLookup = loadSidecarForSelection(effectiveSelection);
|
|
753
|
+
if (sidecarLookup.warning) {
|
|
754
|
+
process.stderr.write(`✗ sidecar: ${sidecarLookup.warning}\n`);
|
|
755
|
+
return 1;
|
|
756
|
+
}
|
|
757
|
+
process.stderr.write(`✓ sidecar: ${sidecarLookup.sidecar ? sidecarLookup.sidecar.mountFile : '(none)'}\n`);
|
|
758
|
+
// Check 2: harness-kit translation. buildInteractiveSpec validates
|
|
759
|
+
// permissions shape, mcpServers shape, and required runtime fields.
|
|
760
|
+
// We resolve env + mcp leniently (same as the live launch path) so
|
|
761
|
+
// the spec call sees the same inputs it would at runtime.
|
|
762
|
+
const callerEnv = { ...process.env, ...inputResolution.values };
|
|
763
|
+
const envResolution = resolveStringMapLenient(effectiveSelection.env, callerEnv, 'env');
|
|
764
|
+
const mcpResolution = resolveMcpServersLenient(effectiveSelection.mcpServers, callerEnv);
|
|
765
|
+
emitDropWarnings(formatDropWarnings(envResolution.dropped, mcpResolution.dropped, mcpResolution.droppedServers));
|
|
766
|
+
let spec;
|
|
767
|
+
try {
|
|
768
|
+
spec = buildInteractiveSpec({
|
|
769
|
+
harness: runtime.harness,
|
|
770
|
+
personaId,
|
|
771
|
+
model: runtime.model,
|
|
772
|
+
systemPrompt: runtime.systemPrompt,
|
|
773
|
+
harnessSettings: runtime.harnessSettings,
|
|
774
|
+
mcpServers: mcpResolution.servers,
|
|
775
|
+
permissions: effectiveSelection.permissions
|
|
776
|
+
});
|
|
777
|
+
}
|
|
778
|
+
catch (err) {
|
|
779
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
780
|
+
process.stderr.write(`✗ harness spec: ${msg}\n`);
|
|
781
|
+
return 1;
|
|
782
|
+
}
|
|
783
|
+
for (const w of spec.warnings)
|
|
784
|
+
process.stderr.write(`warning: ${w}\n`);
|
|
785
|
+
process.stderr.write(`✓ harness spec: ${spec.bin} (${spec.args.length} args)\n`);
|
|
786
|
+
// Check 3: skill installs.
|
|
787
|
+
const plan = materializeSkills(effectiveSelection.skills, runtime.harness);
|
|
788
|
+
if (plan.installs.length === 0) {
|
|
789
|
+
process.stderr.write('✓ skills: (none declared)\n');
|
|
790
|
+
process.stderr.write('✓ dry-run ok\n');
|
|
791
|
+
return 0;
|
|
792
|
+
}
|
|
793
|
+
const tempDir = mkdtempSync(join(tmpdir(), `agentworkforce-dryrun-${personaId}-`));
|
|
794
|
+
process.stderr.write(`• temp dir: ${tempDir}\n`);
|
|
795
|
+
process.stderr.write(`• installing ${plan.installs.length} skill(s)\n`);
|
|
796
|
+
const failures = [];
|
|
797
|
+
for (const inst of plan.installs) {
|
|
798
|
+
const [bin, ...args] = inst.installCommand;
|
|
799
|
+
if (!bin) {
|
|
800
|
+
process.stderr.write(` skipped ${inst.skillId}: empty install command\n`);
|
|
801
|
+
continue;
|
|
802
|
+
}
|
|
803
|
+
process.stderr.write(`• ${inst.skillId} (${inst.sourceKind}) → ${inst.packageRef}\n`);
|
|
804
|
+
const res = spawnSync(bin, args, { stdio: 'inherit', shell: false, cwd: tempDir });
|
|
805
|
+
const code = subprocessExitCode(res);
|
|
806
|
+
if (code === 0) {
|
|
807
|
+
process.stderr.write(` ✓ ${inst.skillId}\n`);
|
|
808
|
+
}
|
|
809
|
+
else {
|
|
810
|
+
process.stderr.write(` ✗ ${inst.skillId} (exit ${code})\n`);
|
|
811
|
+
failures.push({ skillId: inst.skillId, exitCode: code });
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
if (failures.length === 0) {
|
|
815
|
+
try {
|
|
816
|
+
rmSync(tempDir, { recursive: true, force: true });
|
|
817
|
+
}
|
|
818
|
+
catch (err) {
|
|
819
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
820
|
+
process.stderr.write(`warning: failed to clean up ${tempDir}: ${msg}\n`);
|
|
821
|
+
}
|
|
822
|
+
process.stderr.write(`✓ dry-run ok: ${plan.installs.length} skill(s) installed cleanly\n`);
|
|
823
|
+
return 0;
|
|
824
|
+
}
|
|
825
|
+
process.stderr.write(`✗ dry-run failed: ${failures.length} of ${plan.installs.length} skill(s) failed\n`);
|
|
826
|
+
process.stderr.write(` inspect ${tempDir} for installer output\n`);
|
|
827
|
+
for (const f of failures) {
|
|
828
|
+
process.stderr.write(` - ${f.skillId} (exit ${f.exitCode})\n`);
|
|
829
|
+
}
|
|
830
|
+
return failures[0]?.exitCode || 1;
|
|
831
|
+
}
|
|
680
832
|
async function runInteractive(selection, options) {
|
|
681
833
|
const inputResolution = resolvePersonaInputs(selection.inputs, selection.inputValues, process.env);
|
|
682
834
|
const renderedSystemPrompt = renderPersonaInputs(selection.runtime.systemPrompt, inputResolution.values);
|
|
@@ -1368,7 +1520,8 @@ function collectPersonaRows() {
|
|
|
1368
1520
|
intent: spec.intent,
|
|
1369
1521
|
tags: spec.tags,
|
|
1370
1522
|
description: spec.description,
|
|
1371
|
-
rating: tier
|
|
1523
|
+
rating: tier,
|
|
1524
|
+
defaultTier: spec.defaultTier
|
|
1372
1525
|
});
|
|
1373
1526
|
}
|
|
1374
1527
|
};
|
|
@@ -1517,7 +1670,7 @@ function runList(args) {
|
|
|
1517
1670
|
return false;
|
|
1518
1671
|
if (applyRecommended) {
|
|
1519
1672
|
const rule = recommendedByIntent[r.intent];
|
|
1520
|
-
if (r.rating !== (rule?.tier ?? 'best-value'))
|
|
1673
|
+
if (r.rating !== (rule?.tier ?? r.defaultTier ?? 'best-value'))
|
|
1521
1674
|
return false;
|
|
1522
1675
|
}
|
|
1523
1676
|
return true;
|
|
@@ -1611,7 +1764,7 @@ function resolveShowTarget(selector, all) {
|
|
|
1611
1764
|
}
|
|
1612
1765
|
else {
|
|
1613
1766
|
const rule = routingProfiles.default.intents[spec.intent];
|
|
1614
|
-
tiers = [rule?.tier ?? 'best-value'];
|
|
1767
|
+
tiers = [rule?.tier ?? spec.defaultTier ?? 'best-value'];
|
|
1615
1768
|
}
|
|
1616
1769
|
return { spec, source, tiers, explicitTier };
|
|
1617
1770
|
}
|
|
@@ -1628,6 +1781,9 @@ function formatPersonaShow(spec, source, tiers, tierNote) {
|
|
|
1628
1781
|
lines.push(`INTENT ${spec.intent}`);
|
|
1629
1782
|
lines.push(`TAGS ${spec.tags.length ? spec.tags.join(', ') : '(none)'}`);
|
|
1630
1783
|
lines.push(`DESCRIPTION ${spec.description}`);
|
|
1784
|
+
if (spec.defaultTier) {
|
|
1785
|
+
lines.push(`DEFAULT TIER ${spec.defaultTier}`);
|
|
1786
|
+
}
|
|
1631
1787
|
lines.push(`TIERS SHOWN ${tiers.join(', ')}${tierNote ? ` (${tierNote})` : ''}`);
|
|
1632
1788
|
lines.push('');
|
|
1633
1789
|
lines.push('SKILLS');
|
|
@@ -1846,6 +2002,10 @@ async function runAgentSelector(selector, flags, inputValues) {
|
|
|
1846
2002
|
...buildSelection(target.spec, target.tier, target.kind),
|
|
1847
2003
|
...(inputValues ? { inputValues } : {})
|
|
1848
2004
|
};
|
|
2005
|
+
if (flags.dryRun) {
|
|
2006
|
+
const code = runDryRun(selection);
|
|
2007
|
+
process.exit(code);
|
|
2008
|
+
}
|
|
1849
2009
|
const code = await runInteractive(selection, {
|
|
1850
2010
|
installInRepo: flags.installInRepo,
|
|
1851
2011
|
noLaunchMetadata: flags.noLaunchMetadata,
|
|
@@ -1972,7 +2132,7 @@ async function runPick(args) {
|
|
|
1972
2132
|
...buildCreateInputValues(target),
|
|
1973
2133
|
TASK_DESCRIPTION: task
|
|
1974
2134
|
};
|
|
1975
|
-
await runAgentSelector(CREATE_SELECTOR, { installInRepo: false, noLaunchMetadata: false }, inputValues);
|
|
2135
|
+
await runAgentSelector(CREATE_SELECTOR, { installInRepo: false, noLaunchMetadata: false, dryRun: false }, inputValues);
|
|
1976
2136
|
// runAgentSelector terminates via process.exit; this satisfies TS's
|
|
1977
2137
|
// reachable-end-point check for the `Promise<never>` return type.
|
|
1978
2138
|
process.exit(0);
|
|
@@ -2033,7 +2193,11 @@ export async function main() {
|
|
|
2033
2193
|
await runAgentSelector(selector, flags);
|
|
2034
2194
|
}
|
|
2035
2195
|
export function parseAgentArgs(args) {
|
|
2036
|
-
const flags = {
|
|
2196
|
+
const flags = {
|
|
2197
|
+
installInRepo: false,
|
|
2198
|
+
noLaunchMetadata: false,
|
|
2199
|
+
dryRun: false
|
|
2200
|
+
};
|
|
2037
2201
|
const positional = [];
|
|
2038
2202
|
let seenDoubleDash = false;
|
|
2039
2203
|
for (const arg of args) {
|
|
@@ -2053,6 +2217,10 @@ export function parseAgentArgs(args) {
|
|
|
2053
2217
|
flags.noLaunchMetadata = true;
|
|
2054
2218
|
continue;
|
|
2055
2219
|
}
|
|
2220
|
+
if (arg === '--dry-run') {
|
|
2221
|
+
flags.dryRun = true;
|
|
2222
|
+
continue;
|
|
2223
|
+
}
|
|
2056
2224
|
if (arg === '-h' || arg === '--help') {
|
|
2057
2225
|
process.stdout.write(USAGE);
|
|
2058
2226
|
process.exit(0);
|
|
@@ -2062,7 +2230,12 @@ export function parseAgentArgs(args) {
|
|
|
2062
2230
|
return { flags, positional };
|
|
2063
2231
|
}
|
|
2064
2232
|
export function parseCreateArgs(args) {
|
|
2065
|
-
const flags = {
|
|
2233
|
+
const flags = {
|
|
2234
|
+
installInRepo: false,
|
|
2235
|
+
noLaunchMetadata: false,
|
|
2236
|
+
dryRun: false,
|
|
2237
|
+
saveDefault: false
|
|
2238
|
+
};
|
|
2066
2239
|
let seenDoubleDash = false;
|
|
2067
2240
|
const positional = [];
|
|
2068
2241
|
const valueOf = (i, flag) => {
|