@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.
Files changed (259) hide show
  1. package/CHANGELOG.md +96 -0
  2. package/README.md +80 -53
  3. package/dist/bootstrap.d.ts +7 -6
  4. package/dist/bootstrap.js +20 -27
  5. package/dist/cli/command-registry.js +5 -1
  6. package/dist/commands/accounts.d.ts +6 -13
  7. package/dist/commands/accounts.js +330 -143
  8. package/dist/commands/alias.js +7 -3
  9. package/dist/commands/apply.js +1 -1
  10. package/dist/commands/auth-mint.d.ts +7 -3
  11. package/dist/commands/auth-mint.js +21 -9
  12. package/dist/commands/auth.js +2 -3
  13. package/dist/commands/browser.js +10 -10
  14. package/dist/commands/daemon.d.ts +7 -3
  15. package/dist/commands/daemon.js +40 -25
  16. package/dist/commands/doctor.js +28 -2
  17. package/dist/commands/exec.js +87 -39
  18. package/dist/commands/fleet-capture.js +21 -2
  19. package/dist/commands/harness-wizard.js +2 -2
  20. package/dist/commands/lease.js +7 -12
  21. package/dist/commands/profiles.d.ts +2 -2
  22. package/dist/commands/profiles.js +20 -13
  23. package/dist/commands/repo.js +3 -3
  24. package/dist/commands/run-account-picker.d.ts +3 -3
  25. package/dist/commands/run-account-picker.js +29 -30
  26. package/dist/commands/secrets-passthrough.d.ts +20 -0
  27. package/dist/commands/secrets-passthrough.js +43 -0
  28. package/dist/commands/setup-accounts.d.ts +3 -2
  29. package/dist/commands/setup-accounts.js +4 -4
  30. package/dist/commands/setup-secrets.d.ts +16 -21
  31. package/dist/commands/setup-secrets.js +43 -224
  32. package/dist/commands/ssh.js +2 -2
  33. package/dist/commands/sync.js +1 -1
  34. package/dist/commands/update.d.ts +10 -0
  35. package/dist/commands/update.js +43 -40
  36. package/dist/commands/versions.d.ts +11 -11
  37. package/dist/commands/versions.js +131 -83
  38. package/dist/commands/view.d.ts +1 -9
  39. package/dist/commands/view.js +41 -55
  40. package/dist/commands/webhook.js +5 -5
  41. package/dist/commands/workflows.js +2 -1
  42. package/dist/index.d.ts +12 -12
  43. package/dist/index.js +13 -42
  44. package/dist/lib/account-capabilities.d.ts +1 -1
  45. package/dist/lib/account-capabilities.js +1 -1
  46. package/dist/lib/account-catalog.d.ts +121 -6
  47. package/dist/lib/account-catalog.js +421 -7
  48. package/dist/lib/account-registry.d.ts +8 -30
  49. package/dist/lib/account-registry.js +36 -79
  50. package/dist/lib/account-schema.d.ts +1 -1
  51. package/dist/lib/account-schema.js +1 -1
  52. package/dist/lib/accounting/account-pool-collect.js +16 -4
  53. package/dist/lib/accounting/rotate.d.ts +20 -7
  54. package/dist/lib/accounting/rotate.js +89 -13
  55. package/dist/lib/accounting/usage.js +11 -16
  56. package/dist/lib/accounts/add.d.ts +138 -0
  57. package/dist/lib/accounts/add.js +651 -0
  58. package/dist/lib/accounts/migrate.d.ts +117 -0
  59. package/dist/lib/accounts/migrate.js +536 -0
  60. package/dist/lib/accounts/slots.d.ts +13 -0
  61. package/dist/lib/accounts/slots.js +100 -0
  62. package/dist/lib/agent-spec/agents.d.ts +16 -0
  63. package/dist/lib/agent-spec/agents.js +38 -4
  64. package/dist/lib/app-bundle-install.js +5 -4
  65. package/dist/lib/auth-health.d.ts +3 -0
  66. package/dist/lib/auth-health.js +11 -0
  67. package/dist/lib/auth-mint.d.ts +52 -16
  68. package/dist/lib/auth-mint.js +117 -39
  69. package/dist/lib/browser/chrome.d.ts +1 -1
  70. package/dist/lib/browser/chrome.js +5 -5
  71. package/dist/lib/byok-usage.js +3 -3
  72. package/dist/lib/claude-account-token.d.ts +47 -3
  73. package/dist/lib/claude-account-token.js +172 -50
  74. package/dist/lib/cloud/antigravity.js +4 -4
  75. package/dist/lib/cloud/cursor.js +4 -4
  76. package/dist/lib/crabbox/cli.d.ts +1 -1
  77. package/dist/lib/crabbox/cli.js +6 -6
  78. package/dist/lib/crabbox/runtimes.d.ts +3 -3
  79. package/dist/lib/crabbox/runtimes.js +5 -5
  80. package/dist/lib/daemon/account-state-daemon-service.d.ts +37 -1
  81. package/dist/lib/daemon/account-state-daemon-service.js +199 -3
  82. package/dist/lib/daemon/auth-sync-service.js +32 -1
  83. package/dist/lib/daemon/daemon.d.ts +6 -16
  84. package/dist/lib/daemon/daemon.js +52 -97
  85. package/dist/lib/daemon/daemon.test-fixture.d.ts +7 -9
  86. package/dist/lib/daemon/daemon.test-fixture.js +22 -40
  87. package/dist/lib/daemon/harness-update-service.d.ts +1 -1
  88. package/dist/lib/daemon/harness-update-service.js +1 -1
  89. package/dist/lib/daemon/runner.d.ts +15 -3
  90. package/dist/lib/daemon/runner.js +49 -24
  91. package/dist/lib/daemon-health.d.ts +1 -2
  92. package/dist/lib/daemon-health.js +7 -6
  93. package/dist/lib/daemon-services.d.ts +1 -1
  94. package/dist/lib/daemon-services.js +1 -11
  95. package/dist/lib/daemon-webhooks.d.ts +8 -7
  96. package/dist/lib/daemon-webhooks.js +10 -9
  97. package/dist/lib/device-config.js +1 -1
  98. package/dist/lib/devices/doctor-findings.d.ts +1 -1
  99. package/dist/lib/devices/harness-inventory.d.ts +39 -0
  100. package/dist/lib/devices/harness-inventory.js +126 -4
  101. package/dist/lib/doctor-diff.js +2 -1
  102. package/dist/lib/exec-account-home.d.ts +38 -0
  103. package/dist/lib/exec-account-home.js +164 -0
  104. package/dist/lib/exec.d.ts +30 -0
  105. package/dist/lib/exec.js +101 -31
  106. package/dist/lib/fleet/apply.d.ts +2 -2
  107. package/dist/lib/fleet/apply.js +4 -4
  108. package/dist/lib/fleet/auth-sync.js +4 -3
  109. package/dist/lib/fleet-shared-repo-sync.js +6 -9
  110. package/dist/lib/harness/adapter.d.ts +7 -7
  111. package/dist/lib/harness/adapter.js +10 -6
  112. package/dist/lib/harness/adapters/grok.js +8 -3
  113. package/dist/lib/harness/adapters/muse.js +1 -1
  114. package/dist/lib/harness/adapters/opencode.js +12 -3
  115. package/dist/lib/harness-auth-capabilities.d.ts +61 -0
  116. package/dist/lib/harness-auth-capabilities.js +52 -0
  117. package/dist/lib/helper-versions.d.ts +6 -4
  118. package/dist/lib/helper-versions.js +5 -4
  119. package/dist/lib/hosts/credential-transport.d.ts +10 -0
  120. package/dist/lib/hosts/credential-transport.js +37 -0
  121. package/dist/lib/hosts/dispatch.d.ts +7 -0
  122. package/dist/lib/hosts/dispatch.js +13 -6
  123. package/dist/lib/identity/client.d.ts +3 -3
  124. package/dist/lib/identity/client.js +3 -3
  125. package/dist/lib/installations/index.d.ts +1 -1
  126. package/dist/lib/installations/index.js +1 -1
  127. package/dist/lib/installations/migrate.js +9 -0
  128. package/dist/lib/installations/resolve.js +1 -1
  129. package/dist/lib/installations/shims.d.ts +21 -4
  130. package/dist/lib/installations/shims.js +86 -5
  131. package/dist/lib/installations/store.d.ts +43 -0
  132. package/dist/lib/installations/store.js +75 -7
  133. package/dist/lib/installations/versions.js +1 -1
  134. package/dist/lib/menubar/install-menubar.d.ts +3 -3
  135. package/dist/lib/menubar/install-menubar.js +3 -3
  136. package/dist/lib/native-accounts.d.ts +35 -0
  137. package/dist/lib/native-accounts.js +41 -0
  138. package/dist/lib/net-close.d.ts +11 -0
  139. package/dist/lib/net-close.js +25 -0
  140. package/dist/lib/openclaw-keychain.js +27 -1
  141. package/dist/lib/profiles.js +22 -9
  142. package/dist/lib/project-resources.js +1 -1
  143. package/dist/lib/reserved-stores.d.ts +53 -0
  144. package/dist/lib/reserved-stores.js +120 -0
  145. package/dist/lib/secrets-client.d.ts +199 -0
  146. package/dist/lib/secrets-client.js +718 -0
  147. package/dist/lib/secrets-policy.d.ts +235 -0
  148. package/dist/lib/secrets-policy.js +505 -0
  149. package/dist/lib/secrets-types.d.ts +188 -0
  150. package/dist/lib/secrets-types.js +24 -0
  151. package/dist/lib/self-heal/checks/shims.js +5 -3
  152. package/dist/lib/service-manifest.js +3 -4
  153. package/dist/lib/session/db.d.ts +18 -0
  154. package/dist/lib/session/db.js +47 -14
  155. package/dist/lib/session/sync/config.js +2 -2
  156. package/dist/lib/sha256-asset.d.ts +11 -16
  157. package/dist/lib/sha256-asset.js +11 -16
  158. package/dist/lib/share/config.js +14 -5
  159. package/dist/lib/signin-badge.d.ts +26 -0
  160. package/dist/lib/signin-badge.js +42 -0
  161. package/dist/lib/staleness/detectors/workflows.js +3 -105
  162. package/dist/lib/staleness/writers/workflows.js +2 -1
  163. package/dist/lib/state.d.ts +7 -4
  164. package/dist/lib/state.js +18 -7
  165. package/dist/lib/sync-umbrella.js +2 -2
  166. package/dist/lib/teams/agents.js +1 -1
  167. package/dist/lib/types.d.ts +74 -33
  168. package/dist/lib/view-types.d.ts +6 -3
  169. package/dist/lib/workflows-registry.d.ts +71 -0
  170. package/dist/lib/workflows-registry.js +280 -0
  171. package/dist/lib/workflows.d.ts +21 -21
  172. package/dist/lib/workflows.js +12 -327
  173. package/package.json +2 -3
  174. package/scripts/postinstall.js +35 -30
  175. package/dist/commands/secrets-import.d.ts +0 -18
  176. package/dist/commands/secrets-import.js +0 -74
  177. package/dist/commands/secrets-migrate.d.ts +0 -25
  178. package/dist/commands/secrets-migrate.js +0 -334
  179. package/dist/commands/secrets-rotate-passphrase.d.ts +0 -17
  180. package/dist/commands/secrets-rotate-passphrase.js +0 -96
  181. package/dist/commands/secrets-sync.d.ts +0 -11
  182. package/dist/commands/secrets-sync.js +0 -153
  183. package/dist/commands/secrets-vault.d.ts +0 -10
  184. package/dist/commands/secrets-vault.js +0 -130
  185. package/dist/commands/secrets.d.ts +0 -212
  186. package/dist/commands/secrets.js +0 -3030
  187. package/dist/lib/accounts/connect.d.ts +0 -176
  188. package/dist/lib/accounts/connect.js +0 -453
  189. package/dist/lib/daemon/keychain-reap-service.d.ts +0 -17
  190. package/dist/lib/daemon/keychain-reap-service.js +0 -32
  191. package/dist/lib/daemon/secrets-broker-service.d.ts +0 -21
  192. package/dist/lib/daemon/secrets-broker-service.js +0 -51
  193. package/dist/lib/secrets/agent.d.ts +0 -358
  194. package/dist/lib/secrets/agent.js +0 -1291
  195. package/dist/lib/secrets/audit.d.ts +0 -46
  196. package/dist/lib/secrets/audit.js +0 -101
  197. package/dist/lib/secrets/bundles.d.ts +0 -290
  198. package/dist/lib/secrets/bundles.js +0 -1547
  199. package/dist/lib/secrets/download-keychain.d.ts +0 -47
  200. package/dist/lib/secrets/download-keychain.js +0 -70
  201. package/dist/lib/secrets/drivers/rush.d.ts +0 -14
  202. package/dist/lib/secrets/drivers/rush.js +0 -90
  203. package/dist/lib/secrets/fallback.d.ts +0 -48
  204. package/dist/lib/secrets/fallback.js +0 -48
  205. package/dist/lib/secrets/filestore.d.ts +0 -222
  206. package/dist/lib/secrets/filestore.js +0 -1099
  207. package/dist/lib/secrets/headless.d.ts +0 -43
  208. package/dist/lib/secrets/headless.js +0 -56
  209. package/dist/lib/secrets/icloud-import.d.ts +0 -79
  210. package/dist/lib/secrets/icloud-import.js +0 -206
  211. package/dist/lib/secrets/index.d.ts +0 -451
  212. package/dist/lib/secrets/index.js +0 -1568
  213. package/dist/lib/secrets/install-helper.d.ts +0 -72
  214. package/dist/lib/secrets/install-helper.js +0 -245
  215. package/dist/lib/secrets/lease.d.ts +0 -25
  216. package/dist/lib/secrets/lease.js +0 -44
  217. package/dist/lib/secrets/linux.d.ts +0 -77
  218. package/dist/lib/secrets/linux.js +0 -393
  219. package/dist/lib/secrets/list-filter.d.ts +0 -109
  220. package/dist/lib/secrets/list-filter.js +0 -261
  221. package/dist/lib/secrets/mcp.d.ts +0 -93
  222. package/dist/lib/secrets/mcp.js +0 -211
  223. package/dist/lib/secrets/profiles.d.ts +0 -10
  224. package/dist/lib/secrets/profiles.js +0 -13
  225. package/dist/lib/secrets/push.d.ts +0 -133
  226. package/dist/lib/secrets/push.js +0 -273
  227. package/dist/lib/secrets/rc-hygiene.d.ts +0 -63
  228. package/dist/lib/secrets/rc-hygiene.js +0 -143
  229. package/dist/lib/secrets/read-backoff.d.ts +0 -27
  230. package/dist/lib/secrets/read-backoff.js +0 -64
  231. package/dist/lib/secrets/reaper.d.ts +0 -90
  232. package/dist/lib/secrets/reaper.js +0 -243
  233. package/dist/lib/secrets/remote.d.ts +0 -152
  234. package/dist/lib/secrets/remote.js +0 -344
  235. package/dist/lib/secrets/reserved-sync.d.ts +0 -66
  236. package/dist/lib/secrets/reserved-sync.js +0 -147
  237. package/dist/lib/secrets/scope.d.ts +0 -26
  238. package/dist/lib/secrets/scope.js +0 -29
  239. package/dist/lib/secrets/session-store.d.ts +0 -107
  240. package/dist/lib/secrets/session-store.js +0 -342
  241. package/dist/lib/secrets/sync-backend.d.ts +0 -48
  242. package/dist/lib/secrets/sync-backend.js +0 -13
  243. package/dist/lib/secrets/sync-commands.d.ts +0 -21
  244. package/dist/lib/secrets/sync-commands.js +0 -21
  245. package/dist/lib/secrets/sync.d.ts +0 -48
  246. package/dist/lib/secrets/sync.js +0 -237
  247. package/dist/lib/secrets/unlock-hints.d.ts +0 -27
  248. package/dist/lib/secrets/unlock-hints.js +0 -36
  249. package/dist/lib/secrets/usage-db.d.ts +0 -46
  250. package/dist/lib/secrets/usage-db.js +0 -96
  251. package/dist/lib/secrets/vault-age-helper.d.ts +0 -1
  252. package/dist/lib/secrets/vault-age-helper.js +0 -34
  253. package/dist/lib/secrets/vault.d.ts +0 -49
  254. package/dist/lib/secrets/vault.js +0 -399
  255. package/dist/lib/secrets/windows.d.ts +0 -81
  256. package/dist/lib/secrets/windows.js +0 -556
  257. package/scripts/install-helper.js +0 -97
  258. /package/dist/lib/{secrets/sync-passphrase.d.ts → sync-passphrase.d.ts} +0 -0
  259. /package/dist/lib/{secrets/sync-passphrase.js → sync-passphrase.js} +0 -0
