@phnx-labs/agents-cli 1.22.84 → 1.22.86
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 +96 -0
- package/README.md +80 -53
- package/dist/bootstrap.d.ts +7 -6
- package/dist/bootstrap.js +20 -27
- package/dist/cli/command-registry.js +5 -1
- package/dist/commands/accounts.d.ts +6 -13
- package/dist/commands/accounts.js +330 -143
- package/dist/commands/alias.js +7 -3
- package/dist/commands/apply.js +1 -1
- package/dist/commands/auth-mint.d.ts +7 -3
- package/dist/commands/auth-mint.js +21 -9
- package/dist/commands/auth.js +2 -3
- package/dist/commands/browser.js +10 -10
- package/dist/commands/daemon.d.ts +7 -3
- package/dist/commands/daemon.js +40 -25
- package/dist/commands/doctor.js +28 -2
- package/dist/commands/exec.js +87 -39
- package/dist/commands/fleet-capture.js +21 -2
- package/dist/commands/harness-wizard.js +2 -2
- package/dist/commands/lease.js +7 -12
- package/dist/commands/profiles.d.ts +2 -2
- package/dist/commands/profiles.js +20 -13
- package/dist/commands/repo.js +3 -3
- package/dist/commands/run-account-picker.d.ts +3 -3
- package/dist/commands/run-account-picker.js +29 -30
- package/dist/commands/secrets-passthrough.d.ts +20 -0
- package/dist/commands/secrets-passthrough.js +43 -0
- package/dist/commands/setup-accounts.d.ts +3 -2
- package/dist/commands/setup-accounts.js +4 -4
- package/dist/commands/setup-secrets.d.ts +16 -21
- package/dist/commands/setup-secrets.js +43 -224
- package/dist/commands/ssh.js +2 -2
- package/dist/commands/sync.js +1 -1
- package/dist/commands/update.d.ts +10 -0
- package/dist/commands/update.js +43 -40
- package/dist/commands/versions.d.ts +11 -11
- package/dist/commands/versions.js +131 -83
- package/dist/commands/view.d.ts +1 -9
- package/dist/commands/view.js +41 -55
- package/dist/commands/webhook.js +5 -5
- package/dist/commands/workflows.js +2 -1
- package/dist/index.d.ts +12 -12
- package/dist/index.js +13 -42
- package/dist/lib/account-capabilities.d.ts +1 -1
- package/dist/lib/account-capabilities.js +1 -1
- package/dist/lib/account-catalog.d.ts +121 -6
- package/dist/lib/account-catalog.js +421 -7
- package/dist/lib/account-registry.d.ts +8 -30
- package/dist/lib/account-registry.js +36 -79
- package/dist/lib/account-schema.d.ts +1 -1
- package/dist/lib/account-schema.js +1 -1
- package/dist/lib/accounting/account-pool-collect.js +16 -4
- package/dist/lib/accounting/rotate.d.ts +20 -7
- package/dist/lib/accounting/rotate.js +89 -13
- package/dist/lib/accounting/usage.js +11 -16
- package/dist/lib/accounts/add.d.ts +138 -0
- package/dist/lib/accounts/add.js +651 -0
- package/dist/lib/accounts/migrate.d.ts +117 -0
- package/dist/lib/accounts/migrate.js +536 -0
- package/dist/lib/accounts/slots.d.ts +13 -0
- package/dist/lib/accounts/slots.js +100 -0
- package/dist/lib/agent-spec/agents.d.ts +16 -0
- package/dist/lib/agent-spec/agents.js +38 -4
- package/dist/lib/app-bundle-install.js +5 -4
- package/dist/lib/auth-health.d.ts +3 -0
- package/dist/lib/auth-health.js +11 -0
- package/dist/lib/auth-mint.d.ts +52 -16
- package/dist/lib/auth-mint.js +117 -39
- package/dist/lib/browser/chrome.d.ts +1 -1
- package/dist/lib/browser/chrome.js +5 -5
- package/dist/lib/byok-usage.js +3 -3
- package/dist/lib/claude-account-token.d.ts +47 -3
- package/dist/lib/claude-account-token.js +172 -50
- package/dist/lib/cloud/antigravity.js +4 -4
- package/dist/lib/cloud/cursor.js +4 -4
- package/dist/lib/crabbox/cli.d.ts +1 -1
- package/dist/lib/crabbox/cli.js +6 -6
- package/dist/lib/crabbox/runtimes.d.ts +3 -3
- package/dist/lib/crabbox/runtimes.js +5 -5
- package/dist/lib/daemon/account-state-daemon-service.d.ts +37 -1
- package/dist/lib/daemon/account-state-daemon-service.js +199 -3
- package/dist/lib/daemon/auth-sync-service.js +32 -1
- package/dist/lib/daemon/daemon.d.ts +6 -16
- package/dist/lib/daemon/daemon.js +52 -97
- package/dist/lib/daemon/daemon.test-fixture.d.ts +7 -9
- package/dist/lib/daemon/daemon.test-fixture.js +22 -40
- package/dist/lib/daemon/harness-update-service.d.ts +1 -1
- package/dist/lib/daemon/harness-update-service.js +1 -1
- package/dist/lib/daemon/runner.d.ts +15 -3
- package/dist/lib/daemon/runner.js +49 -24
- package/dist/lib/daemon-health.d.ts +1 -2
- package/dist/lib/daemon-health.js +7 -6
- package/dist/lib/daemon-services.d.ts +1 -1
- package/dist/lib/daemon-services.js +1 -11
- package/dist/lib/daemon-webhooks.d.ts +8 -7
- package/dist/lib/daemon-webhooks.js +10 -9
- package/dist/lib/device-config.js +1 -1
- package/dist/lib/devices/doctor-findings.d.ts +1 -1
- package/dist/lib/devices/harness-inventory.d.ts +39 -0
- package/dist/lib/devices/harness-inventory.js +126 -4
- package/dist/lib/doctor-diff.js +2 -1
- package/dist/lib/exec-account-home.d.ts +38 -0
- package/dist/lib/exec-account-home.js +164 -0
- package/dist/lib/exec.d.ts +30 -0
- package/dist/lib/exec.js +101 -31
- package/dist/lib/fleet/apply.d.ts +2 -2
- package/dist/lib/fleet/apply.js +4 -4
- package/dist/lib/fleet/auth-sync.js +4 -3
- package/dist/lib/fleet-shared-repo-sync.js +6 -9
- package/dist/lib/harness/adapter.d.ts +7 -7
- package/dist/lib/harness/adapter.js +10 -6
- package/dist/lib/harness/adapters/grok.js +8 -3
- package/dist/lib/harness/adapters/muse.js +1 -1
- package/dist/lib/harness/adapters/opencode.js +12 -3
- package/dist/lib/harness-auth-capabilities.d.ts +61 -0
- package/dist/lib/harness-auth-capabilities.js +52 -0
- package/dist/lib/helper-versions.d.ts +6 -4
- package/dist/lib/helper-versions.js +5 -4
- package/dist/lib/hosts/credential-transport.d.ts +10 -0
- package/dist/lib/hosts/credential-transport.js +37 -0
- package/dist/lib/hosts/dispatch.d.ts +7 -0
- package/dist/lib/hosts/dispatch.js +13 -6
- package/dist/lib/identity/client.d.ts +3 -3
- package/dist/lib/identity/client.js +3 -3
- package/dist/lib/installations/index.d.ts +1 -1
- package/dist/lib/installations/index.js +1 -1
- package/dist/lib/installations/migrate.js +9 -0
- package/dist/lib/installations/resolve.js +1 -1
- package/dist/lib/installations/shims.d.ts +21 -4
- package/dist/lib/installations/shims.js +86 -5
- package/dist/lib/installations/store.d.ts +43 -0
- package/dist/lib/installations/store.js +75 -7
- package/dist/lib/installations/versions.js +1 -1
- package/dist/lib/menubar/install-menubar.d.ts +3 -3
- package/dist/lib/menubar/install-menubar.js +3 -3
- package/dist/lib/native-accounts.d.ts +35 -0
- package/dist/lib/native-accounts.js +41 -0
- package/dist/lib/net-close.d.ts +11 -0
- package/dist/lib/net-close.js +25 -0
- package/dist/lib/openclaw-keychain.js +27 -1
- package/dist/lib/profiles.js +22 -9
- package/dist/lib/project-resources.js +1 -1
- package/dist/lib/reserved-stores.d.ts +53 -0
- package/dist/lib/reserved-stores.js +120 -0
- package/dist/lib/secrets-client.d.ts +199 -0
- package/dist/lib/secrets-client.js +718 -0
- package/dist/lib/secrets-policy.d.ts +235 -0
- package/dist/lib/secrets-policy.js +505 -0
- package/dist/lib/secrets-types.d.ts +188 -0
- package/dist/lib/secrets-types.js +24 -0
- package/dist/lib/self-heal/checks/shims.js +5 -3
- package/dist/lib/service-manifest.js +3 -4
- package/dist/lib/session/db.d.ts +18 -0
- package/dist/lib/session/db.js +47 -14
- package/dist/lib/session/sync/config.js +2 -2
- package/dist/lib/sha256-asset.d.ts +11 -16
- package/dist/lib/sha256-asset.js +11 -16
- package/dist/lib/share/config.js +14 -5
- package/dist/lib/signin-badge.d.ts +26 -0
- package/dist/lib/signin-badge.js +42 -0
- package/dist/lib/staleness/detectors/workflows.js +3 -105
- package/dist/lib/staleness/writers/workflows.js +2 -1
- package/dist/lib/state.d.ts +7 -4
- package/dist/lib/state.js +18 -7
- package/dist/lib/sync-umbrella.js +2 -2
- package/dist/lib/teams/agents.js +1 -1
- package/dist/lib/types.d.ts +74 -33
- package/dist/lib/view-types.d.ts +6 -3
- package/dist/lib/workflows-registry.d.ts +71 -0
- package/dist/lib/workflows-registry.js +280 -0
- package/dist/lib/workflows.d.ts +21 -21
- package/dist/lib/workflows.js +12 -327
- package/package.json +2 -3
- package/scripts/postinstall.js +35 -30
- package/dist/commands/secrets-import.d.ts +0 -18
- package/dist/commands/secrets-import.js +0 -74
- package/dist/commands/secrets-migrate.d.ts +0 -25
- package/dist/commands/secrets-migrate.js +0 -334
- package/dist/commands/secrets-rotate-passphrase.d.ts +0 -17
- package/dist/commands/secrets-rotate-passphrase.js +0 -96
- package/dist/commands/secrets-sync.d.ts +0 -11
- package/dist/commands/secrets-sync.js +0 -153
- package/dist/commands/secrets-vault.d.ts +0 -10
- package/dist/commands/secrets-vault.js +0 -130
- package/dist/commands/secrets.d.ts +0 -212
- package/dist/commands/secrets.js +0 -3030
- package/dist/lib/accounts/connect.d.ts +0 -176
- package/dist/lib/accounts/connect.js +0 -453
- package/dist/lib/daemon/keychain-reap-service.d.ts +0 -17
- package/dist/lib/daemon/keychain-reap-service.js +0 -32
- package/dist/lib/daemon/secrets-broker-service.d.ts +0 -21
- package/dist/lib/daemon/secrets-broker-service.js +0 -51
- package/dist/lib/secrets/agent.d.ts +0 -358
- package/dist/lib/secrets/agent.js +0 -1291
- package/dist/lib/secrets/audit.d.ts +0 -46
- package/dist/lib/secrets/audit.js +0 -101
- package/dist/lib/secrets/bundles.d.ts +0 -290
- package/dist/lib/secrets/bundles.js +0 -1547
- package/dist/lib/secrets/download-keychain.d.ts +0 -47
- package/dist/lib/secrets/download-keychain.js +0 -70
- package/dist/lib/secrets/drivers/rush.d.ts +0 -14
- package/dist/lib/secrets/drivers/rush.js +0 -90
- package/dist/lib/secrets/fallback.d.ts +0 -48
- package/dist/lib/secrets/fallback.js +0 -48
- package/dist/lib/secrets/filestore.d.ts +0 -222
- package/dist/lib/secrets/filestore.js +0 -1099
- package/dist/lib/secrets/headless.d.ts +0 -43
- package/dist/lib/secrets/headless.js +0 -56
- package/dist/lib/secrets/icloud-import.d.ts +0 -79
- package/dist/lib/secrets/icloud-import.js +0 -206
- package/dist/lib/secrets/index.d.ts +0 -451
- package/dist/lib/secrets/index.js +0 -1568
- package/dist/lib/secrets/install-helper.d.ts +0 -72
- package/dist/lib/secrets/install-helper.js +0 -245
- package/dist/lib/secrets/lease.d.ts +0 -25
- package/dist/lib/secrets/lease.js +0 -44
- package/dist/lib/secrets/linux.d.ts +0 -77
- package/dist/lib/secrets/linux.js +0 -393
- package/dist/lib/secrets/list-filter.d.ts +0 -109
- package/dist/lib/secrets/list-filter.js +0 -261
- package/dist/lib/secrets/mcp.d.ts +0 -93
- package/dist/lib/secrets/mcp.js +0 -211
- package/dist/lib/secrets/profiles.d.ts +0 -10
- package/dist/lib/secrets/profiles.js +0 -13
- package/dist/lib/secrets/push.d.ts +0 -133
- package/dist/lib/secrets/push.js +0 -273
- package/dist/lib/secrets/rc-hygiene.d.ts +0 -63
- package/dist/lib/secrets/rc-hygiene.js +0 -143
- package/dist/lib/secrets/read-backoff.d.ts +0 -27
- package/dist/lib/secrets/read-backoff.js +0 -64
- package/dist/lib/secrets/reaper.d.ts +0 -90
- package/dist/lib/secrets/reaper.js +0 -243
- package/dist/lib/secrets/remote.d.ts +0 -152
- package/dist/lib/secrets/remote.js +0 -344
- package/dist/lib/secrets/reserved-sync.d.ts +0 -66
- package/dist/lib/secrets/reserved-sync.js +0 -147
- package/dist/lib/secrets/scope.d.ts +0 -26
- package/dist/lib/secrets/scope.js +0 -29
- package/dist/lib/secrets/session-store.d.ts +0 -107
- package/dist/lib/secrets/session-store.js +0 -342
- package/dist/lib/secrets/sync-backend.d.ts +0 -48
- package/dist/lib/secrets/sync-backend.js +0 -13
- package/dist/lib/secrets/sync-commands.d.ts +0 -21
- package/dist/lib/secrets/sync-commands.js +0 -21
- package/dist/lib/secrets/sync.d.ts +0 -48
- package/dist/lib/secrets/sync.js +0 -237
- package/dist/lib/secrets/unlock-hints.d.ts +0 -27
- package/dist/lib/secrets/unlock-hints.js +0 -36
- package/dist/lib/secrets/usage-db.d.ts +0 -46
- package/dist/lib/secrets/usage-db.js +0 -96
- package/dist/lib/secrets/vault-age-helper.d.ts +0 -1
- package/dist/lib/secrets/vault-age-helper.js +0 -34
- package/dist/lib/secrets/vault.d.ts +0 -49
- package/dist/lib/secrets/vault.js +0 -399
- package/dist/lib/secrets/windows.d.ts +0 -81
- package/dist/lib/secrets/windows.js +0 -556
- package/scripts/install-helper.js +0 -97
- /package/dist/lib/{secrets/sync-passphrase.d.ts → sync-passphrase.d.ts} +0 -0
- /package/dist/lib/{secrets/sync-passphrase.js → sync-passphrase.js} +0 -0
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire-shared types for the standalone `secrets` CLI (PHNX-3989).
|
|
3
|
+
*
|
|
4
|
+
* The standalone engine (`@phnx-labs/secrets-cli`, extracted from what used to
|
|
5
|
+
* be `cli/src/lib/secrets/**`) owns every one of these shapes; this module only
|
|
6
|
+
* re-declares them so `secrets-client.ts` and its consumers keep exact static
|
|
7
|
+
* types across the process-client boundary with no runtime dependency on the
|
|
8
|
+
* (now deleted) in-repo engine. Keep byte-for-byte in sync with
|
|
9
|
+
* `secrets-cli/src/schema.ts` / `src/core/bundles.ts` — this is the one seam
|
|
10
|
+
* both sides legitimately re-declare rather than share a package for (see the
|
|
11
|
+
* `secrets-client.ts` docblock).
|
|
12
|
+
*/
|
|
13
|
+
/** Supported bundle storage backends. */
|
|
14
|
+
export type SecretsBackend = 'keychain' | 'file' | 'vault';
|
|
15
|
+
/** Supported secret resolution providers for a bundle var. */
|
|
16
|
+
export type SecretProvider = 'keychain' | 'env' | 'file' | 'exec';
|
|
17
|
+
/** A typed reference to a secret: a provider plus a provider-specific value. */
|
|
18
|
+
export interface SecretRef {
|
|
19
|
+
provider: SecretProvider;
|
|
20
|
+
value: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A bundle value: either a string (literal or provider-prefixed ref) or an
|
|
24
|
+
* object `{value: string}` used to escape a literal that would otherwise be
|
|
25
|
+
* parsed as a ref (e.g. a URL that happens to start with `env:`).
|
|
26
|
+
*/
|
|
27
|
+
export type BundleValue = string | {
|
|
28
|
+
value: string;
|
|
29
|
+
};
|
|
30
|
+
/** Remote (bundle@host) push destination backend. */
|
|
31
|
+
export type RemoteBackend = 'keychain' | 'file';
|
|
32
|
+
export declare const SECRET_TYPES: readonly ["api-key", "token", "password", "url", "database-url", "ssh-key", "certificate", "webhook", "note"];
|
|
33
|
+
export type SecretType = (typeof SECRET_TYPES)[number];
|
|
34
|
+
/** Per-secret metadata; absent fields are omitted at write time. */
|
|
35
|
+
export interface VarMeta {
|
|
36
|
+
type?: SecretType;
|
|
37
|
+
/** Future-dated ISO date ('YYYY-MM-DD'). */
|
|
38
|
+
expires?: string;
|
|
39
|
+
note?: string;
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Bundle prompt policy. `hold` (default): one Touch ID per hold window (~7d),
|
|
43
|
+
* then silent via the secrets-agent. `always`: prompt every read. `never`: no
|
|
44
|
+
* biometry ACL — least-safe, automation-only.
|
|
45
|
+
*/
|
|
46
|
+
export type SecretsPolicy = 'always' | 'hold' | 'never';
|
|
47
|
+
/** A named set of environment variable definitions backed by secret stores. */
|
|
48
|
+
export interface SecretsBundle {
|
|
49
|
+
name: string;
|
|
50
|
+
description?: string;
|
|
51
|
+
allow_exec?: boolean;
|
|
52
|
+
/** Absent ⇒ `keychain`. */
|
|
53
|
+
backend?: SecretsBackend;
|
|
54
|
+
/** Absent ⇒ configured default (`hold`). */
|
|
55
|
+
policy?: SecretsPolicy;
|
|
56
|
+
created_at?: string;
|
|
57
|
+
updated_at?: string;
|
|
58
|
+
last_used?: string;
|
|
59
|
+
vars: Record<string, BundleValue>;
|
|
60
|
+
meta?: Record<string, VarMeta>;
|
|
61
|
+
}
|
|
62
|
+
/** Per-key kind breakdown of an already-resolved bundle. */
|
|
63
|
+
export interface BundleEntryInfo {
|
|
64
|
+
key: string;
|
|
65
|
+
kind: 'literal' | 'keychain' | 'env' | 'file' | 'exec';
|
|
66
|
+
/** Ref target, or empty for a literal. Never a resolved value. */
|
|
67
|
+
detail: string;
|
|
68
|
+
}
|
|
69
|
+
/** Options for `writeBundle` / `writeBundleWithItems`. */
|
|
70
|
+
export interface WriteBundleOptions {
|
|
71
|
+
/** Skip evicting the broker-held copy (no-op writers such as `stampLastUsed`). */
|
|
72
|
+
skipBrokerEviction?: boolean;
|
|
73
|
+
/** Allow writing a reserved `__<harness>__` store. */
|
|
74
|
+
allowReservedStore?: boolean;
|
|
75
|
+
}
|
|
76
|
+
/** Options for `readAndResolveBundleEnv`. */
|
|
77
|
+
export interface ResolveBundleOptions {
|
|
78
|
+
caller?: string;
|
|
79
|
+
/** Harness type whose unlock may be reused. */
|
|
80
|
+
agent?: string;
|
|
81
|
+
/** Duration shown in the Touch ID prompt. */
|
|
82
|
+
duration?: string;
|
|
83
|
+
/** Allow this call to raise an interactive biometric prompt. */
|
|
84
|
+
interactiveUnlock?: boolean;
|
|
85
|
+
/** Skip the broker fast-path and read from the keychain directly. */
|
|
86
|
+
noAgent?: boolean;
|
|
87
|
+
/** Resolve only from an already-unlocked broker snapshot; fail before prompting. */
|
|
88
|
+
agentOnly?: boolean;
|
|
89
|
+
/** Inject only these keys. Errors if any requested key is absent. */
|
|
90
|
+
keys?: string[];
|
|
91
|
+
/** Skip the per-key expiry gate. */
|
|
92
|
+
allowExpired?: boolean;
|
|
93
|
+
/** `process` projects dotted keys to shell-safe env names; `storage` preserves them. */
|
|
94
|
+
keyMode?: 'process' | 'storage';
|
|
95
|
+
/** Read a reserved `__<harness>__` store (system readers only). */
|
|
96
|
+
allowReservedStore?: boolean;
|
|
97
|
+
}
|
|
98
|
+
/** Options for `renameBundle`. */
|
|
99
|
+
export interface RenameOptions {
|
|
100
|
+
/** Overwrite an existing destination bundle. */
|
|
101
|
+
force?: boolean;
|
|
102
|
+
}
|
|
103
|
+
/** Options for `rotateBundleSecret`. */
|
|
104
|
+
export interface RotateOptions {
|
|
105
|
+
/** New plaintext value to write into the store (replaces the old one). */
|
|
106
|
+
newValue: string;
|
|
107
|
+
/** When true, drop existing meta for this key. Mutually exclusive with `meta`. */
|
|
108
|
+
clearMeta?: boolean;
|
|
109
|
+
/** Patch to merge into existing meta. Undefined fields preserve current values. */
|
|
110
|
+
meta?: Partial<VarMeta>;
|
|
111
|
+
}
|
|
112
|
+
/** Reading a keychain-backed item through the standalone. */
|
|
113
|
+
export interface KeychainReadContext {
|
|
114
|
+
agent?: string;
|
|
115
|
+
bundle?: string;
|
|
116
|
+
sessionId?: string;
|
|
117
|
+
reason?: string;
|
|
118
|
+
duration?: string;
|
|
119
|
+
defaultPolicy?: 'hold' | 'always' | 'never';
|
|
120
|
+
forceDuration?: boolean;
|
|
121
|
+
/**
|
|
122
|
+
* The caller attests the item(s) carry NO biometry ACL — so the read is
|
|
123
|
+
* silent even when no one is at the screen. Never pass this for an
|
|
124
|
+
* ACL-protected item.
|
|
125
|
+
*/
|
|
126
|
+
silentNoAcl?: boolean;
|
|
127
|
+
}
|
|
128
|
+
/** One held bundle unlock reported by `agent.agentStatus`. */
|
|
129
|
+
export interface AgentStatusEntry {
|
|
130
|
+
name: string;
|
|
131
|
+
expiresAt: number;
|
|
132
|
+
keyCount: number;
|
|
133
|
+
harness: string;
|
|
134
|
+
leaseId?: string;
|
|
135
|
+
keys?: string[];
|
|
136
|
+
}
|
|
137
|
+
/** Options for `pushBundleToHost` / `pushBundleToHostAsync`. */
|
|
138
|
+
export interface PushBundleOptions {
|
|
139
|
+
remoteBackend: RemoteBackend;
|
|
140
|
+
/** Overwrite a key that already exists on the remote. */
|
|
141
|
+
force?: boolean;
|
|
142
|
+
/**
|
|
143
|
+
* Ignored. File-backend export never forwards the passphrase (PHNX-2371);
|
|
144
|
+
* the remote auto-provisions its own machine-local key. Kept on the options
|
|
145
|
+
* type so existing callers that passed one still compile.
|
|
146
|
+
*/
|
|
147
|
+
passphrase?: string;
|
|
148
|
+
/** Label for the audit trail — `export --device` vs `fleet apply`. */
|
|
149
|
+
operation: string;
|
|
150
|
+
/** Preserve an automation account's permanent prompt-free policy remotely. */
|
|
151
|
+
policyNever?: boolean;
|
|
152
|
+
/** Permit a human-invoked push to read locally without requiring the agent broker. */
|
|
153
|
+
agentOnly?: boolean;
|
|
154
|
+
/** Non-secret literals whose bundle value kind must survive the dotenv transport. */
|
|
155
|
+
literalValues?: Record<string, string>;
|
|
156
|
+
/** Per-SSH-operation deadline. Async daemon callers must set this explicitly. */
|
|
157
|
+
timeoutMs?: number;
|
|
158
|
+
}
|
|
159
|
+
export interface PushBundleResult {
|
|
160
|
+
ok: boolean;
|
|
161
|
+
host: string;
|
|
162
|
+
bundle: string;
|
|
163
|
+
keyCount: number;
|
|
164
|
+
/** One line for the caller to render. Never contains a secret value. */
|
|
165
|
+
message: string;
|
|
166
|
+
}
|
|
167
|
+
/** Lightweight listing entry returned by the managed sync transport. */
|
|
168
|
+
export interface RemoteBundleSummary {
|
|
169
|
+
name: string;
|
|
170
|
+
updated_at: string;
|
|
171
|
+
}
|
|
172
|
+
/** Options for `pullBundle` (the `agents sync --secrets` umbrella stage). */
|
|
173
|
+
export interface PullOptions {
|
|
174
|
+
passphrase: string;
|
|
175
|
+
/** When true, overwrite an existing local bundle. */
|
|
176
|
+
force?: boolean;
|
|
177
|
+
}
|
|
178
|
+
/** One credential-shaped shell-rc export finding. */
|
|
179
|
+
export interface RcSecretFinding {
|
|
180
|
+
/** Basename of the rc file, e.g. `.zshenv`. */
|
|
181
|
+
file: string;
|
|
182
|
+
/** 1-based line number of the export. */
|
|
183
|
+
line: number;
|
|
184
|
+
/** The exported variable name. Never the value. */
|
|
185
|
+
name: string;
|
|
186
|
+
/** The file-store master passphrase gets called out separately. */
|
|
187
|
+
isMasterPassphrase: boolean;
|
|
188
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Wire-shared types for the standalone `secrets` CLI (PHNX-3989).
|
|
3
|
+
*
|
|
4
|
+
* The standalone engine (`@phnx-labs/secrets-cli`, extracted from what used to
|
|
5
|
+
* be `cli/src/lib/secrets/**`) owns every one of these shapes; this module only
|
|
6
|
+
* re-declares them so `secrets-client.ts` and its consumers keep exact static
|
|
7
|
+
* types across the process-client boundary with no runtime dependency on the
|
|
8
|
+
* (now deleted) in-repo engine. Keep byte-for-byte in sync with
|
|
9
|
+
* `secrets-cli/src/schema.ts` / `src/core/bundles.ts` — this is the one seam
|
|
10
|
+
* both sides legitimately re-declare rather than share a package for (see the
|
|
11
|
+
* `secrets-client.ts` docblock).
|
|
12
|
+
*/
|
|
13
|
+
// --- bundle document ---------------------------------------------------
|
|
14
|
+
export const SECRET_TYPES = [
|
|
15
|
+
'api-key',
|
|
16
|
+
'token',
|
|
17
|
+
'password',
|
|
18
|
+
'url',
|
|
19
|
+
'database-url',
|
|
20
|
+
'ssh-key',
|
|
21
|
+
'certificate',
|
|
22
|
+
'webhook',
|
|
23
|
+
'note',
|
|
24
|
+
];
|
|
@@ -46,10 +46,12 @@ export const shimsCheck = {
|
|
|
46
46
|
if (!ctx.dryRun && removeLegacyUserShim(agent))
|
|
47
47
|
fixed.push(`removed legacy ${cmd} shim`);
|
|
48
48
|
}
|
|
49
|
-
// Prune orphaned legacy command shims (browser/
|
|
50
|
-
//
|
|
49
|
+
// Prune orphaned legacy command shims (browser/sessions/… left by a removed
|
|
50
|
+
// install) whose baked AGENTS_BIN is dead — the current source never
|
|
51
51
|
// regenerates them, and they either die with exit 127 or shadow the real
|
|
52
|
-
// package bin on PATH. Only removes shims whose target install is gone
|
|
52
|
+
// package bin on PATH. Only removes shims whose target install is gone — plus
|
|
53
|
+
// the legacy `secrets` shim regardless: it re-enters `agents secrets`, which is
|
|
54
|
+
// a passthrough to the standalone binary since PHNX-3989, so it can only recurse.
|
|
53
55
|
if (!ctx.dryRun) {
|
|
54
56
|
for (const name of listShimFileNames()) {
|
|
55
57
|
if (pruneOrphanedCommandShim(name))
|
|
@@ -27,10 +27,9 @@
|
|
|
27
27
|
* module is the single place both rules live, so a new manifest has one obvious
|
|
28
28
|
* thing to call.
|
|
29
29
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* of its own — so it has no HOME to bake and was deliberately left alone.
|
|
30
|
+
* A third consumer that used to keep its own literal `SERVICE_LABEL` for a
|
|
31
|
+
* retire-only `bootout` — the in-repo secrets broker's launchd cleanup — moved
|
|
32
|
+
* out of this repo entirely with the standalone `secrets` engine (PHNX-3989).
|
|
34
33
|
*/
|
|
35
34
|
import * as crypto from 'crypto';
|
|
36
35
|
import * as os from 'os';
|
package/dist/lib/session/db.d.ts
CHANGED
|
@@ -817,6 +817,22 @@ export declare function buildFtsQuery(input: string): {
|
|
|
817
817
|
* so "higher = better" is consistent across all tiers.
|
|
818
818
|
*/
|
|
819
819
|
export declare function ftsSearch(input: string, limit?: number): FtsHit[];
|
|
820
|
+
/**
|
|
821
|
+
* Rewrite file_path for sessions whose path starts with any of `moves.from`,
|
|
822
|
+
* replacing that prefix with `moves.to` and clearing the matching scan_ledger
|
|
823
|
+
* entries so the next scan re-indexes from the new location.
|
|
824
|
+
*
|
|
825
|
+
* One transaction for the whole batch (PHNX-3940 T7): a migration that moves
|
|
826
|
+
* several homes into slots and several version dirs into trash must not leave
|
|
827
|
+
* the index half-rewritten. Longest `from` wins when prefixes nest, and each
|
|
828
|
+
* session row is rewritten at most once.
|
|
829
|
+
*
|
|
830
|
+
* Returns the number of session rows updated.
|
|
831
|
+
*/
|
|
832
|
+
export declare function reindexMovedSessionPaths(moves: ReadonlyArray<{
|
|
833
|
+
from: string;
|
|
834
|
+
to: string;
|
|
835
|
+
}>): number;
|
|
820
836
|
/**
|
|
821
837
|
* Rewrite file_path for all sessions whose path starts with oldPrefix, replacing
|
|
822
838
|
* it with newPrefix + the unchanged suffix. Also clears the matching scan_ledger
|
|
@@ -827,6 +843,8 @@ export declare function ftsSearch(input: string, limit?: number): FtsHit[];
|
|
|
827
843
|
* Returns the number of session rows updated.
|
|
828
844
|
*/
|
|
829
845
|
export declare function updateSessionFilePaths(oldPrefix: string, newPrefix: string): number;
|
|
846
|
+
/** Count indexed sessions whose transcript path sits under `prefix`. */
|
|
847
|
+
export declare function countSessionsWithFilePrefix(prefix: string): number;
|
|
830
848
|
/** Per-kind capture tallies for a browser task. Counts only -- never the bytes. */
|
|
831
849
|
interface BrowserCaptureCounts {
|
|
832
850
|
screenshot: number;
|
package/dist/lib/session/db.js
CHANGED
|
@@ -4317,6 +4317,44 @@ export function ftsSearch(input, limit = 200) {
|
|
|
4317
4317
|
hits.sort((a, b) => b.score - a.score);
|
|
4318
4318
|
return hits.slice(0, limit);
|
|
4319
4319
|
}
|
|
4320
|
+
/**
|
|
4321
|
+
* Rewrite file_path for sessions whose path starts with any of `moves.from`,
|
|
4322
|
+
* replacing that prefix with `moves.to` and clearing the matching scan_ledger
|
|
4323
|
+
* entries so the next scan re-indexes from the new location.
|
|
4324
|
+
*
|
|
4325
|
+
* One transaction for the whole batch (PHNX-3940 T7): a migration that moves
|
|
4326
|
+
* several homes into slots and several version dirs into trash must not leave
|
|
4327
|
+
* the index half-rewritten. Longest `from` wins when prefixes nest, and each
|
|
4328
|
+
* session row is rewritten at most once.
|
|
4329
|
+
*
|
|
4330
|
+
* Returns the number of session rows updated.
|
|
4331
|
+
*/
|
|
4332
|
+
export function reindexMovedSessionPaths(moves) {
|
|
4333
|
+
const usable = moves.filter((m) => m.from && m.from !== m.to);
|
|
4334
|
+
if (usable.length === 0)
|
|
4335
|
+
return 0;
|
|
4336
|
+
const db = getDB();
|
|
4337
|
+
const sorted = [...usable].sort((a, b) => b.from.length - a.from.length);
|
|
4338
|
+
return db.transaction(() => {
|
|
4339
|
+
let n = 0;
|
|
4340
|
+
const seen = new Set();
|
|
4341
|
+
const update = db.prepare(`UPDATE sessions SET file_path = ? WHERE id = ?`);
|
|
4342
|
+
const dropLedger = db.prepare(`DELETE FROM scan_ledger WHERE file_path = ?`);
|
|
4343
|
+
const select = db.prepare(`SELECT id, file_path FROM sessions WHERE file_path LIKE ?`);
|
|
4344
|
+
for (const { from, to } of sorted) {
|
|
4345
|
+
const rows = select.all(from + '%');
|
|
4346
|
+
for (const { id, file_path } of rows) {
|
|
4347
|
+
if (seen.has(id))
|
|
4348
|
+
continue;
|
|
4349
|
+
seen.add(id);
|
|
4350
|
+
update.run(to + file_path.slice(from.length), id);
|
|
4351
|
+
dropLedger.run(canonicalLedgerKey(file_path));
|
|
4352
|
+
n++;
|
|
4353
|
+
}
|
|
4354
|
+
}
|
|
4355
|
+
return n;
|
|
4356
|
+
})();
|
|
4357
|
+
}
|
|
4320
4358
|
/**
|
|
4321
4359
|
* Rewrite file_path for all sessions whose path starts with oldPrefix, replacing
|
|
4322
4360
|
* it with newPrefix + the unchanged suffix. Also clears the matching scan_ledger
|
|
@@ -4327,21 +4365,16 @@ export function ftsSearch(input, limit = 200) {
|
|
|
4327
4365
|
* Returns the number of session rows updated.
|
|
4328
4366
|
*/
|
|
4329
4367
|
export function updateSessionFilePaths(oldPrefix, newPrefix) {
|
|
4330
|
-
|
|
4331
|
-
|
|
4332
|
-
|
|
4333
|
-
|
|
4334
|
-
if (
|
|
4368
|
+
return reindexMovedSessionPaths([{ from: oldPrefix, to: newPrefix }]);
|
|
4369
|
+
}
|
|
4370
|
+
/** Count indexed sessions whose transcript path sits under `prefix`. */
|
|
4371
|
+
export function countSessionsWithFilePrefix(prefix) {
|
|
4372
|
+
if (!prefix)
|
|
4335
4373
|
return 0;
|
|
4336
|
-
const
|
|
4337
|
-
|
|
4338
|
-
|
|
4339
|
-
|
|
4340
|
-
db.prepare(`DELETE FROM scan_ledger WHERE file_path = ?`).run(canonicalLedgerKey(file_path));
|
|
4341
|
-
}
|
|
4342
|
-
});
|
|
4343
|
-
txn();
|
|
4344
|
-
return rows.length;
|
|
4374
|
+
const row = getDB()
|
|
4375
|
+
.prepare(`SELECT COUNT(*) AS c FROM sessions WHERE file_path LIKE ?`)
|
|
4376
|
+
.get(prefix + '%');
|
|
4377
|
+
return row.c;
|
|
4345
4378
|
}
|
|
4346
4379
|
/**
|
|
4347
4380
|
* Upsert one browser task's durable metadata.
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* background sync. Credentials come from the `r2.backups` secrets bundle (OS
|
|
12
12
|
* keychain on macOS, libsecret on Linux) — never from env or disk.
|
|
13
13
|
*/
|
|
14
|
-
import {
|
|
14
|
+
import { readAndResolveBundleEnvSync } from '../../secrets-client.js';
|
|
15
15
|
/** Secrets bundle holding the R2 credentials. */
|
|
16
16
|
export const SYNC_BUNDLE = 'r2.backups';
|
|
17
17
|
/**
|
|
@@ -30,7 +30,7 @@ function resolveR2Config() {
|
|
|
30
30
|
// and degrades to no-transport (sync disabled) with no prompt and no crash —
|
|
31
31
|
// unlock once (`agents secrets unlock r2.backups`) or set it no-ACL
|
|
32
32
|
// (`agents secrets policy r2.backups never`) for silent zero-friction sync.
|
|
33
|
-
const { env } =
|
|
33
|
+
const { env } = readAndResolveBundleEnvSync(SYNC_BUNDLE, { caller: 'session-transport', agentOnly: true });
|
|
34
34
|
const accountId = env.R2_ACCOUNT_ID?.trim();
|
|
35
35
|
const bucket = env.R2_BUCKET_NAME?.trim();
|
|
36
36
|
const accessKeyId = env.R2_ACCESS_KEY_ID?.trim();
|
|
@@ -3,22 +3,17 @@
|
|
|
3
3
|
*
|
|
4
4
|
* These live in their own LEAF module — importing only `node:crypto` and
|
|
5
5
|
* `node:fs` — on purpose. They used to sit in `computer/ssh-tunnel.ts`, whose
|
|
6
|
-
* own import graph
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* which threw `ReferenceError: Cannot access 'EXPECTED_TEAM_ID' before
|
|
19
|
-
* initialization` at `secrets/download-keychain.ts:45` for any entry point that
|
|
20
|
-
* reached `helper-download.ts` first (RUSH-3113). Keep this module a leaf: adding
|
|
21
|
-
* a local import here can reintroduce that cycle.
|
|
6
|
+
* own import graph reached `browser/drivers/ssh.ts` -> `browser/chrome.ts` ->
|
|
7
|
+
* the in-repo secrets engine's own keychain-helper downloader, which imported
|
|
8
|
+
* back into `helper-download.ts` while it was still evaluating — before
|
|
9
|
+
* `EXPECTED_TEAM_ID` was bound, throwing `ReferenceError: Cannot access
|
|
10
|
+
* 'EXPECTED_TEAM_ID' before initialization` for any entry point that reached
|
|
11
|
+
* `helper-download.ts` first (RUSH-3113). The secrets engine that closed that
|
|
12
|
+
* cycle is gone now (PHNX-3989 — the standalone `secrets` CLI downloads its own
|
|
13
|
+
* helper), but the discipline that fixed it still holds: keep this module a
|
|
14
|
+
* leaf, since `helper-download.ts` needs nothing beyond these two pure
|
|
15
|
+
* functions and adding a local import here can reintroduce a cycle with
|
|
16
|
+
* whatever imports it next.
|
|
22
17
|
*/
|
|
23
18
|
/** Pull the digest out of a `<sha256> <filename>` release asset. */
|
|
24
19
|
export declare function parseSha256Asset(text: string): string;
|
package/dist/lib/sha256-asset.js
CHANGED
|
@@ -3,22 +3,17 @@
|
|
|
3
3
|
*
|
|
4
4
|
* These live in their own LEAF module — importing only `node:crypto` and
|
|
5
5
|
* `node:fs` — on purpose. They used to sit in `computer/ssh-tunnel.ts`, whose
|
|
6
|
-
* own import graph
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* which threw `ReferenceError: Cannot access 'EXPECTED_TEAM_ID' before
|
|
19
|
-
* initialization` at `secrets/download-keychain.ts:45` for any entry point that
|
|
20
|
-
* reached `helper-download.ts` first (RUSH-3113). Keep this module a leaf: adding
|
|
21
|
-
* a local import here can reintroduce that cycle.
|
|
6
|
+
* own import graph reached `browser/drivers/ssh.ts` -> `browser/chrome.ts` ->
|
|
7
|
+
* the in-repo secrets engine's own keychain-helper downloader, which imported
|
|
8
|
+
* back into `helper-download.ts` while it was still evaluating — before
|
|
9
|
+
* `EXPECTED_TEAM_ID` was bound, throwing `ReferenceError: Cannot access
|
|
10
|
+
* 'EXPECTED_TEAM_ID' before initialization` for any entry point that reached
|
|
11
|
+
* `helper-download.ts` first (RUSH-3113). The secrets engine that closed that
|
|
12
|
+
* cycle is gone now (PHNX-3989 — the standalone `secrets` CLI downloads its own
|
|
13
|
+
* helper), but the discipline that fixed it still holds: keep this module a
|
|
14
|
+
* leaf, since `helper-download.ts` needs nothing beyond these two pure
|
|
15
|
+
* functions and adding a local import here can reintroduce a cycle with
|
|
16
|
+
* whatever imports it next.
|
|
22
17
|
*/
|
|
23
18
|
import { createHash } from 'node:crypto';
|
|
24
19
|
import * as fs from 'node:fs';
|
package/dist/lib/share/config.js
CHANGED
|
@@ -9,8 +9,7 @@
|
|
|
9
9
|
// `cloudflare` bundle.
|
|
10
10
|
import { randomBytes } from 'node:crypto';
|
|
11
11
|
import { readMeta, updateMeta } from '../state.js';
|
|
12
|
-
import {
|
|
13
|
-
import { secretsKeychainItem } from '../secrets/index.js';
|
|
12
|
+
import { bundleExistsSync as bundleExists, keychainRef, readAndResolveBundleEnvSync as readAndResolveBundleEnv, readBundleSync as readBundle, secretsKeychainItem, writeBundleWithItemsSync as writeBundleWithItems, } from '../secrets-client.js';
|
|
14
13
|
export const SHARE_BUNDLE = 'share';
|
|
15
14
|
export const SHARE_TOKEN_KEY = 'WRITE_TOKEN';
|
|
16
15
|
export const SHARE_TOKEN_ENV_KEY = 'SHARE_WRITE_TOKEN';
|
|
@@ -113,10 +112,12 @@ export function storeWriteToken(token) {
|
|
|
113
112
|
vars: {},
|
|
114
113
|
};
|
|
115
114
|
}
|
|
116
|
-
|
|
117
|
-
|
|
115
|
+
// writeBundleWithItems decides the ACL (keychain backend) purely from
|
|
116
|
+
// `bundle.policy === 'never'` — the fresh-bundle case above sets it
|
|
117
|
+
// explicitly, and an existing bundle already carries its own explicit tier.
|
|
118
118
|
bundle.vars[SHARE_TOKEN_KEY] = keychainRef(SHARE_TOKEN_KEY);
|
|
119
|
-
|
|
119
|
+
const item = secretsKeychainItem(bundle.name, SHARE_TOKEN_KEY);
|
|
120
|
+
writeBundleWithItems(bundle, new Map([[item, token]]));
|
|
120
121
|
}
|
|
121
122
|
/** Read the raw write token from the `share` secrets bundle. */
|
|
122
123
|
export function readWriteTokenFromBundle() {
|
|
@@ -178,6 +179,14 @@ export function readCloudflareCreds(bundle = DEFAULT_CF_BUNDLE, override) {
|
|
|
178
179
|
if (override?.apiToken) {
|
|
179
180
|
return { apiToken: override.apiToken, accountId: override.accountId ?? '' };
|
|
180
181
|
}
|
|
182
|
+
// Check existence first (same guard as readShareToken above): resolving a
|
|
183
|
+
// missing bundle through the process client surfaces an opaque transport code
|
|
184
|
+
// (e.g. LOCKED), never naming the bundle the user typed — so name it here.
|
|
185
|
+
if (!bundleExists(bundle)) {
|
|
186
|
+
throw new Error(`The '${bundle}' bundle does not exist. ` +
|
|
187
|
+
`Pass credentials directly with --token <t> [--account <id>], or create it: ` +
|
|
188
|
+
`agents secrets add ${bundle} CLOUDFLARE_API_TOKEN`);
|
|
189
|
+
}
|
|
181
190
|
const { env } = readAndResolveBundleEnv(bundle, {
|
|
182
191
|
caller: 'share',
|
|
183
192
|
// Setup is still a read; only `agents secrets unlock` may authenticate.
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
import type { AccountInfo } from './agents.js';
|
|
2
|
+
import type { AuthVerdict } from './auth-health.js';
|
|
2
3
|
import type { AgentId } from './types.js';
|
|
4
|
+
export type AccountVerdict = Exclude<AuthVerdict, 'unconfigured' | 'error'> | 'missing' | 'per-device' | 'ready';
|
|
5
|
+
export type AccountProvisioning = 'portable' | 'per-device';
|
|
3
6
|
/**
|
|
4
7
|
* The exact command that logs a given agent in — for warn banners and nudges.
|
|
5
8
|
* Driven off the registry `cliCommand` with the per-agent subcommand overrides
|
|
@@ -8,6 +11,29 @@ import type { AgentId } from './types.js';
|
|
|
8
11
|
* remaining agents (kimi, gemini, …) start their device/oauth flow on launch.
|
|
9
12
|
*/
|
|
10
13
|
export declare function loginHint(agentId: AgentId): string;
|
|
14
|
+
/**
|
|
15
|
+
* Exact action shown beside a non-live account. Every emitted command exists
|
|
16
|
+
* today — never a planned surface and never a hidden verb:
|
|
17
|
+
* - Per-device harnesses repair per box via `agents devices login`.
|
|
18
|
+
* - Named accounts re-auth through `agents accounts login <harness>#<name>`.
|
|
19
|
+
* A known account with no slot on a headed device is onboarded with
|
|
20
|
+
* `agents accounts add <harness> <name>`. A worker never runs an
|
|
21
|
+
* interactive login — the hint is `add.ts`'s worker refusal (add on the
|
|
22
|
+
* personal device; this box is provisioned from the durable credential).
|
|
23
|
+
* - Unnamed legacy homes use the same version-targeted command shape as
|
|
24
|
+
* doctor, so the hint never logs a different/default home in by accident.
|
|
25
|
+
* - `unverified` emits nothing: the probe could not confirm state (e.g. a
|
|
26
|
+
* worker whose token lacks the usage scope), so there is nothing to repair.
|
|
27
|
+
*/
|
|
28
|
+
export declare function fixFor(input: {
|
|
29
|
+
agent: AgentId;
|
|
30
|
+
verdict: AccountVerdict;
|
|
31
|
+
name?: string | null;
|
|
32
|
+
version?: string | null;
|
|
33
|
+
provisioning?: AccountProvisioning;
|
|
34
|
+
/** When false, this named account has no slot on this device yet. */
|
|
35
|
+
hasSlot?: boolean;
|
|
36
|
+
}): string | null;
|
|
11
37
|
/**
|
|
12
38
|
* Whether `agents run` should probe login state before launching. True only for
|
|
13
39
|
* a launch that actually opens the interactive TUI — where discovering a logged-out
|
package/dist/lib/signin-badge.js
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
* on it (the run preflight) WARN and continue; they never block.
|
|
10
10
|
*/
|
|
11
11
|
import chalk from 'chalk';
|
|
12
|
+
import { addWorkerRefusal } from './accounts/add.js';
|
|
12
13
|
import { AGENTS } from './agents.js';
|
|
14
|
+
import { CONFIG_ENV_ISOLATED_AGENTS } from './installations/shims.js';
|
|
13
15
|
/**
|
|
14
16
|
* The exact command that logs a given agent in — for warn banners and nudges.
|
|
15
17
|
* Driven off the registry `cliCommand` with the per-agent subcommand overrides
|
|
@@ -34,6 +36,46 @@ export function loginHint(agentId) {
|
|
|
34
36
|
return cli;
|
|
35
37
|
}
|
|
36
38
|
}
|
|
39
|
+
/**
|
|
40
|
+
* Exact action shown beside a non-live account. Every emitted command exists
|
|
41
|
+
* today — never a planned surface and never a hidden verb:
|
|
42
|
+
* - Per-device harnesses repair per box via `agents devices login`.
|
|
43
|
+
* - Named accounts re-auth through `agents accounts login <harness>#<name>`.
|
|
44
|
+
* A known account with no slot on a headed device is onboarded with
|
|
45
|
+
* `agents accounts add <harness> <name>`. A worker never runs an
|
|
46
|
+
* interactive login — the hint is `add.ts`'s worker refusal (add on the
|
|
47
|
+
* personal device; this box is provisioned from the durable credential).
|
|
48
|
+
* - Unnamed legacy homes use the same version-targeted command shape as
|
|
49
|
+
* doctor, so the hint never logs a different/default home in by accident.
|
|
50
|
+
* - `unverified` emits nothing: the probe could not confirm state (e.g. a
|
|
51
|
+
* worker whose token lacks the usage scope), so there is nothing to repair.
|
|
52
|
+
*/
|
|
53
|
+
export function fixFor(input) {
|
|
54
|
+
const { agent, verdict } = input;
|
|
55
|
+
if (verdict === 'live' || verdict === 'rate_limited' || verdict === 'unverified' || verdict === 'ready')
|
|
56
|
+
return null;
|
|
57
|
+
if (input.provisioning === 'per-device' || verdict === 'per-device') {
|
|
58
|
+
return `agents devices login --agents ${agent}`;
|
|
59
|
+
}
|
|
60
|
+
if (input.name) {
|
|
61
|
+
const worker = addWorkerRefusal(agent, input.name);
|
|
62
|
+
if (worker)
|
|
63
|
+
return worker;
|
|
64
|
+
if (input.hasSlot === false)
|
|
65
|
+
return `agents accounts add ${agent} ${input.name}`;
|
|
66
|
+
return `agents accounts login ${agent}#${input.name}`;
|
|
67
|
+
}
|
|
68
|
+
const version = input.version ?? null;
|
|
69
|
+
if (!version || !CONFIG_ENV_ISOLATED_AGENTS.includes(agent))
|
|
70
|
+
return loginHint(agent);
|
|
71
|
+
if (agent === 'claude')
|
|
72
|
+
return `agents run ${agent}@${version}, then /login`;
|
|
73
|
+
if (agent === 'codex' || agent === 'grok')
|
|
74
|
+
return `agents run ${agent}@${version} -- login`;
|
|
75
|
+
if (agent === 'opencode')
|
|
76
|
+
return `agents run ${agent}@${version} -- auth login`;
|
|
77
|
+
return `agents run ${agent}@${version}`;
|
|
78
|
+
}
|
|
37
79
|
/**
|
|
38
80
|
* Whether `agents run` should probe login state before launching. True only for
|
|
39
81
|
* a launch that actually opens the interactive TUI — where discovering a logged-out
|