@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
@@ -0,0 +1,280 @@
1
+ /**
2
+ * Workflow target registry — the ONE place that says how each
3
+ * workflows-capable harness stores a synced workflow on disk.
4
+ *
5
+ * `WORKFLOW_TARGETS` is the declarative shape (container dir, file layout,
6
+ * transform, ownership marker); the engine below (`listWorkflowsForAgent`,
7
+ * `syncWorkflowToVersion`, `removeWorkflowFromVersion`,
8
+ * `workflowContentMatches`) and the staleness detector are generic over it, so
9
+ * adding a harness is one entry here plus its `workflows` capability flag in
10
+ * `agent-spec/agents.ts` — never another `if (agent === '...')` arm in the
11
+ * writer, the lister, the remover, the doctor drift check, and the detector.
12
+ * A completeness test pins `Object.keys(WORKFLOW_TARGETS)` to
13
+ * `capableAgents('workflows')` so the flag and the shape cannot drift.
14
+ *
15
+ * Same pattern as `SUBAGENT_TARGETS` in `subagents-registry.ts`.
16
+ */
17
+ import * as fs from 'fs';
18
+ import * as path from 'path';
19
+ import { getVersionHomePath } from './installations/versions.js';
20
+ import { dirsContentMatch, normalizeResourceContent } from './resource-content-diff.js';
21
+ import { antigravityWorkflowMarker, antigravityWorkflowsDir, grokWorkflowMarker, kimiWorkflowMarker, openclawWorkflowMarker, parseWorkflowFrontmatter, renderGooseRecipeYaml, selectedWorkflowSubagents, transformWorkflowForAntigravity, transformWorkflowForGrok, transformWorkflowForKimi, transformWorkflowForOpenClaw, writeGooseSubrecipe, } from './workflows.js';
22
+ function readdirSafe(dir) {
23
+ try {
24
+ return fs.readdirSync(dir, { withFileTypes: true });
25
+ }
26
+ catch {
27
+ return [];
28
+ }
29
+ }
30
+ function renderedMatches(homePath, expected) {
31
+ let actual;
32
+ try {
33
+ actual = fs.readFileSync(homePath, 'utf-8');
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ return normalizeResourceContent(actual) === normalizeResourceContent(expected);
39
+ }
40
+ // ── layouts ──────────────────────────────────────────────────────────────────
41
+ /**
42
+ * One rendered `<name><ext>` file per workflow, owned via a marker the
43
+ * transform embeds (antigravity, openclaw, grok).
44
+ */
45
+ function renderedFile(opts) {
46
+ const file = (dir, name) => path.join(dir, `${name}${opts.ext}`);
47
+ return {
48
+ label: opts.label,
49
+ dir: opts.dir,
50
+ names(dir) {
51
+ return readdirSafe(dir)
52
+ .filter((d) => d.isFile() && d.name.endsWith(opts.ext) && !d.name.startsWith('.'))
53
+ .map((d) => d.name.slice(0, -opts.ext.length))
54
+ .filter((base) => opts.marker(file(dir, base)) === base);
55
+ },
56
+ write(dir, wf) {
57
+ fs.mkdirSync(dir, { recursive: true });
58
+ fs.writeFileSync(file(dir, wf.name), opts.transform(wf.path, wf.name), 'utf-8');
59
+ },
60
+ occupied(dir, name) {
61
+ const target = file(dir, name);
62
+ return fs.existsSync(target) ? [target] : [];
63
+ },
64
+ managed(dir, name) {
65
+ const target = file(dir, name);
66
+ if (!fs.existsSync(target))
67
+ return null;
68
+ return opts.marker(target) === name;
69
+ },
70
+ matches(dir, wf) {
71
+ return renderedMatches(file(dir, wf.name), opts.transform(wf.path, wf.name));
72
+ },
73
+ };
74
+ }
75
+ /**
76
+ * Kimi flow skill: a `<name>/SKILL.md` directory whose frontmatter carries
77
+ * `type: flow` and the `agents_workflow` marker.
78
+ */
79
+ const kimiFlowSkill = {
80
+ label: 'Kimi skill',
81
+ dir: (versionHome) => path.join(versionHome, '.kimi-code', 'skills'),
82
+ names(dir) {
83
+ return readdirSafe(dir)
84
+ .filter((d) => d.isDirectory() && fs.existsSync(path.join(dir, d.name, 'SKILL.md')))
85
+ .filter((d) => kimiWorkflowMarker(path.join(dir, d.name, 'SKILL.md')) === d.name)
86
+ .map((d) => d.name);
87
+ },
88
+ write(dir, wf) {
89
+ const skillDir = path.join(dir, wf.name);
90
+ fs.mkdirSync(skillDir, { recursive: true });
91
+ fs.writeFileSync(path.join(skillDir, 'SKILL.md'), transformWorkflowForKimi(wf.path, wf.name), 'utf-8');
92
+ },
93
+ occupied(dir, name) {
94
+ const skillDir = path.join(dir, name);
95
+ return fs.existsSync(skillDir) ? [skillDir] : [];
96
+ },
97
+ managed(dir, name) {
98
+ const skillDir = path.join(dir, name);
99
+ if (!fs.existsSync(skillDir))
100
+ return null;
101
+ return kimiWorkflowMarker(path.join(skillDir, 'SKILL.md')) === name;
102
+ },
103
+ matches(dir, wf) {
104
+ return renderedMatches(path.join(dir, wf.name, 'SKILL.md'), transformWorkflowForKimi(wf.path, wf.name));
105
+ },
106
+ };
107
+ /**
108
+ * Goose recipe: `<name>.yaml` plus a `<name>.subrecipes/` dir holding one YAML
109
+ * per selected workflow subagent. Goose has no ownership marker, so presence
110
+ * is ownership.
111
+ */
112
+ const gooseRecipe = {
113
+ label: 'Goose recipe',
114
+ dir: (versionHome) => path.join(versionHome, '.config', 'goose', 'recipes'),
115
+ names(dir) {
116
+ return readdirSafe(dir)
117
+ .filter((d) => d.isFile() && d.name.endsWith('.yaml') && !d.name.startsWith('.'))
118
+ .map((d) => d.name.slice(0, -'.yaml'.length));
119
+ },
120
+ write(dir, wf) {
121
+ const frontmatter = parseWorkflowFrontmatter(wf.path);
122
+ const recipeYaml = frontmatter ? renderGooseRecipeYaml(wf.path, wf.name) : null;
123
+ if (!frontmatter || recipeYaml == null) {
124
+ throw new Error(`Workflow '${wf.name}' has invalid WORKFLOW.md frontmatter`);
125
+ }
126
+ const subrecipesDir = path.join(dir, `${wf.name}.subrecipes`);
127
+ fs.mkdirSync(dir, { recursive: true });
128
+ if (fs.existsSync(subrecipesDir)) {
129
+ fs.rmSync(subrecipesDir, { recursive: true, force: true });
130
+ }
131
+ for (const subagentName of selectedWorkflowSubagents(wf.path, frontmatter.allowedAgents)) {
132
+ writeGooseSubrecipe(wf.path, subagentName, subrecipesDir);
133
+ }
134
+ fs.writeFileSync(path.join(dir, `${wf.name}.yaml`), recipeYaml, 'utf-8');
135
+ },
136
+ occupied(dir, name) {
137
+ return [path.join(dir, `${name}.yaml`), path.join(dir, `${name}.subrecipes`)].filter((p) => fs.existsSync(p));
138
+ },
139
+ managed(dir, name) {
140
+ return gooseRecipe.occupied(dir, name).length > 0 ? true : null;
141
+ },
142
+ matches(dir, wf) {
143
+ const expected = renderGooseRecipeYaml(wf.path, wf.name);
144
+ if (expected == null)
145
+ return false;
146
+ return renderedMatches(path.join(dir, `${wf.name}.yaml`), expected);
147
+ },
148
+ };
149
+ /**
150
+ * The canonical bundle copied verbatim: `<name>/WORKFLOW.md` (plus its
151
+ * subagents/ tree) under `{versionHome}/workflows/`. No marker — the dir is
152
+ * agents-cli's by construction.
153
+ */
154
+ const workflowBundle = {
155
+ label: 'Workflow',
156
+ dir: (versionHome) => path.join(versionHome, 'workflows'),
157
+ names(dir) {
158
+ return readdirSafe(dir)
159
+ .filter((d) => d.isDirectory() && fs.existsSync(path.join(dir, d.name, 'WORKFLOW.md')))
160
+ .map((d) => d.name);
161
+ },
162
+ write(dir, wf) {
163
+ const target = path.join(dir, wf.name);
164
+ fs.mkdirSync(dir, { recursive: true });
165
+ if (fs.existsSync(target)) {
166
+ fs.rmSync(target, { recursive: true, force: true });
167
+ }
168
+ fs.cpSync(wf.path, target, { recursive: true });
169
+ },
170
+ occupied(dir, name) {
171
+ const target = path.join(dir, name);
172
+ return fs.existsSync(target) ? [target] : [];
173
+ },
174
+ managed(dir, name) {
175
+ return fs.existsSync(path.join(dir, name)) ? true : null;
176
+ },
177
+ matches(dir, wf) {
178
+ return dirsContentMatch(wf.path, path.join(dir, wf.name));
179
+ },
180
+ };
181
+ // ── the registry ─────────────────────────────────────────────────────────────
182
+ /**
183
+ * Single source of truth for how each workflows-capable harness stores
184
+ * workflows. The keys MUST match `capableAgents('workflows')` (the `workflows`
185
+ * flag in `agent-spec/agents.ts`): the capability flag is the version gate,
186
+ * this table is the shape.
187
+ */
188
+ export const WORKFLOW_TARGETS = {
189
+ claude: workflowBundle,
190
+ kimi: kimiFlowSkill,
191
+ goose: gooseRecipe,
192
+ // Antigravity discovers workflows in the shared HOME-global dir `agy` scans
193
+ // at startup, never in a version home — see `antigravityWorkflowsDir`.
194
+ antigravity: renderedFile({
195
+ label: 'Antigravity workflow',
196
+ dir: () => antigravityWorkflowsDir(),
197
+ ext: '.md',
198
+ transform: transformWorkflowForAntigravity,
199
+ marker: antigravityWorkflowMarker,
200
+ }),
201
+ openclaw: renderedFile({
202
+ label: 'OpenClaw workflow',
203
+ dir: (versionHome) => path.join(versionHome, '.openclaw', 'workflows'),
204
+ ext: '.lobster',
205
+ transform: transformWorkflowForOpenClaw,
206
+ marker: openclawWorkflowMarker,
207
+ }),
208
+ grok: renderedFile({
209
+ label: 'Grok workflow',
210
+ dir: (versionHome) => path.join(versionHome, '.grok', 'workflows'),
211
+ ext: '.rhai',
212
+ transform: transformWorkflowForGrok,
213
+ marker: grokWorkflowMarker,
214
+ }),
215
+ };
216
+ /** The registered target for `agent`; throws for a harness that has none. */
217
+ export function workflowTarget(agent) {
218
+ const target = WORKFLOW_TARGETS[agent];
219
+ if (!target) {
220
+ throw new Error(`${agent} has no workflow target (not in capableAgents('workflows'))`);
221
+ }
222
+ return target;
223
+ }
224
+ // ── the generic engine ───────────────────────────────────────────────────────
225
+ /** Workflow names agents-cli has synced into `versionHome` for `agent`. */
226
+ export function listWorkflowsForAgent(agent, versionHome) {
227
+ const target = workflowTarget(agent);
228
+ return target.names(target.dir(versionHome));
229
+ }
230
+ /**
231
+ * Materialize the central bundle at `workflowPath` as `name` in `agent`'s
232
+ * `versionHome`, in that harness's native layout. Refuses to clobber a
233
+ * user-authored file of the same name (the ownership marker is the tell) and
234
+ * is idempotent over an agents-cli-managed one.
235
+ */
236
+ export function syncWorkflowToVersion(workflowPath, name, agent, versionHome) {
237
+ const target = workflowTarget(agent);
238
+ const dir = target.dir(versionHome);
239
+ try {
240
+ if (target.managed(dir, name) === false) {
241
+ return { success: false, error: `${target.label} '${name}' already exists and is not managed by agents-cli` };
242
+ }
243
+ target.write(dir, { name, path: workflowPath });
244
+ return { success: true };
245
+ }
246
+ catch (err) {
247
+ return { success: false, error: err.message };
248
+ }
249
+ }
250
+ /** Remove workflow `name` from `agent@version`; refuses a user-authored file. */
251
+ export function removeWorkflowFromVersion(agent, version, name) {
252
+ const target = workflowTarget(agent);
253
+ const dir = target.dir(getVersionHomePath(agent, version));
254
+ const occupied = target.occupied(dir, name);
255
+ if (occupied.length === 0) {
256
+ return { success: false, error: `Workflow '${name}' not synced to ${agent}@${version}` };
257
+ }
258
+ if (target.managed(dir, name) === false) {
259
+ return { success: false, error: `${target.label} '${name}' is not managed by agents-cli` };
260
+ }
261
+ try {
262
+ for (const entry of occupied) {
263
+ fs.rmSync(entry, { recursive: true, force: true });
264
+ }
265
+ return { success: true };
266
+ }
267
+ catch (err) {
268
+ return { success: false, error: err.message };
269
+ }
270
+ }
271
+ /**
272
+ * True when workflow `name` materialized in `agent`'s `versionHome` byte-matches
273
+ * what the writer would produce NOW from `sourcePath` — the content-drift
274
+ * predicate `agents doctor` uses. Returns false when the home copy is absent
275
+ * (surfaced as `missing` at the name level, not here).
276
+ */
277
+ export function workflowContentMatches(agent, versionHome, name, sourcePath) {
278
+ const target = workflowTarget(agent);
279
+ return target.matches(target.dir(versionHome), { name, path: sourcePath });
280
+ }
@@ -373,29 +373,29 @@ export declare function removeWorkflow(name: string): {
373
373
  success: boolean;
374
374
  error?: string;
375
375
  };
376
- /** List workflow names synced into a specific agent version home. */
377
- export declare function listWorkflowsForAgent(agent: AgentId, versionHome: string): string[];
378
376
  /**
379
- * True when workflow `name` materialized in `agent`'s version home byte-matches
380
- * what the writer would produce NOW from `sourcePath` — the content-drift
381
- * predicate `agents doctor` uses. Layout-aware per the same per-harness map the
382
- * writer (`syncWorkflowToVersion`) and detector use: Claude/default copy the
383
- * whole WORKFLOW.md tree (recursive dir compare); Kimi/Antigravity/OpenClaw/Grok
384
- * render one transformed file; Goose renders a recipe YAML. Antigravity's target
385
- * is the shared HOME-global dir, not a per-version path. Returns false when the
386
- * home copy is absent (surfaced as `missing` at the name level, not here).
377
+ * Antigravity user workflows are NOT version-isolated. `agy` scans a single,
378
+ * shared, HOME-global directory at startup — `~/.gemini/config/global_workflows/`
379
+ * — and that dir is a real directory in the user's home, never symlinked into a
380
+ * per-version home (only `~/.gemini/antigravity-cli` is version-scoped). Writing
381
+ * into a version home therefore lands somewhere agy never reads. So every
382
+ * antigravity version resolves to the same real shared dir; `versionHome` is
383
+ * intentionally ignored. (Verified via strace of `agy`: it opens
384
+ * `$HOME/.gemini/config/global_workflows/<name>.md` and never the version home.)
387
385
  */
388
- export declare function workflowContentMatches(agent: AgentId, versionHome: string, name: string, sourcePath: string): boolean;
389
- /** Copy a workflow directory into a version home at {versionHome}/workflows/<name>/. */
390
- export declare function syncWorkflowToVersion(workflowPath: string, name: string, agent: AgentId, versionHome: string): {
391
- success: boolean;
392
- error?: string;
393
- };
394
- /** Remove a workflow from a specific agent version home. */
395
- export declare function removeWorkflowFromVersion(agent: AgentId, version: string, name: string): {
396
- success: boolean;
397
- error?: string;
398
- };
386
+ export declare function antigravityWorkflowsDir(): string;
387
+ export declare function selectedWorkflowSubagents(workflowPath: string, allowedAgents?: string[]): string[];
388
+ export declare function writeGooseSubrecipe(workflowPath: string, subrecipeName: string, destDir: string): void;
389
+ /**
390
+ * Render the main Goose recipe YAML for a workflow — the exact bytes the Goose
391
+ * `WORKFLOW_TARGETS` entry writes to `<name>.yaml`. Extracted so the writer and
392
+ * the doctor content-drift check (`matches`) render from ONE source and can
393
+ * never disagree. Returns null on invalid frontmatter.
394
+ */
395
+ export declare function renderGooseRecipeYaml(workflowPath: string, name: string): string | null;
396
+ export declare function kimiWorkflowMarker(filePath: string): string | null;
397
+ export declare function antigravityWorkflowMarker(filePath: string): string | null;
398
+ export declare function openclawWorkflowMarker(filePath: string): string | null;
399
399
  /** Iterate all installed (agent, version) pairs that support workflows. */
400
400
  export declare function iterWorkflowsCapableVersions(filter?: {
401
401
  agent?: AgentId;