@@ -1,115 +1,13 @@
1
- /**
2
- * Workflows detector — scans the agent-specific on-disk layout for synced
3
- * workflow names (Claude WORKFLOW.md trees, Kimi flow skills, Antigravity
4
- * global_workflows, Goose recipes, OpenClaw Lobster, Grok Rhai).
5
- */
6
- import * as fs from 'fs';
7
- import * as os from 'os';
8
- import * as path from 'path';
9
- import * as yaml from 'yaml';
10
1
  import { capableAgents } from '../../capabilities.js';
11
- import { grokWorkflowMarker } from '../../workflows.js';
2
+ import { workflowTarget } from '../../workflows-registry.js';
12
3
  import { lazyAgentMap } from '../writers/lazy-map.js';
13
4
  function buildWorkflowsDetector(agent) {
14
5
  return {
15
6
  kind: 'workflows',
16
7
  agent,
17
8
  list({ versionHome }) {
18
- if (agent === 'kimi') {
19
- const skillsDir = path.join(versionHome, '.kimi-code', 'skills');
20
- if (!fs.existsSync(skillsDir))
21
- return [];
22
- return fs.readdirSync(skillsDir, { withFileTypes: true })
23
- .filter(d => d.isDirectory() && fs.existsSync(path.join(skillsDir, d.name, 'SKILL.md')))
24
- .filter(d => {
25
- try {
26
- const skill = fs.readFileSync(path.join(skillsDir, d.name, 'SKILL.md'), 'utf-8');
27
- const lines = skill.split('\n');
28
- if (lines[0] !== '---')
29
- return false;
30
- const endIndex = lines.slice(1).findIndex(l => l === '---');
31
- if (endIndex < 0)
32
- return false;
33
- const parsed = yaml.parse(lines.slice(1, endIndex + 1).join('\n'));
34
- return parsed?.type === 'flow' && parsed.agents_workflow === d.name;
35
- }
36
- catch {
37
- return false;
38
- }
39
- })
40
- .map(d => d.name);
41
- }
42
- if (agent === 'antigravity') {
43
- // Antigravity user workflows are HOME-global and shared across versions,
44
- // not version-isolated — see workflows.ts:antigravityWorkflowsDir(). agy
45
- // scans the real ~/.gemini/config/global_workflows/, so the detector reads
46
- // the same shared dir the writer targets (versionHome is intentionally unused).
47
- const dir = path.join(process.env.HOME ?? os.homedir(), '.gemini', 'config', 'global_workflows');
48
- if (!fs.existsSync(dir))
49
- return [];
50
- return fs.readdirSync(dir, { withFileTypes: true })
51
- .filter(d => d.isFile() && d.name.endsWith('.md') && !d.name.startsWith('.'))
52
- .filter(d => {
53
- try {
54
- const content = fs.readFileSync(path.join(dir, d.name), 'utf-8');
55
- const lines = content.split('\n');
56
- if (lines[0] !== '---')
57
- return false;
58
- const endIndex = lines.slice(1).findIndex(l => l === '---');
59
- if (endIndex < 0)
60
- return false;
61
- const parsed = yaml.parse(lines.slice(1, endIndex + 1).join('\n'));
62
- return parsed?.agents_workflow === d.name.slice(0, -'.md'.length);
63
- }
64
- catch {
65
- return false;
66
- }
67
- })
68
- .map(d => d.name.slice(0, -'.md'.length));
69
- }
70
- if (agent === 'goose') {
71
- const recipesDir = path.join(versionHome, '.config', 'goose', 'recipes');
72
- if (!fs.existsSync(recipesDir))
73
- return [];
74
- return fs.readdirSync(recipesDir, { withFileTypes: true })
75
- .filter(d => d.isFile() && d.name.endsWith('.yaml') && !d.name.startsWith('.'))
76
- .map(d => d.name.slice(0, -'.yaml'.length));
77
- }
78
- if (agent === 'openclaw') {
79
- const dir = path.join(versionHome, '.openclaw', 'workflows');
80
- if (!fs.existsSync(dir))
81
- return [];
82
- return fs.readdirSync(dir, { withFileTypes: true })
83
- .filter(d => d.isFile() && d.name.endsWith('.lobster') && !d.name.startsWith('.'))
84
- .filter(d => {
85
- try {
86
- const parsed = yaml.parse(fs.readFileSync(path.join(dir, d.name), 'utf-8'));
87
- const env = parsed && typeof parsed === 'object' && parsed.env && typeof parsed.env === 'object' && !Array.isArray(parsed.env)
88
- ? parsed.env
89
- : {};
90
- return env.AGENTS_CLI_WORKFLOW === d.name.slice(0, -'.lobster'.length);
91
- }
92
- catch {
93
- return false;
94
- }
95
- })
96
- .map(d => d.name.slice(0, -'.lobster'.length));
97
- }
98
- if (agent === 'grok') {
99
- const workflowsDir = path.join(versionHome, '.grok', 'workflows');
100
- if (!fs.existsSync(workflowsDir))
101
- return [];
102
- return fs.readdirSync(workflowsDir, { withFileTypes: true })
103
- .filter(d => d.isFile() && d.name.endsWith('.rhai') && !d.name.startsWith('.'))
104
- .filter(d => grokWorkflowMarker(path.join(workflowsDir, d.name)) === d.name.slice(0, -'.rhai'.length))
105
- .map(d => d.name.slice(0, -'.rhai'.length));
106
- }
107
- const workflowsDir = path.join(versionHome, 'workflows');
108
- if (!fs.existsSync(workflowsDir))
109
- return [];
110
- return fs.readdirSync(workflowsDir, { withFileTypes: true })
111
- .filter(d => d.isDirectory() && fs.existsSync(path.join(workflowsDir, d.name, 'WORKFLOW.md')))
112
- .map(d => d.name);
9
+ const target = workflowTarget(agent);
10
+ return target.names(target.dir(versionHome));
113
11
  },
114
12
  };
115
13
  }
