@phnx-labs/agents-cli 1.20.4 → 1.20.6
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 +19 -0
- package/README.md +49 -18
- package/dist/commands/browser.js +31 -4
- package/dist/commands/cli.js +1 -1
- package/dist/commands/cloud.js +1 -1
- package/dist/commands/commands.js +2 -0
- package/dist/commands/computer.js +10 -2
- package/dist/commands/defaults.d.ts +7 -0
- package/dist/commands/defaults.js +89 -0
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/exec.js +73 -19
- package/dist/commands/hooks.js +6 -6
- package/dist/commands/inspect.d.ts +26 -0
- package/dist/commands/inspect.js +590 -0
- package/dist/commands/mcp.js +17 -16
- package/dist/commands/models.js +1 -1
- package/dist/commands/packages.js +6 -4
- package/dist/commands/permissions.js +13 -12
- package/dist/commands/plugins.d.ts +13 -0
- package/dist/commands/plugins.js +100 -11
- package/dist/commands/prune.js +3 -2
- package/dist/commands/pull.d.ts +12 -5
- package/dist/commands/pull.js +26 -422
- package/dist/commands/push.d.ts +14 -0
- package/dist/commands/push.js +30 -0
- package/dist/commands/repo.d.ts +1 -1
- package/dist/commands/repo.js +155 -112
- package/dist/commands/resource-view.d.ts +2 -0
- package/dist/commands/resource-view.js +12 -3
- package/dist/commands/routines.js +32 -7
- package/dist/commands/rules.js +4 -4
- package/dist/commands/secrets.js +46 -9
- package/dist/commands/sessions.js +1 -0
- package/dist/commands/setup.d.ts +3 -3
- package/dist/commands/setup.js +17 -17
- package/dist/commands/skills.js +6 -5
- package/dist/commands/subagents.js +5 -4
- package/dist/commands/sync.d.ts +18 -5
- package/dist/commands/sync.js +251 -65
- package/dist/commands/teams.js +109 -11
- package/dist/commands/tmux.d.ts +25 -0
- package/dist/commands/tmux.js +415 -0
- package/dist/commands/trash.d.ts +2 -2
- package/dist/commands/trash.js +1 -1
- package/dist/commands/versions.js +2 -2
- package/dist/commands/view.d.ts +12 -1
- package/dist/commands/view.js +128 -40
- package/dist/commands/workflows.js +4 -3
- package/dist/commands/worktree.d.ts +4 -5
- package/dist/commands/worktree.js +4 -4
- package/dist/index.js +106 -41
- package/dist/lib/agents.d.ts +23 -10
- package/dist/lib/agents.js +88 -25
- package/dist/lib/auto-pull-worker.d.ts +1 -1
- package/dist/lib/auto-pull-worker.js +2 -2
- package/dist/lib/auto-pull.d.ts +1 -1
- package/dist/lib/auto-pull.js +1 -1
- package/dist/lib/beta.d.ts +1 -1
- package/dist/lib/beta.js +1 -1
- package/dist/lib/browser/chrome.d.ts +10 -0
- package/dist/lib/browser/chrome.js +84 -3
- package/dist/lib/capabilities.js +2 -0
- package/dist/lib/commands.d.ts +28 -1
- package/dist/lib/commands.js +125 -20
- package/dist/lib/doctor-diff.js +2 -2
- package/dist/lib/exec.d.ts +14 -0
- package/dist/lib/exec.js +59 -5
- package/dist/lib/fuzzy.d.ts +12 -2
- package/dist/lib/fuzzy.js +29 -4
- package/dist/lib/git.js +8 -1
- package/dist/lib/hooks.d.ts +2 -2
- package/dist/lib/hooks.js +97 -10
- package/dist/lib/mcp.js +32 -2
- package/dist/lib/migrate.d.ts +51 -0
- package/dist/lib/migrate.js +233 -5
- package/dist/lib/models.js +62 -15
- package/dist/lib/permissions.d.ts +59 -2
- package/dist/lib/permissions.js +299 -7
- package/dist/lib/plugin-marketplace.d.ts +98 -40
- package/dist/lib/plugin-marketplace.js +196 -93
- package/dist/lib/plugins.d.ts +21 -4
- package/dist/lib/plugins.js +130 -49
- package/dist/lib/profiles-presets.js +12 -12
- package/dist/lib/project-launch.d.ts +70 -0
- package/dist/lib/project-launch.js +404 -0
- package/dist/lib/pty-client.js +1 -1
- package/dist/lib/pty-server.d.ts +1 -1
- package/dist/lib/pty-server.js +8 -5
- package/dist/lib/refresh.d.ts +26 -0
- package/dist/lib/refresh.js +315 -0
- package/dist/lib/resource-patterns.d.ts +1 -1
- package/dist/lib/resource-patterns.js +1 -1
- package/dist/lib/resources/commands.js +2 -2
- package/dist/lib/resources/hooks.d.ts +1 -1
- package/dist/lib/resources/hooks.js +1 -1
- package/dist/lib/resources/mcp.d.ts +1 -1
- package/dist/lib/resources/mcp.js +5 -6
- package/dist/lib/resources/permissions.js +5 -2
- package/dist/lib/resources/rules.js +3 -2
- package/dist/lib/resources/skills.js +3 -2
- package/dist/lib/resources/types.d.ts +1 -1
- package/dist/lib/resources.d.ts +2 -0
- package/dist/lib/resources.js +4 -3
- package/dist/lib/rotate.d.ts +1 -1
- package/dist/lib/rotate.js +7 -19
- package/dist/lib/routines.d.ts +16 -4
- package/dist/lib/routines.js +67 -17
- package/dist/lib/rules/compile.js +22 -10
- package/dist/lib/rules/rules.js +3 -3
- package/dist/lib/run-config.d.ts +9 -0
- package/dist/lib/run-config.js +35 -0
- package/dist/lib/run-defaults.d.ts +42 -0
- package/dist/lib/run-defaults.js +180 -0
- package/dist/lib/runner.js +16 -3
- package/dist/lib/scheduler.js +15 -1
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +9 -1
- package/dist/lib/secrets/Agents CLI.app/Contents/embedded.provisionprofile +0 -0
- package/dist/lib/secrets/install-helper.d.ts +11 -3
- package/dist/lib/secrets/install-helper.js +48 -6
- package/dist/lib/secrets/linux.d.ts +56 -9
- package/dist/lib/secrets/linux.js +327 -59
- package/dist/lib/session/db.js +15 -2
- package/dist/lib/session/discover.js +118 -3
- package/dist/lib/session/parse.js +3 -0
- package/dist/lib/session/types.d.ts +1 -1
- package/dist/lib/session/types.js +1 -1
- package/dist/lib/shims.d.ts +18 -9
- package/dist/lib/shims.js +133 -50
- package/dist/lib/skills.d.ts +1 -1
- package/dist/lib/skills.js +10 -9
- package/dist/lib/staleness/detectors/commands.d.ts +3 -0
- package/dist/lib/staleness/detectors/commands.js +46 -0
- package/dist/lib/staleness/detectors/hooks.d.ts +3 -0
- package/dist/lib/staleness/detectors/hooks.js +44 -0
- package/dist/lib/staleness/detectors/mcp.d.ts +3 -0
- package/dist/lib/staleness/detectors/mcp.js +31 -0
- package/dist/lib/staleness/detectors/permissions.d.ts +3 -0
- package/dist/lib/staleness/detectors/permissions.js +201 -0
- package/dist/lib/staleness/detectors/plugins.d.ts +8 -0
- package/dist/lib/staleness/detectors/plugins.js +23 -0
- package/dist/lib/staleness/detectors/rules.d.ts +3 -0
- package/dist/lib/staleness/detectors/rules.js +34 -0
- package/dist/lib/staleness/detectors/skills.d.ts +3 -0
- package/dist/lib/staleness/detectors/skills.js +71 -0
- package/dist/lib/staleness/detectors/subagents.d.ts +3 -0
- package/dist/lib/staleness/detectors/subagents.js +50 -0
- package/dist/lib/staleness/detectors/types.d.ts +22 -0
- package/dist/lib/staleness/detectors/types.js +1 -0
- package/dist/lib/staleness/detectors/workflows.d.ts +3 -0
- package/dist/lib/staleness/detectors/workflows.js +28 -0
- package/dist/lib/staleness/registry.d.ts +26 -0
- package/dist/lib/staleness/registry.js +123 -0
- package/dist/lib/staleness/writers/commands.d.ts +3 -0
- package/dist/lib/staleness/writers/commands.js +111 -0
- package/dist/lib/staleness/writers/hooks.d.ts +3 -0
- package/dist/lib/staleness/writers/hooks.js +47 -0
- package/dist/lib/staleness/writers/kinds.d.ts +10 -0
- package/dist/lib/staleness/writers/kinds.js +15 -0
- package/dist/lib/staleness/writers/lazy-map.d.ts +13 -0
- package/dist/lib/staleness/writers/lazy-map.js +19 -0
- package/dist/lib/staleness/writers/mcp.d.ts +10 -0
- package/dist/lib/staleness/writers/mcp.js +19 -0
- package/dist/lib/staleness/writers/permissions.d.ts +13 -0
- package/dist/lib/staleness/writers/permissions.js +26 -0
- package/dist/lib/staleness/writers/plugins.d.ts +7 -0
- package/dist/lib/staleness/writers/plugins.js +31 -0
- package/dist/lib/staleness/writers/rules.d.ts +7 -0
- package/dist/lib/staleness/writers/rules.js +55 -0
- package/dist/lib/staleness/writers/skills.d.ts +3 -0
- package/dist/lib/staleness/writers/skills.js +81 -0
- package/dist/lib/staleness/writers/sources.d.ts +16 -0
- package/dist/lib/staleness/writers/sources.js +72 -0
- package/dist/lib/staleness/writers/subagents.d.ts +3 -0
- package/dist/lib/staleness/writers/subagents.js +53 -0
- package/dist/lib/staleness/writers/types.d.ts +36 -0
- package/dist/lib/staleness/writers/types.js +1 -0
- package/dist/lib/staleness/writers/workflows.d.ts +7 -0
- package/dist/lib/staleness/writers/workflows.js +31 -0
- package/dist/lib/state.d.ts +34 -11
- package/dist/lib/state.js +58 -13
- package/dist/lib/subagents.d.ts +0 -2
- package/dist/lib/subagents.js +6 -6
- package/dist/lib/teams/agents.js +1 -1
- package/dist/lib/teams/api.d.ts +67 -0
- package/dist/lib/teams/api.js +78 -0
- package/dist/lib/teams/parsers.d.ts +1 -1
- package/dist/lib/tmux/binary.d.ts +67 -0
- package/dist/lib/tmux/binary.js +141 -0
- package/dist/lib/tmux/index.d.ts +8 -0
- package/dist/lib/tmux/index.js +8 -0
- package/dist/lib/tmux/paths.d.ts +17 -0
- package/dist/lib/tmux/paths.js +30 -0
- package/dist/lib/tmux/session.d.ts +122 -0
- package/dist/lib/tmux/session.js +305 -0
- package/dist/lib/types.d.ts +73 -13
- package/dist/lib/types.js +1 -1
- package/dist/lib/usage.js +1 -1
- package/dist/lib/versions.d.ts +4 -4
- package/dist/lib/versions.js +138 -496
- package/dist/lib/workflows.d.ts +2 -4
- package/dist/lib/workflows.js +3 -4
- package/package.json +6 -3
- package/scripts/postinstall.js +16 -63
- package/dist/commands/status.d.ts +0 -9
- package/dist/commands/status.js +0 -25
package/dist/lib/migrate.js
CHANGED
|
@@ -8,11 +8,76 @@ import * as fs from 'fs';
|
|
|
8
8
|
import * as path from 'path';
|
|
9
9
|
import * as os from 'os';
|
|
10
10
|
import * as yaml from 'yaml';
|
|
11
|
+
import { AGENTS, agentConfigDirName } from './agents.js';
|
|
11
12
|
const HOME = process.env.HOME ?? os.homedir();
|
|
12
|
-
const SYSTEM_DIR = path.join(HOME, '.agents-system');
|
|
13
13
|
const USER_DIR = path.join(HOME, '.agents');
|
|
14
|
+
/** Canonical system-repo location (post-fold). */
|
|
15
|
+
const SYSTEM_DIR = path.join(USER_DIR, '.system');
|
|
16
|
+
/** Legacy system-repo location — folded into SYSTEM_DIR by foldLegacySystemRepo(). */
|
|
17
|
+
const LEGACY_SYSTEM_DIR = path.join(HOME, '.agents-system');
|
|
14
18
|
const HISTORY_DIR = path.join(USER_DIR, '.history');
|
|
15
19
|
const CACHE_DIR = path.join(USER_DIR, '.cache');
|
|
20
|
+
/**
|
|
21
|
+
* Fold ~/.agents-system/ into ~/.agents/.system/.
|
|
22
|
+
*
|
|
23
|
+
* MUST run first in runMigration() — every other migrator reads SYSTEM_DIR
|
|
24
|
+
* (the new path), so the contents have to be there before they execute.
|
|
25
|
+
*
|
|
26
|
+
* Strategy:
|
|
27
|
+
* 1. If legacy dir doesn't exist or is already a symlink, no-op.
|
|
28
|
+
* 2. If new path doesn't exist yet, rename in one shot (fast path).
|
|
29
|
+
* 3. If both exist (mid-migration / re-run on partially-migrated state),
|
|
30
|
+
* merge legacy → new with new winning on collision, then drop legacy.
|
|
31
|
+
*
|
|
32
|
+
* After the contents move, the legacy path becomes a symlink → SYSTEM_DIR
|
|
33
|
+
* so external tooling that still references ~/.agents-system/ keeps
|
|
34
|
+
* resolving correctly. The symlink is harmless on its own and can be
|
|
35
|
+
* removed with `rm ~/.agents-system` once everything has updated.
|
|
36
|
+
*
|
|
37
|
+
* Idempotent: re-running converges to "contents at SYSTEM_DIR, symlink at
|
|
38
|
+
* LEGACY_SYSTEM_DIR" without duplicating data.
|
|
39
|
+
*/
|
|
40
|
+
export function foldLegacySystemRepo() {
|
|
41
|
+
let legacyStat = null;
|
|
42
|
+
try {
|
|
43
|
+
legacyStat = fs.lstatSync(LEGACY_SYSTEM_DIR);
|
|
44
|
+
}
|
|
45
|
+
catch { /* missing */ }
|
|
46
|
+
if (!legacyStat)
|
|
47
|
+
return;
|
|
48
|
+
if (legacyStat.isSymbolicLink())
|
|
49
|
+
return;
|
|
50
|
+
if (!legacyStat.isDirectory())
|
|
51
|
+
return;
|
|
52
|
+
try {
|
|
53
|
+
fs.mkdirSync(USER_DIR, { recursive: true, mode: 0o700 });
|
|
54
|
+
}
|
|
55
|
+
catch { /* best-effort */ }
|
|
56
|
+
if (!fs.existsSync(SYSTEM_DIR)) {
|
|
57
|
+
try {
|
|
58
|
+
fs.renameSync(LEGACY_SYSTEM_DIR, SYSTEM_DIR);
|
|
59
|
+
try {
|
|
60
|
+
fs.symlinkSync(SYSTEM_DIR, LEGACY_SYSTEM_DIR);
|
|
61
|
+
}
|
|
62
|
+
catch { /* best-effort */ }
|
|
63
|
+
console.error('Folded ~/.agents-system/ into ~/.agents/.system/ (left back-compat symlink)');
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// Cross-device rename or perm issue — fall through to copy + remove.
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
try {
|
|
71
|
+
copyDirSkipExisting(LEGACY_SYSTEM_DIR, SYSTEM_DIR);
|
|
72
|
+
fs.rmSync(LEGACY_SYSTEM_DIR, { recursive: true, force: true });
|
|
73
|
+
try {
|
|
74
|
+
fs.symlinkSync(SYSTEM_DIR, LEGACY_SYSTEM_DIR);
|
|
75
|
+
}
|
|
76
|
+
catch { /* best-effort */ }
|
|
77
|
+
console.error('Merged ~/.agents-system/ into ~/.agents/.system/ (left back-compat symlink)');
|
|
78
|
+
}
|
|
79
|
+
catch { /* best-effort */ }
|
|
80
|
+
}
|
|
16
81
|
/**
|
|
17
82
|
* Move ~/.agents-system/agents.yaml -> ~/.agents/agents.yaml.
|
|
18
83
|
* No-op if user file already exists or system file absent.
|
|
@@ -608,12 +673,13 @@ function repairAgentConfigSymlinks() {
|
|
|
608
673
|
}
|
|
609
674
|
let repaired = 0;
|
|
610
675
|
for (const { agent, version } of defaults) {
|
|
611
|
-
const
|
|
612
|
-
|
|
613
|
-
|
|
676
|
+
const configDirName = agent in AGENTS ? agentConfigDirName(agent) : `.${agent}`;
|
|
677
|
+
const userTarget = fs.existsSync(path.join(HISTORY_DIR, 'versions', agent, version, 'home', configDirName))
|
|
678
|
+
? path.join(HISTORY_DIR, 'versions', agent, version, 'home', configDirName)
|
|
679
|
+
: path.join(USER_DIR, 'versions', agent, version, 'home', configDirName);
|
|
614
680
|
if (!fs.existsSync(userTarget))
|
|
615
681
|
continue;
|
|
616
|
-
const symlinkPath = path.join(HOME,
|
|
682
|
+
const symlinkPath = path.join(HOME, configDirName);
|
|
617
683
|
let stat = null;
|
|
618
684
|
try {
|
|
619
685
|
stat = fs.lstatSync(symlinkPath);
|
|
@@ -1461,8 +1527,166 @@ function migrateVersionResourcesToPatterns() {
|
|
|
1461
1527
|
console.error('Migrated agents.yaml versions: entries to pattern format');
|
|
1462
1528
|
}
|
|
1463
1529
|
}
|
|
1530
|
+
/**
|
|
1531
|
+
* Rename the legacy `extras-extras/` plugin-marketplace dir to `agents-extras/`
|
|
1532
|
+
* inside every installed agent version-home, and rewrite cross-references in
|
|
1533
|
+
* `known_marketplaces.json` and the agent's `settings.json`.
|
|
1534
|
+
*
|
|
1535
|
+
* A previous dev build of `agents-cli` named the extras-aliased repo's
|
|
1536
|
+
* synthesized marketplace dir `extras-extras` (double "extras" because the alias
|
|
1537
|
+
* itself was `extras`). The new naming convention is `agents-<alias>`, so the
|
|
1538
|
+
* directory should be `agents-extras`. Without this migration the orphan dir
|
|
1539
|
+
* stays on disk and Claude Code loads two parallel marketplaces (the legacy
|
|
1540
|
+
* `extras-extras` entry from `known_marketplaces.json` plus the freshly
|
|
1541
|
+
* synthesized `agents-extras` from the new code path).
|
|
1542
|
+
*
|
|
1543
|
+
* Strategy per `<historyDir>/versions/<agent>/<ver>/home/.<agent>/plugins/`:
|
|
1544
|
+
* 1. `marketplaces/extras-extras/` → `marketplaces/agents-extras/`
|
|
1545
|
+
* (drops `extras-extras/` outright when `agents-extras/` already exists —
|
|
1546
|
+
* previous incomplete migration ran)
|
|
1547
|
+
* 2. Inside the renamed dir's `.claude-plugin/marketplace.json`, set
|
|
1548
|
+
* `"name": "agents-extras"`.
|
|
1549
|
+
* 3. In `<configDir>/plugins/known_marketplaces.json`, rename the
|
|
1550
|
+
* `extras-extras` key to `agents-extras` and rewrite `source.path` /
|
|
1551
|
+
* `installLocation`.
|
|
1552
|
+
* 4. In `<configDir>/settings.json`'s `enabledPlugins`, rename every
|
|
1553
|
+
* `<plugin>@extras-extras` key to `<plugin>@agents-extras` (preserving
|
|
1554
|
+
* its boolean value, skipping if the new key already exists).
|
|
1555
|
+
*
|
|
1556
|
+
* Idempotent: re-running converges without further writes once everything is on
|
|
1557
|
+
* the new name.
|
|
1558
|
+
*/
|
|
1559
|
+
export function migrateExtrasExtrasToAgentsExtras(historyDir = HISTORY_DIR) {
|
|
1560
|
+
const versionsRoot = path.join(historyDir, 'versions');
|
|
1561
|
+
if (!fs.existsSync(versionsRoot))
|
|
1562
|
+
return;
|
|
1563
|
+
const OLD = 'extras-extras';
|
|
1564
|
+
const NEW = 'agents-extras';
|
|
1565
|
+
let agentEntries;
|
|
1566
|
+
try {
|
|
1567
|
+
agentEntries = fs.readdirSync(versionsRoot, { withFileTypes: true });
|
|
1568
|
+
}
|
|
1569
|
+
catch {
|
|
1570
|
+
return;
|
|
1571
|
+
}
|
|
1572
|
+
let renamedDirs = 0;
|
|
1573
|
+
let rewroteKnown = 0;
|
|
1574
|
+
let rewroteSettings = 0;
|
|
1575
|
+
for (const agentEntry of agentEntries) {
|
|
1576
|
+
if (!agentEntry.isDirectory())
|
|
1577
|
+
continue;
|
|
1578
|
+
const agentId = agentEntry.name;
|
|
1579
|
+
const agentVersionsDir = path.join(versionsRoot, agentId);
|
|
1580
|
+
let verEntries;
|
|
1581
|
+
try {
|
|
1582
|
+
verEntries = fs.readdirSync(agentVersionsDir, { withFileTypes: true });
|
|
1583
|
+
}
|
|
1584
|
+
catch {
|
|
1585
|
+
continue;
|
|
1586
|
+
}
|
|
1587
|
+
for (const ver of verEntries) {
|
|
1588
|
+
if (!ver.isDirectory())
|
|
1589
|
+
continue;
|
|
1590
|
+
const configDir = path.join(agentVersionsDir, ver.name, 'home', `.${agentId}`);
|
|
1591
|
+
const pluginsDir = path.join(configDir, 'plugins');
|
|
1592
|
+
if (!fs.existsSync(pluginsDir))
|
|
1593
|
+
continue;
|
|
1594
|
+
const marketplacesDir = path.join(pluginsDir, 'marketplaces');
|
|
1595
|
+
const oldDir = path.join(marketplacesDir, OLD);
|
|
1596
|
+
const newDir = path.join(marketplacesDir, NEW);
|
|
1597
|
+
const oldExists = fs.existsSync(oldDir);
|
|
1598
|
+
const newExists = fs.existsSync(newDir);
|
|
1599
|
+
if (oldExists && !newExists) {
|
|
1600
|
+
try {
|
|
1601
|
+
fs.renameSync(oldDir, newDir);
|
|
1602
|
+
renamedDirs++;
|
|
1603
|
+
}
|
|
1604
|
+
catch { /* best-effort, leave orphan */ }
|
|
1605
|
+
}
|
|
1606
|
+
else if (oldExists && newExists) {
|
|
1607
|
+
// Previous incomplete migration — drop the stale old dir.
|
|
1608
|
+
try {
|
|
1609
|
+
fs.rmSync(oldDir, { recursive: true, force: true });
|
|
1610
|
+
}
|
|
1611
|
+
catch { /* best-effort */ }
|
|
1612
|
+
}
|
|
1613
|
+
// Rewrite marketplace.json name field inside the (now) agents-extras dir.
|
|
1614
|
+
const marketplaceJson = path.join(newDir, '.claude-plugin', 'marketplace.json');
|
|
1615
|
+
if (fs.existsSync(marketplaceJson)) {
|
|
1616
|
+
try {
|
|
1617
|
+
const raw = fs.readFileSync(marketplaceJson, 'utf-8');
|
|
1618
|
+
const parsed = JSON.parse(raw);
|
|
1619
|
+
if (parsed?.name === OLD) {
|
|
1620
|
+
parsed.name = NEW;
|
|
1621
|
+
fs.writeFileSync(marketplaceJson, JSON.stringify(parsed, null, 2) + '\n', 'utf-8');
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
catch { /* best-effort */ }
|
|
1625
|
+
}
|
|
1626
|
+
// Rewrite known_marketplaces.json key + path fields.
|
|
1627
|
+
const knownFile = path.join(pluginsDir, 'known_marketplaces.json');
|
|
1628
|
+
if (fs.existsSync(knownFile)) {
|
|
1629
|
+
try {
|
|
1630
|
+
const raw = fs.readFileSync(knownFile, 'utf-8');
|
|
1631
|
+
const known = JSON.parse(raw);
|
|
1632
|
+
if (known && typeof known === 'object' && OLD in known) {
|
|
1633
|
+
const entry = known[OLD];
|
|
1634
|
+
if (!(NEW in known)) {
|
|
1635
|
+
if (entry?.source?.path)
|
|
1636
|
+
entry.source.path = entry.source.path.split(OLD).join(NEW);
|
|
1637
|
+
if (entry?.installLocation)
|
|
1638
|
+
entry.installLocation = entry.installLocation.split(OLD).join(NEW);
|
|
1639
|
+
known[NEW] = entry;
|
|
1640
|
+
}
|
|
1641
|
+
delete known[OLD];
|
|
1642
|
+
fs.writeFileSync(knownFile, JSON.stringify(known, null, 2) + '\n', 'utf-8');
|
|
1643
|
+
rewroteKnown++;
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
catch { /* best-effort */ }
|
|
1647
|
+
}
|
|
1648
|
+
// Rewrite settings.json enabledPlugins keys.
|
|
1649
|
+
const settingsFile = path.join(configDir, 'settings.json');
|
|
1650
|
+
if (fs.existsSync(settingsFile)) {
|
|
1651
|
+
try {
|
|
1652
|
+
const raw = fs.readFileSync(settingsFile, 'utf-8');
|
|
1653
|
+
const settings = JSON.parse(raw);
|
|
1654
|
+
const enabled = settings?.enabledPlugins;
|
|
1655
|
+
if (enabled && typeof enabled === 'object') {
|
|
1656
|
+
const suffix = `@${OLD}`;
|
|
1657
|
+
const newSuffix = `@${NEW}`;
|
|
1658
|
+
let changed = false;
|
|
1659
|
+
for (const key of Object.keys(enabled)) {
|
|
1660
|
+
if (!key.endsWith(suffix))
|
|
1661
|
+
continue;
|
|
1662
|
+
const renamed = key.slice(0, -suffix.length) + newSuffix;
|
|
1663
|
+
if (renamed in enabled) {
|
|
1664
|
+
delete enabled[key];
|
|
1665
|
+
}
|
|
1666
|
+
else {
|
|
1667
|
+
enabled[renamed] = enabled[key];
|
|
1668
|
+
delete enabled[key];
|
|
1669
|
+
}
|
|
1670
|
+
changed = true;
|
|
1671
|
+
}
|
|
1672
|
+
if (changed) {
|
|
1673
|
+
fs.writeFileSync(settingsFile, JSON.stringify(settings, null, 2) + '\n', 'utf-8');
|
|
1674
|
+
rewroteSettings++;
|
|
1675
|
+
}
|
|
1676
|
+
}
|
|
1677
|
+
}
|
|
1678
|
+
catch { /* best-effort */ }
|
|
1679
|
+
}
|
|
1680
|
+
}
|
|
1681
|
+
}
|
|
1682
|
+
if (renamedDirs > 0 || rewroteKnown > 0 || rewroteSettings > 0) {
|
|
1683
|
+
console.error(`Renamed extras-extras → agents-extras (dirs: ${renamedDirs}, known_marketplaces: ${rewroteKnown}, settings: ${rewroteSettings})`);
|
|
1684
|
+
}
|
|
1685
|
+
}
|
|
1464
1686
|
/** Run all idempotent migrations. Safe to call multiple times. */
|
|
1465
1687
|
export async function runMigration() {
|
|
1688
|
+
// MUST run first: every other migrator reads SYSTEM_DIR (the new path).
|
|
1689
|
+
foldLegacySystemRepo();
|
|
1466
1690
|
migrateAgentsYaml();
|
|
1467
1691
|
deleteSystemPromptsJson();
|
|
1468
1692
|
migrateSystemConfigJson();
|
|
@@ -1503,6 +1727,10 @@ export async function runMigration() {
|
|
|
1503
1727
|
await migrateSystemCloudToCache();
|
|
1504
1728
|
dropDeadSystemArtifacts();
|
|
1505
1729
|
warnSystemOrphans();
|
|
1730
|
+
// Rename the legacy extras-extras marketplace dir to agents-extras across every
|
|
1731
|
+
// installed version-home. Runs after migrateRuntimeToHistory so the version
|
|
1732
|
+
// homes are at their canonical HISTORY_DIR location.
|
|
1733
|
+
migrateExtrasExtrasToAgentsExtras();
|
|
1506
1734
|
// Symlink repair runs LAST so it can find the post-move version homes.
|
|
1507
1735
|
repairAgentConfigSymlinks();
|
|
1508
1736
|
}
|
package/dist/lib/models.js
CHANGED
|
@@ -78,27 +78,72 @@ export function locateModelSource(agent, version) {
|
|
|
78
78
|
return null;
|
|
79
79
|
}
|
|
80
80
|
if (agent === 'codex') {
|
|
81
|
+
// Codex's vendored binary has moved across releases:
|
|
82
|
+
// <=0.98: @openai/codex/vendor/<triple>/codex/codex
|
|
83
|
+
// 0.99..0.13: @openai/codex-<plat>-<arch>/vendor/<triple>/codex/codex
|
|
84
|
+
// 0.134+: @openai/codex-<plat>-<arch>/vendor/<triple>/bin/codex
|
|
85
|
+
// We probe all known shapes; first hit wins.
|
|
86
|
+
const triples = ['aarch64-apple-darwin', 'x86_64-apple-darwin', 'x86_64-unknown-linux-musl', 'aarch64-unknown-linux-musl', 'x86_64-pc-windows-msvc', 'aarch64-pc-windows-msvc'];
|
|
81
87
|
const triple = currentTargetTriple();
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
88
|
+
const orderedTriples = triple ? [triple, ...triples.filter((t) => t !== triple)] : triples;
|
|
89
|
+
const platformPkgFor = (t) => `codex-${t.includes('apple') ? 'darwin' : t.includes('linux') ? 'linux' : 'win32'}-${t.includes('aarch64') ? 'arm64' : 'x64'}`;
|
|
90
|
+
for (const t of orderedTriples) {
|
|
91
|
+
const candidates = [
|
|
92
|
+
path.join(versionDir, 'node_modules', '@openai', platformPkgFor(t), 'vendor', t, 'bin', 'codex'),
|
|
93
|
+
path.join(versionDir, 'node_modules', '@openai', platformPkgFor(t), 'vendor', t, 'codex', 'codex'),
|
|
94
|
+
path.join(versionDir, 'node_modules', '@openai', 'codex', 'vendor', t, 'bin', 'codex'),
|
|
95
|
+
path.join(versionDir, 'node_modules', '@openai', 'codex', 'vendor', t, 'codex', 'codex'),
|
|
96
|
+
];
|
|
97
|
+
for (const p of candidates) {
|
|
98
|
+
if (fs.existsSync(p))
|
|
99
|
+
return { path: p, kind: 'binary' };
|
|
100
|
+
}
|
|
93
101
|
}
|
|
94
102
|
return null;
|
|
95
103
|
}
|
|
96
104
|
if (agent === 'gemini') {
|
|
97
|
-
//
|
|
98
|
-
//
|
|
105
|
+
// <=0.41 shipped a clean ES module at @google/gemini-cli-core/dist/src/config/models.js.
|
|
106
|
+
// 0.42+ inlines the same constants into a minified chunk under @google/gemini-cli/bundle/.
|
|
99
107
|
const modelsJs = path.join(versionDir, 'node_modules', '@google', 'gemini-cli-core', 'dist', 'src', 'config', 'models.js');
|
|
100
108
|
if (fs.existsSync(modelsJs))
|
|
101
109
|
return { path: modelsJs, kind: 'js' };
|
|
110
|
+
const bundleDir = path.join(versionDir, 'node_modules', '@google', 'gemini-cli', 'bundle');
|
|
111
|
+
if (fs.existsSync(bundleDir)) {
|
|
112
|
+
try {
|
|
113
|
+
const entries = fs.readdirSync(bundleDir);
|
|
114
|
+
// The model constants live in a single chunk; pick the first .js file
|
|
115
|
+
// whose contents contain VALID_GEMINI_MODELS. Skip subdirectories.
|
|
116
|
+
for (const name of entries) {
|
|
117
|
+
if (!name.endsWith('.js'))
|
|
118
|
+
continue;
|
|
119
|
+
const full = path.join(bundleDir, name);
|
|
120
|
+
let stat;
|
|
121
|
+
try {
|
|
122
|
+
stat = fs.statSync(full);
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
continue;
|
|
126
|
+
}
|
|
127
|
+
if (!stat.isFile())
|
|
128
|
+
continue;
|
|
129
|
+
// Most chunks just re-export the constants; only the defining chunk
|
|
130
|
+
// actually has `var VALID_GEMINI_MODELS = ... new Set(`. Match that
|
|
131
|
+
// shape so we pick the chunk that the extractor can parse.
|
|
132
|
+
let body;
|
|
133
|
+
try {
|
|
134
|
+
body = fs.readFileSync(full, 'utf-8');
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
continue;
|
|
138
|
+
}
|
|
139
|
+
if (/var\s+VALID_GEMINI_MODELS\s*=[^\n]*new\s+Set/.test(body) &&
|
|
140
|
+
/var\s+DEFAULT_GEMINI_MODEL\s*=/.test(body)) {
|
|
141
|
+
return { path: full, kind: 'js' };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
catch { /* unreadable bundle dir */ }
|
|
146
|
+
}
|
|
102
147
|
return null;
|
|
103
148
|
}
|
|
104
149
|
if (agent === 'opencode') {
|
|
@@ -296,7 +341,9 @@ function extractCodexCatalog(text) {
|
|
|
296
341
|
* would pollute the runtime and ES-module interop is awkward from a CJS build).
|
|
297
342
|
*/
|
|
298
343
|
function extractGeminiCatalog(text) {
|
|
299
|
-
const
|
|
344
|
+
// Old (<=0.41) layout used `export const FOO = 'bar';` in models.js.
|
|
345
|
+
// New (0.42+) bundle inlines the same constants as `var FOO = "bar";`.
|
|
346
|
+
const constRe = /(?:export\s+const|var)\s+([A-Z0-9_]+)\s*=\s*['"]([^'"]+)['"]/g;
|
|
300
347
|
const constants = new Map();
|
|
301
348
|
let m;
|
|
302
349
|
while ((m = constRe.exec(text)) !== null) {
|
|
@@ -305,7 +352,7 @@ function extractGeminiCatalog(text) {
|
|
|
305
352
|
// The set of ids the CLI accepts as "valid model names". Names (not values)
|
|
306
353
|
// are listed inside `new Set([...])`, so we expand them via the constants map.
|
|
307
354
|
const validIds = new Set();
|
|
308
|
-
const setBlock = text.match(/VALID_GEMINI_MODELS\s*=\s*new\s+Set\(\[([\s\S]*?)\]\)/);
|
|
355
|
+
const setBlock = text.match(/VALID_GEMINI_MODELS\s*=\s*(?:\/\*[^*]*\*\/\s*)?new\s+Set\(\[([\s\S]*?)\]\)/);
|
|
309
356
|
if (setBlock) {
|
|
310
357
|
const nameRe = /([A-Z0-9_]+)/g;
|
|
311
358
|
let nm;
|
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
import type { AgentId, PermissionSet, InstalledPermission, ClaudePermissions, OpenCodePermissions, CodexPermissions } from './types.js';
|
|
2
|
-
/** Agents that support the permissions subsystem. */
|
|
3
|
-
export declare const PERMISSIONS_CAPABLE_AGENTS: AgentId[];
|
|
4
2
|
/** Filename used for Codex Starlark deny-rules generated from permission groups. */
|
|
5
3
|
export declare const CODEX_RULES_FILENAME = "agents-deny.rules";
|
|
6
4
|
export type ParsedRules = PermissionSet;
|
|
@@ -110,6 +108,65 @@ export declare function convertToGeminiFormat(set: PermissionSet): {
|
|
|
110
108
|
allowed: string[];
|
|
111
109
|
};
|
|
112
110
|
};
|
|
111
|
+
/**
|
|
112
|
+
* Convert canonical permission set to Antigravity format.
|
|
113
|
+
* Antigravity reads ~/.gemini/antigravity-cli/settings.json with
|
|
114
|
+
* { permissions: { allow: [...], deny: [...] } }
|
|
115
|
+
* where each entry is action-namespaced: command(...), read_file(...),
|
|
116
|
+
* write_file(...), read_url(...), mcp(...).
|
|
117
|
+
* Bash maps to `command`, Read to `read_file`, Write to `write_file`,
|
|
118
|
+
* WebFetch to `read_url`. Other canonical tools are skipped.
|
|
119
|
+
* Note: Antigravity matches `command(npm install)` as an exact string,
|
|
120
|
+
* not a prefix — `Bash(npm:*)` becomes `command(npm *)` which is a glob
|
|
121
|
+
* but Antigravity upstream has a known exact-match bug for some forms.
|
|
122
|
+
*/
|
|
123
|
+
export declare function convertToAntigravityFormat(set: PermissionSet): {
|
|
124
|
+
permissions: {
|
|
125
|
+
allow: string[];
|
|
126
|
+
deny?: string[];
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
/**
|
|
130
|
+
* Convert canonical permission set to Grok format.
|
|
131
|
+
* Grok reads ~/.grok/config.toml with
|
|
132
|
+
* [permission]
|
|
133
|
+
* rules = [ { action = "allow", tool = "bash", pattern = "git *" }, ... ]
|
|
134
|
+
* Tool names are lowercase: bash, read, edit, grep, mcptool, webfetch.
|
|
135
|
+
* Canonical Write maps to Grok's `edit` tool.
|
|
136
|
+
*/
|
|
137
|
+
export declare function convertToGrokFormat(set: PermissionSet): {
|
|
138
|
+
permission: {
|
|
139
|
+
rules: GrokRule[];
|
|
140
|
+
};
|
|
141
|
+
};
|
|
142
|
+
export type GrokRule = {
|
|
143
|
+
action: 'allow' | 'deny';
|
|
144
|
+
tool: string;
|
|
145
|
+
pattern?: string;
|
|
146
|
+
};
|
|
147
|
+
export type KimiRule = {
|
|
148
|
+
decision: 'allow' | 'deny';
|
|
149
|
+
pattern: string;
|
|
150
|
+
};
|
|
151
|
+
/**
|
|
152
|
+
* Convert a canonical permission set to Kimi Code's `[permission].rules` format.
|
|
153
|
+
* Kimi (`~/.kimi-code/config.toml`) reads rules of the form
|
|
154
|
+
* [[permission.rules]]
|
|
155
|
+
* decision = "allow"
|
|
156
|
+
* pattern = "Bash(git status*)"
|
|
157
|
+
* Tool names are capitalized and the Bash arg-glob uses a trailing `*` (no
|
|
158
|
+
* Claude `:*` separator). Without this conversion the canonical strings match
|
|
159
|
+
* nothing in Kimi's engine and every tool call falls through to a prompt.
|
|
160
|
+
*
|
|
161
|
+
* Each `:*` Bash rule expands to TWO patterns (`cmd*` and `cmd*/**`) so the
|
|
162
|
+
* command auto-approves whether or not its arguments contain a slash — see
|
|
163
|
+
* `kimiBashPatterns` for why Kimi's picomatch matcher needs both.
|
|
164
|
+
*/
|
|
165
|
+
export declare function convertToKimiFormat(set: PermissionSet): {
|
|
166
|
+
permission: {
|
|
167
|
+
rules: KimiRule[];
|
|
168
|
+
};
|
|
169
|
+
};
|
|
113
170
|
/**
|
|
114
171
|
* Convert canonical permission set to OpenCode format.
|
|
115
172
|
* OpenCode uses: { permission: { bash: { "git *": "allow", "rm *": "deny" } } }
|