@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,95 @@
|
|
|
1
|
+
import { AGENTS } from '../agents.js';
|
|
2
|
+
import { isSelfHost } from '../devices/self-host.js';
|
|
3
|
+
import { nativeResume } from '../exec.js';
|
|
4
|
+
import { machineId, normalizeHost } from '../machine-id.js';
|
|
5
|
+
import { collectRunCandidates, formatNoHealthyAccountError, pickBalancedCandidate, readinessFromCandidate, } from '../rotate.js';
|
|
6
|
+
export class SessionRecoveryError extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'SessionRecoveryError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
/** Canonical origin-device label for every recovery consumer. */
|
|
13
|
+
export function sessionOriginDevice(session, self = machineId()) {
|
|
14
|
+
return normalizeHost(session.machine ?? self);
|
|
15
|
+
}
|
|
16
|
+
/** The peer that must execute recovery, or undefined when this is the origin. */
|
|
17
|
+
export function sessionRecoveryPeer(session, selfCheck = isSelfHost) {
|
|
18
|
+
if (!session.machine || selfCheck(session.machine))
|
|
19
|
+
return undefined;
|
|
20
|
+
return normalizeHost(session.machine);
|
|
21
|
+
}
|
|
22
|
+
/** Whether an explicit placement names the session's origin device. */
|
|
23
|
+
export function sessionRecoveryDestinationMatches(session, requestedHost, self = machineId()) {
|
|
24
|
+
const requested = normalizeHost(requestedHost.split('@').pop() || requestedHost);
|
|
25
|
+
return requested === sessionOriginDevice(session, self);
|
|
26
|
+
}
|
|
27
|
+
function runnableSessionAgent(session) {
|
|
28
|
+
if (!(session.agent in AGENTS)) {
|
|
29
|
+
throw new SessionRecoveryError(`Session ${session.shortId} belongs to ${session.agent}, which is indexed but cannot be launched by agents run.`);
|
|
30
|
+
}
|
|
31
|
+
return session.agent;
|
|
32
|
+
}
|
|
33
|
+
function sourceReason(session, candidates) {
|
|
34
|
+
if (!session.version)
|
|
35
|
+
return 'the origin version was not recorded';
|
|
36
|
+
const source = candidates.find((candidate) => candidate.version === session.version);
|
|
37
|
+
if (!source)
|
|
38
|
+
return `origin ${session.agent}@${session.version} is not installed`;
|
|
39
|
+
const readiness = readinessFromCandidate(source);
|
|
40
|
+
return readiness.ready
|
|
41
|
+
? `origin ${session.agent}@${session.version} has no native resume form`
|
|
42
|
+
: `origin ${session.agent}@${session.version} is ${readiness.reason}`;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Decide how a durable session resumes on the device that owns it.
|
|
46
|
+
*
|
|
47
|
+
* Native resume is legal only in the exact origin version's isolated home and
|
|
48
|
+
* only while that account is healthy. Every other successful path stays on the
|
|
49
|
+
* same harness and uses `/continue`, whose indexed transcript reader can reach
|
|
50
|
+
* retained version trash. No healthy same-harness account is a loud failure.
|
|
51
|
+
*/
|
|
52
|
+
export function resolveSessionRecoveryFromCandidates(session, candidates, supportsNative = nativeResume) {
|
|
53
|
+
const agent = runnableSessionAgent(session);
|
|
54
|
+
const device = sessionOriginDevice(session);
|
|
55
|
+
const source = session.version
|
|
56
|
+
? candidates.find((candidate) => candidate.version === session.version)
|
|
57
|
+
: undefined;
|
|
58
|
+
const sourceReady = source ? readinessFromCandidate(source).ready : false;
|
|
59
|
+
// An exact healthy origin is deterministic: preserve its isolated home. If
|
|
60
|
+
// native resume is unavailable for that harness, /continue still launches in
|
|
61
|
+
// that same healthy home. Only an unusable/missing origin enters balanced
|
|
62
|
+
// account selection.
|
|
63
|
+
const selection = sourceReady
|
|
64
|
+
? { picked: source }
|
|
65
|
+
: pickBalancedCandidate(candidates);
|
|
66
|
+
if (!selection) {
|
|
67
|
+
const detail = formatNoHealthyAccountError(agent, 'balanced', candidates);
|
|
68
|
+
throw new SessionRecoveryError(`Cannot recover session ${session.shortId} on ${device}; origin ${agent}@${session.version ?? 'unknown'}. ${detail}`);
|
|
69
|
+
}
|
|
70
|
+
const version = selection.picked.version;
|
|
71
|
+
if (session.version === version && supportsNative(agent, version)) {
|
|
72
|
+
return {
|
|
73
|
+
mode: 'native',
|
|
74
|
+
agent,
|
|
75
|
+
version,
|
|
76
|
+
reason: `origin ${agent}@${version} is installed and healthy`,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
mode: 'continue',
|
|
81
|
+
agent,
|
|
82
|
+
version,
|
|
83
|
+
reason: `${sourceReason(session, candidates)}; continuing with healthy ${agent}@${version}`,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
export async function resolveSessionRecovery(session) {
|
|
87
|
+
const agent = runnableSessionAgent(session);
|
|
88
|
+
return resolveSessionRecoveryFromCandidates(session, await collectRunCandidates(agent));
|
|
89
|
+
}
|
|
90
|
+
/** Stable self-command used by focus, resume, and attach. The owning device runs
|
|
91
|
+
* the recovery resolver above; callers must not native-resume another version's
|
|
92
|
+
* isolated home themselves. */
|
|
93
|
+
export function sessionRecoveryRunArgs(session) {
|
|
94
|
+
return ['run', 'auto', '--resume', session.id, '--interactive'];
|
|
95
|
+
}
|
package/dist/lib/shims.d.ts
CHANGED
|
@@ -77,7 +77,7 @@ export interface ConflictInfo {
|
|
|
77
77
|
* top-level entry add/remove — deep edits to plugin contents won't
|
|
78
78
|
* trigger auto-resync, run `agents sync` for that.
|
|
79
79
|
*/
|
|
80
|
-
export declare const SHIM_SCHEMA_VERSION =
|
|
80
|
+
export declare const SHIM_SCHEMA_VERSION = 29;
|
|
81
81
|
/**
|
|
82
82
|
* Generate the full bash shim script for the given agent. The returned string
|
|
83
83
|
* is written to ~/.agents/shims/{cliCommand} and made executable.
|
|
@@ -160,7 +160,7 @@ export declare function removeShim(agent: AgentId): boolean;
|
|
|
160
160
|
* the versioned home (installer run with GROK_HOME set, or grok
|
|
161
161
|
* self-update under the shim).
|
|
162
162
|
*/
|
|
163
|
-
export declare const VERSIONED_ALIAS_SCHEMA_VERSION =
|
|
163
|
+
export declare const VERSIONED_ALIAS_SCHEMA_VERSION = 15;
|
|
164
164
|
/**
|
|
165
165
|
* Agents whose config directory can be relocated by an environment variable
|
|
166
166
|
* (the per-agent `managedEnv` block in `generateVersionedAliasScript` below).
|
package/dist/lib/shims.js
CHANGED
|
@@ -223,7 +223,7 @@ async function promptConflictStrategy(conflictInfos) {
|
|
|
223
223
|
// The old dispatcher checked only the global dir, so a pinned grok that
|
|
224
224
|
// installed into the versioned home fell through to the "not installed"
|
|
225
225
|
// error.
|
|
226
|
-
export const SHIM_SCHEMA_VERSION =
|
|
226
|
+
export const SHIM_SCHEMA_VERSION = 29;
|
|
227
227
|
/** Internal marker string used to embed the schema version in shim scripts. */
|
|
228
228
|
const SHIM_VERSION_MARKER = 'agents-shim-version:';
|
|
229
229
|
function shellQuote(value) {
|
|
@@ -299,7 +299,18 @@ export OPENCODE_CONFIG_DIR="$VERSION_DIR/home/.config/opencode"
|
|
|
299
299
|
# mcp.json, sessions, skills, hooks). Point it at the versioned home.
|
|
300
300
|
export KIMI_CODE_HOME="$VERSION_DIR/home/${configDirName}"
|
|
301
301
|
`
|
|
302
|
-
: ''
|
|
302
|
+
: agent === 'muse'
|
|
303
|
+
? `
|
|
304
|
+
# Muse Code has no MUSE_CONFIG_DIR. It resolves config via XDG:
|
|
305
|
+
# $XDG_CONFIG_HOME/muse (settings, skills, hooks, auth)
|
|
306
|
+
# $XDG_DATA_HOME/muse (sessions, plugins)
|
|
307
|
+
# Pin XDG into the version home so managed runs never walk the adopt-time
|
|
308
|
+
# ~/.config/muse -> version-home symlink — Muse refuses agent-definition
|
|
309
|
+
# sources that are SymlinkOrReparse (exit 1). Same idea as CLAUDE_CONFIG_DIR.
|
|
310
|
+
export XDG_CONFIG_HOME="$VERSION_DIR/home/.config"
|
|
311
|
+
export XDG_DATA_HOME="$VERSION_DIR/home/.local/share"
|
|
312
|
+
`
|
|
313
|
+
: '';
|
|
303
314
|
const launchArgs = agent === 'codex' ? ` ${codexShimLaunchArgs()}` : '';
|
|
304
315
|
return `#!/bin/bash
|
|
305
316
|
# Auto-generated by agents-cli - do not edit
|
|
@@ -871,7 +882,7 @@ export function removeShim(agent) {
|
|
|
871
882
|
* the versioned home (installer run with GROK_HOME set, or grok
|
|
872
883
|
* self-update under the shim).
|
|
873
884
|
*/
|
|
874
|
-
export const VERSIONED_ALIAS_SCHEMA_VERSION =
|
|
885
|
+
export const VERSIONED_ALIAS_SCHEMA_VERSION = 15;
|
|
875
886
|
/** Internal marker string used to embed the schema version in versioned alias scripts. */
|
|
876
887
|
const VERSIONED_ALIAS_VERSION_MARKER = 'agents-versioned-alias-version:';
|
|
877
888
|
// The version string is interpolated into a generated bash script and into
|
|
@@ -898,7 +909,7 @@ function assertSafeVersion(version) {
|
|
|
898
909
|
* KEEP IN SYNC with the `managedEnv` switch in `generateVersionedAliasScript`.
|
|
899
910
|
* The colocated test `shims.isolation-capability.test.ts` enforces this.
|
|
900
911
|
*/
|
|
901
|
-
export const CONFIG_ENV_ISOLATED_AGENTS = ['claude', 'codex', 'copilot', 'grok', 'kimi', 'opencode'];
|
|
912
|
+
export const CONFIG_ENV_ISOLATED_AGENTS = ['claude', 'codex', 'copilot', 'grok', 'kimi', 'opencode', 'muse'];
|
|
902
913
|
/**
|
|
903
914
|
* Whether an agent supports a clean `--isolated` install — i.e. its config
|
|
904
915
|
* location can be redirected by an env var so the isolated copy stays fully
|
|
@@ -956,7 +967,15 @@ export OPENCODE_CONFIG_DIR="$HOME/.agents/.history/versions/${agent}/${version}/
|
|
|
956
967
|
# mcp.json, sessions, skills, hooks). Point direct aliases at the versioned home.
|
|
957
968
|
export KIMI_CODE_HOME="$HOME/.agents/.history/versions/${agent}/${version}/home/${configDirName}"
|
|
958
969
|
`
|
|
959
|
-
: ''
|
|
970
|
+
: agent === 'muse'
|
|
971
|
+
? `
|
|
972
|
+
# Muse Code: no dedicated config env var. Pin XDG so config/sessions live under
|
|
973
|
+
# the version home as real directories (not via the adopt symlink at
|
|
974
|
+
# ~/.config/muse, which Muse rejects with SymlinkOrReparse).
|
|
975
|
+
export XDG_CONFIG_HOME="$HOME/.agents/.history/versions/${agent}/${version}/home/.config"
|
|
976
|
+
export XDG_DATA_HOME="$HOME/.agents/.history/versions/${agent}/${version}/home/.local/share"
|
|
977
|
+
`
|
|
978
|
+
: '';
|
|
960
979
|
const launchArgs = agent === 'codex' ? ` ${codexShimLaunchArgs()}` : '';
|
|
961
980
|
// Resolve the binary the same way the main shim does (see generateShimScript).
|
|
962
981
|
// Grok and Droid do NOT ship into node_modules/.bin — Grok downloads a native
|
|
@@ -51,6 +51,7 @@ export declare const loadFork: ModuleLoader;
|
|
|
51
51
|
export declare const loadDefaults: ModuleLoader;
|
|
52
52
|
export declare const loadSet: ModuleLoader;
|
|
53
53
|
export declare const loadModels: ModuleLoader;
|
|
54
|
+
export declare const loadModes: ModuleLoader;
|
|
54
55
|
export declare const loadPrune: ModuleLoader;
|
|
55
56
|
export declare const loadTrash: ModuleLoader;
|
|
56
57
|
export declare const loadRestore: ModuleLoader;
|
|
@@ -29,6 +29,7 @@ export const loadFork = async () => (await import('../../commands/fork.js')).reg
|
|
|
29
29
|
export const loadDefaults = async () => (await import('../../commands/defaults.js')).registerDefaultsCommands;
|
|
30
30
|
export const loadSet = async () => (await import('../../commands/set.js')).registerSetCommand;
|
|
31
31
|
export const loadModels = async () => (await import('../../commands/models.js')).registerModelsCommand;
|
|
32
|
+
export const loadModes = async () => (await import('../../commands/modes.js')).registerModesCommand;
|
|
32
33
|
export const loadPrune = async () => (await import('../../commands/prune.js')).registerPruneCommand;
|
|
33
34
|
export const loadTrash = async () => (await import('../../commands/trash.js')).registerTrashCommands;
|
|
34
35
|
export const loadRestore = async () => (await import('../../commands/trash.js')).registerRestoreCommand;
|
|
@@ -154,6 +155,7 @@ export const COMMAND_LOADERS = {
|
|
|
154
155
|
defaults: [loadDefaults],
|
|
155
156
|
set: [loadSet],
|
|
156
157
|
models: [loadModels],
|
|
158
|
+
modes: [loadModes],
|
|
157
159
|
trash: [loadTrash],
|
|
158
160
|
restore: [loadRestore],
|
|
159
161
|
doctor: [loadDoctor],
|
|
@@ -68,6 +68,11 @@ export interface RunUmbrellaArgs {
|
|
|
68
68
|
yes: boolean;
|
|
69
69
|
/** Secrets passphrase, if available (env var or prompt). Undefined => skip secrets. */
|
|
70
70
|
passphrase?: string;
|
|
71
|
+
/**
|
|
72
|
+
* Suppress human progress from the reconcile stage (`refresh`). Required so
|
|
73
|
+
* `agents sync --json` / fleet fan-out leave stdout as a single JSON object.
|
|
74
|
+
*/
|
|
75
|
+
quiet?: boolean;
|
|
71
76
|
}
|
|
72
77
|
/**
|
|
73
78
|
* Execute the planned stages in order: repos -> secrets -> reconcile.
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
import { pullRepo } from './git.js';
|
|
19
19
|
import { getUserAgentsDir, getEnabledExtraRepos } from './state.js';
|
|
20
20
|
import { listRemoteBundles, pullBundle } from './secrets/sync.js';
|
|
21
|
+
import { SYNC_PASSPHRASE_ENV } from './secrets/sync-passphrase.js';
|
|
21
22
|
/**
|
|
22
23
|
* Decide which stages run. Pure — no I/O. Semantics:
|
|
23
24
|
* bare (no flags) fetch repos, then reconcile
|
|
@@ -52,7 +53,7 @@ export function planUmbrellaStages(f) {
|
|
|
52
53
|
* reconcile — `agents sync` should make as much current as it can in one pass.
|
|
53
54
|
*/
|
|
54
55
|
export async function runUmbrellaSync(args) {
|
|
55
|
-
const { flags, log, yes, passphrase } = args;
|
|
56
|
+
const { flags, log, yes, passphrase, quiet = false } = args;
|
|
56
57
|
const plan = planUmbrellaStages(flags);
|
|
57
58
|
const result = { plan, reconciled: false };
|
|
58
59
|
if (plan.fetchRepos) {
|
|
@@ -79,10 +80,10 @@ export async function runUmbrellaSync(args) {
|
|
|
79
80
|
result.secrets = {
|
|
80
81
|
pulled: 0,
|
|
81
82
|
skipped: true,
|
|
82
|
-
reason:
|
|
83
|
+
reason: `no passphrase — set ${SYNC_PASSPHRASE_ENV} or run \`agents login\` (#366)`,
|
|
83
84
|
errors: [],
|
|
84
85
|
};
|
|
85
|
-
log(
|
|
86
|
+
log(`secrets: skipped (no passphrase — set ${SYNC_PASSPHRASE_ENV})`);
|
|
86
87
|
}
|
|
87
88
|
else {
|
|
88
89
|
let pulled = 0;
|
|
@@ -108,7 +109,7 @@ export async function runUmbrellaSync(args) {
|
|
|
108
109
|
}
|
|
109
110
|
if (plan.reconcile) {
|
|
110
111
|
const { refresh } = await import('./refresh.js');
|
|
111
|
-
await refresh({ skipPrompts: yes });
|
|
112
|
+
await refresh({ skipPrompts: yes, quiet });
|
|
112
113
|
result.reconciled = true;
|
|
113
114
|
// Keep already-registered devices' reachability current, and surface newly
|
|
114
115
|
// appeared tailnet nodes as "pending" for the menu-bar Register/Ignore gate
|
|
@@ -114,6 +114,8 @@ export interface TmuxClient {
|
|
|
114
114
|
export declare function listClients(socket?: string): Promise<TmuxClient[]>;
|
|
115
115
|
/** A dead pane's exit status, read from tmux while the pane lingers under remain-on-exit. */
|
|
116
116
|
export interface PaneExit {
|
|
117
|
+
/** False when the pane/socket no longer exists or tmux could not query it. */
|
|
118
|
+
found: boolean;
|
|
117
119
|
/** True once the process that ran in the pane has exited (pane is dead). */
|
|
118
120
|
dead: boolean;
|
|
119
121
|
/** Exit status of the dead pane's process, when tmux reports it. */
|
|
@@ -122,8 +124,8 @@ export interface PaneExit {
|
|
|
122
124
|
/**
|
|
123
125
|
* Read whether a pane's process has exited and, if so, its exit status. Used by
|
|
124
126
|
* the spawn-wrap path to recover the wrapped agent's exit code after the attach
|
|
125
|
-
* client returns.
|
|
126
|
-
*
|
|
127
|
+
* client returns. `found: false` distinguishes a missing pane from a living one;
|
|
128
|
+
* focus must recover the former instead of attaching a retained/stale target.
|
|
127
129
|
*/
|
|
128
130
|
export declare function paneExitStatus(pane: string, socket?: string): Promise<PaneExit>;
|
|
129
131
|
/**
|
package/dist/lib/tmux/session.js
CHANGED
|
@@ -248,8 +248,8 @@ export async function listClients(socket) {
|
|
|
248
248
|
/**
|
|
249
249
|
* Read whether a pane's process has exited and, if so, its exit status. Used by
|
|
250
250
|
* the spawn-wrap path to recover the wrapped agent's exit code after the attach
|
|
251
|
-
* client returns.
|
|
252
|
-
*
|
|
251
|
+
* client returns. `found: false` distinguishes a missing pane from a living one;
|
|
252
|
+
* focus must recover the former instead of attaching a retained/stale target.
|
|
253
253
|
*/
|
|
254
254
|
export async function paneExitStatus(pane, socket) {
|
|
255
255
|
let res;
|
|
@@ -261,13 +261,13 @@ export async function paneExitStatus(pane, socket) {
|
|
|
261
261
|
});
|
|
262
262
|
}
|
|
263
263
|
catch {
|
|
264
|
-
return { dead: false };
|
|
264
|
+
return { found: false, dead: false };
|
|
265
265
|
}
|
|
266
266
|
if (res.code !== 0)
|
|
267
|
-
return { dead: false };
|
|
267
|
+
return { found: false, dead: false };
|
|
268
268
|
const [deadRaw, statusRaw] = res.stdout.trim().split(/\s+/);
|
|
269
269
|
const status = statusRaw !== undefined && statusRaw !== '' ? parseInt(statusRaw, 10) : undefined;
|
|
270
|
-
return { dead: deadRaw === '1', status: Number.isFinite(status) ? status : undefined };
|
|
270
|
+
return { found: true, dead: deadRaw === '1', status: Number.isFinite(status) ? status : undefined };
|
|
271
271
|
}
|
|
272
272
|
/**
|
|
273
273
|
* Bind a per-session hook. Used by the spawn-wrap path to install a `pane-died`
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { FeedBroadcastConfig } from './feed-broadcast.js';
|
|
|
11
11
|
export type AgentId = 'claude' | 'codex' | 'gemini' | 'cursor' | 'opencode' | 'openclaw' | 'copilot' | 'amp' | 'kiro' | 'goose' | 'antigravity' | 'grok' | 'kimi' | 'droid' | 'hermes' | 'pi' | 'muse';
|
|
12
12
|
/** How `agents run <agent>` chooses an installed version when none is pinned. */
|
|
13
13
|
export type RunStrategy = 'pinned' | 'available' | 'balanced';
|
|
14
|
+
export type RunEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'auto';
|
|
14
15
|
/**
|
|
15
16
|
* Reserved `<agent>` keyword for `agents run auto` — full-auto dispatch:
|
|
16
17
|
* host (14d launch affinity) → harness (best-account headroom, weighted) →
|
|
@@ -36,6 +37,7 @@ export interface AgentRunConfig {
|
|
|
36
37
|
export interface RunDefaults {
|
|
37
38
|
mode?: Mode;
|
|
38
39
|
model?: string;
|
|
40
|
+
effort?: RunEffort;
|
|
39
41
|
}
|
|
40
42
|
/** `run:` section in agents.yaml. Agent keys keep strategy; `defaults` stores selector rules. */
|
|
41
43
|
export type RunConfig = Partial<Record<AgentId, AgentRunConfig>> & {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@phnx-labs/agents-cli",
|
|
3
|
-
"version": "1.22.
|
|
3
|
+
"version": "1.22.24",
|
|
4
4
|
"description": "One CLI for all your AI coding agents - versions, config, cloud dispatch, sessions, and teams (now with first-class Grok Build CLI support)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|