@phnx-labs/agents-cli 1.20.3 → 1.20.5
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 +27 -0
- package/README.md +48 -17
- package/dist/commands/cli.js +1 -1
- package/dist/commands/cloud.js +1 -1
- package/dist/commands/commands.js +2 -0
- package/dist/commands/doctor.js +1 -1
- package/dist/commands/exec.js +52 -16
- package/dist/commands/hooks.js +6 -6
- package/dist/commands/import.js +90 -37
- 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 +1 -1
- package/dist/commands/sessions.js +1 -0
- package/dist/commands/setup.d.ts +3 -3
- package/dist/commands/setup.js +15 -15
- 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 +1 -0
- 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.js +14 -4
- 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 +68 -20
- package/dist/lib/agents.d.ts +19 -10
- package/dist/lib/agents.js +102 -28
- 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/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 +39 -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/import.d.ts +21 -0
- package/dist/lib/import.js +55 -2
- package/dist/lib/mcp.js +32 -2
- package/dist/lib/migrate.d.ts +51 -0
- package/dist/lib/migrate.js +227 -1
- package/dist/lib/models.js +62 -15
- package/dist/lib/permissions.d.ts +36 -2
- package/dist/lib/permissions.js +217 -7
- package/dist/lib/plugin-marketplace.d.ts +108 -40
- package/dist/lib/plugin-marketplace.js +243 -94
- 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 +65 -0
- package/dist/lib/project-launch.js +367 -0
- package/dist/lib/pty-client.js +1 -1
- package/dist/lib/pty-server.d.ts +1 -1
- package/dist/lib/pty-server.js +28 -4
- 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.js +2 -2
- package/dist/lib/rotate.d.ts +1 -1
- package/dist/lib/rotate.js +1 -1
- 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/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/linux.d.ts +44 -9
- package/dist/lib/secrets/linux.js +302 -48
- 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 +10 -9
- package/dist/lib/shims.js +101 -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/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 +58 -7
- 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 +154 -491
- package/dist/lib/workflows.d.ts +2 -4
- package/dist/lib/workflows.js +3 -4
- package/package.json +7 -7
- package/scripts/postinstall.js +16 -63
- package/dist/commands/status.d.ts +0 -9
- package/dist/commands/status.js +0 -25
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Per-(kind, agent) writer contract.
|
|
3
|
+
*
|
|
4
|
+
* The aggregator in `syncResourcesToVersion` (versions.ts) selects names per
|
|
5
|
+
* kind, then dispatches into a writer from `../registry.ts`. The writer owns
|
|
6
|
+
* everything kind-specific: the agent's storage format, the layered source
|
|
7
|
+
* search, the conversion/copy step. Writers MUST be reached only after a
|
|
8
|
+
* `supports(agent, kind, version).ok === true` precheck — they throw when
|
|
9
|
+
* called on a (kind, agent) pair that the capability matrix says is false.
|
|
10
|
+
*
|
|
11
|
+
* The shape is intentionally narrow. Writers don't accept ambient state; the
|
|
12
|
+
* caller passes the names already resolved against availability. Selection is
|
|
13
|
+
* a string[] for most kinds, a PermissionsSelection object for permissions,
|
|
14
|
+
* and a RulesSelection object for rules — see kind-specific writer modules.
|
|
15
|
+
*/
|
|
16
|
+
import type { AgentId } from '../../types.js';
|
|
17
|
+
import type { ResourceKind } from './kinds.js';
|
|
18
|
+
export interface WriteArgs<Sel> {
|
|
19
|
+
/** Agent version (e.g. "1.2.3") — passed for version-gated capability checks and side files. */
|
|
20
|
+
version: string;
|
|
21
|
+
/** Absolute path to the version's home dir, i.e. `~/.agents/.history/versions/<agent>/<version>/home`. */
|
|
22
|
+
versionHome: string;
|
|
23
|
+
/** Kind-specific selection payload. */
|
|
24
|
+
selection: Sel;
|
|
25
|
+
/** Current working directory — used by writers that consult project-layer state. */
|
|
26
|
+
cwd: string;
|
|
27
|
+
}
|
|
28
|
+
export interface WriteResult {
|
|
29
|
+
/** Names actually written. Empty array = write produced nothing (not an error). */
|
|
30
|
+
synced: string[];
|
|
31
|
+
}
|
|
32
|
+
export interface ResourceWriter<Sel = string[]> {
|
|
33
|
+
readonly kind: ResourceKind;
|
|
34
|
+
readonly agent: AgentId;
|
|
35
|
+
write(args: WriteArgs<Sel>): WriteResult;
|
|
36
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workflows writer — copies each workflow directory into
|
|
3
|
+
* `<versionHome>/workflows/<name>/` via `syncWorkflowToVersion`.
|
|
4
|
+
*/
|
|
5
|
+
import type { AgentId } from '../../types.js';
|
|
6
|
+
import type { ResourceWriter } from './types.js';
|
|
7
|
+
export declare const workflowsWriters: Partial<Record<AgentId, ResourceWriter<string[]>>>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { capableAgents } from '../../capabilities.js';
|
|
2
|
+
import { listInstalledWorkflows, syncWorkflowToVersion } from '../../workflows.js';
|
|
3
|
+
import { lazyAgentMap } from './lazy-map.js';
|
|
4
|
+
function buildWorkflowsWriter(agent) {
|
|
5
|
+
return {
|
|
6
|
+
kind: 'workflows',
|
|
7
|
+
agent,
|
|
8
|
+
write({ versionHome, selection }) {
|
|
9
|
+
const all = listInstalledWorkflows();
|
|
10
|
+
const synced = [];
|
|
11
|
+
for (const name of selection) {
|
|
12
|
+
const wf = all.get(name);
|
|
13
|
+
if (!wf)
|
|
14
|
+
continue;
|
|
15
|
+
try {
|
|
16
|
+
const r = syncWorkflowToVersion(wf.path, name, agent, versionHome);
|
|
17
|
+
if (r.success)
|
|
18
|
+
synced.push(name);
|
|
19
|
+
}
|
|
20
|
+
catch { /* per-item failure: skip */ }
|
|
21
|
+
}
|
|
22
|
+
return { synced };
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
export const workflowsWriters = lazyAgentMap(() => {
|
|
27
|
+
const m = {};
|
|
28
|
+
for (const agent of capableAgents('workflows'))
|
|
29
|
+
m[agent] = buildWorkflowsWriter(agent);
|
|
30
|
+
return m;
|
|
31
|
+
});
|
package/dist/lib/state.d.ts
CHANGED
|
@@ -1,28 +1,34 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Filesystem layout and persistent state for agents-cli.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* - ~/.agents-system/ — system repo (npm-shipped resources, read-only defaults)
|
|
6
|
-
* - ~/.agents/ — user repo (resources + agents.yaml + operational state)
|
|
4
|
+
* Single root at ~/.agents/ with three internal buckets:
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* ~/.agents/ — user repo: user-authored resources + agents.yaml
|
|
7
|
+
* (git-tracked via `agents repo push`).
|
|
8
|
+
* ~/.agents/.system/ — system repo: npm-shipped resources, regenerable.
|
|
9
|
+
* Don't hand-edit; maintained by npm install /
|
|
10
|
+
* `agents repo pull system`.
|
|
11
|
+
* ~/.agents/.history/ — durable runtime data (sessions, versions, runs,
|
|
12
12
|
* teams/agents, trash, backups). Backed up by
|
|
13
13
|
* `agents repo push`.
|
|
14
|
-
*
|
|
14
|
+
* ~/.agents/.cache/ — regenerable runtime data (shims, packages, helpers
|
|
15
15
|
* for daemon/pty, terminals, cloud, drive, browser
|
|
16
16
|
* chrome-data, logs, companion). Gitignored.
|
|
17
17
|
*
|
|
18
18
|
* Resolution precedence for resources: project > user > system.
|
|
19
19
|
* Every module that needs a path or reads/writes agents.yaml goes through here.
|
|
20
|
+
*
|
|
21
|
+
* Legacy layout (pre-fold): system repo lived at ~/.agents-system/ as a peer
|
|
22
|
+
* of ~/.agents/. runMigration() folds it into ~/.agents/.system/ on first run
|
|
23
|
+
* and leaves a back-compat symlink at the old path.
|
|
20
24
|
*/
|
|
21
25
|
import type { Meta } from './types.js';
|
|
22
|
-
/** Root of the system data directory (~/.agents
|
|
26
|
+
/** Root of the system data directory (~/.agents/.system/). */
|
|
23
27
|
export declare function getAgentsDir(): string;
|
|
24
|
-
/** Root of the system data directory (~/.agents
|
|
28
|
+
/** Root of the system data directory (~/.agents/.system/). */
|
|
25
29
|
export declare function getSystemAgentsDir(): string;
|
|
30
|
+
/** Legacy system-repo location (~/.agents-system/). Exported for migration only. */
|
|
31
|
+
export declare function getLegacySystemAgentsDir(): string;
|
|
26
32
|
/** Root of the user repo (~/.agents/). Always present after ensureAgentsDir(). */
|
|
27
33
|
export declare function getUserAgentsDir(): string;
|
|
28
34
|
/**
|
|
@@ -55,7 +61,7 @@ export declare function getMcpDir(): string;
|
|
|
55
61
|
export declare function getPermissionsDir(): string;
|
|
56
62
|
/** Path to subagent definition directories — system repo. */
|
|
57
63
|
export declare function getSubagentsDir(): string;
|
|
58
|
-
/** Path to ~/.agents
|
|
64
|
+
/** Path to ~/.agents/.system/hooks/promptcuts.yaml (system defaults). */
|
|
59
65
|
export declare function getPromptcutsPath(): string;
|
|
60
66
|
/**
|
|
61
67
|
* Resolve the effective promptcuts file: user file if it exists, otherwise
|
|
@@ -101,6 +107,15 @@ export declare function getCacheDir(): string;
|
|
|
101
107
|
export declare function getPackagesDir(): string;
|
|
102
108
|
/** Path to routine YAML definitions (~/.agents/routines/). */
|
|
103
109
|
export declare function getRoutinesDir(): string;
|
|
110
|
+
/**
|
|
111
|
+
* Path to a project-scoped routines directory (`<project>/.agents/routines/`),
|
|
112
|
+
* or null when no project `.agents/` is found by walking up from cwd.
|
|
113
|
+
*
|
|
114
|
+
* Project routines participate in `list`/`view`/`run` for inspection but are
|
|
115
|
+
* NOT fired by the daemon (which runs from $HOME and only loads user routines).
|
|
116
|
+
* Opt-in firing for project routines is tracked as a follow-up.
|
|
117
|
+
*/
|
|
118
|
+
export declare function getProjectRoutinesDir(cwd?: string): string | null;
|
|
104
119
|
/** Path to routine execution logs (~/.agents/.history/runs/). */
|
|
105
120
|
export declare function getRunsDir(): string;
|
|
106
121
|
/** Path to installed agent CLI binaries (~/.agents/.history/versions/). */
|
|
@@ -117,6 +132,12 @@ export declare function getBinDir(): string;
|
|
|
117
132
|
export declare function getBackupsDir(): string;
|
|
118
133
|
/** Path to plugin bundles (~/.agents/plugins/) — user-authored resource. */
|
|
119
134
|
export declare function getPluginsDir(): string;
|
|
135
|
+
/** Path to system plugin bundles (~/.agents/.system/plugins/) — npm-shipped, read-only defaults. */
|
|
136
|
+
export declare function getSystemPluginsDir(): string;
|
|
137
|
+
/** Path to an extra repo's plugin bundles (~/.agents-<alias>/plugins/). */
|
|
138
|
+
export declare function getExtraPluginsDir(alias: string): string;
|
|
139
|
+
/** Path to a project-scoped plugins directory (<project>/.agents/plugins/), or null when none. */
|
|
140
|
+
export declare function getProjectPluginsDir(cwd?: string): string | null;
|
|
120
141
|
/** Path to synced remote session data (~/.agents/.cache/drive/). */
|
|
121
142
|
export declare function getDriveDir(): string;
|
|
122
143
|
/** Path to soft-deleted resources (~/.agents/.history/trash/). */
|
|
@@ -149,6 +170,8 @@ export declare function getHelpersDir(): string;
|
|
|
149
170
|
export declare function getDaemonDir(): string;
|
|
150
171
|
/** Path to PTY server scratch (~/.agents/.cache/helpers/pty/). */
|
|
151
172
|
export declare function getPtyDir(): string;
|
|
173
|
+
/** Path to tmux scratch (~/.agents/.cache/helpers/tmux/) — shared server socket + per-session meta JSONs. */
|
|
174
|
+
export declare function getTmuxDir(): string;
|
|
152
175
|
/** Path to remote-resource auto-pull cache (~/.agents/.cache/.fetch/). */
|
|
153
176
|
export declare function getFetchCacheDir(): string;
|
|
154
177
|
/** Path to the CLI version cache file (~/.agents/.cache/.cli-version-cache.json). */
|
package/dist/lib/state.js
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Filesystem layout and persistent state for agents-cli.
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* - ~/.agents-system/ — system repo (npm-shipped resources, read-only defaults)
|
|
6
|
-
* - ~/.agents/ — user repo (resources + agents.yaml + operational state)
|
|
4
|
+
* Single root at ~/.agents/ with three internal buckets:
|
|
7
5
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
6
|
+
* ~/.agents/ — user repo: user-authored resources + agents.yaml
|
|
7
|
+
* (git-tracked via `agents repo push`).
|
|
8
|
+
* ~/.agents/.system/ — system repo: npm-shipped resources, regenerable.
|
|
9
|
+
* Don't hand-edit; maintained by npm install /
|
|
10
|
+
* `agents repo pull system`.
|
|
11
|
+
* ~/.agents/.history/ — durable runtime data (sessions, versions, runs,
|
|
12
12
|
* teams/agents, trash, backups). Backed up by
|
|
13
13
|
* `agents repo push`.
|
|
14
|
-
*
|
|
14
|
+
* ~/.agents/.cache/ — regenerable runtime data (shims, packages, helpers
|
|
15
15
|
* for daemon/pty, terminals, cloud, drive, browser
|
|
16
16
|
* chrome-data, logs, companion). Gitignored.
|
|
17
17
|
*
|
|
18
18
|
* Resolution precedence for resources: project > user > system.
|
|
19
19
|
* Every module that needs a path or reads/writes agents.yaml goes through here.
|
|
20
|
+
*
|
|
21
|
+
* Legacy layout (pre-fold): system repo lived at ~/.agents-system/ as a peer
|
|
22
|
+
* of ~/.agents/. runMigration() folds it into ~/.agents/.system/ on first run
|
|
23
|
+
* and leaves a back-compat symlink at the old path.
|
|
20
24
|
*/
|
|
21
25
|
import * as fs from 'fs';
|
|
22
26
|
import * as path from 'path';
|
|
@@ -26,10 +30,16 @@ import { ensureLockTarget, atomicWriteFileSync, withFileLock } from './fs-atomic
|
|
|
26
30
|
import { SEEDED_REGISTRIES } from './types.js';
|
|
27
31
|
const HOME = process.env.HOME ?? os.homedir();
|
|
28
32
|
// ─── Root directories ─────────────────────────────────────────────────────────
|
|
29
|
-
/** System repo — npm-shipped, read-only from user commands. */
|
|
30
|
-
const SYSTEM_AGENTS_DIR = path.join(HOME, '.agents-system');
|
|
31
33
|
/** User repo — user-authored resources and agents.yaml. Always-on. */
|
|
32
34
|
const USER_AGENTS_DIR = path.join(HOME, '.agents');
|
|
35
|
+
/** System repo — npm-shipped, read-only from user commands. Lives inside the user repo. */
|
|
36
|
+
const SYSTEM_AGENTS_DIR = path.join(USER_AGENTS_DIR, '.system');
|
|
37
|
+
/**
|
|
38
|
+
* Legacy system-repo location (pre-fold). Exported so the migrator can fold
|
|
39
|
+
* it into SYSTEM_AGENTS_DIR. No runtime code outside the migrator should
|
|
40
|
+
* reference this — use SYSTEM_AGENTS_DIR.
|
|
41
|
+
*/
|
|
42
|
+
const LEGACY_SYSTEM_AGENTS_DIR = path.join(HOME, '.agents-system');
|
|
33
43
|
// ─── Meta file (agents.yaml lives in the user repo) ──────────────────────────
|
|
34
44
|
const META_FILE = path.join(USER_AGENTS_DIR, 'agents.yaml');
|
|
35
45
|
/** Legacy location — used only for one-shot migration in readMeta(). */
|
|
@@ -43,6 +53,7 @@ const SYSTEM_MCP_DIR = path.join(SYSTEM_AGENTS_DIR, 'mcp');
|
|
|
43
53
|
const SYSTEM_PERMISSIONS_DIR = path.join(SYSTEM_AGENTS_DIR, 'permissions');
|
|
44
54
|
const SYSTEM_SUBAGENTS_DIR = path.join(SYSTEM_AGENTS_DIR, 'subagents');
|
|
45
55
|
const SYSTEM_WORKFLOWS_DIR = path.join(SYSTEM_AGENTS_DIR, 'workflows');
|
|
56
|
+
const SYSTEM_PLUGINS_DIR = path.join(SYSTEM_AGENTS_DIR, 'plugins');
|
|
46
57
|
const SYSTEM_PROMPTCUTS_FILE = path.join(SYSTEM_AGENTS_DIR, 'hooks', 'promptcuts.yaml');
|
|
47
58
|
const SYSTEM_MCP_CONFIG_FILE = path.join(SYSTEM_AGENTS_DIR, 'mcp.json');
|
|
48
59
|
const SYSTEM_INSTRUCTIONS_FILE = path.join(SYSTEM_AGENTS_DIR, 'instructions.md');
|
|
@@ -81,6 +92,7 @@ const BROWSER_RUNTIME_DIR = path.join(CACHE_DIR, 'browser');
|
|
|
81
92
|
const HELPERS_DIR = path.join(CACHE_DIR, 'helpers');
|
|
82
93
|
const DAEMON_DIR = path.join(HELPERS_DIR, 'daemon');
|
|
83
94
|
const PTY_DIR = path.join(HELPERS_DIR, 'pty');
|
|
95
|
+
const TMUX_DIR = path.join(HELPERS_DIR, 'tmux');
|
|
84
96
|
const FETCH_CACHE_DIR = path.join(CACHE_DIR, '.fetch');
|
|
85
97
|
const CLI_VERSION_CACHE_FILE = path.join(CACHE_DIR, '.cli-version-cache.json');
|
|
86
98
|
const MODELS_CACHE_FILE = path.join(CACHE_DIR, '.models-cache.json');
|
|
@@ -103,14 +115,18 @@ const META_HEADER = `# agents-cli metadata
|
|
|
103
115
|
|
|
104
116
|
`;
|
|
105
117
|
// ─── Root getters ─────────────────────────────────────────────────────────────
|
|
106
|
-
/** Root of the system data directory (~/.agents
|
|
118
|
+
/** Root of the system data directory (~/.agents/.system/). */
|
|
107
119
|
export function getAgentsDir() {
|
|
108
120
|
return SYSTEM_AGENTS_DIR;
|
|
109
121
|
}
|
|
110
|
-
/** Root of the system data directory (~/.agents
|
|
122
|
+
/** Root of the system data directory (~/.agents/.system/). */
|
|
111
123
|
export function getSystemAgentsDir() {
|
|
112
124
|
return SYSTEM_AGENTS_DIR;
|
|
113
125
|
}
|
|
126
|
+
/** Legacy system-repo location (~/.agents-system/). Exported for migration only. */
|
|
127
|
+
export function getLegacySystemAgentsDir() {
|
|
128
|
+
return LEGACY_SYSTEM_AGENTS_DIR;
|
|
129
|
+
}
|
|
114
130
|
/** Root of the user repo (~/.agents/). Always present after ensureAgentsDir(). */
|
|
115
131
|
export function getUserAgentsDir() {
|
|
116
132
|
return USER_AGENTS_DIR;
|
|
@@ -187,7 +203,7 @@ export function getMcpDir() { return SYSTEM_MCP_DIR; }
|
|
|
187
203
|
export function getPermissionsDir() { return SYSTEM_PERMISSIONS_DIR; }
|
|
188
204
|
/** Path to subagent definition directories — system repo. */
|
|
189
205
|
export function getSubagentsDir() { return SYSTEM_SUBAGENTS_DIR; }
|
|
190
|
-
/** Path to ~/.agents
|
|
206
|
+
/** Path to ~/.agents/.system/hooks/promptcuts.yaml (system defaults). */
|
|
191
207
|
export function getPromptcutsPath() { return SYSTEM_PROMPTCUTS_FILE; }
|
|
192
208
|
/**
|
|
193
209
|
* Resolve the effective promptcuts file: user file if it exists, otherwise
|
|
@@ -261,6 +277,20 @@ export function getCacheDir() { return CACHE_DIR; }
|
|
|
261
277
|
export function getPackagesDir() { return PACKAGES_DIR; }
|
|
262
278
|
/** Path to routine YAML definitions (~/.agents/routines/). */
|
|
263
279
|
export function getRoutinesDir() { return ROUTINES_DIR; }
|
|
280
|
+
/**
|
|
281
|
+
* Path to a project-scoped routines directory (`<project>/.agents/routines/`),
|
|
282
|
+
* or null when no project `.agents/` is found by walking up from cwd.
|
|
283
|
+
*
|
|
284
|
+
* Project routines participate in `list`/`view`/`run` for inspection but are
|
|
285
|
+
* NOT fired by the daemon (which runs from $HOME and only loads user routines).
|
|
286
|
+
* Opt-in firing for project routines is tracked as a follow-up.
|
|
287
|
+
*/
|
|
288
|
+
export function getProjectRoutinesDir(cwd = process.cwd()) {
|
|
289
|
+
const projectAgentsDir = getProjectAgentsDir(cwd);
|
|
290
|
+
if (!projectAgentsDir)
|
|
291
|
+
return null;
|
|
292
|
+
return path.join(projectAgentsDir, 'routines');
|
|
293
|
+
}
|
|
264
294
|
/** Path to routine execution logs (~/.agents/.history/runs/). */
|
|
265
295
|
export function getRunsDir() { return RUNS_DIR; }
|
|
266
296
|
/** Path to installed agent CLI binaries (~/.agents/.history/versions/). */
|
|
@@ -277,6 +307,19 @@ export function getBinDir() { return BIN_DIR; }
|
|
|
277
307
|
export function getBackupsDir() { return BACKUPS_DIR; }
|
|
278
308
|
/** Path to plugin bundles (~/.agents/plugins/) — user-authored resource. */
|
|
279
309
|
export function getPluginsDir() { return PLUGINS_DIR; }
|
|
310
|
+
/** Path to system plugin bundles (~/.agents/.system/plugins/) — npm-shipped, read-only defaults. */
|
|
311
|
+
export function getSystemPluginsDir() { return SYSTEM_PLUGINS_DIR; }
|
|
312
|
+
/** Path to an extra repo's plugin bundles (~/.agents-<alias>/plugins/). */
|
|
313
|
+
export function getExtraPluginsDir(alias) {
|
|
314
|
+
return path.join(getExtraRepoDir(alias), 'plugins');
|
|
315
|
+
}
|
|
316
|
+
/** Path to a project-scoped plugins directory (<project>/.agents/plugins/), or null when none. */
|
|
317
|
+
export function getProjectPluginsDir(cwd = process.cwd()) {
|
|
318
|
+
const projectAgentsDir = getProjectAgentsDir(cwd);
|
|
319
|
+
if (!projectAgentsDir)
|
|
320
|
+
return null;
|
|
321
|
+
return path.join(projectAgentsDir, 'plugins');
|
|
322
|
+
}
|
|
280
323
|
/** Path to synced remote session data (~/.agents/.cache/drive/). */
|
|
281
324
|
export function getDriveDir() { return DRIVE_DIR; }
|
|
282
325
|
/** Path to soft-deleted resources (~/.agents/.history/trash/). */
|
|
@@ -309,6 +352,8 @@ export function getHelpersDir() { return HELPERS_DIR; }
|
|
|
309
352
|
export function getDaemonDir() { return DAEMON_DIR; }
|
|
310
353
|
/** Path to PTY server scratch (~/.agents/.cache/helpers/pty/). */
|
|
311
354
|
export function getPtyDir() { return PTY_DIR; }
|
|
355
|
+
/** Path to tmux scratch (~/.agents/.cache/helpers/tmux/) — shared server socket + per-session meta JSONs. */
|
|
356
|
+
export function getTmuxDir() { return TMUX_DIR; }
|
|
312
357
|
/** Path to remote-resource auto-pull cache (~/.agents/.cache/.fetch/). */
|
|
313
358
|
export function getFetchCacheDir() { return FETCH_CACHE_DIR; }
|
|
314
359
|
/** Path to the CLI version cache file (~/.agents/.cache/.cli-version-cache.json). */
|
package/dist/lib/subagents.d.ts
CHANGED
|
@@ -73,8 +73,6 @@ export declare function removeSubagentFromAgent(subagentName: string, agent: Age
|
|
|
73
73
|
* Check if subagent content matches between source and installed
|
|
74
74
|
*/
|
|
75
75
|
export declare function subagentContentMatches(installedDir: string, sourceDir: string): boolean;
|
|
76
|
-
/** Agents that support the subagent system (Claude via flattened .md, OpenClaw via directory copy). */
|
|
77
|
-
export declare const SUBAGENT_CAPABLE_AGENTS: AgentId[];
|
|
78
76
|
/**
|
|
79
77
|
* List subagents installed to a specific agent's home
|
|
80
78
|
* Claude: scans ~/.claude/agents/{name}.md
|
package/dist/lib/subagents.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
import * as fs from 'fs';
|
|
10
10
|
import * as path from 'path';
|
|
11
11
|
import * as yaml from 'yaml';
|
|
12
|
+
import { capableAgents } from './capabilities.js';
|
|
12
13
|
import { getSubagentsDir, getUserSubagentsDir, getTrashSubagentsDir } from './state.js';
|
|
13
14
|
import { listInstalledVersions, getVersionHomePath } from './versions.js';
|
|
14
15
|
import { safeJoin } from './paths.js';
|
|
@@ -333,8 +334,9 @@ export function subagentContentMatches(installedDir, sourceDir) {
|
|
|
333
334
|
}
|
|
334
335
|
return true;
|
|
335
336
|
}
|
|
336
|
-
|
|
337
|
-
|
|
337
|
+
// SUBAGENT_CAPABLE_AGENTS removed — use `capableAgents('subagents')` from
|
|
338
|
+
// lib/capabilities.ts. The capability matrix on AgentConfig is the single
|
|
339
|
+
// source of truth.
|
|
338
340
|
/**
|
|
339
341
|
* List subagents installed to a specific agent's home
|
|
340
342
|
* Claude: scans ~/.claude/agents/{name}.md
|
|
@@ -408,8 +410,6 @@ export function listSubagentsForAgent(agentId, home) {
|
|
|
408
410
|
}
|
|
409
411
|
return subagents;
|
|
410
412
|
}
|
|
411
|
-
// Agents that support subagents
|
|
412
|
-
const SUBAGENTS_CAPABLE_AGENTS = ['claude', 'openclaw'];
|
|
413
413
|
/**
|
|
414
414
|
* Compare a version home's subagents against discovered subagents.
|
|
415
415
|
* Returns orphan subagent names.
|
|
@@ -461,9 +461,9 @@ export function diffVersionSubagents(agent, version) {
|
|
|
461
461
|
*/
|
|
462
462
|
export function iterSubagentsCapableVersions(filter) {
|
|
463
463
|
const pairs = [];
|
|
464
|
-
const agents = filter?.agent ? [filter.agent] :
|
|
464
|
+
const agents = filter?.agent ? [filter.agent] : capableAgents('subagents');
|
|
465
465
|
for (const agent of agents) {
|
|
466
|
-
if (!
|
|
466
|
+
if (!capableAgents('subagents').includes(agent))
|
|
467
467
|
continue;
|
|
468
468
|
const versions = listInstalledVersions(agent);
|
|
469
469
|
for (const version of versions) {
|
package/dist/lib/teams/agents.js
CHANGED
|
@@ -172,7 +172,7 @@ export function captureProcessStartTime(pid) {
|
|
|
172
172
|
}
|
|
173
173
|
}
|
|
174
174
|
/** Agent types the team runner supports. */
|
|
175
|
-
const TEAM_AGENT_TYPES = ['codex', 'cursor', 'gemini', 'claude', 'opencode', 'grok', 'antigravity'];
|
|
175
|
+
const TEAM_AGENT_TYPES = ['codex', 'cursor', 'gemini', 'claude', 'opencode', 'grok', 'antigravity', 'kimi'];
|
|
176
176
|
// Suffix appended to all prompts to ensure agents provide a summary
|
|
177
177
|
const PROMPT_SUFFIX = `
|
|
178
178
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Supported agent CLI types for team spawning. */
|
|
2
|
-
export type AgentType = 'codex' | 'gemini' | 'cursor' | 'claude' | 'opencode' | 'grok' | 'antigravity';
|
|
2
|
+
export type AgentType = 'codex' | 'gemini' | 'cursor' | 'claude' | 'opencode' | 'grok' | 'antigravity' | 'kimi';
|
|
3
3
|
/** Normalize a raw JSON event from any agent type into an array of unified event objects. */
|
|
4
4
|
export declare function normalizeEvents(agentType: AgentType, raw: any): any[];
|
|
5
5
|
/** Normalize a raw JSON event, returning only the first unified event (convenience wrapper). */
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tmux binary discovery + spawn helpers.
|
|
3
|
+
*
|
|
4
|
+
* Every shell-out goes through `runTmux()` so:
|
|
5
|
+
* - args are passed as an array, never interpolated into a shell string (no
|
|
6
|
+
* quoting bugs like swarmify's `command.replace(/'/g, "'\\''")` hack);
|
|
7
|
+
* - the socket arg is positioned correctly (`-S <sock>` MUST come before the
|
|
8
|
+
* subcommand);
|
|
9
|
+
* - stdout/stderr capture is consistent for the session module to parse.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Locate the tmux binary on PATH. Cached after first call — tmux either is or
|
|
13
|
+
* isn't installed for the duration of the process.
|
|
14
|
+
*
|
|
15
|
+
* Returns null when tmux is not installed.
|
|
16
|
+
*/
|
|
17
|
+
export declare function findTmuxBinary(): string | null;
|
|
18
|
+
/** True when tmux is installed somewhere on PATH. */
|
|
19
|
+
export declare function isTmuxInstalled(): boolean;
|
|
20
|
+
/** Best-effort tmux version string (e.g. "tmux 3.6a"). Returns null when not installed or version probe fails. */
|
|
21
|
+
export declare function getTmuxVersion(): string | null;
|
|
22
|
+
/**
|
|
23
|
+
* Throw a user-friendly error when tmux isn't installed. Command handlers call
|
|
24
|
+
* this first thing so the error message is the same shape every time.
|
|
25
|
+
*/
|
|
26
|
+
export declare function assertTmuxAvailable(): string;
|
|
27
|
+
export declare class TmuxUnavailableError extends Error {
|
|
28
|
+
constructor(message: string);
|
|
29
|
+
}
|
|
30
|
+
export declare class TmuxCommandError extends Error {
|
|
31
|
+
readonly stderr: string;
|
|
32
|
+
readonly stdout: string;
|
|
33
|
+
readonly code: number | null;
|
|
34
|
+
constructor(message: string, stderr: string, stdout: string, code: number | null);
|
|
35
|
+
}
|
|
36
|
+
export interface RunTmuxOptions {
|
|
37
|
+
/** Socket path (default: shared server socket). */
|
|
38
|
+
socket?: string;
|
|
39
|
+
/** Args after `tmux -S <socket>` — e.g. `['has-session', '-t', 'foo']`. */
|
|
40
|
+
args: string[];
|
|
41
|
+
/** Throw on nonzero exit. Defaults true. */
|
|
42
|
+
throwOnError?: boolean;
|
|
43
|
+
/** Child process env. */
|
|
44
|
+
env?: NodeJS.ProcessEnv;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Run a tmux command and capture stdout/stderr. The socket arg is hoisted in
|
|
48
|
+
* front of `args` so callers never have to remember the `-S` position.
|
|
49
|
+
*
|
|
50
|
+
* For interactive `attach`, use `attachTmux()` instead — this helper is for
|
|
51
|
+
* scripted commands where you want output back as strings.
|
|
52
|
+
*/
|
|
53
|
+
export declare function runTmux(opts: RunTmuxOptions): Promise<{
|
|
54
|
+
stdout: string;
|
|
55
|
+
stderr: string;
|
|
56
|
+
code: number;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* Foreground attach. Replaces this process's stdio with tmux's so the user is
|
|
60
|
+
* fully inside tmux. Returns the tmux exit code (which the caller should mirror
|
|
61
|
+
* via process.exit so detach/Ctrl-D propagates cleanly).
|
|
62
|
+
*/
|
|
63
|
+
export declare function attachTmux(opts: {
|
|
64
|
+
socket: string;
|
|
65
|
+
args: string[];
|
|
66
|
+
env?: NodeJS.ProcessEnv;
|
|
67
|
+
}): Promise<number>;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tmux binary discovery + spawn helpers.
|
|
3
|
+
*
|
|
4
|
+
* Every shell-out goes through `runTmux()` so:
|
|
5
|
+
* - args are passed as an array, never interpolated into a shell string (no
|
|
6
|
+
* quoting bugs like swarmify's `command.replace(/'/g, "'\\''")` hack);
|
|
7
|
+
* - the socket arg is positioned correctly (`-S <sock>` MUST come before the
|
|
8
|
+
* subcommand);
|
|
9
|
+
* - stdout/stderr capture is consistent for the session module to parse.
|
|
10
|
+
*/
|
|
11
|
+
import { spawn, spawnSync } from 'child_process';
|
|
12
|
+
import { existsSync } from 'fs';
|
|
13
|
+
let cachedBin;
|
|
14
|
+
/**
|
|
15
|
+
* Locate the tmux binary on PATH. Cached after first call — tmux either is or
|
|
16
|
+
* isn't installed for the duration of the process.
|
|
17
|
+
*
|
|
18
|
+
* Returns null when tmux is not installed.
|
|
19
|
+
*/
|
|
20
|
+
export function findTmuxBinary() {
|
|
21
|
+
if (cachedBin !== undefined)
|
|
22
|
+
return cachedBin;
|
|
23
|
+
// Try `which` first (respects PATH); fall back to common Homebrew/Linux paths
|
|
24
|
+
// so a stripped CI shell with a sparse PATH still works.
|
|
25
|
+
const fromWhich = spawnSync('sh', ['-c', 'command -v tmux'], { encoding: 'utf8' });
|
|
26
|
+
if (fromWhich.status === 0) {
|
|
27
|
+
const out = fromWhich.stdout.trim();
|
|
28
|
+
if (out && existsSync(out)) {
|
|
29
|
+
cachedBin = out;
|
|
30
|
+
return cachedBin;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
for (const p of ['/opt/homebrew/bin/tmux', '/usr/local/bin/tmux', '/usr/bin/tmux']) {
|
|
34
|
+
if (existsSync(p)) {
|
|
35
|
+
cachedBin = p;
|
|
36
|
+
return cachedBin;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
cachedBin = null;
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
/** True when tmux is installed somewhere on PATH. */
|
|
43
|
+
export function isTmuxInstalled() {
|
|
44
|
+
return findTmuxBinary() !== null;
|
|
45
|
+
}
|
|
46
|
+
/** Best-effort tmux version string (e.g. "tmux 3.6a"). Returns null when not installed or version probe fails. */
|
|
47
|
+
export function getTmuxVersion() {
|
|
48
|
+
const bin = findTmuxBinary();
|
|
49
|
+
if (!bin)
|
|
50
|
+
return null;
|
|
51
|
+
const res = spawnSync(bin, ['-V'], { encoding: 'utf8' });
|
|
52
|
+
if (res.status !== 0)
|
|
53
|
+
return null;
|
|
54
|
+
return res.stdout.trim() || null;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Throw a user-friendly error when tmux isn't installed. Command handlers call
|
|
58
|
+
* this first thing so the error message is the same shape every time.
|
|
59
|
+
*/
|
|
60
|
+
export function assertTmuxAvailable() {
|
|
61
|
+
const bin = findTmuxBinary();
|
|
62
|
+
if (!bin) {
|
|
63
|
+
const platform = process.platform;
|
|
64
|
+
const hint = platform === 'darwin'
|
|
65
|
+
? 'Install with: brew install tmux'
|
|
66
|
+
: platform === 'linux'
|
|
67
|
+
? 'Install with: apt install tmux (or dnf/yum/pacman equivalent)'
|
|
68
|
+
: 'Install tmux from https://github.com/tmux/tmux';
|
|
69
|
+
throw new TmuxUnavailableError(`tmux is not installed. ${hint}`);
|
|
70
|
+
}
|
|
71
|
+
return bin;
|
|
72
|
+
}
|
|
73
|
+
export class TmuxUnavailableError extends Error {
|
|
74
|
+
constructor(message) {
|
|
75
|
+
super(message);
|
|
76
|
+
this.name = 'TmuxUnavailableError';
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export class TmuxCommandError extends Error {
|
|
80
|
+
stderr;
|
|
81
|
+
stdout;
|
|
82
|
+
code;
|
|
83
|
+
constructor(message, stderr, stdout, code) {
|
|
84
|
+
super(message);
|
|
85
|
+
this.name = 'TmuxCommandError';
|
|
86
|
+
this.stderr = stderr;
|
|
87
|
+
this.stdout = stdout;
|
|
88
|
+
this.code = code;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Run a tmux command and capture stdout/stderr. The socket arg is hoisted in
|
|
93
|
+
* front of `args` so callers never have to remember the `-S` position.
|
|
94
|
+
*
|
|
95
|
+
* For interactive `attach`, use `attachTmux()` instead — this helper is for
|
|
96
|
+
* scripted commands where you want output back as strings.
|
|
97
|
+
*/
|
|
98
|
+
export async function runTmux(opts) {
|
|
99
|
+
const bin = assertTmuxAvailable();
|
|
100
|
+
const fullArgs = [];
|
|
101
|
+
if (opts.socket)
|
|
102
|
+
fullArgs.push('-S', opts.socket);
|
|
103
|
+
fullArgs.push(...opts.args);
|
|
104
|
+
return new Promise((resolve, reject) => {
|
|
105
|
+
const child = spawn(bin, fullArgs, {
|
|
106
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
107
|
+
env: opts.env ?? process.env,
|
|
108
|
+
});
|
|
109
|
+
let stdout = '';
|
|
110
|
+
let stderr = '';
|
|
111
|
+
child.stdout?.on('data', (b) => { stdout += b.toString('utf8'); });
|
|
112
|
+
child.stderr?.on('data', (b) => { stderr += b.toString('utf8'); });
|
|
113
|
+
child.on('error', reject);
|
|
114
|
+
child.on('close', (code) => {
|
|
115
|
+
const exitCode = code ?? -1;
|
|
116
|
+
const throwOnError = opts.throwOnError !== false;
|
|
117
|
+
if (throwOnError && exitCode !== 0) {
|
|
118
|
+
reject(new TmuxCommandError(`tmux ${fullArgs.join(' ')} failed (exit ${exitCode}): ${stderr.trim() || stdout.trim()}`, stderr, stdout, exitCode));
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
resolve({ stdout, stderr, code: exitCode });
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Foreground attach. Replaces this process's stdio with tmux's so the user is
|
|
127
|
+
* fully inside tmux. Returns the tmux exit code (which the caller should mirror
|
|
128
|
+
* via process.exit so detach/Ctrl-D propagates cleanly).
|
|
129
|
+
*/
|
|
130
|
+
export function attachTmux(opts) {
|
|
131
|
+
const bin = assertTmuxAvailable();
|
|
132
|
+
const fullArgs = ['-S', opts.socket, ...opts.args];
|
|
133
|
+
return new Promise((resolve, reject) => {
|
|
134
|
+
const child = spawn(bin, fullArgs, {
|
|
135
|
+
stdio: 'inherit',
|
|
136
|
+
env: opts.env ?? process.env,
|
|
137
|
+
});
|
|
138
|
+
child.on('error', reject);
|
|
139
|
+
child.on('close', (code) => resolve(code ?? 0));
|
|
140
|
+
});
|
|
141
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public entry-point for the tmux integration. Consumers outside the CLI
|
|
3
|
+
* (swarmify extension, `agents teams` multiplexer mode, future MCP wrapper)
|
|
4
|
+
* should import from here.
|
|
5
|
+
*/
|
|
6
|
+
export { findTmuxBinary, isTmuxInstalled, getTmuxVersion, assertTmuxAvailable, TmuxUnavailableError, TmuxCommandError, runTmux, attachTmux, } from './binary.js';
|
|
7
|
+
export { getDefaultSocketPath, getSessionMetaPath, ensureTmuxDir, } from './paths.js';
|
|
8
|
+
export { assertValidSessionName, slugifyName, hasSession, createSession, killSession, killAll, listSessions, splitPane, sendKeys, capturePane, readSessionMeta, TmuxSessionError, type SessionMeta, type CreateSessionOptions, type ListedSession, type SplitOptions, type SendOptions, type CaptureOptions, } from './session.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public entry-point for the tmux integration. Consumers outside the CLI
|
|
3
|
+
* (swarmify extension, `agents teams` multiplexer mode, future MCP wrapper)
|
|
4
|
+
* should import from here.
|
|
5
|
+
*/
|
|
6
|
+
export { findTmuxBinary, isTmuxInstalled, getTmuxVersion, assertTmuxAvailable, TmuxUnavailableError, TmuxCommandError, runTmux, attachTmux, } from './binary.js';
|
|
7
|
+
export { getDefaultSocketPath, getSessionMetaPath, ensureTmuxDir, } from './paths.js';
|
|
8
|
+
export { assertValidSessionName, slugifyName, hasSession, createSession, killSession, killAll, listSessions, splitPane, sendKeys, capturePane, readSessionMeta, TmuxSessionError, } from './session.js';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filesystem paths for the tmux integration.
|
|
3
|
+
*
|
|
4
|
+
* Layout under ~/.agents/.cache/helpers/tmux/:
|
|
5
|
+
* server.sock — shared tmux server socket hosting all named sessions
|
|
6
|
+
* <name>.json — per-session provenance (cmd, cwd, created_at, source)
|
|
7
|
+
*
|
|
8
|
+
* A single shared server is simpler than per-session sockets: one round-trip
|
|
9
|
+
* for `tmux ls`, one place to clean up, and no extra tmux servers eating
|
|
10
|
+
* memory. Per-session isolation can still be opted into via `--socket`.
|
|
11
|
+
*/
|
|
12
|
+
/** Default shared server socket — every `agents tmux *` command targets this unless overridden. */
|
|
13
|
+
export declare function getDefaultSocketPath(): string;
|
|
14
|
+
/** Per-session provenance JSON. tmux itself is the source of truth for liveness; this file is metadata only. */
|
|
15
|
+
export declare function getSessionMetaPath(name: string): string;
|
|
16
|
+
/** Ensure the tmux scratch dir exists with restrictive permissions (sockets are user-private). */
|
|
17
|
+
export declare function ensureTmuxDir(): string;
|