@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,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
|
+
}
|
package/dist/lib/workflows.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
380
|
-
*
|
|
381
|
-
*
|
|
382
|
-
*
|
|
383
|
-
*
|
|
384
|
-
*
|
|
385
|
-
*
|
|
386
|
-
*
|
|
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
|
|
389
|
-
|
|
390
|
-
export declare function
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
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;
|