@@ -1,5 +1,6 @@
1
1
  import { capableAgents } from '../../capabilities.js';
2
- import { listInstalledWorkflows, syncWorkflowToVersion } from '../../workflows.js';
2
+ import { listInstalledWorkflows } from '../../workflows.js';
3
+ import { syncWorkflowToVersion } from '../../workflows-registry.js';
3
4
  import { lazyAgentMap } from './lazy-map.js';
4
5
  function buildWorkflowsWriter(agent) {
5
6
  return {
@@ -123,10 +123,13 @@ export declare function getUserSecretsDir(): string;
123
123
  * AGENTS_SECRETS_DB without racing the module-load capture of USER_SECRETS_DIR —
124
124
  * mirrors the AGENTS_EVENTS_PATH / AGENTS_DEVICES_DIR escape hatches. Holds only
125
125
  * value-free usage telemetry (which bundle was created/imported/exported/viewed/
126
- * accessed/unlocked, when, by whom), never a secret value. It is a derived index
127
- * fed FROM the emitSecretAudit chokepoint alongside the append-only
128
- * ~/.agents/.history/events/YYYY-MM-DD audit log — the same way sessions.db indexes session
129
- * metadata off the real session flow — not a second write path.
126
+ * accessed/unlocked, when, by whom), never a secret value. It used to be a
127
+ * derived index fed FROM the in-repo secrets engine's own emitSecretAudit
128
+ * chokepoint — not a second write path — the same way sessions.db indexes
129
+ * session metadata off the real session flow. That engine (and its audit
130
+ * emission) moved out of this repo entirely with the standalone `secrets`
131
+ * engine (PHNX-3989), so nothing writes this DB from agents-cli today; the
132
+ * read-side queries in `analytics/usage-db.ts` have no current caller.
130
133
  */
131
134
  export declare function getSecretsDbPath(): string;
132
135
  /**
package/dist/lib/state.js CHANGED
@@ -396,10 +396,13 @@ export function getUserSecretsDir() { return USER_SECRETS_DIR; }
396
396
  * AGENTS_SECRETS_DB without racing the module-load capture of USER_SECRETS_DIR —
397
397
  * mirrors the AGENTS_EVENTS_PATH / AGENTS_DEVICES_DIR escape hatches. Holds only
398
398
  * value-free usage telemetry (which bundle was created/imported/exported/viewed/
399
- * accessed/unlocked, when, by whom), never a secret value. It is a derived index
400
- * fed FROM the emitSecretAudit chokepoint alongside the append-only
401
- * ~/.agents/.history/events/YYYY-MM-DD audit log — the same way sessions.db indexes session
402
- * metadata off the real session flow — not a second write path.
399
+ * accessed/unlocked, when, by whom), never a secret value. It used to be a
400
+ * derived index fed FROM the in-repo secrets engine's own emitSecretAudit
401
+ * chokepoint — not a second write path — the same way sessions.db indexes
402
+ * session metadata off the real session flow. That engine (and its audit
403
+ * emission) moved out of this repo entirely with the standalone `secrets`
404
+ * engine (PHNX-3989), so nothing writes this DB from agents-cli today; the
405
+ * read-side queries in `analytics/usage-db.ts` have no current caller.
403
406
  */
404
407
  export function getSecretsDbPath() {
405
408
  return process.env.AGENTS_SECRETS_DB ?? path.join(USER_SECRETS_DIR, 'secrets.db');
@@ -1332,7 +1335,9 @@ export function writeMetaUnlocked(meta) {
1332
1335
  // In-flight connect attempts (PHNX-3940), device-scoped like homes.
1333
1336
  const accountsPending = deviceAccounts?.pendingConnects && Object.keys(deviceAccounts.pendingConnects).length > 0
1334
1337
  ? deviceAccounts.pendingConnects : undefined;
1335
- if (accountsNative || accountsBindings || accountsHomes || accountsPending) {
1338
+ const accountsSlots = deviceAccounts?.slots && Object.keys(deviceAccounts.slots).length > 0
1339
+ ? deviceAccounts.slots : undefined;
1340
+ if (accountsNative || accountsBindings || accountsHomes || accountsPending || accountsSlots) {
1336
1341
  const da = {};
1337
1342
  if (accountsNative)
1338
1343
  da.native = accountsNative;
@@ -1342,6 +1347,8 @@ export function writeMetaUnlocked(meta) {
1342
1347
  da.homes = accountsHomes;
1343
1348
  if (accountsPending)
1344
1349
  da.pendingConnects = accountsPending;
1350
+ if (accountsSlots)
1351
+ da.slots = accountsSlots;
1345
1352
  doc.accounts = da;
1346
1353
  }
1347
1354
  else if (writesDeviceAccounts)
@@ -1487,12 +1494,16 @@ function overlayMachineLocal(meta) {
1487
1494
  if (acc.pendingConnects !== undefined && !isMap(acc.pendingConnects)) {
1488
1495
  throw new Error(`Device config corrupted at ${devicePath}: accounts.pendingConnects must be a map.`);
1489
1496
  }
1497
+ if (acc.slots !== undefined && !isMap(acc.slots)) {
1498
+ throw new Error(`Device config corrupted at ${devicePath}: accounts.slots must be a map.`);
1499
+ }
1490
1500
  const native = acc.native;
1491
1501
  const bindings = acc.bindings;
1492
1502
  const homes = acc.homes;
1493
1503
  const pendingConnects = acc.pendingConnects;
1494
- if (native || bindings || homes || pendingConnects)
1495
- meta.deviceAccounts = { ...(native ? { native } : {}), ...(bindings ? { bindings } : {}), ...(homes ? { homes } : {}), ...(pendingConnects ? { pendingConnects } : {}) };
1504
+ const slots = acc.slots;
1505
+ if (native || bindings || homes || pendingConnects || slots)
1506
+ meta.deviceAccounts = { ...(native ? { native } : {}), ...(bindings ? { bindings } : {}), ...(homes ? { homes } : {}), ...(pendingConnects ? { pendingConnects } : {}), ...(slots ? { slots } : {}) };
1496
1507
  }
1497
1508
  if (Object.prototype.hasOwnProperty.call(dm, 'routines')) {
1498
1509
  if (!Array.isArray(dm.routines) || dm.routines.some((name) => typeof name !== 'string')) {
@@ -17,8 +17,8 @@
17
17
  */
18
18
  import { pullRepo, adoptUserRepoIfNeeded } from './git.js';
19
19
  import { getUserAgentsDir, getEnabledExtraRepos } from './state.js';
20
- import { listRemoteBundles, pullBundle } from './secrets/sync.js';
21
- import { SYNC_PASSPHRASE_ENV } from './secrets/sync-passphrase.js';
20
+ import { listRemoteBundles, pullBundle } from './secrets-client.js';
21
+ import { SYNC_PASSPHRASE_ENV } from './sync-passphrase.js';
22
22
  /**
23
23
  * Decide which stages run. Pure — no I/O. Semantics:
24
24
  * bare (no flags) fetch repos, then reconcile
@@ -21,7 +21,7 @@ import { debug } from './debug.js';
21
21
  import { getAgentsDir as getSystemAgentsDir, getShimsDir } from '../state.js';
22
22
  import { AGENTS, getAccountInfo } from '../agents.js';
23
23
  import { resolveVersion, isVersionInstalled, verifyInstalledBinaryLaunches } from '../installations/versions.js';
24
- import { sanitizeProcessEnv } from '../secrets/bundles.js';
24
+ import { sanitizeProcessEnv } from '../secrets-client.js';
25
25
  import { resolveActor, actorEnv } from '../actor.js';
26
26
  import { recordRunName } from '../session/run-names.js';
27
27
  import { sshExec, shellQuote } from '../ssh-exec.js';
@@ -11,6 +11,61 @@ import type { FeedBroadcastConfig } from './feed-broadcast.js';
11
11
  export declare const AGENT_IDS: readonly ["claude", "codex", "gemini", "cursor", "opencode", "openclaw", "copilot", "amp", "goose", "antigravity", "grok", "kimi", "droid", "hermes", "muse", "warp"];
12
12
  export type AgentId = typeof AGENT_IDS[number];
13
13
  export declare function isAgentId(value: string): value is AgentId;
14
+ /**
15
+ * How THIS box authenticates one account slot (PHNX-3940). Native OAuth stays
16
+ * on the headed device that minted it; a worker uses a durable credential;
17
+ * per-device harnesses log in on each box.
18
+ */
19
+ export type AccountAuthMode = 'native' | 'durable' | 'per-device';
20
+ /**
21
+ * Live auth verdict vocabulary (mirrors lib/auth-health.ts AuthVerdict).
22
+ * Duplicated here so Meta can name the field without importing the probe module.
23
+ */
24
+ export type AuthVerdictName = 'live' | 'revoked' | 'expired' | 'rate_limited' | 'unverified' | 'unconfigured' | 'error';
25
+ /**
26
+ * Per-(account, device) materialization of an Account row. Lives in the device
27
+ * doc (`deviceAccounts.slots`), never the fleet-synced central file — slot
28
+ * paths are per box. Native OAuth files stay inside `slotDir` on this device.
29
+ */
30
+ export interface DeviceAccountSlot {
31
+ accountId: string;
32
+ /** `~/.agents/.history/accounts/<harness>/<accountId>/` — HOME-shaped, no binary. */
33
+ slotDir: string;
34
+ authMode: AccountAuthMode;
35
+ verdict: AuthVerdictName;
36
+ checkedAt?: string;
37
+ /** Onboarding in flight; cleared once the account row is registered. */
38
+ pending?: boolean;
39
+ }
40
+ /** Whether a worker can be provisioned from a durable credential, or must log in per box. */
41
+ export type AccountProvisioning = 'portable' | 'per-device';
42
+ /**
43
+ * Pointer to the durable worker credential in a reserved store. Never the
44
+ * secret value itself — that stays in the secrets backend.
45
+ */
46
+ export interface NativeAccountWorkerCredential {
47
+ bundle: string;
48
+ key: string;
49
+ kind: 'setup-token' | 'api-key';
50
+ mintedAt: string;
51
+ }
52
+ /**
53
+ * Fleet-synced native-account row (central `accounts.native` or a device-scoped
54
+ * copy). Additive fields from account-model v2 (PHNX-3940); existing rows
55
+ * migrate in place with these absent.
56
+ */
57
+ export interface NativeAccountRecord {
58
+ id: string;
59
+ name: string;
60
+ agent: AgentId;
61
+ identityKey: string;
62
+ identityLabel?: string;
63
+ scope: 'version' | 'device';
64
+ workerCredential?: NativeAccountWorkerCredential;
65
+ provisioning?: AccountProvisioning;
66
+ /** Device that minted this row (the headed origin). */
67
+ createdOn?: string;
68
+ }
14
69
  /** How `agents run <agent>` chooses an installed version when none is pinned. */
15
70
  export type RunStrategy = 'pinned' | 'available' | 'balanced';
16
71
  export type RunEffort = 'low' | 'medium' | 'high' | 'xhigh' | 'max' | 'auto';
@@ -833,14 +888,7 @@ export interface Meta {
833
888
  * the harness home. Central-synced via agents.yaml; labels bind to
834
889
  * `(agent, identityKey)`.
835
890
  */
836
- native?: Record<string, {
837
- id: string;
838
- name: string;
839
- agent: AgentId;
840
- identityKey: string;
841
- identityLabel?: string;
842
- scope: 'version' | 'device';
843
- }>;
891
+ native?: Record<string, NativeAccountRecord>;
844
892
  /** Exact installation/custom-harness target -> stable account id. */
845
893
  bindings?: Record<string, string>;
846
894
  };
@@ -854,38 +902,31 @@ export interface Meta {
854
902
  * natives) and every device doc's block; only this machine writes this key.
855
903
  */
856
904
  deviceAccounts?: {
857
- native?: Record<string, {
858
- id: string;
859
- name: string;
860
- agent: AgentId;
861
- identityKey: string;
862
- identityLabel?: string;
863
- scope: 'version' | 'device';
864
- }>;
905
+ native?: Record<string, NativeAccountRecord>;
865
906
  bindings?: Record<string, string>;
866
907
  /**
867
- * THIS box's account⇄home map (PHNX-3940): stable account id → the local
868
- * installation label whose isolated home hosts that account's native login,
869
- * as created by `agents accounts connect`. It is DEVICE-scoped on purpose —
870
- * one account materializes a different home per host, and the label a box
871
- * minted must never be assumed to exist on another box — so it lives in the
872
- * device doc, never the fleet-synced central `accounts.native` identity row.
873
- * A reconnect reads this to reuse the exact home even when its credential has
874
- * expired (so local signed-in discovery can no longer find it).
908
+ * THIS box's leftover account⇄home map (PHNX-3940): stable account id → a
909
+ * local installation label (`acct-*` from the retired connect verb). Device-
910
+ * scoped: a label minted here is not assumed to exist on another box, so it
911
+ * lives in the device doc, never the fleet-synced central `accounts.native`
912
+ * identity row. `nativeAccountHome` still reads it so T5/T7 can resolve a
913
+ * legacy home; spawn-time HOME is {@link DeviceAccountSlot slots}.
875
914
  */
876
915
  homes?: Record<string, string>;
877
916
  /**
878
- * THIS box's IN-FLIGHT `agents accounts connect` attempts (PHNX-3940):
879
- * `${agent}:${name}` (lowercased) → the opaque slot minted for that attempt,
880
- * BEFORE its login completed. It exists so a failed/cancelled named connect
881
- * retries into the SAME fresh home instead of orphaning a new one each time,
882
- * WITHOUT a deterministic name→slot function (which would recompute an
883
- * already-taken slot after a rename and overwrite another account's login —
884
- * the security flaw this replaces). It is cleared the moment the account is
885
- * registered, so a live pending slot is by definition not yet an account's
886
- * home. Device-scoped for the same reason as {@link homes}.
917
+ * Leftover in-flight connect map from the retired verb
918
+ * (PHNX-3940). No writer remains; state still round-trips the field so an
919
+ * older device doc does not fail to load.
887
920
  */
888
921
  pendingConnects?: Record<string, string>;
922
+ /**
923
+ * THIS box's account slots (PHNX-3940): stable account id → HOME-shaped
924
+ * dir under `~/.agents/.history/accounts/<harness>/<accountId>/`. Device-
925
+ * scoped: a slot path is local and a native OAuth file never leaves this
926
+ * box. Replaces `homes` as the spawn-time HOME; `homes` remains the
927
+ * installation-label map so leftover `acct-*` labels still resolve.
928
+ */
929
+ slots?: Record<string, DeviceAccountSlot>;
889
930
  };
890
931
  agents?: Partial<Record<AgentId, string>>;
891
932
  /**
@@ -2,7 +2,7 @@ import type { ConfiguredModelSource } from './models.js';
2
2
  import type { ProfileSummary } from './profiles.js';
3
3
  import type { AgentId } from './types.js';
4
4
  import type { AuthVerdict } from './auth-health.js';
5
- import type { NativeAccountCatalogRow } from './account-catalog.js';
5
+ import type { AccountListEntryJson } from './account-catalog.js';
6
6
  export type SyncState = 'synced' | 'new' | 'modified' | 'deleted';
7
7
  export interface ViewJsonVersion {
8
8
  /** Stable installation label; retained for existing machine consumers. */
@@ -69,8 +69,11 @@ export interface ViewJsonVersion {
69
69
  export interface ViewJsonAgent {
70
70
  agent: AgentId;
71
71
  versions: ViewJsonVersion[];
72
- /** Account-first projection, additive so older consumers keep working. */
73
- accounts?: NativeAccountCatalogRow[];
72
+ /**
73
+ * The same public JSON v2 account projection `accounts list --json` emits —
74
+ * never the internal catalog row, so consumers (AGI EXT) read one shape.
75
+ */
76
+ accounts?: AccountListEntryJson[];
74
77
  harnesses: ProfileSummary[];
75
78
  }
76
79
  export type ResourceSection = 'commands' | 'skills' | 'mcp' | 'memory' | 'hooks' | 'workflows' | 'plugins';
@@ -0,0 +1,71 @@
1
+ import type { AgentId } from './types.js';
2
+ /** A central workflow bundle: its synced name and the source dir holding WORKFLOW.md. */
3
+ export interface WorkflowSource {
4
+ name: string;
5
+ path: string;
6
+ }
7
+ /**
8
+ * The complete on-disk contract for one harness's workflows. Every operation
9
+ * is expressed here so the engine below never branches on the agent id.
10
+ */
11
+ export interface WorkflowTarget {
12
+ /** Noun used in ownership errors, e.g. "Kimi skill", "Grok workflow". */
13
+ readonly label: string;
14
+ /**
15
+ * Absolute container dir for `versionHome`. A harness whose native store is
16
+ * HOME-global (antigravity) ignores `versionHome` and resolves from `$HOME`.
17
+ */
18
+ dir(versionHome: string): string;
19
+ /** Names of the workflows in `dir` that agents-cli manages (lister + detector). */
20
+ names(dir: string): string[];
21
+ /** Materialize `wf` into `dir`. Throws on an invalid source or fs error. */
22
+ write(dir: string, wf: WorkflowSource): void;
23
+ /** Paths workflow `name` occupies in `dir`; empty when it is not installed. */
24
+ occupied(dir: string, name: string): string[];
25
+ /**
26
+ * Ownership of what sits at `name` in `dir`: `null` when nothing is there,
27
+ * `true` when agents-cli wrote it (or the format has no ownership marker),
28
+ * `false` when a user-authored file of the same name is in the way.
29
+ */
30
+ managed(dir: string, name: string): boolean | null;
31
+ /**
32
+ * True when the installed copy byte-matches what `write` would render from
33
+ * `wf.path` NOW — the drift predicate `agents doctor` uses. Re-renders the
34
+ * current source through the same transform the writer uses (never a stored
35
+ * hash), so a body edit to the source surfaces as drift under an unchanged name.
36
+ */
37
+ matches(dir: string, wf: WorkflowSource): boolean;
38
+ }
39
+ /**
40
+ * Single source of truth for how each workflows-capable harness stores
41
+ * workflows. The keys MUST match `capableAgents('workflows')` (the `workflows`
42
+ * flag in `agent-spec/agents.ts`): the capability flag is the version gate,
43
+ * this table is the shape.
44
+ */
45
+ export declare const WORKFLOW_TARGETS: Partial<Record<AgentId, WorkflowTarget>>;
46
+ /** The registered target for `agent`; throws for a harness that has none. */
47
+ export declare function workflowTarget(agent: AgentId): WorkflowTarget;
48
+ /** Workflow names agents-cli has synced into `versionHome` for `agent`. */
49
+ export declare function listWorkflowsForAgent(agent: AgentId, versionHome: string): string[];
50
+ /**
51
+ * Materialize the central bundle at `workflowPath` as `name` in `agent`'s
52
+ * `versionHome`, in that harness's native layout. Refuses to clobber a
53
+ * user-authored file of the same name (the ownership marker is the tell) and
54
+ * is idempotent over an agents-cli-managed one.
55
+ */
56
+ export declare function syncWorkflowToVersion(workflowPath: string, name: string, agent: AgentId, versionHome: string): {
57
+ success: boolean;
58
+ error?: string;
59
+ };
60
+ /** Remove workflow `name` from `agent@version`; refuses a user-authored file. */
61
+ export declare function removeWorkflowFromVersion(agent: AgentId, version: string, name: string): {
62
+ success: boolean;
63
+ error?: string;
64
+ };
65
+ /**
66
+ * True when workflow `name` materialized in `agent`'s `versionHome` byte-matches
67
+ * what the writer would produce NOW from `sourcePath` — the content-drift
68
+ * predicate `agents doctor` uses. Returns false when the home copy is absent
69
+ * (surfaced as `missing` at the name level, not here).
70
+ */
71
+ export declare function workflowContentMatches(agent: AgentId, versionHome: string, name: string, sourcePath: string): boolean;