@phnx-labs/agents-cli 1.22.23 → 1.22.24
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 +193 -0
- package/README.md +5 -4
- package/dist/bin/agents +0 -0
- package/dist/commands/attach.d.ts +2 -0
- package/dist/commands/attach.js +32 -7
- package/dist/commands/defaults.js +2 -0
- package/dist/commands/doctor.js +5 -0
- package/dist/commands/exec.js +80 -28
- package/dist/commands/feed.d.ts +18 -0
- package/dist/commands/feed.js +44 -1
- package/dist/commands/focus.d.ts +34 -3
- package/dist/commands/focus.js +300 -56
- package/dist/commands/go.d.ts +14 -1
- package/dist/commands/go.js +49 -5
- package/dist/commands/insights.js +6 -2
- package/dist/commands/inspect.js +39 -5
- package/dist/commands/menubar.js +6 -1
- package/dist/commands/models.js +1 -0
- package/dist/commands/modes.d.ts +12 -0
- package/dist/commands/modes.js +147 -0
- package/dist/commands/secrets-sync.js +11 -13
- package/dist/commands/secrets.d.ts +2 -0
- package/dist/commands/secrets.js +54 -17
- package/dist/commands/sessions-browser.d.ts +35 -0
- package/dist/commands/sessions-browser.js +140 -14
- package/dist/commands/sessions-resume.d.ts +2 -0
- package/dist/commands/sessions-resume.js +26 -11
- package/dist/commands/sessions.d.ts +10 -0
- package/dist/commands/sessions.js +34 -59
- package/dist/commands/setup-secrets.js +1 -1
- package/dist/commands/sync.js +246 -42
- package/dist/commands/view.js +2 -0
- package/dist/index.js +2 -1
- package/dist/lib/agent-modes.d.ts +49 -0
- package/dist/lib/agent-modes.js +70 -0
- package/dist/lib/doctor-diff.d.ts +3 -0
- package/dist/lib/doctor-diff.js +15 -13
- package/dist/lib/event-stream.d.ts +3 -1
- package/dist/lib/event-stream.js +14 -1
- package/dist/lib/exec.d.ts +12 -0
- package/dist/lib/exec.js +88 -9
- package/dist/lib/hooks/cache.js +36 -3
- package/dist/lib/hooks.d.ts +19 -7
- package/dist/lib/hooks.js +88 -38
- package/dist/lib/hosts/session-index.d.ts +4 -0
- package/dist/lib/hosts/session-index.js +7 -0
- package/dist/lib/manifest.d.ts +12 -2
- package/dist/lib/manifest.js +60 -5
- package/dist/lib/menubar/MenubarHelper.app/Contents/CodeResources +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +5 -1
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +15 -2
- package/dist/lib/menubar/install-menubar.d.ts +52 -2
- package/dist/lib/menubar/install-menubar.js +128 -6
- package/dist/lib/refresh.d.ts +5 -0
- package/dist/lib/refresh.js +37 -33
- package/dist/lib/resource-inventory.d.ts +79 -0
- package/dist/lib/resource-inventory.js +122 -0
- package/dist/lib/resources.js +8 -5
- package/dist/lib/run-defaults.d.ts +2 -0
- package/dist/lib/run-defaults.js +23 -2
- package/dist/lib/runner.js +22 -17
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +2 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +13 -1
- package/dist/lib/secrets/bundles.js +157 -65
- package/dist/lib/secrets/filestore.d.ts +5 -3
- package/dist/lib/secrets/filestore.js +12 -8
- package/dist/lib/secrets/index.js +34 -8
- package/dist/lib/secrets/reaper.d.ts +10 -0
- package/dist/lib/secrets/reaper.js +50 -15
- package/dist/lib/secrets/sync-passphrase.d.ts +27 -0
- package/dist/lib/secrets/sync-passphrase.js +78 -0
- package/dist/lib/session/recovery.d.ts +37 -0
- package/dist/lib/session/recovery.js +95 -0
- package/dist/lib/shims.d.ts +2 -2
- package/dist/lib/shims.js +24 -5
- package/dist/lib/startup/command-registry.d.ts +1 -0
- package/dist/lib/startup/command-registry.js +2 -0
- package/dist/lib/sync-umbrella.d.ts +5 -0
- package/dist/lib/sync-umbrella.js +5 -4
- package/dist/lib/tmux/session.d.ts +4 -2
- package/dist/lib/tmux/session.js +5 -5
- package/dist/lib/types.d.ts +2 -0
- package/package.json +1 -1
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource inventory — the single chokepoint for "what does this agent@version
|
|
3
|
+
* have" (RUSH-2238, parent RUSH-2236; spec: openspec/specs/resource-inventory).
|
|
4
|
+
*
|
|
5
|
+
* One API answers four orthogonal questions per (agent, version, kind):
|
|
6
|
+
*
|
|
7
|
+
* capable — the agent+version feature flags allow the kind at all
|
|
8
|
+
* declared — resources the DotAgents layers (project/user/system/extra)
|
|
9
|
+
* declare for sync
|
|
10
|
+
* onDisk — resources actually installed in the version home filesystem
|
|
11
|
+
* (the installed-resource truth — NOT agents.yaml tracking data)
|
|
12
|
+
* wired — resources the harness native config references so they fire
|
|
13
|
+
* unmanaged — onDisk − declared (orphans no layer declares anymore)
|
|
14
|
+
*
|
|
15
|
+
* Callers (inspect, doctor, view, sync) MUST come here rather than
|
|
16
|
+
* re-implementing path joins or config parsing per command. Wiring parsing
|
|
17
|
+
* currently covers the settings.json family (claude, droid,
|
|
18
|
+
* muse), Grok hooks.json, and Kimi config.toml via checkVersionHookWiring.
|
|
19
|
+
*/
|
|
20
|
+
import type { AgentId } from './types.js';
|
|
21
|
+
import { type HookWiringReport } from './hooks.js';
|
|
22
|
+
/** Resource kinds the inventory can report. Only 'hooks' is implemented so far
|
|
23
|
+
* (RUSH-2238); the remaining kinds land with their follow-up tickets. */
|
|
24
|
+
export type InventoryKind = 'hooks' | 'skills' | 'commands' | 'plugins' | 'mcp';
|
|
25
|
+
/** A reference to one resource in one state (declared / onDisk / wired). */
|
|
26
|
+
export interface ResourceRef {
|
|
27
|
+
/** Stable install name (script basename without extension for hooks). */
|
|
28
|
+
name: string;
|
|
29
|
+
/** Declared/onDisk: absolute file path. Wired: the command string the native
|
|
30
|
+
* config references. */
|
|
31
|
+
path: string;
|
|
32
|
+
/** Origin: a layer name for declared ('project' | 'user' | 'system' | extra
|
|
33
|
+
* repo alias), 'user'/'project' scope or 'version-home' for onDisk,
|
|
34
|
+
* 'native-config' for wired. */
|
|
35
|
+
source: string;
|
|
36
|
+
/** Optional context — e.g. the lifecycle events a wired hook fires on. */
|
|
37
|
+
detail?: string;
|
|
38
|
+
}
|
|
39
|
+
export interface ResourceInventory {
|
|
40
|
+
agent: AgentId;
|
|
41
|
+
version: string;
|
|
42
|
+
kind: InventoryKind;
|
|
43
|
+
/** Agent+version feature flags allow this kind (version-aware gate). */
|
|
44
|
+
capable: boolean;
|
|
45
|
+
/** Declared in the DotAgents layers. */
|
|
46
|
+
declared: ResourceRef[];
|
|
47
|
+
/** Installed on disk in the version home. */
|
|
48
|
+
onDisk: ResourceRef[];
|
|
49
|
+
/** Referenced by the harness native config (empty when wiringSupported is
|
|
50
|
+
* false — the format parser for that harness is not implemented yet). */
|
|
51
|
+
wired: ResourceRef[];
|
|
52
|
+
/** onDisk − declared: installed orphans no layer declares. */
|
|
53
|
+
unmanaged: ResourceRef[];
|
|
54
|
+
/** Whether this harness's native wiring was read successfully. When false,
|
|
55
|
+
* `wired: []` means "unknown" (unsupported family OR unparseable config),
|
|
56
|
+
* NOT "nothing wired". Format-supported but corrupt configs set this false. */
|
|
57
|
+
wiringSupported: boolean;
|
|
58
|
+
/** Native-format diagnostic retained for doctor; derived in this same pass. */
|
|
59
|
+
wiring?: HookWiringReport;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The single inventory API. Harness-scoped (claude/codex/grok/kimi/droid) —
|
|
63
|
+
* never a model or profile. Throws for kinds without an implementation rather
|
|
64
|
+
* than returning a half-empty report that looks like truth.
|
|
65
|
+
*/
|
|
66
|
+
export declare function getResourceInventory(agent: AgentId, version: string, kind: InventoryKind, opts?: {
|
|
67
|
+
cwd?: string;
|
|
68
|
+
}): ResourceInventory;
|
|
69
|
+
/**
|
|
70
|
+
* On-disk hook listing for an explicit home (version home or effective home)
|
|
71
|
+
* plus the project overlay — the one listing `getAgentResources` routes
|
|
72
|
+
* through, so inspect/doctor/view share a single hooks source. Paths resolve
|
|
73
|
+
* through the absolute-hooksDir-safe join (RUSH-2237), so grok/kimi version
|
|
74
|
+
* homes list their real hooks.
|
|
75
|
+
*/
|
|
76
|
+
export declare function listOnDiskHooks(agent: AgentId, opts?: {
|
|
77
|
+
home?: string;
|
|
78
|
+
cwd?: string;
|
|
79
|
+
}): ResourceRef[];
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resource inventory — the single chokepoint for "what does this agent@version
|
|
3
|
+
* have" (RUSH-2238, parent RUSH-2236; spec: openspec/specs/resource-inventory).
|
|
4
|
+
*
|
|
5
|
+
* One API answers four orthogonal questions per (agent, version, kind):
|
|
6
|
+
*
|
|
7
|
+
* capable — the agent+version feature flags allow the kind at all
|
|
8
|
+
* declared — resources the DotAgents layers (project/user/system/extra)
|
|
9
|
+
* declare for sync
|
|
10
|
+
* onDisk — resources actually installed in the version home filesystem
|
|
11
|
+
* (the installed-resource truth — NOT agents.yaml tracking data)
|
|
12
|
+
* wired — resources the harness native config references so they fire
|
|
13
|
+
* unmanaged — onDisk − declared (orphans no layer declares anymore)
|
|
14
|
+
*
|
|
15
|
+
* Callers (inspect, doctor, view, sync) MUST come here rather than
|
|
16
|
+
* re-implementing path joins or config parsing per command. Wiring parsing
|
|
17
|
+
* currently covers the settings.json family (claude, droid,
|
|
18
|
+
* muse), Grok hooks.json, and Kimi config.toml via checkVersionHookWiring.
|
|
19
|
+
*/
|
|
20
|
+
import { AGENTS } from './agents.js';
|
|
21
|
+
import { supports } from './capabilities.js';
|
|
22
|
+
import { listResources } from './resources.js';
|
|
23
|
+
import { checkVersionHookWiring, listHooksInVersionHome, listInstalledHooksWithScope, } from './hooks.js';
|
|
24
|
+
const IMPLEMENTED_KINDS = ['hooks'];
|
|
25
|
+
/**
|
|
26
|
+
* The single inventory API. Harness-scoped (claude/codex/grok/kimi/droid) —
|
|
27
|
+
* never a model or profile. Throws for kinds without an implementation rather
|
|
28
|
+
* than returning a half-empty report that looks like truth.
|
|
29
|
+
*/
|
|
30
|
+
export function getResourceInventory(agent, version, kind, opts = {}) {
|
|
31
|
+
if (!IMPLEMENTED_KINDS.includes(kind)) {
|
|
32
|
+
// Fail loud at the boundary: the kind is part of the API shape but its
|
|
33
|
+
// inventory lands with a RUSH-2236 follow-up — a silent empty report would
|
|
34
|
+
// read as "nothing installed".
|
|
35
|
+
throw new Error(`getResourceInventory: kind '${kind}' is not implemented yet (implemented: ${IMPLEMENTED_KINDS.join(', ')}; tracked under RUSH-2236)`);
|
|
36
|
+
}
|
|
37
|
+
return hooksInventory(agent, version, opts.cwd);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* On-disk hook listing for an explicit home (version home or effective home)
|
|
41
|
+
* plus the project overlay — the one listing `getAgentResources` routes
|
|
42
|
+
* through, so inspect/doctor/view share a single hooks source. Paths resolve
|
|
43
|
+
* through the absolute-hooksDir-safe join (RUSH-2237), so grok/kimi version
|
|
44
|
+
* homes list their real hooks.
|
|
45
|
+
*/
|
|
46
|
+
export function listOnDiskHooks(agent, opts = {}) {
|
|
47
|
+
return listInstalledHooksWithScope(agent, opts.cwd ?? process.cwd(), { home: opts.home }).map((h) => ({
|
|
48
|
+
name: h.name,
|
|
49
|
+
path: h.path,
|
|
50
|
+
source: h.scope,
|
|
51
|
+
detail: h.dataFile,
|
|
52
|
+
}));
|
|
53
|
+
}
|
|
54
|
+
function hooksInventory(agent, version, cwd) {
|
|
55
|
+
const capable = supports(agent, 'hooks', version).ok;
|
|
56
|
+
// Declared: the layered DotAgents repos are the declaration surface. Hook
|
|
57
|
+
// script names carry their extension here ('git-guard.sh'); normalize to the
|
|
58
|
+
// extension-less install name so declared/onDisk sets compare.
|
|
59
|
+
const declared = listResources('hooks', cwd).map((r) => ({
|
|
60
|
+
name: r.name.replace(/\.[^./]+$/, ''),
|
|
61
|
+
path: r.path,
|
|
62
|
+
source: r.source,
|
|
63
|
+
}));
|
|
64
|
+
// onDisk / wired need the version home; both are empty for an agent whose
|
|
65
|
+
// hooks capability is gated off (unknown agents included — AGENTS lookup
|
|
66
|
+
// would otherwise throw).
|
|
67
|
+
let onDisk = [];
|
|
68
|
+
let wired = [];
|
|
69
|
+
let wiringSupported = false;
|
|
70
|
+
let wiring;
|
|
71
|
+
if (capable && AGENTS[agent]?.supportsHooks) {
|
|
72
|
+
onDisk = listHooksInVersionHome(agent, version).map((e) => ({
|
|
73
|
+
name: e.name,
|
|
74
|
+
path: e.scriptPath,
|
|
75
|
+
source: 'version-home',
|
|
76
|
+
detail: e.dataFile,
|
|
77
|
+
}));
|
|
78
|
+
const report = checkVersionHookWiring(agent, version);
|
|
79
|
+
wiring = report;
|
|
80
|
+
// supported=true means the harness format is known; settingsUnparseable means
|
|
81
|
+
// we could not trust the file. Only report wired counts when the parse succeeded —
|
|
82
|
+
// otherwise inspect/doctor would render "wired 0" for corrupt configs (PR #2140 review).
|
|
83
|
+
wiringSupported = report.supported && !report.settingsUnparseable;
|
|
84
|
+
if (wiringSupported) {
|
|
85
|
+
// One ref per hook, events folded into detail — a hook wired under
|
|
86
|
+
// PreToolUse AND Stop is one inventory entry, not two.
|
|
87
|
+
const eventsByName = new Map();
|
|
88
|
+
const commandByName = new Map();
|
|
89
|
+
for (const issue of report.wired) {
|
|
90
|
+
let events = eventsByName.get(issue.name);
|
|
91
|
+
if (!events) {
|
|
92
|
+
events = new Set();
|
|
93
|
+
eventsByName.set(issue.name, events);
|
|
94
|
+
commandByName.set(issue.name, issue.command);
|
|
95
|
+
}
|
|
96
|
+
events.add(issue.event);
|
|
97
|
+
}
|
|
98
|
+
wired = [...eventsByName.entries()]
|
|
99
|
+
.sort(([a], [b]) => a.localeCompare(b))
|
|
100
|
+
.map(([name, events]) => ({
|
|
101
|
+
name,
|
|
102
|
+
path: commandByName.get(name),
|
|
103
|
+
source: 'native-config',
|
|
104
|
+
detail: [...events].sort().join('/'),
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const declaredNames = new Set(declared.map((r) => r.name));
|
|
109
|
+
const unmanaged = onDisk.filter((r) => !declaredNames.has(r.name));
|
|
110
|
+
return {
|
|
111
|
+
agent,
|
|
112
|
+
version,
|
|
113
|
+
kind: 'hooks',
|
|
114
|
+
capable,
|
|
115
|
+
declared,
|
|
116
|
+
onDisk,
|
|
117
|
+
wired,
|
|
118
|
+
unmanaged,
|
|
119
|
+
wiringSupported,
|
|
120
|
+
wiring,
|
|
121
|
+
};
|
|
122
|
+
}
|
package/dist/lib/resources.js
CHANGED
|
@@ -7,7 +7,7 @@ import * as path from 'path';
|
|
|
7
7
|
import { AGENTS, listInstalledMcpsWithScope } from './agents.js';
|
|
8
8
|
import { listInstalledCommandsWithScope } from './commands.js';
|
|
9
9
|
import { listInstalledSkillsWithScope } from './skills.js';
|
|
10
|
-
import {
|
|
10
|
+
import { listOnDiskHooks } from './resource-inventory.js';
|
|
11
11
|
import { listInstalledInstructionsWithScope } from './rules/rules.js';
|
|
12
12
|
import { getEffectiveHome } from './versions.js';
|
|
13
13
|
import { listMcpServerConfigs } from './mcp.js';
|
|
@@ -352,11 +352,14 @@ export function getAgentResources(agentId, options = {}) {
|
|
|
352
352
|
});
|
|
353
353
|
}
|
|
354
354
|
}
|
|
355
|
-
// Hooks
|
|
355
|
+
// Hooks — routed through the resource-inventory chokepoint (RUSH-2238) so
|
|
356
|
+
// inspect/doctor/view share one listing and one (absolute-hooksDir-safe)
|
|
357
|
+
// path resolution.
|
|
356
358
|
const hooks = [];
|
|
357
|
-
for (const
|
|
358
|
-
|
|
359
|
-
|
|
359
|
+
for (const ref of listOnDiskHooks(agentId, { cwd, home })) {
|
|
360
|
+
const hookScope = ref.source;
|
|
361
|
+
if (shouldInclude(hookScope)) {
|
|
362
|
+
hooks.push({ name: ref.name, path: ref.path, scope: hookScope });
|
|
360
363
|
}
|
|
361
364
|
}
|
|
362
365
|
// Workflows
|
|
@@ -21,6 +21,7 @@ export interface ResolvedRunDefaults extends RunDefaults {
|
|
|
21
21
|
sources: {
|
|
22
22
|
mode?: string;
|
|
23
23
|
model?: string;
|
|
24
|
+
effort?: string;
|
|
24
25
|
};
|
|
25
26
|
}
|
|
26
27
|
export interface RunDefaultEntry {
|
|
@@ -30,6 +31,7 @@ export interface RunDefaultEntry {
|
|
|
30
31
|
type RunDefaultsInput = {
|
|
31
32
|
mode?: unknown;
|
|
32
33
|
model?: unknown;
|
|
34
|
+
effort?: unknown;
|
|
33
35
|
};
|
|
34
36
|
export declare function normalizeRunDefaultMode(input: string): Mode;
|
|
35
37
|
export declare function parseRunDefaultSelector(input: string): ParsedRunDefaultSelector;
|
package/dist/lib/run-defaults.js
CHANGED
|
@@ -17,6 +17,7 @@ import { readMeta, updateMeta } from './state.js';
|
|
|
17
17
|
import { getProjectRunConfigs } from './run-config.js';
|
|
18
18
|
import chalk from 'chalk';
|
|
19
19
|
const VERSION_RE = /^(?:\*|latest|(?!.*\.\.)[A-Za-z0-9._+-]{1,64})$/;
|
|
20
|
+
const RUN_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max', 'auto'];
|
|
20
21
|
function isAgentId(value) {
|
|
21
22
|
return value in AGENTS;
|
|
22
23
|
}
|
|
@@ -42,6 +43,12 @@ function normalizeRunDefaults(defaults, selector) {
|
|
|
42
43
|
}
|
|
43
44
|
out.model = defaults.model.trim();
|
|
44
45
|
}
|
|
46
|
+
if (defaults.effort !== undefined) {
|
|
47
|
+
if (typeof defaults.effort !== 'string' || !RUN_EFFORTS.includes(defaults.effort)) {
|
|
48
|
+
throw new Error('Invalid effort in run.defaults.' + selector + ': use one of: ' + RUN_EFFORTS.join(', ') + '.');
|
|
49
|
+
}
|
|
50
|
+
out.effort = defaults.effort;
|
|
51
|
+
}
|
|
45
52
|
return out;
|
|
46
53
|
}
|
|
47
54
|
export function parseRunDefaultSelector(input) {
|
|
@@ -97,6 +104,10 @@ export function resolveRunDefaultsFromConfig(runConfig, agent, version) {
|
|
|
97
104
|
resolved.model = wildcard.model;
|
|
98
105
|
resolved.sources.model = wildcardSelector;
|
|
99
106
|
}
|
|
107
|
+
if (wildcard?.effort) {
|
|
108
|
+
resolved.effort = wildcard.effort;
|
|
109
|
+
resolved.sources.effort = wildcardSelector;
|
|
110
|
+
}
|
|
100
111
|
if (exactSelector && defaults[exactSelector]) {
|
|
101
112
|
const exact = normalizeRunDefaults(defaults[exactSelector], exactSelector);
|
|
102
113
|
if (exact.mode) {
|
|
@@ -107,6 +118,10 @@ export function resolveRunDefaultsFromConfig(runConfig, agent, version) {
|
|
|
107
118
|
resolved.model = exact.model;
|
|
108
119
|
resolved.sources.model = exactSelector;
|
|
109
120
|
}
|
|
121
|
+
if (exact.effort) {
|
|
122
|
+
resolved.effort = exact.effort;
|
|
123
|
+
resolved.sources.effort = exactSelector;
|
|
124
|
+
}
|
|
110
125
|
}
|
|
111
126
|
return resolved;
|
|
112
127
|
}
|
|
@@ -122,6 +137,10 @@ export function resolveRunDefaultsFromConfigs(runConfigs, agent, version) {
|
|
|
122
137
|
resolved.model = next.model;
|
|
123
138
|
resolved.sources.model = next.sources.model;
|
|
124
139
|
}
|
|
140
|
+
if (next.effort) {
|
|
141
|
+
resolved.effort = next.effort;
|
|
142
|
+
resolved.sources.effort = next.sources.effort;
|
|
143
|
+
}
|
|
125
144
|
}
|
|
126
145
|
return resolved;
|
|
127
146
|
}
|
|
@@ -135,6 +154,8 @@ export function formatRunDefaultEntry(entry) {
|
|
|
135
154
|
parts.push(`mode ${chalk.white(entry.defaults.mode)}`);
|
|
136
155
|
if (entry.defaults.model)
|
|
137
156
|
parts.push(`model ${chalk.white(entry.defaults.model)}`);
|
|
157
|
+
if (entry.defaults.effort)
|
|
158
|
+
parts.push('effort ' + chalk.white(entry.defaults.effort));
|
|
138
159
|
return `${chalk.cyan(entry.selector.padEnd(22))} ${parts.join(' ')}`;
|
|
139
160
|
}
|
|
140
161
|
export function listRunDefaults() {
|
|
@@ -149,8 +170,8 @@ export function listRunDefaults() {
|
|
|
149
170
|
export function setRunDefault(selectorInput, defaultsInput) {
|
|
150
171
|
const parsed = parseRunDefaultSelector(selectorInput);
|
|
151
172
|
const defaults = normalizeRunDefaults(defaultsInput, parsed.selector);
|
|
152
|
-
if (!defaults.mode && !defaults.model) {
|
|
153
|
-
throw new Error('Set at least one default: --mode <mode
|
|
173
|
+
if (!defaults.mode && !defaults.model && !defaults.effort) {
|
|
174
|
+
throw new Error('Set at least one default: --mode <mode>, --model <model>, or --effort <effort>.');
|
|
154
175
|
}
|
|
155
176
|
updateMeta((meta) => {
|
|
156
177
|
const run = { ...(meta.run ?? {}) };
|
package/dist/lib/runner.js
CHANGED
|
@@ -31,7 +31,8 @@ import { backgroundSpawnOptions, killTree } from './platform/process.js';
|
|
|
31
31
|
import lockfile from 'proper-lockfile';
|
|
32
32
|
import { ensureLockTarget } from './fs-atomic.js';
|
|
33
33
|
import { walkForFiles } from './fs-walk.js';
|
|
34
|
-
import { getBinaryPath, isVersionInstalled, resolveVersion } from './versions.js';
|
|
34
|
+
import { getBinaryPath, isVersionInstalled, resolveVersion, getVersionHomePath } from './versions.js';
|
|
35
|
+
import { resolveClaudeSetupToken } from './claude-account-token.js';
|
|
35
36
|
import { getConfiguredRunStrategy, resolveRunVersion, resolveAccountVersion, rotationFailoverChain, readinessFromCandidate, formatNoHealthyAccountError, } from './rotate.js';
|
|
36
37
|
import { readAuthHealth, isDeadVerdict } from './auth-health.js';
|
|
37
38
|
import { machineId } from './machine-id.js';
|
|
@@ -537,22 +538,26 @@ export function buildRoutineSpawnEnv(baseEnv, agent, version, timezone, overlayH
|
|
|
537
538
|
if (v !== undefined)
|
|
538
539
|
out[k] = v;
|
|
539
540
|
}
|
|
540
|
-
//
|
|
541
|
-
//
|
|
542
|
-
//
|
|
543
|
-
//
|
|
544
|
-
//
|
|
545
|
-
//
|
|
546
|
-
//
|
|
547
|
-
//
|
|
548
|
-
//
|
|
549
|
-
//
|
|
550
|
-
//
|
|
551
|
-
//
|
|
552
|
-
//
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
541
|
+
// CLAUDE_CODE_OAUTH_TOKEN comes in two flavours, and only one is safe for a
|
|
542
|
+
// routine. KEEP a per-account `claude setup-token` (long-lived, NON-rotating,
|
|
543
|
+
// keyed to this home's own account) that buildExecEnv injected from the reserved
|
|
544
|
+
// `auth` bundle (resolveClaudeSetupToken) — that is the durable cure for the
|
|
545
|
+
// single-use-refresh-token revocation storm: a setup-token never rotates, so a
|
|
546
|
+
// scheduled routine can't land on a sibling home's just-rotated-out credential.
|
|
547
|
+
// STRIP an INHERITED ambient value instead: buildExecEnv spreads process.env
|
|
548
|
+
// (exec.ts) and sanitizeProcessEnv leaves credentials, so a daemon env that
|
|
549
|
+
// happens to carry a shared/rotating CLAUDE_CODE_OAUTH_TOKEN would otherwise make
|
|
550
|
+
// every routine run on that one token — the RUSH-1822 fleet-wide-logout path.
|
|
551
|
+
// Distinguish by value: only the resolved setup-token survives.
|
|
552
|
+
// Authoritative: buildExecEnv injects the setup-token but then spreads the caller
|
|
553
|
+
// env over it, so an ambient CLAUDE_CODE_OAUTH_TOKEN would win — re-assert here.
|
|
554
|
+
const setupToken = agent === 'claude' && version
|
|
555
|
+
? resolveClaudeSetupToken(getVersionHomePath('claude', version))
|
|
556
|
+
: null;
|
|
557
|
+
if (setupToken)
|
|
558
|
+
out.CLAUDE_CODE_OAUTH_TOKEN = setupToken;
|
|
559
|
+
else
|
|
560
|
+
delete out.CLAUDE_CODE_OAUTH_TOKEN;
|
|
556
561
|
if (agent === 'cursor' && overlayHome) {
|
|
557
562
|
// prepareJobHome links this host's Cursor auth file here. Pin XDG_CONFIG_HOME
|
|
558
563
|
// to the overlay so an ambient value cannot bypass the routine sandbox.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -3,9 +3,21 @@
|
|
|
3
3
|
<plist version="1.0">
|
|
4
4
|
<dict>
|
|
5
5
|
<key>files</key>
|
|
6
|
-
<dict
|
|
6
|
+
<dict>
|
|
7
|
+
<key>Resources/AppIcon.icns</key>
|
|
8
|
+
<data>
|
|
9
|
+
DFq5H08EkhgWIC3UvGMR9B58BZw=
|
|
10
|
+
</data>
|
|
11
|
+
</dict>
|
|
7
12
|
<key>files2</key>
|
|
8
13
|
<dict>
|
|
14
|
+
<key>Resources/AppIcon.icns</key>
|
|
15
|
+
<dict>
|
|
16
|
+
<key>hash2</key>
|
|
17
|
+
<data>
|
|
18
|
+
mBSjM6jlvN7J1jQowsvqTl7CHM0pur0e6qsHMuzk5k0=
|
|
19
|
+
</data>
|
|
20
|
+
</dict>
|
|
9
21
|
<key>embedded.provisionprofile</key>
|
|
10
22
|
<dict>
|
|
11
23
|
<key>hash2</key>
|