@phnx-labs/agents-cli 1.22.117 → 1.22.118
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 +235 -0
- package/dist/bootstrap.js +4 -11
- package/dist/commands/browser.d.ts +52 -70
- package/dist/commands/browser.js +192 -3562
- package/dist/commands/daemon.d.ts +39 -2
- package/dist/commands/daemon.js +72 -73
- package/dist/commands/events.js +1 -1
- package/dist/commands/exec.js +53 -1
- package/dist/commands/repo.js +13 -49
- package/dist/commands/route.js +5 -5
- package/dist/commands/routines.js +39 -12
- package/dist/commands/sessions-render.d.ts +1 -1
- package/dist/commands/sessions-render.js +0 -1
- package/dist/commands/sessions.test-fixture.d.ts +0 -1
- package/dist/commands/sessions.test-fixture.js +0 -37
- package/dist/commands/setup-browser.d.ts +17 -12
- package/dist/commands/setup-browser.js +52 -87
- package/dist/commands/setup-preferences.d.ts +0 -17
- package/dist/commands/setup-preferences.js +18 -49
- package/dist/commands/setup.js +9 -9
- package/dist/commands/ssh.js +10 -1
- package/dist/commands/sync.js +6 -44
- package/dist/commands/teams.js +0 -1
- package/dist/commands/update.d.ts +19 -0
- package/dist/commands/update.js +34 -6
- package/dist/commands/view.d.ts +12 -1
- package/dist/commands/view.js +47 -2
- package/dist/index.js +107 -26
- package/dist/lib/account-capabilities.js +0 -2
- package/dist/lib/account-catalog.d.ts +38 -0
- package/dist/lib/account-catalog.js +110 -26
- package/dist/lib/account-provider-registry.js +1 -1
- package/dist/lib/account-registry.d.ts +1 -1
- package/dist/lib/account-registry.js +36 -2
- package/dist/lib/accounting/rotate.js +22 -8
- package/dist/lib/accounting/usage-ingest.d.ts +6 -1
- package/dist/lib/accounting/usage-ingest.js +115 -45
- package/dist/lib/accounting/usage-sync.d.ts +134 -31
- package/dist/lib/accounting/usage-sync.js +227 -66
- package/dist/lib/accounting/usage.d.ts +16 -3
- package/dist/lib/accounting/usage.js +26 -8
- package/dist/lib/accounts/slots.d.ts +8 -0
- package/dist/lib/accounts/slots.js +17 -0
- package/dist/lib/add-dir.js +0 -1
- package/dist/lib/agent-cli-commands.js +0 -1
- package/dist/lib/agent-spec/agents.d.ts +6 -7
- package/dist/lib/agent-spec/agents.js +6 -60
- package/dist/lib/auth-health.d.ts +69 -1
- package/dist/lib/auth-health.js +133 -4
- package/dist/lib/browser/context.d.ts +82 -0
- package/dist/lib/browser/context.js +88 -0
- package/dist/lib/browser/paths.d.ts +25 -0
- package/dist/lib/browser/paths.js +51 -0
- package/dist/lib/browser/record.d.ts +38 -0
- package/dist/lib/browser/record.js +57 -0
- package/dist/lib/browser/sessions-list.js +1 -2
- package/dist/lib/browser-client.d.ts +158 -0
- package/dist/lib/browser-client.js +234 -0
- package/dist/lib/channels/owner-sink.d.ts +1 -18
- package/dist/lib/channels/owner-sink.js +29 -82
- package/dist/lib/channels/providers/rush.d.ts +7 -7
- package/dist/lib/channels/providers/rush.js +127 -57
- package/dist/lib/claude-statusline.d.ts +1 -1
- package/dist/lib/claude-statusline.js +15 -3
- package/dist/lib/commands.js +1 -1
- package/dist/lib/crabbox/lease.js +1 -1
- package/dist/lib/crabbox/runtimes.js +1 -3
- package/dist/lib/daemon/account-state-daemon-service.js +1 -0
- package/dist/lib/daemon/auth-sync-service.d.ts +21 -18
- package/dist/lib/daemon/auth-sync-service.js +37 -43
- package/dist/lib/daemon/daemon.d.ts +25 -14
- package/dist/lib/daemon/daemon.js +92 -154
- package/dist/lib/daemon/runner.d.ts +2 -2
- package/dist/lib/daemon/runner.js +32 -9
- package/dist/lib/daemon/self-update-service.d.ts +35 -34
- package/dist/lib/daemon/self-update-service.js +40 -36
- package/dist/lib/daemon/service.d.ts +12 -8
- package/dist/lib/daemon/supervisor.d.ts +65 -54
- package/dist/lib/daemon/supervisor.js +136 -171
- package/dist/lib/daemon/testdata/process-view-start.js +5 -2
- package/dist/lib/daemon/usage-sync-service.d.ts +21 -30
- package/dist/lib/daemon/usage-sync-service.js +46 -78
- package/dist/lib/daemon-health.d.ts +22 -5
- package/dist/lib/daemon-health.js +47 -3
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +0 -10
- package/dist/lib/daemon-ticks.js +4 -2
- package/dist/lib/devices/doctor-findings.js +8 -11
- package/dist/lib/devices/harness-inventory.js +14 -5
- package/dist/lib/exec-account-home.js +5 -0
- package/dist/lib/exec.js +0 -11
- package/dist/lib/feed/events.js +0 -1
- package/dist/lib/feed/tool-activity.js +5 -2
- package/dist/lib/fleet-shared-state.d.ts +45 -0
- package/dist/lib/fleet-shared-state.js +78 -9
- package/dist/lib/fs-atomic.js +25 -0
- package/dist/lib/harness-auth-capabilities.js +0 -1
- package/dist/lib/helper-versions.js +1 -1
- package/dist/lib/hooks/cache.d.ts +7 -0
- package/dist/lib/hooks/cache.js +27 -2
- package/dist/lib/hooks/install.js +7 -1
- package/dist/lib/hosts/ready.d.ts +38 -8
- package/dist/lib/hosts/ready.js +62 -14
- package/dist/lib/installations/active-check.d.ts +27 -0
- package/dist/lib/installations/active-check.js +61 -0
- package/dist/lib/installations/migrate.js +6 -3
- package/dist/lib/installations/shims.js +9 -7
- package/dist/lib/installations/update.js +21 -15
- package/dist/lib/installations/versions.js +12 -1
- package/dist/lib/manifest.js +1 -1
- package/dist/lib/models.js +0 -2
- package/dist/lib/open-url.js +28 -54
- package/dist/lib/profiles.js +0 -2
- package/dist/lib/refresh.js +1 -1
- package/dist/lib/routine-readiness.d.ts +35 -0
- package/dist/lib/routine-readiness.js +74 -16
- package/dist/lib/rules/compile.js +6 -0
- package/dist/lib/sandbox.js +0 -2
- package/dist/lib/secrets-policy.d.ts +89 -11
- package/dist/lib/secrets-policy.js +175 -28
- package/dist/lib/session/db.d.ts +1 -1
- package/dist/lib/session/db.js +65 -18
- package/dist/lib/session/discover.js +1 -283
- package/dist/lib/session/mirror.d.ts +4 -3
- package/dist/lib/session/mirror.js +4 -3
- package/dist/lib/session/parse.d.ts +0 -2
- package/dist/lib/session/parse.js +1 -138
- package/dist/lib/session/throughput.d.ts +1 -3
- package/dist/lib/session/throughput.js +0 -20
- package/dist/lib/session/types.d.ts +2 -2
- package/dist/lib/session/types.js +2 -2
- package/dist/lib/sessions-client.d.ts +60 -1
- package/dist/lib/sessions-client.js +227 -4
- package/dist/lib/setup-tool-status.js +5 -10
- package/dist/lib/signin-badge.d.ts +3 -2
- package/dist/lib/signin-badge.js +6 -3
- package/dist/lib/smart-launch.js +4 -1
- package/dist/lib/staleness/detectors/commands.d.ts +1 -1
- package/dist/lib/staleness/detectors/hooks.d.ts +1 -1
- package/dist/lib/staleness/detectors/mcp.d.ts +1 -1
- package/dist/lib/staleness/detectors/permissions.d.ts +1 -1
- package/dist/lib/staleness/detectors/plugins.d.ts +1 -1
- package/dist/lib/staleness/detectors/rules.d.ts +1 -1
- package/dist/lib/staleness/detectors/skills.d.ts +1 -1
- package/dist/lib/staleness/detectors/subagents.d.ts +1 -1
- package/dist/lib/staleness/detectors/workflows.d.ts +1 -1
- package/dist/lib/staleness/writers/commands.d.ts +1 -1
- package/dist/lib/staleness/writers/hooks.d.ts +1 -1
- package/dist/lib/staleness/writers/mcp.d.ts +1 -1
- package/dist/lib/staleness/writers/permissions.d.ts +1 -1
- package/dist/lib/staleness/writers/plugins.d.ts +1 -1
- package/dist/lib/staleness/writers/rules.d.ts +1 -1
- package/dist/lib/staleness/writers/skills.d.ts +1 -1
- package/dist/lib/staleness/writers/sources.js +5 -0
- package/dist/lib/staleness/writers/subagents.d.ts +1 -1
- package/dist/lib/staleness/writers/workflows.d.ts +1 -1
- package/dist/lib/state.d.ts +6 -4
- package/dist/lib/state.js +7 -17
- package/dist/lib/teams/parsers.d.ts +1 -1
- package/dist/lib/teams/parsers.js +1 -136
- package/dist/lib/teams/placement-probe.js +50 -15
- package/dist/lib/teams/scheduler.d.ts +7 -0
- package/dist/lib/types.d.ts +10 -1
- package/dist/lib/types.js +1 -1
- package/dist/lib/view-types.d.ts +32 -0
- package/dist/lib/watchdog/read.js +0 -1
- package/dist/lib/watchdog/rotate.js +1 -2
- package/dist/lib/watchdog/runner.js +2 -2
- package/dist/lib/watchdog/watchdog.d.ts +1 -1
- package/dist/lib/watchdog/watchdogTail.js +0 -31
- package/package.json +1 -1
- package/scripts/postinstall.js +8 -8
- package/dist/browser.d.ts +0 -2
- package/dist/browser.js +0 -17
- package/dist/commands/browser-picker.d.ts +0 -18
- package/dist/commands/browser-picker.js +0 -97
- package/dist/lib/browser/arc-discovery.d.ts +0 -52
- package/dist/lib/browser/arc-discovery.js +0 -197
- package/dist/lib/browser/arc-dom.d.ts +0 -14
- package/dist/lib/browser/arc-dom.js +0 -121
- package/dist/lib/browser/caller-identity.d.ts +0 -40
- package/dist/lib/browser/caller-identity.js +0 -175
- package/dist/lib/browser/cdp.d.ts +0 -51
- package/dist/lib/browser/cdp.js +0 -254
- package/dist/lib/browser/chrome.d.ts +0 -141
- package/dist/lib/browser/chrome.js +0 -704
- package/dist/lib/browser/chromium-discovery.d.ts +0 -28
- package/dist/lib/browser/chromium-discovery.js +0 -96
- package/dist/lib/browser/devices.d.ts +0 -34
- package/dist/lib/browser/devices.js +0 -61
- package/dist/lib/browser/domain-skills.d.ts +0 -71
- package/dist/lib/browser/domain-skills.js +0 -195
- package/dist/lib/browser/drivers/arc.d.ts +0 -40
- package/dist/lib/browser/drivers/arc.js +0 -276
- package/dist/lib/browser/drivers/firefox.d.ts +0 -99
- package/dist/lib/browser/drivers/firefox.js +0 -377
- package/dist/lib/browser/drivers/local.d.ts +0 -55
- package/dist/lib/browser/drivers/local.js +0 -266
- package/dist/lib/browser/drivers/ssh.d.ts +0 -120
- package/dist/lib/browser/drivers/ssh.js +0 -467
- package/dist/lib/browser/editor.d.ts +0 -3
- package/dist/lib/browser/editor.js +0 -50
- package/dist/lib/browser/ffmpeg.d.ts +0 -12
- package/dist/lib/browser/ffmpeg.js +0 -184
- package/dist/lib/browser/firefox-discovery.d.ts +0 -69
- package/dist/lib/browser/firefox-discovery.js +0 -162
- package/dist/lib/browser/har.d.ts +0 -85
- package/dist/lib/browser/har.js +0 -77
- package/dist/lib/browser/hygiene.d.ts +0 -97
- package/dist/lib/browser/hygiene.js +0 -153
- package/dist/lib/browser/index.d.ts +0 -5
- package/dist/lib/browser/index.js +0 -5
- package/dist/lib/browser/input.d.ts +0 -7
- package/dist/lib/browser/input.js +0 -92
- package/dist/lib/browser/ipc.d.ts +0 -204
- package/dist/lib/browser/ipc.js +0 -1453
- package/dist/lib/browser/login-detection.d.ts +0 -87
- package/dist/lib/browser/login-detection.js +0 -274
- package/dist/lib/browser/profiles.d.ts +0 -422
- package/dist/lib/browser/profiles.js +0 -1157
- package/dist/lib/browser/refs.d.ts +0 -89
- package/dist/lib/browser/refs.js +0 -191
- package/dist/lib/browser/registry.d.ts +0 -70
- package/dist/lib/browser/registry.js +0 -252
- package/dist/lib/browser/remote-control.d.ts +0 -59
- package/dist/lib/browser/remote-control.js +0 -85
- package/dist/lib/browser/resolve-target.d.ts +0 -66
- package/dist/lib/browser/resolve-target.js +0 -264
- package/dist/lib/browser/runtime-state.d.ts +0 -291
- package/dist/lib/browser/runtime-state.js +0 -584
- package/dist/lib/browser/secret-ref.d.ts +0 -10
- package/dist/lib/browser/secret-ref.js +0 -14
- package/dist/lib/browser/service.d.ts +0 -812
- package/dist/lib/browser/service.js +0 -4693
- package/dist/lib/browser/stream.d.ts +0 -17
- package/dist/lib/browser/stream.js +0 -72
- package/dist/lib/browser/task-index.d.ts +0 -78
- package/dist/lib/browser/task-index.js +0 -199
- package/dist/lib/browser/types.d.ts +0 -647
- package/dist/lib/browser/types.js +0 -61
- package/dist/lib/browser/upload.d.ts +0 -29
- package/dist/lib/browser/upload.js +0 -298
- package/dist/lib/daemon/browser-ipc-service.d.ts +0 -20
- package/dist/lib/daemon/browser-ipc-service.js +0 -46
- package/dist/lib/daemon/browser-task-reap-service.d.ts +0 -14
- package/dist/lib/daemon/browser-task-reap-service.js +0 -26
- package/dist/lib/fleet-shared-repo-sync.d.ts +0 -55
- package/dist/lib/fleet-shared-repo-sync.js +0 -490
|
@@ -7,7 +7,66 @@ export declare function invocation(bin: string): {
|
|
|
7
7
|
command: string;
|
|
8
8
|
prefix: string[];
|
|
9
9
|
};
|
|
10
|
-
|
|
10
|
+
/** True if any 0.2.0-only filter flag is present — one case that needs the version probe. */
|
|
11
|
+
export declare function usesFilterFlags(args: string[]): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* True if the 0.2.1 point-to-one remote read flag `--host <value>` (or `--host=value`)
|
|
14
|
+
* is present — the other case that needs the version probe, gated on its own floor.
|
|
15
|
+
*/
|
|
16
|
+
export declare function usesHostFlag(args: string[]): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Whether the resolved `sessions` binary is at or above `minVersion`. A probe
|
|
19
|
+
* failure or an unparseable version reads as unsupported — the safe direction
|
|
20
|
+
* (in-repo engine handles it), never a mis-route to an old binary.
|
|
21
|
+
*/
|
|
22
|
+
export declare function sessionsBinSupports(bin: string, minVersion: string): boolean;
|
|
23
|
+
/** Whether the resolved `sessions` binary is new enough for the 0.2.0 filters. */
|
|
24
|
+
export declare function sessionsBinSupportsFilters(bin: string): boolean;
|
|
25
|
+
/** Whether the resolved `sessions` binary is new enough for the 0.2.1 `--host` flag. */
|
|
26
|
+
export declare function sessionsBinSupportsHost(bin: string): boolean;
|
|
27
|
+
export declare function isReadQuery(args: string[], opts?: {
|
|
28
|
+
filters?: boolean;
|
|
29
|
+
host?: boolean;
|
|
30
|
+
}): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Plan the rewrite of a `sessions` READ query that names EXACTLY ONE device via
|
|
33
|
+
* `--device <name>` (and no explicit `--host`) into the standalone's
|
|
34
|
+
* point-to-one remote read: the caller resolves the device to an ssh target and
|
|
35
|
+
* appends `--host ssh://<target>` to `readArgs`, forwarding it to the LOCAL
|
|
36
|
+
* standalone (which owns the ssh hop). This is the local-orchestration collapse
|
|
37
|
+
* (secrets-cli model): `sessions` owns the remote read, replacing the in-repo
|
|
38
|
+
* `--device` peer fan-out — WHEN it is safe (the caller gates on the LOCAL
|
|
39
|
+
* standalone supporting `--host`, >=0.2.1, and falls through to the in-repo
|
|
40
|
+
* fan-out if the PEER lacks the standalone).
|
|
41
|
+
*
|
|
42
|
+
* `sessions --host` is point-to-one, so ONLY a single unambiguous device may
|
|
43
|
+
* collapse; a multi-device query MUST stay on the in-repo fan-out, which parses
|
|
44
|
+
* commander's variadic `--device` correctly. Returns null (→ in-repo path,
|
|
45
|
+
* unchanged) when the query is not a single-device read:
|
|
46
|
+
* - no `--device`/`-D`, or a missing/flag-shaped value;
|
|
47
|
+
* - `--device`/`-D` appears more than once (`--device box --device mac-mini`);
|
|
48
|
+
* - the value is a fan-out sentinel `all`/`fleet` (case-insensitive);
|
|
49
|
+
* - a bare token immediately follows the value (`--device box mac-mini`) —
|
|
50
|
+
* commander's variadic would take it as a second device, so this is
|
|
51
|
+
* multi-device too;
|
|
52
|
+
* - an explicit `--host` is already on the argv — it wins, matching `secrets`'
|
|
53
|
+
* `rewriteDeviceToHost`, so we never add a second `--host`;
|
|
54
|
+
* - the remaining query (with `--device` stripped) is not a read — a lifecycle
|
|
55
|
+
* `--device` (resume/watch/inject/focus/…) keeps its in-repo/`runOnPeer`
|
|
56
|
+
* behavior exactly.
|
|
57
|
+
*
|
|
58
|
+
* Pure and argv-only: fleet resolution (device → ssh target, via
|
|
59
|
+
* `resolveRemoteDevice`) and the version gate live in the caller so this is unit
|
|
60
|
+
* testable with real inputs. `filters` mirrors the caller's version gate for the
|
|
61
|
+
* 0.2.0 filter flags (the `--device` token is not a filter flag, so it is
|
|
62
|
+
* computed identically on the original argv and on `readArgs`).
|
|
63
|
+
*/
|
|
64
|
+
export declare function planDeviceHostRead(args: string[], opts?: {
|
|
65
|
+
filters?: boolean;
|
|
66
|
+
}): {
|
|
67
|
+
device: string;
|
|
68
|
+
readArgs: string[];
|
|
69
|
+
} | null;
|
|
11
70
|
/** Test seam: drop the memoized bin so PATH fixtures can re-resolve. */
|
|
12
71
|
export declare function _resetSessionsClientForTest(): void;
|
|
13
72
|
export declare const SESSIONS_INSTALL_HINT = "npm i -g @phnx-labs/sessions-cli";
|
|
@@ -12,8 +12,29 @@
|
|
|
12
12
|
* `agents sessions`, and resolving it would recurse (the 1.22.85 secrets
|
|
13
13
|
* fork bomb with the names swapped — agi-cli#3532).
|
|
14
14
|
*/
|
|
15
|
+
import { spawnSync } from 'node:child_process';
|
|
15
16
|
import { findInPath } from './agent-spec/agents.js';
|
|
17
|
+
import { compareVersions } from './agent-spec/primitives.js';
|
|
18
|
+
import { stripRoutingFlags } from './hosts/remote-cmd.js';
|
|
16
19
|
const INSTALL_HINT = 'npm i -g @phnx-labs/sessions-cli';
|
|
20
|
+
/**
|
|
21
|
+
* First `sessions` release that implements the metadata filters and sort
|
|
22
|
+
* (`-p/--project`, `--since`, `--until`, `--sort`, the `@version` agent suffix,
|
|
23
|
+
* and the harness shorthands). An older binary would treat these as FTS tokens,
|
|
24
|
+
* so a box with `sessions` < this floor keeps them on the in-repo engine (which
|
|
25
|
+
* implements the same filters) rather than mis-routing to a binary that can't.
|
|
26
|
+
*/
|
|
27
|
+
const SESSIONS_FILTERS_MIN_VERSION = '0.2.0';
|
|
28
|
+
/**
|
|
29
|
+
* First `sessions` release that implements the point-to-one remote read flag
|
|
30
|
+
* `--host <target>` (SSH to ONE box, run `sessions … --local`, stream JSON back).
|
|
31
|
+
* An older binary would treat `--host` as an FTS token, so a box with `sessions`
|
|
32
|
+
* below this floor keeps a `--host` query on the in-repo engine (which resolves
|
|
33
|
+
* `--device` against the fleet) rather than mis-routing it. Kept separate from the
|
|
34
|
+
* filter floor above even though 0.2.1 ≥ 0.2.0 — a 0.2.0 binary supports the
|
|
35
|
+
* filters but NOT `--host`, so the two gates are checked independently.
|
|
36
|
+
*/
|
|
37
|
+
const SESSIONS_HOST_MIN_VERSION = '0.2.1';
|
|
17
38
|
export class SessionsClientError extends Error {
|
|
18
39
|
code;
|
|
19
40
|
constructor(code, message) {
|
|
@@ -52,6 +73,83 @@ const READ_FLAGS = new Set([
|
|
|
52
73
|
'--local',
|
|
53
74
|
'--no-interactive',
|
|
54
75
|
]);
|
|
76
|
+
/**
|
|
77
|
+
* Boolean harness-shorthand flags added in 0.2.0 (`--claude` = `--agent claude`).
|
|
78
|
+
* Recognized as read flags only when the resolved binary supports filters.
|
|
79
|
+
*/
|
|
80
|
+
const FILTER_BOOL_FLAGS = new Set([
|
|
81
|
+
'--claude',
|
|
82
|
+
'--codex',
|
|
83
|
+
'--kimi',
|
|
84
|
+
'--antigravity',
|
|
85
|
+
'--grok',
|
|
86
|
+
'--opencode',
|
|
87
|
+
]);
|
|
88
|
+
/**
|
|
89
|
+
* Value-taking filter flags added in 0.2.0 (each consumes the next argv token,
|
|
90
|
+
* or is written `--flag=value`). `--agent`/`--limit` are NOT here — they are the
|
|
91
|
+
* 0.1.x base set handled unconditionally below.
|
|
92
|
+
*/
|
|
93
|
+
const FILTER_VALUE_FLAGS = new Set([
|
|
94
|
+
'--project',
|
|
95
|
+
'--since',
|
|
96
|
+
'--until',
|
|
97
|
+
'--sort',
|
|
98
|
+
]);
|
|
99
|
+
/** True if any 0.2.0-only filter flag is present — one case that needs the version probe. */
|
|
100
|
+
export function usesFilterFlags(args) {
|
|
101
|
+
return args.some((arg) => {
|
|
102
|
+
if (arg === '-p' || arg === '-a')
|
|
103
|
+
return true;
|
|
104
|
+
if (FILTER_BOOL_FLAGS.has(arg))
|
|
105
|
+
return true;
|
|
106
|
+
for (const vf of FILTER_VALUE_FLAGS) {
|
|
107
|
+
if (arg === vf || arg.startsWith(`${vf}=`))
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
return false;
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* True if the 0.2.1 point-to-one remote read flag `--host <value>` (or `--host=value`)
|
|
115
|
+
* is present — the other case that needs the version probe, gated on its own floor.
|
|
116
|
+
*/
|
|
117
|
+
export function usesHostFlag(args) {
|
|
118
|
+
return args.some((arg) => arg === '--host' || arg.startsWith('--host='));
|
|
119
|
+
}
|
|
120
|
+
let cachedProbedVersion;
|
|
121
|
+
/**
|
|
122
|
+
* Probe `sessions --version` ONCE per process (cached), returning the parsed
|
|
123
|
+
* version string, or `null` when the probe fails or the output is unparseable.
|
|
124
|
+
* The single cache is what keeps the filter and host gates to one spawn between
|
|
125
|
+
* them, however many `sessionsBinSupports*` calls a query makes.
|
|
126
|
+
*/
|
|
127
|
+
function probeSessionsVersion(bin) {
|
|
128
|
+
if (cachedProbedVersion !== undefined)
|
|
129
|
+
return cachedProbedVersion;
|
|
130
|
+
const { command, prefix } = invocation(bin);
|
|
131
|
+
const res = spawnSync(command, [...prefix, '--version'], { encoding: 'utf8', timeout: 3000 });
|
|
132
|
+
const version = (res.stdout ?? '').trim();
|
|
133
|
+
cachedProbedVersion = !res.error && /^\d+\.\d+\.\d+/.test(version) ? version : null;
|
|
134
|
+
return cachedProbedVersion;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Whether the resolved `sessions` binary is at or above `minVersion`. A probe
|
|
138
|
+
* failure or an unparseable version reads as unsupported — the safe direction
|
|
139
|
+
* (in-repo engine handles it), never a mis-route to an old binary.
|
|
140
|
+
*/
|
|
141
|
+
export function sessionsBinSupports(bin, minVersion) {
|
|
142
|
+
const version = probeSessionsVersion(bin);
|
|
143
|
+
return version !== null && compareVersions(version, minVersion) >= 0;
|
|
144
|
+
}
|
|
145
|
+
/** Whether the resolved `sessions` binary is new enough for the 0.2.0 filters. */
|
|
146
|
+
export function sessionsBinSupportsFilters(bin) {
|
|
147
|
+
return sessionsBinSupports(bin, SESSIONS_FILTERS_MIN_VERSION);
|
|
148
|
+
}
|
|
149
|
+
/** Whether the resolved `sessions` binary is new enough for the 0.2.1 `--host` flag. */
|
|
150
|
+
export function sessionsBinSupportsHost(bin) {
|
|
151
|
+
return sessionsBinSupports(bin, SESSIONS_HOST_MIN_VERSION);
|
|
152
|
+
}
|
|
55
153
|
const ENGINE_VERBS = new Set([
|
|
56
154
|
'resume',
|
|
57
155
|
'detach',
|
|
@@ -76,19 +174,45 @@ const ENGINE_VERBS = new Set([
|
|
|
76
174
|
'migrations',
|
|
77
175
|
'export',
|
|
78
176
|
]);
|
|
79
|
-
export function isReadQuery(args) {
|
|
177
|
+
export function isReadQuery(args, opts = {}) {
|
|
80
178
|
if (args.length === 0)
|
|
81
179
|
return false;
|
|
180
|
+
// Base (0.1.x) value flags, always recognized; the 0.2.0 filter value flags
|
|
181
|
+
// join them only when the binary supports filters, and the 0.2.1 `--host`
|
|
182
|
+
// value flag only when the binary supports it (its own, higher floor).
|
|
183
|
+
const valueFlags = new Set(['--limit', '--agent']);
|
|
184
|
+
const boolFlags = new Set(READ_FLAGS);
|
|
185
|
+
if (opts.filters) {
|
|
186
|
+
for (const vf of FILTER_VALUE_FLAGS)
|
|
187
|
+
valueFlags.add(vf);
|
|
188
|
+
for (const bf of FILTER_BOOL_FLAGS)
|
|
189
|
+
boolFlags.add(bf);
|
|
190
|
+
}
|
|
191
|
+
if (opts.host)
|
|
192
|
+
valueFlags.add('--host');
|
|
82
193
|
for (let i = 0; i < args.length; i++) {
|
|
83
194
|
const arg = args[i];
|
|
84
|
-
|
|
195
|
+
// `-a` (agent) and `-p` (project) are 0.2.0 short flags that take a value.
|
|
196
|
+
if (opts.filters && (arg === '-a' || arg === '-p')) {
|
|
85
197
|
i += 1;
|
|
86
198
|
continue;
|
|
87
199
|
}
|
|
88
|
-
|
|
200
|
+
let matchedValue = false;
|
|
201
|
+
for (const vf of valueFlags) {
|
|
202
|
+
if (arg === vf) {
|
|
203
|
+
i += 1;
|
|
204
|
+
matchedValue = true;
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
if (arg.startsWith(`${vf}=`)) {
|
|
208
|
+
matchedValue = true;
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (matchedValue)
|
|
89
213
|
continue;
|
|
90
214
|
if (arg.startsWith('-')) {
|
|
91
|
-
if (!
|
|
215
|
+
if (!boolFlags.has(arg))
|
|
92
216
|
return false;
|
|
93
217
|
continue;
|
|
94
218
|
}
|
|
@@ -97,8 +221,107 @@ export function isReadQuery(args) {
|
|
|
97
221
|
}
|
|
98
222
|
return true;
|
|
99
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Scan an argv for the `sessions` `--device`/`-D` flag, which commander defines
|
|
226
|
+
* as VARIADIC (`-D, --device <target...>`) — so it can appear more than once and
|
|
227
|
+
* a space-form value greedily consumes following bare tokens as extra devices.
|
|
228
|
+
* Returns how many times it occurs, the FIRST value, and the index of the last
|
|
229
|
+
* argv token that value occupies (the flag token itself for the `=`/glued forms,
|
|
230
|
+
* the following value token for the space form). Pure; no imports.
|
|
231
|
+
*/
|
|
232
|
+
function scanDeviceFlag(args) {
|
|
233
|
+
let count = 0;
|
|
234
|
+
let value;
|
|
235
|
+
let valueEndIndex;
|
|
236
|
+
for (let i = 0; i < args.length; i++) {
|
|
237
|
+
const a = args[i];
|
|
238
|
+
let matched = false;
|
|
239
|
+
let v;
|
|
240
|
+
let endIdx = i;
|
|
241
|
+
if (a === '--device' || a === '-D') {
|
|
242
|
+
matched = true;
|
|
243
|
+
v = args[i + 1];
|
|
244
|
+
endIdx = i + 1;
|
|
245
|
+
}
|
|
246
|
+
else if (a.startsWith('--device=')) {
|
|
247
|
+
matched = true;
|
|
248
|
+
v = a.slice('--device='.length);
|
|
249
|
+
}
|
|
250
|
+
else if (a.startsWith('-D=')) {
|
|
251
|
+
matched = true;
|
|
252
|
+
v = a.slice(3);
|
|
253
|
+
}
|
|
254
|
+
else if (/^-D.+/.test(a)) {
|
|
255
|
+
matched = true;
|
|
256
|
+
v = a.slice(2);
|
|
257
|
+
}
|
|
258
|
+
if (matched) {
|
|
259
|
+
count += 1;
|
|
260
|
+
if (count === 1) {
|
|
261
|
+
value = v;
|
|
262
|
+
valueEndIndex = endIdx;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
return { count, value, valueEndIndex };
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Plan the rewrite of a `sessions` READ query that names EXACTLY ONE device via
|
|
270
|
+
* `--device <name>` (and no explicit `--host`) into the standalone's
|
|
271
|
+
* point-to-one remote read: the caller resolves the device to an ssh target and
|
|
272
|
+
* appends `--host ssh://<target>` to `readArgs`, forwarding it to the LOCAL
|
|
273
|
+
* standalone (which owns the ssh hop). This is the local-orchestration collapse
|
|
274
|
+
* (secrets-cli model): `sessions` owns the remote read, replacing the in-repo
|
|
275
|
+
* `--device` peer fan-out — WHEN it is safe (the caller gates on the LOCAL
|
|
276
|
+
* standalone supporting `--host`, >=0.2.1, and falls through to the in-repo
|
|
277
|
+
* fan-out if the PEER lacks the standalone).
|
|
278
|
+
*
|
|
279
|
+
* `sessions --host` is point-to-one, so ONLY a single unambiguous device may
|
|
280
|
+
* collapse; a multi-device query MUST stay on the in-repo fan-out, which parses
|
|
281
|
+
* commander's variadic `--device` correctly. Returns null (→ in-repo path,
|
|
282
|
+
* unchanged) when the query is not a single-device read:
|
|
283
|
+
* - no `--device`/`-D`, or a missing/flag-shaped value;
|
|
284
|
+
* - `--device`/`-D` appears more than once (`--device box --device mac-mini`);
|
|
285
|
+
* - the value is a fan-out sentinel `all`/`fleet` (case-insensitive);
|
|
286
|
+
* - a bare token immediately follows the value (`--device box mac-mini`) —
|
|
287
|
+
* commander's variadic would take it as a second device, so this is
|
|
288
|
+
* multi-device too;
|
|
289
|
+
* - an explicit `--host` is already on the argv — it wins, matching `secrets`'
|
|
290
|
+
* `rewriteDeviceToHost`, so we never add a second `--host`;
|
|
291
|
+
* - the remaining query (with `--device` stripped) is not a read — a lifecycle
|
|
292
|
+
* `--device` (resume/watch/inject/focus/…) keeps its in-repo/`runOnPeer`
|
|
293
|
+
* behavior exactly.
|
|
294
|
+
*
|
|
295
|
+
* Pure and argv-only: fleet resolution (device → ssh target, via
|
|
296
|
+
* `resolveRemoteDevice`) and the version gate live in the caller so this is unit
|
|
297
|
+
* testable with real inputs. `filters` mirrors the caller's version gate for the
|
|
298
|
+
* 0.2.0 filter flags (the `--device` token is not a filter flag, so it is
|
|
299
|
+
* computed identically on the original argv and on `readArgs`).
|
|
300
|
+
*/
|
|
301
|
+
export function planDeviceHostRead(args, opts = {}) {
|
|
302
|
+
const { count, value, valueEndIndex } = scanDeviceFlag(args);
|
|
303
|
+
// Exactly one occurrence, with a real (non-flag) value — else fall through.
|
|
304
|
+
if (count !== 1)
|
|
305
|
+
return null;
|
|
306
|
+
if (value === undefined || value === '' || value.startsWith('-'))
|
|
307
|
+
return null;
|
|
308
|
+
if (usesHostFlag(args))
|
|
309
|
+
return null;
|
|
310
|
+
const lower = value.toLowerCase();
|
|
311
|
+
if (lower === 'all' || lower === 'fleet')
|
|
312
|
+
return null;
|
|
313
|
+
// A bare token after the value is a second variadic device (multi-device).
|
|
314
|
+
const next = valueEndIndex !== undefined ? args[valueEndIndex + 1] : undefined;
|
|
315
|
+
if (next !== undefined && !next.startsWith('-'))
|
|
316
|
+
return null;
|
|
317
|
+
const readArgs = stripRoutingFlags(args, [{ long: 'device', short: 'D', takesValue: true }]);
|
|
318
|
+
if (!isReadQuery(readArgs, { filters: opts.filters }))
|
|
319
|
+
return null;
|
|
320
|
+
return { device: value, readArgs };
|
|
321
|
+
}
|
|
100
322
|
/** Test seam: drop the memoized bin so PATH fixtures can re-resolve. */
|
|
101
323
|
export function _resetSessionsClientForTest() {
|
|
102
324
|
cachedBin = undefined;
|
|
325
|
+
cachedProbedVersion = undefined;
|
|
103
326
|
}
|
|
104
327
|
export const SESSIONS_INSTALL_HINT = INSTALL_HINT;
|
|
@@ -5,7 +5,7 @@ import { getCacheDir, getDeviceMetaPath, getHelpersDir, getUserAgentsDir } from
|
|
|
5
5
|
import { atomicWriteJsonSync, withFileLockAsync } from './fs-atomic.js';
|
|
6
6
|
import { probeCapture } from './probe.js';
|
|
7
7
|
import { invocation, isStandaloneComputer } from './computer-client.js';
|
|
8
|
-
import {
|
|
8
|
+
import { isStandaloneBrowser } from './browser-client.js';
|
|
9
9
|
export const SETUP_TOOLS = ['browser', 'computer', 'secrets', 'term'];
|
|
10
10
|
export function toolSetupCacheDir(options = {}) {
|
|
11
11
|
return path.join(options.cacheDir ?? getCacheDir(), 'setup-tools');
|
|
@@ -15,8 +15,9 @@ function cachePath(tool, options) {
|
|
|
15
15
|
}
|
|
16
16
|
function setupInputs(tool) {
|
|
17
17
|
const inputs = [path.join(getUserAgentsDir(), 'agents.yaml'), getDeviceMetaPath()];
|
|
18
|
+
// browser-cli's IPC socket (integration contract §4). computer's is the helper socket.
|
|
18
19
|
if (tool === 'browser')
|
|
19
|
-
inputs.push(
|
|
20
|
+
inputs.push(path.join(getHelpersDir(), 'browser', 'browser.sock'));
|
|
20
21
|
if (tool === 'computer')
|
|
21
22
|
inputs.push(process.env.COMPUTER_HELPER_SOCKET || path.join(getHelpersDir(), 'computer.sock'));
|
|
22
23
|
return inputs;
|
|
@@ -39,14 +40,8 @@ function binaryMetadata(tool) {
|
|
|
39
40
|
const accept = (candidate) => {
|
|
40
41
|
if (tool === 'computer')
|
|
41
42
|
return isStandaloneComputer(candidate);
|
|
42
|
-
if (tool === 'browser')
|
|
43
|
-
|
|
44
|
-
return !fs.realpathSync(candidate).endsWith(path.join('dist', 'browser.js'));
|
|
45
|
-
}
|
|
46
|
-
catch {
|
|
47
|
-
return false;
|
|
48
|
-
}
|
|
49
|
-
}
|
|
43
|
+
if (tool === 'browser')
|
|
44
|
+
return isStandaloneBrowser(candidate);
|
|
50
45
|
return true;
|
|
51
46
|
};
|
|
52
47
|
let executable = explicit ? (accept(explicit) ? explicit : null) : findInPath(tool, { accept });
|
|
@@ -37,8 +37,9 @@ export declare function loginSubcommand(agent: AgentId): string | null;
|
|
|
37
37
|
* personal device; this box is provisioned from the durable credential).
|
|
38
38
|
* - Unnamed legacy homes use the same version-targeted command shape as
|
|
39
39
|
* doctor, so the hint never logs a different/default home in by accident.
|
|
40
|
-
* - `unverified`
|
|
41
|
-
* worker
|
|
40
|
+
* - `unverified` / `no_evidence` emit nothing: the probe could not confirm state
|
|
41
|
+
* (codex/grok have no probe endpoint; a worker's token lacks the usage scope),
|
|
42
|
+
* so there is nothing to repair.
|
|
42
43
|
*/
|
|
43
44
|
export declare function fixFor(input: {
|
|
44
45
|
agent: AgentId;
|
package/dist/lib/signin-badge.js
CHANGED
|
@@ -66,12 +66,15 @@ export function loginSubcommand(agent) {
|
|
|
66
66
|
* personal device; this box is provisioned from the durable credential).
|
|
67
67
|
* - Unnamed legacy homes use the same version-targeted command shape as
|
|
68
68
|
* doctor, so the hint never logs a different/default home in by accident.
|
|
69
|
-
* - `unverified`
|
|
70
|
-
* worker
|
|
69
|
+
* - `unverified` / `no_evidence` emit nothing: the probe could not confirm state
|
|
70
|
+
* (codex/grok have no probe endpoint; a worker's token lacks the usage scope),
|
|
71
|
+
* so there is nothing to repair.
|
|
71
72
|
*/
|
|
72
73
|
export function fixFor(input) {
|
|
73
74
|
const { agent, verdict } = input;
|
|
74
|
-
|
|
75
|
+
// `no_evidence` (credential present, nothing probed/run here yet) is benign like
|
|
76
|
+
// `unverified` — there is nothing to repair (PHNX-4116).
|
|
77
|
+
if (verdict === 'live' || verdict === 'rate_limited' || verdict === 'unverified' || verdict === 'no_evidence' || verdict === 'ready')
|
|
75
78
|
return null;
|
|
76
79
|
if (input.provisioning === 'per-device' || verdict === 'per-device') {
|
|
77
80
|
return loginHint(agent);
|
package/dist/lib/smart-launch.js
CHANGED
|
@@ -98,7 +98,10 @@ export function formatNoHealthyDeviceError(pool, signals, agent) {
|
|
|
98
98
|
reason = signal.headroom === 'loaded'
|
|
99
99
|
? 'overloaded'
|
|
100
100
|
: signal.installed !== true || signal.signedIn !== true
|
|
101
|
-
|
|
101
|
+
// Surface the box's OWN reason (`runReady.reason`, e.g. "all
|
|
102
|
+
// signed_out") when it gave one, rather than a bare "no ready harness
|
|
103
|
+
// account" that leaves the operator guessing (PHNX-4116).
|
|
104
|
+
? `no ready harness account${signal.reason ? ` (${signal.reason})` : ''}`
|
|
102
105
|
: 'ineligible';
|
|
103
106
|
}
|
|
104
107
|
else if (signal?.timedOut) {
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceDetector } from './types.js';
|
|
2
|
-
export declare const commandsDetectors: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const commandsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceDetector } from './types.js';
|
|
2
|
-
export declare const hooksDetectors: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const hooksDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceDetector } from './types.js';
|
|
2
|
-
export declare const mcpDetectors: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const mcpDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceDetector } from './types.js';
|
|
2
|
-
export declare const permissionsDetectors: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const permissionsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceDetector } from './types.js';
|
|
2
|
-
export declare const pluginsDetectors: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const pluginsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceDetector } from './types.js';
|
|
2
|
-
export declare const rulesDetectors: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const rulesDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ResourceDetector } from './types.js';
|
|
2
2
|
/** Exported for unit tests (RUSH-2320 #2). Production callers: list() below. */
|
|
3
3
|
export declare function skillDirsMatch(src: string, dest: string): boolean;
|
|
4
|
-
export declare const skillsDetectors: Partial<Record<"claude" | "codex" | "
|
|
4
|
+
export declare const skillsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceDetector } from './types.js';
|
|
2
|
-
export declare const subagentsDetectors: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const subagentsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceDetector } from './types.js';
|
|
2
|
-
export declare const workflowsDetectors: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const workflowsDetectors: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceDetector>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceWriter } from './types.js';
|
|
2
|
-
export declare const commandsWriters: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const commandsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceWriter } from './types.js';
|
|
2
|
-
export declare const hooksWriters: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const hooksWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceWriter } from './types.js';
|
|
2
|
-
export declare const mcpWriters: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const mcpWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceWriter } from './types.js';
|
|
2
|
-
export declare const permissionsWriters: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const permissionsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceWriter } from './types.js';
|
|
2
|
-
export declare const pluginsWriters: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const pluginsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
|
|
@@ -3,4 +3,4 @@ export interface RulesSelection {
|
|
|
3
3
|
/** Preset name to compose. Empty string falls through to `"default"` in the composer. */
|
|
4
4
|
preset: string;
|
|
5
5
|
}
|
|
6
|
-
export declare const rulesWriters: Partial<Record<"claude" | "codex" | "
|
|
6
|
+
export declare const rulesWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<RulesSelection>>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceWriter } from './types.js';
|
|
2
|
-
export declare const skillsWriters: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const skillsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
|
|
@@ -11,6 +11,7 @@ import * as fs from 'fs';
|
|
|
11
11
|
import * as path from 'path';
|
|
12
12
|
import { getUserAgentsDir, getAgentsDir, getEnabledExtraRepos, getCommandsDir, getSkillsDir, getHooksDir } from '../../state.js';
|
|
13
13
|
import { isSafeSegmentName, safeJoin } from '../../paths.js';
|
|
14
|
+
import { AGENTS } from '../../agents.js';
|
|
14
15
|
/** Trusted source bases for content-like kinds. Project layer excluded. */
|
|
15
16
|
function trustedSourceBases() {
|
|
16
17
|
return [
|
|
@@ -57,6 +58,10 @@ function pluginSupportsAgent(manifest, agent) {
|
|
|
57
58
|
/** Every `plugins/<plugin>/skills` dir across trusted source bases, filtered to an optional plugin/agent scope. */
|
|
58
59
|
export function pluginSkillDirs(options = {}) {
|
|
59
60
|
const dirs = [];
|
|
61
|
+
// A harness that loads plugin skills natively gets no flattened copy and no
|
|
62
|
+
// plugin credit for a top-level skills/<name>: that copy is an orphan there.
|
|
63
|
+
if (options.agent && AGENTS[options.agent]?.nativePluginSkills)
|
|
64
|
+
return dirs;
|
|
60
65
|
for (const base of trustedSourceBases()) {
|
|
61
66
|
const pluginsDir = path.join(base.dir, 'plugins');
|
|
62
67
|
let entries;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceWriter } from './types.js';
|
|
2
|
-
export declare const subagentsWriters: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const subagentsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import type { ResourceWriter } from './types.js';
|
|
2
|
-
export declare const workflowsWriters: Partial<Record<"claude" | "codex" | "
|
|
2
|
+
export declare const workflowsWriters: Partial<Record<"claude" | "codex" | "cursor" | "opencode" | "openclaw" | "copilot" | "amp" | "goose" | "antigravity" | "grok" | "kimi" | "droid" | "hermes" | "muse" | "warp", ResourceWriter<string[]>>>;
|
package/dist/lib/state.d.ts
CHANGED
|
@@ -427,8 +427,11 @@ export declare function withMetaLock<T>(fn: () => T): T;
|
|
|
427
427
|
* never run inside the short, non-heartbeated lockfile window; the user repo
|
|
428
428
|
* already pushes.
|
|
429
429
|
*
|
|
430
|
-
* Scoped tightly: only called when the central bytes actually changed
|
|
431
|
-
* from the daemon
|
|
430
|
+
* Scoped tightly: only called when the central bytes actually changed — from a
|
|
431
|
+
* CLI command and from the daemon alike, since no daemon tick commits the user
|
|
432
|
+
* repo any more (the shared-state exchange moved to SSH, PHNX-4116), so a
|
|
433
|
+
* daemon-side central write would otherwise sit dirty until the next CLI
|
|
434
|
+
* central edit. A commit failure fails open —
|
|
432
435
|
* a concurrent daemon holding `index.lock`, a mid-rebase repo — leaving
|
|
433
436
|
* agents.yaml dirty; the next successful central write commits it, and until
|
|
434
437
|
* then a pull that would collide refuses rather than losing data. A config
|
|
@@ -489,8 +492,7 @@ export declare function updateMeta(updates: Partial<Meta> | ((meta: Meta) => Met
|
|
|
489
492
|
* A CLI command that actually moved the fleet-shared central agents.yaml commits
|
|
490
493
|
* it so the tree is never left dirty on that file at rest — the window that
|
|
491
494
|
* trips `dirtyTreeRefusal` and wedges pulls fleet-wide (PHNX-3968). Gated on a
|
|
492
|
-
* real byte change
|
|
493
|
-
* commits. See {@link commitCentralConfig}.
|
|
495
|
+
* real byte change. See {@link commitCentralConfig}.
|
|
494
496
|
*/
|
|
495
497
|
export declare function commitCentralConfigAfterWrite(centralChanged: boolean): void;
|
|
496
498
|
/** Derive a filesystem-safe local clone path for a package source URL. */
|
package/dist/lib/state.js
CHANGED
|
@@ -864,17 +864,6 @@ function writeIfChanged(filePath, content) {
|
|
|
864
864
|
atomicWriteFileSync(filePath, content);
|
|
865
865
|
return true;
|
|
866
866
|
}
|
|
867
|
-
/**
|
|
868
|
-
* True in the always-on daemon process (launched as `agents __daemon-run`,
|
|
869
|
-
* see cli/src/index.ts). The daemon owns central git commits through
|
|
870
|
-
* fleet-shared-repo-sync's publish tick, so a central write from inside the
|
|
871
|
-
* daemon must NOT also commit here — that would race the publisher's own
|
|
872
|
-
* add/commit/rebase/push on the same index. Every ordinary CLI invocation
|
|
873
|
-
* returns false and commits its own central edit synchronously.
|
|
874
|
-
*/
|
|
875
|
-
function isDaemonProcess() {
|
|
876
|
-
return process.argv[2] === '__daemon-run';
|
|
877
|
-
}
|
|
878
867
|
/**
|
|
879
868
|
* Commit the central `agents.yaml` in the user repo, synchronously, so a CLI
|
|
880
869
|
* config mutation never leaves the working tree dirty on that one shared-line
|
|
@@ -892,8 +881,11 @@ function isDaemonProcess() {
|
|
|
892
881
|
* never run inside the short, non-heartbeated lockfile window; the user repo
|
|
893
882
|
* already pushes.
|
|
894
883
|
*
|
|
895
|
-
* Scoped tightly: only called when the central bytes actually changed
|
|
896
|
-
* from the daemon
|
|
884
|
+
* Scoped tightly: only called when the central bytes actually changed — from a
|
|
885
|
+
* CLI command and from the daemon alike, since no daemon tick commits the user
|
|
886
|
+
* repo any more (the shared-state exchange moved to SSH, PHNX-4116), so a
|
|
887
|
+
* daemon-side central write would otherwise sit dirty until the next CLI
|
|
888
|
+
* central edit. A commit failure fails open —
|
|
897
889
|
* a concurrent daemon holding `index.lock`, a mid-rebase repo — leaving
|
|
898
890
|
* agents.yaml dirty; the next successful central write commits it, and until
|
|
899
891
|
* then a pull that would collide refuses rather than losing data. A config
|
|
@@ -1685,13 +1677,11 @@ export function updateMeta(updates) {
|
|
|
1685
1677
|
* A CLI command that actually moved the fleet-shared central agents.yaml commits
|
|
1686
1678
|
* it so the tree is never left dirty on that file at rest — the window that
|
|
1687
1679
|
* trips `dirtyTreeRefusal` and wedges pulls fleet-wide (PHNX-3968). Gated on a
|
|
1688
|
-
* real byte change
|
|
1689
|
-
* commits. See {@link commitCentralConfig}.
|
|
1680
|
+
* real byte change. See {@link commitCentralConfig}.
|
|
1690
1681
|
*/
|
|
1691
1682
|
export function commitCentralConfigAfterWrite(centralChanged) {
|
|
1692
|
-
if (centralChanged
|
|
1683
|
+
if (centralChanged)
|
|
1693
1684
|
commitCentralConfig(USER_AGENTS_DIR);
|
|
1694
|
-
}
|
|
1695
1685
|
}
|
|
1696
1686
|
/** Derive a filesystem-safe local clone path for a package source URL. */
|
|
1697
1687
|
export function getPackageLocalPath(source) {
|