@phnx-labs/agents-cli 1.20.77 → 1.20.82
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 +589 -0
- package/README.md +27 -25
- package/dist/bin/agents +0 -0
- package/dist/commands/activity.d.ts +9 -0
- package/dist/commands/activity.js +153 -24
- package/dist/commands/apply.js +11 -4
- package/dist/commands/cli.js +1 -1
- package/dist/commands/commands.d.ts +1 -1
- package/dist/commands/commands.js +7 -6
- package/dist/commands/defaults.js +3 -11
- package/dist/commands/doctor.d.ts +74 -0
- package/dist/commands/doctor.js +718 -40
- package/dist/commands/events.js +1 -1
- package/dist/commands/exec.js +53 -8
- package/dist/commands/feed.d.ts +4 -0
- package/dist/commands/feed.js +87 -11
- package/dist/commands/harness.js +2 -2
- package/dist/commands/hooks.js +1 -1
- package/dist/commands/import.js +8 -4
- package/dist/commands/logs.js +6 -0
- package/dist/commands/models.js +1 -1
- package/dist/commands/packages.js +6 -6
- package/dist/commands/permissions.js +1 -1
- package/dist/commands/profiles.js +1 -1
- package/dist/commands/pull.d.ts +1 -1
- package/dist/commands/pull.js +4 -4
- package/dist/commands/repo.d.ts +78 -0
- package/dist/commands/repo.js +195 -11
- package/dist/commands/routines.js +16 -4
- package/dist/commands/rules.js +13 -12
- package/dist/commands/secrets.d.ts +3 -1
- package/dist/commands/secrets.js +108 -34
- package/dist/commands/sessions-browser.d.ts +45 -3
- package/dist/commands/sessions-browser.js +118 -12
- package/dist/commands/sessions-export.d.ts +3 -0
- package/dist/commands/sessions-export.js +13 -10
- package/dist/commands/sessions-inject.d.ts +7 -4
- package/dist/commands/sessions-inject.js +18 -18
- package/dist/commands/sessions-picker.d.ts +15 -1
- package/dist/commands/sessions-picker.js +90 -7
- package/dist/commands/sessions-resume.d.ts +16 -0
- package/dist/commands/sessions-resume.js +14 -13
- package/dist/commands/sessions.d.ts +126 -1
- package/dist/commands/sessions.js +365 -42
- package/dist/commands/set.d.ts +15 -0
- package/dist/commands/set.js +79 -0
- package/dist/commands/setup-fleet.d.ts +21 -0
- package/dist/commands/setup-fleet.js +201 -0
- package/dist/commands/setup-secrets.d.ts +20 -0
- package/dist/commands/setup-secrets.js +223 -0
- package/dist/commands/setup.js +17 -3
- package/dist/commands/skills.js +1 -1
- package/dist/commands/ssh.js +9 -1
- package/dist/commands/sync.js +7 -2
- package/dist/commands/teams-picker.js +0 -1
- package/dist/commands/teams.d.ts +33 -1
- package/dist/commands/teams.js +208 -44
- package/dist/commands/versions.js +10 -5
- package/dist/commands/view.d.ts +1 -0
- package/dist/commands/view.js +11 -0
- package/dist/index.js +8 -13
- package/dist/lib/acp/harnesses.js +0 -7
- package/dist/lib/activity.d.ts +156 -0
- package/dist/lib/activity.js +282 -0
- package/dist/lib/agents.d.ts +9 -23
- package/dist/lib/agents.js +72 -100
- package/dist/lib/auto-pull.d.ts +16 -8
- package/dist/lib/auto-pull.js +23 -28
- package/dist/lib/browser/service.js +3 -0
- package/dist/lib/browser/types.d.ts +7 -0
- package/dist/lib/capabilities.js +6 -2
- package/dist/lib/crabbox/lease.js +2 -2
- package/dist/lib/crabbox/setup-copy.d.ts +4 -4
- package/dist/lib/crabbox/setup-copy.js +4 -4
- package/dist/lib/daemon.d.ts +26 -40
- package/dist/lib/daemon.js +63 -123
- package/dist/lib/devices/fleet-divergence.d.ts +101 -0
- package/dist/lib/devices/fleet-divergence.js +188 -0
- package/dist/lib/devices/fleet-inventory.d.ts +19 -0
- package/dist/lib/devices/fleet-inventory.js +57 -0
- package/dist/lib/devices/fleet.d.ts +1 -1
- package/dist/lib/devices/fleet.js +1 -1
- package/dist/lib/devices/health-report.d.ts +10 -2
- package/dist/lib/devices/health-report.js +32 -1
- package/dist/lib/doctor-diff.d.ts +20 -0
- package/dist/lib/doctor-diff.js +6 -1
- package/dist/lib/drift.d.ts +31 -11
- package/dist/lib/drift.js +58 -7
- package/dist/lib/events.d.ts +8 -1
- package/dist/lib/events.js +10 -1
- package/dist/lib/exec.js +35 -8
- package/dist/lib/feed-post.d.ts +28 -1
- package/dist/lib/feed-post.js +110 -2
- package/dist/lib/fleet/apply.js +8 -1
- package/dist/lib/fleet/auth-sync.d.ts +18 -1
- package/dist/lib/fleet/auth-sync.js +25 -11
- package/dist/lib/fleet/remote-login.js +5 -0
- package/dist/lib/git.d.ts +27 -14
- package/dist/lib/git.js +138 -43
- package/dist/lib/hooks.d.ts +42 -0
- package/dist/lib/hooks.js +137 -93
- package/dist/lib/hosts/dispatch.d.ts +28 -1
- package/dist/lib/hosts/dispatch.js +33 -5
- package/dist/lib/hosts/option.js +2 -2
- package/dist/lib/hosts/passthrough.d.ts +22 -1
- package/dist/lib/hosts/passthrough.js +238 -13
- package/dist/lib/hosts/remote-cmd.js +2 -0
- package/dist/lib/hosts/run-target.d.ts +2 -0
- package/dist/lib/hosts/run-target.js +1 -0
- package/dist/lib/hq/floor.d.ts +1 -1
- package/dist/lib/hq/floor.js +6 -1
- package/dist/lib/mcp.js +3 -71
- package/dist/lib/menubar/MenubarHelper.app/Contents/Info.plist +2 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/MacOS/MenubarHelper +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/menubar/MenubarHelper.app/Contents/_CodeSignature/CodeResources +15 -2
- package/dist/lib/menubar/notify-desktop.d.ts +15 -0
- package/dist/lib/menubar/notify-desktop.js +41 -5
- package/dist/lib/merged-resources.d.ts +11 -0
- package/dist/{commands/resources.js → lib/merged-resources.js} +11 -19
- package/dist/lib/permissions.d.ts +0 -32
- package/dist/lib/permissions.js +4 -157
- package/dist/lib/picker.js +1 -1
- package/dist/lib/platform/process.d.ts +16 -5
- package/dist/lib/platform/process.js +54 -0
- package/dist/lib/plugins.d.ts +0 -8
- package/dist/lib/plugins.js +4 -110
- package/dist/lib/project-resources.js +4 -1
- package/dist/lib/refresh.d.ts +5 -3
- package/dist/lib/refresh.js +7 -5
- package/dist/lib/resources/commands.js +4 -1
- package/dist/lib/resources/mcp.js +0 -4
- package/dist/lib/resources/permissions.d.ts +1 -1
- package/dist/lib/resources/permissions.js +1 -5
- package/dist/lib/resources/rules.js +4 -1
- package/dist/lib/resources/skills.js +4 -1
- package/dist/lib/resources/subagents.js +4 -0
- package/dist/lib/resources/types.d.ts +1 -1
- package/dist/lib/routines.d.ts +20 -0
- package/dist/lib/routines.js +6 -0
- package/dist/lib/run-defaults.d.ts +1 -0
- package/dist/lib/run-defaults.js +9 -0
- package/dist/lib/runner.d.ts +0 -12
- package/dist/lib/runner.js +71 -29
- package/dist/lib/sandbox.js +0 -16
- package/dist/lib/secrets/Agents CLI.app/Contents/CodeResources +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/Info.plist +2 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/MacOS/Agents CLI +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/Resources/AppIcon.icns +0 -0
- package/dist/lib/secrets/Agents CLI.app/Contents/_CodeSignature/CodeResources +13 -1
- package/dist/lib/secrets/agent.d.ts +18 -0
- package/dist/lib/secrets/agent.js +131 -17
- package/dist/lib/secrets/audit.d.ts +46 -0
- package/dist/lib/secrets/audit.js +56 -0
- package/dist/lib/secrets/bundles.d.ts +12 -9
- package/dist/lib/secrets/bundles.js +47 -31
- package/dist/lib/secrets/index.d.ts +2 -1
- package/dist/lib/secrets/index.js +8 -2
- package/dist/lib/secrets/remote.d.ts +75 -2
- package/dist/lib/secrets/remote.js +139 -5
- package/dist/lib/secrets/scope.d.ts +26 -0
- package/dist/lib/secrets/scope.js +29 -0
- package/dist/lib/secrets/session-store.d.ts +10 -0
- package/dist/lib/secrets/session-store.js +64 -11
- package/dist/lib/secrets/sync.js +3 -3
- package/dist/lib/session/active.d.ts +117 -26
- package/dist/lib/session/active.js +199 -53
- package/dist/lib/session/actor-sidecar.d.ts +23 -0
- package/dist/lib/session/actor-sidecar.js +101 -0
- package/dist/lib/session/db.d.ts +41 -1
- package/dist/lib/session/db.js +173 -8
- package/dist/lib/session/digest.js +126 -21
- package/dist/lib/session/discover.d.ts +19 -2
- package/dist/lib/session/discover.js +32 -11
- package/dist/lib/session/hook-sessions.d.ts +9 -0
- package/dist/lib/session/hook-sessions.js +57 -8
- package/dist/lib/session/origin-machine.d.ts +18 -0
- package/dist/lib/session/origin-machine.js +34 -0
- package/dist/lib/session/pid-registry.d.ts +13 -0
- package/dist/lib/session/render.d.ts +2 -0
- package/dist/lib/session/render.js +1 -1
- package/dist/lib/session/state.d.ts +1 -0
- package/dist/lib/session/state.js +1 -1
- package/dist/lib/session/sync/config.js +2 -2
- package/dist/lib/session/types.d.ts +16 -0
- package/dist/lib/smart-launch.d.ts +86 -0
- package/dist/lib/smart-launch.js +172 -0
- package/dist/lib/staleness/detectors/commands.js +2 -2
- package/dist/lib/staleness/detectors/permissions.js +1 -45
- package/dist/lib/staleness/writers/commands.js +4 -5
- package/dist/lib/staleness/writers/hooks.js +1 -1
- package/dist/lib/startup/command-registry.d.ts +1 -2
- package/dist/lib/startup/command-registry.js +2 -4
- package/dist/lib/subagents-registry.js +5 -12
- package/dist/lib/subagents.d.ts +0 -10
- package/dist/lib/subagents.js +0 -12
- package/dist/lib/teams/agents.d.ts +0 -2
- package/dist/lib/teams/agents.js +10 -27
- package/dist/lib/teams/index.d.ts +1 -1
- package/dist/lib/teams/index.js +1 -1
- package/dist/lib/types.d.ts +17 -9
- package/dist/lib/usage.d.ts +28 -5
- package/dist/lib/usage.js +271 -8
- package/dist/lib/versions.js +7 -1
- package/dist/lib/watchdog/watchdog.d.ts +1 -1
- package/dist/lib/watchdog/watchdog.js +25 -13
- package/package.json +1 -2
- package/dist/commands/check.d.ts +0 -15
- package/dist/commands/check.js +0 -180
- package/dist/commands/resources.d.ts +0 -5
- package/dist/lib/secrets/account-token.d.ts +0 -20
- package/dist/lib/secrets/account-token.js +0 -64
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import * as fs from 'fs';
|
|
8
8
|
import * as path from 'path';
|
|
9
|
-
import { AGENTS, agentConfigDirName } from '../../agents.js';
|
|
9
|
+
import { AGENTS, MANAGED_AGENT_IDS, agentConfigDirName } from '../../agents.js';
|
|
10
10
|
import { shouldInstallCommandAsSkill, listCommandSkillsInVersion } from '../../command-skills.js';
|
|
11
11
|
import { lazyAgentMap } from '../writers/lazy-map.js';
|
|
12
12
|
function buildCommandsDetector(agent) {
|
|
@@ -34,7 +34,7 @@ function buildCommandsDetector(agent) {
|
|
|
34
34
|
// agents with their own slash-command runtime (nativeCommandRuntime) opt out.
|
|
35
35
|
export const commandsDetectors = lazyAgentMap(() => {
|
|
36
36
|
const m = {};
|
|
37
|
-
for (const id of
|
|
37
|
+
for (const id of MANAGED_AGENT_IDS) {
|
|
38
38
|
const cfg = AGENTS[id];
|
|
39
39
|
if (cfg.capabilities.commands === false && (!cfg.commandsSubdir || cfg.commandsSubdir === '') && cfg.nativeCommandRuntime)
|
|
40
40
|
continue;
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* reports the permission GROUP names that have been applied.
|
|
4
4
|
*
|
|
5
5
|
* For claude/opencode the detector intersects with discovered groups (a group
|
|
6
|
-
* is "applied" if any of its allow/deny rules are present). For Codex /
|
|
6
|
+
* is "applied" if any of its allow/deny rules are present). For Codex /
|
|
7
7
|
* Antigravity / Grok the on-disk format is lossy — once any group has been
|
|
8
8
|
* applied the storage doesn't carry per-group provenance back, so we report
|
|
9
9
|
* "all known groups applied" when any permission artifact is present. This
|
|
@@ -100,29 +100,6 @@ function buildOpenCodeDetector() {
|
|
|
100
100
|
},
|
|
101
101
|
};
|
|
102
102
|
}
|
|
103
|
-
function buildGeminiDetector() {
|
|
104
|
-
return {
|
|
105
|
-
kind: 'permissions',
|
|
106
|
-
agent: 'gemini',
|
|
107
|
-
list({ versionHome }) {
|
|
108
|
-
const settingsPath = path.join(versionHome, '.gemini', 'settings.json');
|
|
109
|
-
if (!fs.existsSync(settingsPath))
|
|
110
|
-
return [];
|
|
111
|
-
try {
|
|
112
|
-
const settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
113
|
-
const core = settings?.tools?.core;
|
|
114
|
-
const exclude = settings?.tools?.exclude;
|
|
115
|
-
const hasCore = Array.isArray(core) && core.length > 0;
|
|
116
|
-
const hasExclude = Array.isArray(exclude) && exclude.length > 0;
|
|
117
|
-
if (hasCore || hasExclude) {
|
|
118
|
-
return discoverPermissionGroups().map(g => g.name);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
catch { /* parse fail */ }
|
|
122
|
-
return [];
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
|
-
}
|
|
126
103
|
function buildAntigravityDetector() {
|
|
127
104
|
return {
|
|
128
105
|
kind: 'permissions',
|
|
@@ -312,25 +289,6 @@ function buildCopilotDetector() {
|
|
|
312
289
|
},
|
|
313
290
|
};
|
|
314
291
|
}
|
|
315
|
-
function buildForgeDetector() {
|
|
316
|
-
return {
|
|
317
|
-
kind: 'permissions',
|
|
318
|
-
agent: 'forge',
|
|
319
|
-
list({ versionHome }) {
|
|
320
|
-
const permissionsPath = path.join(versionHome, '.forge', 'permissions.yaml');
|
|
321
|
-
if (!fs.existsSync(permissionsPath))
|
|
322
|
-
return [];
|
|
323
|
-
try {
|
|
324
|
-
const config = yaml.parse(fs.readFileSync(permissionsPath, 'utf-8'));
|
|
325
|
-
if (config && Array.isArray(config.policies) && config.policies.length > 0) {
|
|
326
|
-
return discoverPermissionGroups().map(g => g.name);
|
|
327
|
-
}
|
|
328
|
-
}
|
|
329
|
-
catch { /* parse fail */ }
|
|
330
|
-
return [];
|
|
331
|
-
},
|
|
332
|
-
};
|
|
333
|
-
}
|
|
334
292
|
function buildHermesDetector() {
|
|
335
293
|
return {
|
|
336
294
|
kind: 'permissions',
|
|
@@ -355,7 +313,6 @@ const handlers = {
|
|
|
355
313
|
claude: buildClaudeDetector,
|
|
356
314
|
codex: buildCodexDetector,
|
|
357
315
|
opencode: buildOpenCodeDetector,
|
|
358
|
-
gemini: buildGeminiDetector,
|
|
359
316
|
antigravity: buildAntigravityDetector,
|
|
360
317
|
grok: buildGrokDetector,
|
|
361
318
|
goose: buildGooseDetector,
|
|
@@ -365,7 +322,6 @@ const handlers = {
|
|
|
365
322
|
kiro: buildKiroDetector,
|
|
366
323
|
openclaw: buildOpenClawDetector,
|
|
367
324
|
copilot: buildCopilotDetector,
|
|
368
|
-
forge: buildForgeDetector,
|
|
369
325
|
hermes: buildHermesDetector,
|
|
370
326
|
};
|
|
371
327
|
export const permissionsDetectors = lazyAgentMap(() => {
|
|
@@ -11,15 +11,14 @@
|
|
|
11
11
|
*
|
|
12
12
|
* - native command file — `{agentDir}/<commandsSubdir>/<name>.md` (or .toml
|
|
13
13
|
* when the agent's format is toml). Standard path for Claude, Codex
|
|
14
|
-
* < 0.117.0,
|
|
15
|
-
* Antigravity.
|
|
14
|
+
* < 0.117.0, Cursor, OpenCode, Copilot, Amp, Kiro, Roo, Antigravity.
|
|
16
15
|
*
|
|
17
16
|
* Source resolution is `resolveCommandSource` (user → system → extras —
|
|
18
17
|
* project layer intentionally excluded).
|
|
19
18
|
*/
|
|
20
19
|
import * as fs from 'fs';
|
|
21
20
|
import * as path from 'path';
|
|
22
|
-
import { AGENTS, agentConfigDirName } from '../../agents.js';
|
|
21
|
+
import { AGENTS, MANAGED_AGENT_IDS, agentConfigDirName } from '../../agents.js';
|
|
23
22
|
import { supports } from '../../capabilities.js';
|
|
24
23
|
import { safeJoin } from '../../paths.js';
|
|
25
24
|
import { markdownToToml } from '../../convert.js';
|
|
@@ -83,7 +82,7 @@ function buildCommandsWriter(agent) {
|
|
|
83
82
|
// Built lazily on first access — see lazy-map.ts for the cycle rationale.
|
|
84
83
|
//
|
|
85
84
|
// Registration covers two cases:
|
|
86
|
-
// - native commands (claude, codex < 0.117.0,
|
|
85
|
+
// - native commands (claude, codex < 0.117.0, grok, etc.) — `commands` cap
|
|
87
86
|
// - commands-as-skills (kimi, codex >= 0.117.0)
|
|
88
87
|
//
|
|
89
88
|
// Agents that have skills but use a NATIVE non-file slash-command system
|
|
@@ -92,7 +91,7 @@ function buildCommandsWriter(agent) {
|
|
|
92
91
|
// commands, so there's nothing to write and nothing to convert.
|
|
93
92
|
export const commandsWriters = lazyAgentMap(() => {
|
|
94
93
|
const m = {};
|
|
95
|
-
for (const id of
|
|
94
|
+
for (const id of MANAGED_AGENT_IDS) {
|
|
96
95
|
const cfg = AGENTS[id];
|
|
97
96
|
if (cfg.capabilities.commands === false && (!cfg.skillsDir || cfg.skillsDir === ''))
|
|
98
97
|
continue;
|
|
@@ -90,7 +90,7 @@ function buildHooksWriter(agent) {
|
|
|
90
90
|
// registerHooksForGrok — file copy alone only sees top-level available.hooks
|
|
91
91
|
// names (RUSH-1353). Copilot/Kiro/Goose load managed *.json under their
|
|
92
92
|
// hooks dirs the same way.
|
|
93
|
-
if (agent === 'claude' || agent === 'codex' || agent === '
|
|
93
|
+
if (agent === 'claude' || agent === 'codex' || agent === 'antigravity' || agent === 'kimi' || agent === 'droid' || agent === 'copilot' || agent === 'kiro' || agent === 'goose' || agent === 'cursor' || agent === 'grok' || agent === 'hermes') {
|
|
94
94
|
registerHooksToSettings(agent, versionHome);
|
|
95
95
|
}
|
|
96
96
|
return { synced };
|
|
@@ -25,7 +25,6 @@ export type Registrar = (program: Command) => void;
|
|
|
25
25
|
export type ModuleLoader = () => Promise<Registrar>;
|
|
26
26
|
export declare const loadView: ModuleLoader;
|
|
27
27
|
export declare const loadInspect: ModuleLoader;
|
|
28
|
-
export declare const loadResources: ModuleLoader;
|
|
29
28
|
export declare const loadFeedback: ModuleLoader;
|
|
30
29
|
export declare const loadCommands: ModuleLoader;
|
|
31
30
|
export declare const loadHooks: ModuleLoader;
|
|
@@ -48,13 +47,13 @@ export declare const loadMonitors: ModuleLoader;
|
|
|
48
47
|
export declare const loadRun: ModuleLoader;
|
|
49
48
|
export declare const loadFork: ModuleLoader;
|
|
50
49
|
export declare const loadDefaults: ModuleLoader;
|
|
50
|
+
export declare const loadSet: ModuleLoader;
|
|
51
51
|
export declare const loadModels: ModuleLoader;
|
|
52
52
|
export declare const loadPrune: ModuleLoader;
|
|
53
53
|
export declare const loadTrash: ModuleLoader;
|
|
54
54
|
export declare const loadRestore: ModuleLoader;
|
|
55
55
|
export declare const loadDoctor: ModuleLoader;
|
|
56
56
|
export declare const loadApply: ModuleLoader;
|
|
57
|
-
export declare const loadCheck: ModuleLoader;
|
|
58
57
|
export declare const loadStatus: ModuleLoader;
|
|
59
58
|
export declare const loadProfiles: ModuleLoader;
|
|
60
59
|
export declare const loadHarness: ModuleLoader;
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
// them into the exact main-branch registration order for the slow path.
|
|
4
4
|
export const loadView = async () => (await import('../../commands/view.js')).registerViewCommand;
|
|
5
5
|
export const loadInspect = async () => (await import('../../commands/inspect.js')).registerInspectCommand;
|
|
6
|
-
export const loadResources = async () => (await import('../../commands/resources.js')).registerResourcesCommand;
|
|
7
6
|
export const loadFeedback = async () => (await import('../../commands/feedback.js')).registerFeedbackCommand;
|
|
8
7
|
export const loadCommands = async () => (await import('../../commands/commands.js')).registerCommandsCommands;
|
|
9
8
|
export const loadHooks = async () => (await import('../../commands/hooks.js')).registerHooksCommands;
|
|
@@ -26,13 +25,13 @@ export const loadMonitors = async () => (await import('../../commands/monitors.j
|
|
|
26
25
|
export const loadRun = async () => (await import('../../commands/exec.js')).registerRunCommand;
|
|
27
26
|
export const loadFork = async () => (await import('../../commands/fork.js')).registerForkCommand;
|
|
28
27
|
export const loadDefaults = async () => (await import('../../commands/defaults.js')).registerDefaultsCommands;
|
|
28
|
+
export const loadSet = async () => (await import('../../commands/set.js')).registerSetCommand;
|
|
29
29
|
export const loadModels = async () => (await import('../../commands/models.js')).registerModelsCommand;
|
|
30
30
|
export const loadPrune = async () => (await import('../../commands/prune.js')).registerPruneCommand;
|
|
31
31
|
export const loadTrash = async () => (await import('../../commands/trash.js')).registerTrashCommands;
|
|
32
32
|
export const loadRestore = async () => (await import('../../commands/trash.js')).registerRestoreCommand;
|
|
33
33
|
export const loadDoctor = async () => (await import('../../commands/doctor.js')).registerDoctorCommand;
|
|
34
34
|
export const loadApply = async () => (await import('../../commands/apply.js')).registerApplyCommand;
|
|
35
|
-
export const loadCheck = async () => (await import('../../commands/check.js')).registerCheckCommand;
|
|
36
35
|
export const loadStatus = async () => (await import('../../commands/status.js')).registerStatusCommand;
|
|
37
36
|
export const loadProfiles = async () => (await import('../../commands/profiles.js')).registerProfilesCommands;
|
|
38
37
|
export const loadHarness = async () => (await import('../../commands/harness.js')).registerHarnessCommands;
|
|
@@ -107,7 +106,6 @@ export const LAZY_COMMAND_NAMES = new Set(['sessions', 'teams', 'cloud', 'messag
|
|
|
107
106
|
export const COMMAND_LOADERS = {
|
|
108
107
|
view: [loadView],
|
|
109
108
|
inspect: [loadInspect],
|
|
110
|
-
resources: [loadResources],
|
|
111
109
|
feedback: [loadFeedback],
|
|
112
110
|
commands: [loadCommands],
|
|
113
111
|
hooks: [loadHooks],
|
|
@@ -138,12 +136,12 @@ export const COMMAND_LOADERS = {
|
|
|
138
136
|
run: [loadRun],
|
|
139
137
|
fork: [loadFork],
|
|
140
138
|
defaults: [loadDefaults],
|
|
139
|
+
set: [loadSet],
|
|
141
140
|
models: [loadModels],
|
|
142
141
|
trash: [loadTrash],
|
|
143
142
|
restore: [loadRestore],
|
|
144
143
|
doctor: [loadDoctor],
|
|
145
144
|
apply: [loadApply],
|
|
146
|
-
check: [loadCheck],
|
|
147
145
|
status: [loadStatus],
|
|
148
146
|
profile: [loadProfiles],
|
|
149
147
|
profiles: [loadProfiles],
|
|
@@ -14,8 +14,8 @@
|
|
|
14
14
|
* every current agent, so most entries are a single call:
|
|
15
15
|
*
|
|
16
16
|
* - `flatFile` one `<name><ext>` file, body from a `transform` fn.
|
|
17
|
-
* (claude,
|
|
18
|
-
* cursor,
|
|
17
|
+
* (claude, grok, droid, codex, opencode, copilot,
|
|
18
|
+
* cursor, kiro, goose)
|
|
19
19
|
* - `dirFile` a `<name>/` directory holding one generated `<file>`.
|
|
20
20
|
* (antigravity: `<name>/agent.md`)
|
|
21
21
|
* - `dirCopy` copy the whole source directory to `<name>/`, applying
|
|
@@ -33,13 +33,13 @@ import * as fs from 'fs';
|
|
|
33
33
|
import * as path from 'path';
|
|
34
34
|
import * as yaml from 'yaml';
|
|
35
35
|
import { safeJoin } from './paths.js';
|
|
36
|
-
import { parseSubagentFrontmatter, transformSubagentForClaude, transformSubagentForCodex, transformSubagentForCopilot, transformSubagentForCursor, transformSubagentForDroid,
|
|
36
|
+
import { parseSubagentFrontmatter, transformSubagentForClaude, transformSubagentForCodex, transformSubagentForCopilot, transformSubagentForCursor, transformSubagentForDroid, transformSubagentForGoose, transformSubagentForKiro, transformSubagentForOpenCode, transformSubagentForAntigravity, writeKimiSubagentFiles, buildKimiSubagentsParentYaml, KIMI_SUBAGENTS_PARENT_FILE, } from './subagents.js';
|
|
37
37
|
// ── metadata readers (the per-format escape hatch) ───────────────────────────
|
|
38
|
-
/** Frontmatter, skipping files that lack a valid block (claude/
|
|
38
|
+
/** Frontmatter, skipping files that lack a valid block (claude/grok/droid/codex). */
|
|
39
39
|
function metaFrontmatterSkip(filePath) {
|
|
40
40
|
return parseSubagentFrontmatter(filePath);
|
|
41
41
|
}
|
|
42
|
-
/** Frontmatter, falling back to an empty description (opencode/copilot/cursor
|
|
42
|
+
/** Frontmatter, falling back to an empty description (opencode/copilot/cursor). */
|
|
43
43
|
function metaFrontmatterFallback(filePath, name) {
|
|
44
44
|
return parseSubagentFrontmatter(filePath) ?? { name, description: '' };
|
|
45
45
|
}
|
|
@@ -251,7 +251,6 @@ const kimiTarget = {
|
|
|
251
251
|
export const SUBAGENT_TARGETS = {
|
|
252
252
|
// Tier 1 -- flat markdown, Claude-compatible flatten.
|
|
253
253
|
claude: flatFile({ subdir: ['.claude', 'agents'], ext: '.md', transform: transformSubagentForClaude }),
|
|
254
|
-
gemini: flatFile({ subdir: ['.gemini', 'agents'], ext: '.md', transform: transformSubagentForClaude }),
|
|
255
254
|
grok: flatFile({ subdir: ['.grok', 'agents'], ext: '.md', transform: transformSubagentForClaude }),
|
|
256
255
|
droid: flatFile({ subdir: ['.factory', 'droids'], ext: '.md', transform: transformSubagentForDroid }),
|
|
257
256
|
// Bespoke frontmatter/format, still one flat file.
|
|
@@ -274,12 +273,6 @@ export const SUBAGENT_TARGETS = {
|
|
|
274
273
|
transform: transformSubagentForCursor,
|
|
275
274
|
readMeta: metaFrontmatterFallback,
|
|
276
275
|
}),
|
|
277
|
-
forge: flatFile({
|
|
278
|
-
subdir: ['.forge', 'agents'],
|
|
279
|
-
ext: '.md',
|
|
280
|
-
transform: transformSubagentForForge,
|
|
281
|
-
readMeta: metaFrontmatterFallback,
|
|
282
|
-
}),
|
|
283
276
|
kiro: flatFile({
|
|
284
277
|
subdir: ['.kiro', 'agents'],
|
|
285
278
|
ext: '.json',
|
package/dist/lib/subagents.d.ts
CHANGED
|
@@ -79,16 +79,6 @@ export declare function transformSubagentForCopilot(subagentDir: string): string
|
|
|
79
79
|
* See https://cursor.com/docs/subagents.
|
|
80
80
|
*/
|
|
81
81
|
export declare function transformSubagentForCursor(subagentDir: string): string;
|
|
82
|
-
/**
|
|
83
|
-
* Transform a subagent into a ForgeCode custom subagent `.md` file.
|
|
84
|
-
*
|
|
85
|
-
* ForgeCode loads named agents from `.forge/agents/*.md` (project) or
|
|
86
|
-
* `~/.forge/agents/*.md` (user) — Markdown with YAML frontmatter (id, title,
|
|
87
|
-
* description, tools, model, temperature) + a system-prompt body. ForgeCode has
|
|
88
|
-
* no `color` field, so this is an alias of transformSubagentForDroid, same as
|
|
89
|
-
* Copilot/Cursor. See https://forgecode.dev/docs/agent-definition-guide/.
|
|
90
|
-
*/
|
|
91
|
-
export declare function transformSubagentForForge(subagentDir: string): string;
|
|
92
82
|
/**
|
|
93
83
|
* Transform a subagent into Antigravity's custom-agent markdown shape.
|
|
94
84
|
*
|
package/dist/lib/subagents.js
CHANGED
|
@@ -290,18 +290,6 @@ export function transformSubagentForCopilot(subagentDir) {
|
|
|
290
290
|
export function transformSubagentForCursor(subagentDir) {
|
|
291
291
|
return transformSubagentForDroid(subagentDir);
|
|
292
292
|
}
|
|
293
|
-
/**
|
|
294
|
-
* Transform a subagent into a ForgeCode custom subagent `.md` file.
|
|
295
|
-
*
|
|
296
|
-
* ForgeCode loads named agents from `.forge/agents/*.md` (project) or
|
|
297
|
-
* `~/.forge/agents/*.md` (user) — Markdown with YAML frontmatter (id, title,
|
|
298
|
-
* description, tools, model, temperature) + a system-prompt body. ForgeCode has
|
|
299
|
-
* no `color` field, so this is an alias of transformSubagentForDroid, same as
|
|
300
|
-
* Copilot/Cursor. See https://forgecode.dev/docs/agent-definition-guide/.
|
|
301
|
-
*/
|
|
302
|
-
export function transformSubagentForForge(subagentDir) {
|
|
303
|
-
return transformSubagentForDroid(subagentDir);
|
|
304
|
-
}
|
|
305
293
|
/**
|
|
306
294
|
* Transform a subagent into Antigravity's custom-agent markdown shape.
|
|
307
295
|
*
|
|
@@ -56,8 +56,6 @@ export declare const VALID_MODES: readonly ["plan", "edit", "auto", "skip", "ful
|
|
|
56
56
|
type Mode = 'plan' | 'edit' | 'auto' | 'skip';
|
|
57
57
|
/** Resolve a mode string to a validated Mode, falling back to the given default. */
|
|
58
58
|
export declare function resolveMode(requestedMode: string | null | undefined, defaultMode?: Mode): Mode;
|
|
59
|
-
/** Ensure Gemini's settings.json has experimental.plan enabled for headless plan mode. */
|
|
60
|
-
export declare function ensureGeminiPlanMode(): Promise<void>;
|
|
61
59
|
/**
|
|
62
60
|
* Check whether the CLI binary for a given agent type is installed.
|
|
63
61
|
* Returns [available, pathOrError].
|
package/dist/lib/teams/agents.js
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Defines the AgentProcess and AgentManager classes that handle spawning,
|
|
5
5
|
* monitoring, stopping, and persisting teammate processes across all supported
|
|
6
|
-
* agent CLIs (Claude, Codex,
|
|
6
|
+
* agent CLIs (Claude, Codex, Cursor, OpenCode). Supports DAG-based
|
|
7
7
|
* dependency scheduling via --after, per-teammate model/effort overrides, and
|
|
8
8
|
* multiple permission modes (plan, edit, full).
|
|
9
9
|
*/
|
|
@@ -18,7 +18,6 @@ import { resolveAgentsDir } from './persistence.js';
|
|
|
18
18
|
import { findExecutable, captureProcessStartTime } from '../platform/index.js';
|
|
19
19
|
import { normalizeEvents } from './parsers.js';
|
|
20
20
|
import { debug } from './debug.js';
|
|
21
|
-
import { setGeminiAutoUpdateDisabled, updateGeminiSettings } from '../gemini-settings.js';
|
|
22
21
|
import { getAgentsDir as getSystemAgentsDir, getShimsDir } from '../state.js';
|
|
23
22
|
import { AGENTS, getAccountInfo } from '../agents.js';
|
|
24
23
|
import { resolveVersion, isVersionInstalled, verifyInstalledBinaryLaunches } from '../versions.js';
|
|
@@ -196,7 +195,7 @@ export function buildTeammateSpawnEnv(envOverrides) {
|
|
|
196
195
|
*/
|
|
197
196
|
export { captureProcessStartTime };
|
|
198
197
|
/** Agent types the team runner supports. */
|
|
199
|
-
const TEAM_AGENT_TYPES = ['codex', 'cursor', '
|
|
198
|
+
const TEAM_AGENT_TYPES = ['codex', 'cursor', 'claude', 'opencode', 'grok', 'antigravity', 'kimi', 'droid'];
|
|
200
199
|
// Suffix appended to all prompts to ensure agents provide a summary
|
|
201
200
|
const PROMPT_SUFFIX = `
|
|
202
201
|
|
|
@@ -294,30 +293,6 @@ export function resolveMode(requestedMode, defaultMode = 'plan') {
|
|
|
294
293
|
}
|
|
295
294
|
return normalizedDefault;
|
|
296
295
|
}
|
|
297
|
-
/** Ensure Gemini's settings.json has experimental.plan enabled for headless plan mode. */
|
|
298
|
-
export async function ensureGeminiPlanMode() {
|
|
299
|
-
const settingsPath = path.join(os.homedir(), '.gemini', 'settings.json');
|
|
300
|
-
try {
|
|
301
|
-
let changed = false;
|
|
302
|
-
const settings = updateGeminiSettings(settingsPath, (nextSettings) => {
|
|
303
|
-
setGeminiAutoUpdateDisabled(nextSettings);
|
|
304
|
-
const experimental = typeof nextSettings.experimental === 'object' && nextSettings.experimental !== null
|
|
305
|
-
? nextSettings.experimental
|
|
306
|
-
: {};
|
|
307
|
-
if (experimental.plan === true) {
|
|
308
|
-
return;
|
|
309
|
-
}
|
|
310
|
-
nextSettings.experimental = { ...experimental, plan: true };
|
|
311
|
-
changed = true;
|
|
312
|
-
});
|
|
313
|
-
if (changed && settings.experimental && typeof settings.experimental === 'object' && settings.experimental.plan === true) {
|
|
314
|
-
console.error('[Swarm] Enabled Gemini experimental.plan in', settingsPath);
|
|
315
|
-
}
|
|
316
|
-
}
|
|
317
|
-
catch (err) {
|
|
318
|
-
console.warn('[Swarm] Could not enable Gemini plan mode:', err);
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
296
|
/**
|
|
322
297
|
* Check whether the CLI binary for a given agent type is installed.
|
|
323
298
|
* Returns [available, pathOrError].
|
|
@@ -1312,6 +1287,14 @@ export class AgentManager {
|
|
|
1312
1287
|
async spawn(taskName, agentType, prompt, cwd = null, mode = null, effort = 'medium', parentSessionId = null, workspaceDir = null, version = null, name = null, after = [], model = null, envOverrides = null, taskType = null, cloudProvider = null, cloudSessionId = null, cloudRepo = null, cloudBranch = null, worktreeName = null, worktreePath = null, profileName = null, hostName = null, hostTarget = null, repoPath = null) {
|
|
1313
1288
|
await this.initialize();
|
|
1314
1289
|
const resolvedMode = resolveMode(mode, this.defaultMode);
|
|
1290
|
+
// Lineage (RUSH-2019): when the caller didn't name a parent, inherit the
|
|
1291
|
+
// orchestrator's own session id from its env (exec.ts stamps AGENTS_SESSION_ID
|
|
1292
|
+
// onto every agent process). A team spawned from inside a running agent then
|
|
1293
|
+
// records which session created it, so the spawn chain traces back to a parent
|
|
1294
|
+
// session; a team started outside any agent simply carries none.
|
|
1295
|
+
if (!parentSessionId) {
|
|
1296
|
+
parentSessionId = process.env.AGENTS_SESSION_ID ?? null;
|
|
1297
|
+
}
|
|
1315
1298
|
// Enforce: teammate names are unique within a team.
|
|
1316
1299
|
const siblings = await this.listByTask(taskName);
|
|
1317
1300
|
if (name && siblings.some((a) => a.name === name)) {
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* to reuse the same agent lifecycle, parsing, summarization, and persistence
|
|
6
6
|
* layer that powers the `agents teams` CLI.
|
|
7
7
|
*/
|
|
8
|
-
export { AgentManager, AgentProcess, AgentStatus, VALID_TASK_TYPES, computePathLCA, checkAllClis, checkCliAvailable,
|
|
8
|
+
export { AgentManager, AgentProcess, AgentStatus, VALID_TASK_TYPES, computePathLCA, checkAllClis, checkCliAvailable, getAgentsDir, resolveMode, type TaskType, type CloudDispatchFn, } from './agents.js';
|
|
9
9
|
export { type AgentType } from './parsers.js';
|
|
10
10
|
export { normalizeEvents, normalizeEvent, parseEvent } from './parsers.js';
|
|
11
11
|
export { handleSpawn, handleStatus, handleStop, handleTasks, type SpawnResult, type AgentStatusDetail, type TaskStatusResult, type StopResult, type TaskInfo, type TasksResult, } from './api.js';
|
package/dist/lib/teams/index.js
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* to reuse the same agent lifecycle, parsing, summarization, and persistence
|
|
6
6
|
* layer that powers the `agents teams` CLI.
|
|
7
7
|
*/
|
|
8
|
-
export { AgentManager, AgentProcess, AgentStatus, VALID_TASK_TYPES, computePathLCA, checkAllClis, checkCliAvailable,
|
|
8
|
+
export { AgentManager, AgentProcess, AgentStatus, VALID_TASK_TYPES, computePathLCA, checkAllClis, checkCliAvailable, getAgentsDir, resolveMode, } from './agents.js';
|
|
9
9
|
export { normalizeEvents, normalizeEvent, parseEvent } from './parsers.js';
|
|
10
10
|
export { handleSpawn, handleStatus, handleStop, handleTasks, } from './api.js';
|
|
11
11
|
export { resolveAgentsDir, resolveBaseDir, } from './persistence.js';
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
* formats for each supported agent.
|
|
7
7
|
*/
|
|
8
8
|
import type { CloudProviderId } from './cloud/types.js';
|
|
9
|
-
/** Unique identifier for a
|
|
10
|
-
export type AgentId = 'claude' | 'codex' | 'gemini' | 'cursor' | 'opencode' | 'openclaw' | 'copilot' | 'amp' | 'kiro' | 'goose' | 'antigravity' | 'grok' | 'kimi' | 'droid' | 'hermes'
|
|
9
|
+
/** Unique identifier for a current or legacy AI coding agent. */
|
|
10
|
+
export type AgentId = 'claude' | 'codex' | 'gemini' | 'cursor' | 'opencode' | 'openclaw' | 'copilot' | 'amp' | 'kiro' | 'goose' | 'antigravity' | 'grok' | 'kimi' | 'droid' | 'hermes';
|
|
11
11
|
/** How `agents run <agent>` chooses an installed version when none is pinned. */
|
|
12
12
|
export type RunStrategy = 'pinned' | 'available' | 'balanced';
|
|
13
13
|
/** Per-agent run strategy config. */
|
|
@@ -107,11 +107,11 @@ export interface AgentConfig {
|
|
|
107
107
|
*/
|
|
108
108
|
cloudProvider?: CloudProviderId;
|
|
109
109
|
/**
|
|
110
|
-
* Set when the upstream vendor has retired this agent's CLI.
|
|
111
|
-
* the agent
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
*
|
|
110
|
+
* Set when the upstream vendor has retired this agent's CLI. A warning-only
|
|
111
|
+
* deprecation leaves the agent manageable; a hard deprecation keeps the id
|
|
112
|
+
* parseable for legacy state but excludes it from install/import/sync targets.
|
|
113
|
+
* Point `replacement` at the successor agent so messages can suggest a
|
|
114
|
+
* migration path.
|
|
115
115
|
*/
|
|
116
116
|
deprecated?: {
|
|
117
117
|
/** Vendor that retired it, e.g. "Google". */
|
|
@@ -124,6 +124,8 @@ export interface AgentConfig {
|
|
|
124
124
|
replacement?: AgentId;
|
|
125
125
|
/** Announcement URL for the deprecation. */
|
|
126
126
|
url?: string;
|
|
127
|
+
/** Hard-deprecated agents are retained only for legacy reads. */
|
|
128
|
+
hard?: boolean;
|
|
127
129
|
};
|
|
128
130
|
capabilities: {
|
|
129
131
|
hooks: Capability;
|
|
@@ -745,7 +747,13 @@ export interface Meta {
|
|
|
745
747
|
* passing `--durable` per unlock; off means the secure split default (survive
|
|
746
748
|
* upgrade/restart, re-lock on sleep). */
|
|
747
749
|
secrets?: {
|
|
748
|
-
|
|
750
|
+
/** Default storage backend used when `agents secrets create/import` create a
|
|
751
|
+
* new bundle without `--backend` or `--synced`. */
|
|
752
|
+
backend?: 'keychain' | 'file' | 'vault';
|
|
753
|
+
/** Default prompt policy. `hold` (the default) holds a bundle for
|
|
754
|
+
* `agent.holdMs`; `daily`/`session` are accepted aliases kept so an existing
|
|
755
|
+
* agents.yaml keeps working. See SecretsPolicy in lib/secrets/bundles.ts. */
|
|
756
|
+
policy?: 'always' | 'hold' | 'daily';
|
|
749
757
|
agent?: {
|
|
750
758
|
auto?: boolean;
|
|
751
759
|
holdMs?: number;
|
|
@@ -933,7 +941,7 @@ export interface BrowserProfileConfig {
|
|
|
933
941
|
/** Optional SSH host where logDir lives, e.g. "user@remote-host". */
|
|
934
942
|
logHost?: string;
|
|
935
943
|
}
|
|
936
|
-
/** Options controlling which agents and resources are synced during `agents
|
|
944
|
+
/** Options controlling which agents and resources are synced during `agents sync` / `agents use`. */
|
|
937
945
|
export interface SyncOptions {
|
|
938
946
|
agents?: AgentId[];
|
|
939
947
|
yes?: boolean;
|
package/dist/lib/usage.d.ts
CHANGED
|
@@ -79,11 +79,11 @@ export declare function buildCanonicalUsageContext(inputs: UsageIdentityInput[])
|
|
|
79
79
|
usageFetchInputs: Map<string, UsageFetchInput>;
|
|
80
80
|
};
|
|
81
81
|
/**
|
|
82
|
-
* Whether an agent exposes usage/limit data we can render — Claude/Kimi/Droid
|
|
83
|
-
* a live API, Codex via local session logs. Everything else has no usage
|
|
84
|
-
* so callers use this to decide whether a missing snapshot is worth
|
|
85
|
-
* "usage unavailable" (a signed-in Claude account with no data)
|
|
86
|
-
* applicable (Antigravity,
|
|
82
|
+
* Whether an agent exposes usage/limit data we can render — Claude/Kimi/Droid/Cursor
|
|
83
|
+
* via a live API, Codex/Grok via local session logs. Everything else has no usage
|
|
84
|
+
* concept, so callers use this to decide whether a missing snapshot is worth
|
|
85
|
+
* flagging as "usage unavailable" (a signed-in Claude account with no data)
|
|
86
|
+
* versus simply not applicable (Antigravity, OpenCode).
|
|
87
87
|
*/
|
|
88
88
|
export declare function agentReportsUsage(agentId: AgentId): boolean;
|
|
89
89
|
/** Fetch usage info for all unique accounts in parallel, keyed by usage key. */
|
|
@@ -296,4 +296,27 @@ export declare function writeClaudeUsageCache(usageKey: string, snapshot: UsageS
|
|
|
296
296
|
* Returns true only when a valid access token can be obtained.
|
|
297
297
|
*/
|
|
298
298
|
export declare function isClaudeAuthValid(home?: string): Promise<boolean>;
|
|
299
|
+
/** Per-model bucket in Cursor's /api/usage response. */
|
|
300
|
+
interface CursorUsageModel {
|
|
301
|
+
numRequests?: number | null;
|
|
302
|
+
maxRequestUsage?: number | null;
|
|
303
|
+
}
|
|
304
|
+
/** Response shape from Cursor's dashboard usage endpoint. */
|
|
305
|
+
export interface CursorUsageResponse {
|
|
306
|
+
/** The premium ("fast request") bucket the plan meters. */
|
|
307
|
+
'gpt-4'?: CursorUsageModel | null;
|
|
308
|
+
/** ISO timestamp the monthly request window resets from. */
|
|
309
|
+
startOfMonth?: string | null;
|
|
310
|
+
[model: string]: CursorUsageModel | string | null | undefined;
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Normalize Cursor's /api/usage payload into the common UsageWindow shape.
|
|
314
|
+
*
|
|
315
|
+
* Only free / legacy request-capped plans carry a `maxRequestUsage` on the
|
|
316
|
+
* premium ("gpt-4") bucket — that's the fast-request cap the plan meters, and it
|
|
317
|
+
* maps cleanly to a monthly window. Usage-based plans report `maxRequestUsage:
|
|
318
|
+
* null` (no request cap — spend is metered in dollars instead), so they have no
|
|
319
|
+
* bar to draw here and return no windows rather than a misleading empty gauge.
|
|
320
|
+
*/
|
|
321
|
+
export declare function normalizeCursorUsage(data: CursorUsageResponse): UsageWindow[];
|
|
299
322
|
export {};
|