@phnx-labs/agents-cli 1.20.78 → 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 +487 -0
- package/README.md +25 -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 +65 -0
- package/dist/commands/doctor.js +575 -31
- package/dist/commands/events.js +1 -1
- package/dist/commands/exec.js +24 -5
- 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 +187 -11
- package/dist/commands/routines.js +12 -2
- package/dist/commands/rules.js +13 -12
- package/dist/commands/secrets.d.ts +3 -1
- package/dist/commands/secrets.js +100 -32
- package/dist/commands/sessions-inject.d.ts +7 -4
- package/dist/commands/sessions-inject.js +18 -18
- package/dist/commands/sessions-picker.js +32 -3
- package/dist/commands/sessions-resume.d.ts +16 -0
- package/dist/commands/sessions-resume.js +14 -13
- package/dist/commands/sessions.d.ts +31 -0
- package/dist/commands/sessions.js +141 -16
- 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/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 +5 -8
- 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 -2
- package/dist/lib/agents.js +72 -63
- 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 +18 -0
- package/dist/lib/daemon.js +47 -6
- package/dist/lib/devices/fleet.d.ts +1 -1
- package/dist/lib/devices/fleet.js +1 -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 +14 -14
- package/dist/lib/git.js +41 -44
- 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/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/MacOS/MenubarHelper +0 -0
- 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 +49 -10
- 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/agent.d.ts +16 -0
- package/dist/lib/secrets/agent.js +105 -3
- package/dist/lib/secrets/audit.d.ts +46 -0
- package/dist/lib/secrets/audit.js +56 -0
- package/dist/lib/secrets/bundles.d.ts +11 -8
- package/dist/lib/secrets/bundles.js +31 -23
- 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/sync.js +3 -3
- package/dist/lib/session/active.d.ts +110 -26
- package/dist/lib/session/active.js +161 -50
- 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 +4 -1
- package/dist/lib/session/db.js +65 -8
- package/dist/lib/session/discover.d.ts +4 -0
- package/dist/lib/session/discover.js +13 -0
- package/dist/lib/session/hook-sessions.d.ts +9 -0
- package/dist/lib/session/hook-sessions.js +57 -8
- 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/types.d.ts +16 -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/commands/teams.js
CHANGED
|
@@ -12,7 +12,7 @@ import { shareRuntimeEnv } from '../lib/share/config.js';
|
|
|
12
12
|
import { runSupervisor } from '../lib/teams/supervisor.js';
|
|
13
13
|
import { debug } from '../lib/teams/debug.js';
|
|
14
14
|
import { runPrWatch, DEFAULT_MAX_WAVES, } from '../lib/teams/pr-watch.js';
|
|
15
|
-
import { handleSpawn, handleStatus, handleStop,
|
|
15
|
+
import { handleSpawn, handleStatus, handleStop, toTaskStatusSummary, } from '../lib/teams/api.js';
|
|
16
16
|
import { createTeam, ensureTeam, getTeam, loadTeams, removeTeam, teamExists, } from '../lib/teams/registry.js';
|
|
17
17
|
import { setHelpSections } from '../lib/help.js';
|
|
18
18
|
import { createWorktree, isGitRepo, hasUncommittedChanges, removeWorktree, } from '../lib/teams/worktree.js';
|
|
@@ -46,7 +46,7 @@ const AGENT_NAMES = {
|
|
|
46
46
|
kimi: 'Kimi',
|
|
47
47
|
droid: 'Droid',
|
|
48
48
|
};
|
|
49
|
-
const VALID_AGENTS =
|
|
49
|
+
const VALID_AGENTS = ['claude', 'codex', 'cursor', 'opencode', 'grok', 'antigravity', 'kimi', 'droid'];
|
|
50
50
|
// 'full' kept as historical alias for 'skip'; normalized to 'skip' downstream.
|
|
51
51
|
const VALID_MODES = ['plan', 'edit', 'auto', 'skip', 'full'];
|
|
52
52
|
const VALID_EFFORTS = ['low', 'medium', 'high', 'xhigh', 'max', 'auto'];
|
|
@@ -77,6 +77,75 @@ function formatTimestamp(iso) {
|
|
|
77
77
|
minute: '2-digit',
|
|
78
78
|
});
|
|
79
79
|
}
|
|
80
|
+
function normalizeTeamListStatus(status) {
|
|
81
|
+
if (Object.values(AgentStatus).includes(status)) {
|
|
82
|
+
return status;
|
|
83
|
+
}
|
|
84
|
+
return AgentStatus.RUNNING;
|
|
85
|
+
}
|
|
86
|
+
function parseTimestamp(value) {
|
|
87
|
+
if (!value)
|
|
88
|
+
return null;
|
|
89
|
+
const date = new Date(value);
|
|
90
|
+
return Number.isNaN(date.getTime()) ? null : date;
|
|
91
|
+
}
|
|
92
|
+
function durationFromSnapshot(agent) {
|
|
93
|
+
const startedAt = parseTimestamp(agent.started_at);
|
|
94
|
+
if (!startedAt)
|
|
95
|
+
return null;
|
|
96
|
+
const completedAt = parseTimestamp(agent.completed_at);
|
|
97
|
+
let seconds;
|
|
98
|
+
if (completedAt) {
|
|
99
|
+
seconds = (completedAt.getTime() - startedAt.getTime()) / 1000;
|
|
100
|
+
}
|
|
101
|
+
else if (normalizeTeamListStatus(agent.status) === AgentStatus.RUNNING) {
|
|
102
|
+
seconds = (Date.now() - startedAt.getTime()) / 1000;
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
if (seconds < 60)
|
|
108
|
+
return `${Math.max(0, Math.floor(seconds))} seconds`;
|
|
109
|
+
return `${Math.max(0, seconds / 60).toFixed(1)} minutes`;
|
|
110
|
+
}
|
|
111
|
+
function snapshotActivityTime(agent) {
|
|
112
|
+
const status = normalizeTeamListStatus(agent.status);
|
|
113
|
+
if (status === AgentStatus.RUNNING)
|
|
114
|
+
return new Date();
|
|
115
|
+
return parseTimestamp(agent.completed_at) || parseTimestamp(agent.started_at) || new Date(0);
|
|
116
|
+
}
|
|
117
|
+
function snapshotToStatusDetail(agent) {
|
|
118
|
+
return {
|
|
119
|
+
agent_id: agent.agent_id,
|
|
120
|
+
agent_type: agent.agent_type,
|
|
121
|
+
status: normalizeTeamListStatus(agent.status),
|
|
122
|
+
prompt: agent.prompt,
|
|
123
|
+
started_at: parseTimestamp(agent.started_at)?.toISOString() || new Date(0).toISOString(),
|
|
124
|
+
completed_at: parseTimestamp(agent.completed_at)?.toISOString() || null,
|
|
125
|
+
duration: durationFromSnapshot(agent),
|
|
126
|
+
files_created: [],
|
|
127
|
+
files_modified: [],
|
|
128
|
+
files_read: [],
|
|
129
|
+
files_deleted: [],
|
|
130
|
+
bash_commands: [],
|
|
131
|
+
recent_tool_calls: [],
|
|
132
|
+
last_messages: [],
|
|
133
|
+
tool_count: 0,
|
|
134
|
+
has_errors: false,
|
|
135
|
+
cursor: snapshotActivityTime(agent).toISOString(),
|
|
136
|
+
mode: agent.mode ?? undefined,
|
|
137
|
+
cloud_session_id: agent.cloud_session_id,
|
|
138
|
+
cloud_provider: agent.cloud_provider,
|
|
139
|
+
pr_url: agent.pr_url,
|
|
140
|
+
version: agent.version,
|
|
141
|
+
remote_session_id: agent.remote_session_id,
|
|
142
|
+
session_label: null,
|
|
143
|
+
name: agent.name,
|
|
144
|
+
after: agent.after,
|
|
145
|
+
task_type: agent.task_type,
|
|
146
|
+
host: agent.host,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
80
149
|
function fullName(type, version) {
|
|
81
150
|
const name = AGENT_NAMES[type];
|
|
82
151
|
return version ? `${name} ${version}` : name;
|
|
@@ -714,23 +783,132 @@ function mergeTeams(registry, tasks) {
|
|
|
714
783
|
}
|
|
715
784
|
return Array.from(byName.values()).sort((a, b) => new Date(b.modified_at).getTime() - new Date(a.modified_at).getTime());
|
|
716
785
|
}
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
786
|
+
function buildTasksFromSnapshots(agents) {
|
|
787
|
+
const byTeam = new Map();
|
|
788
|
+
for (const agent of agents) {
|
|
789
|
+
const teamAgents = byTeam.get(agent.task_name) || [];
|
|
790
|
+
teamAgents.push(agent);
|
|
791
|
+
byTeam.set(agent.task_name, teamAgents);
|
|
792
|
+
}
|
|
793
|
+
const tasks = [];
|
|
794
|
+
for (const [taskName, teamAgents] of byTeam) {
|
|
795
|
+
let pending = 0;
|
|
796
|
+
let running = 0;
|
|
797
|
+
let completed = 0;
|
|
798
|
+
let failed = 0;
|
|
799
|
+
let stopped = 0;
|
|
800
|
+
let earliestStart = null;
|
|
801
|
+
let latestActivity = null;
|
|
802
|
+
let workspaceDir = null;
|
|
803
|
+
for (const agent of teamAgents) {
|
|
804
|
+
const status = normalizeTeamListStatus(agent.status);
|
|
805
|
+
if (status === AgentStatus.PENDING)
|
|
806
|
+
pending++;
|
|
807
|
+
else if (status === AgentStatus.RUNNING)
|
|
808
|
+
running++;
|
|
809
|
+
else if (status === AgentStatus.COMPLETED)
|
|
810
|
+
completed++;
|
|
811
|
+
else if (status === AgentStatus.FAILED)
|
|
812
|
+
failed++;
|
|
813
|
+
else if (status === AgentStatus.STOPPED)
|
|
814
|
+
stopped++;
|
|
815
|
+
const startedAt = parseTimestamp(agent.started_at);
|
|
816
|
+
if (startedAt && (!earliestStart || startedAt < earliestStart)) {
|
|
817
|
+
earliestStart = startedAt;
|
|
818
|
+
}
|
|
819
|
+
const activity = snapshotActivityTime(agent);
|
|
820
|
+
if (!latestActivity || activity > latestActivity) {
|
|
821
|
+
latestActivity = activity;
|
|
822
|
+
}
|
|
823
|
+
if (!workspaceDir && agent.workspace_dir) {
|
|
824
|
+
workspaceDir = agent.workspace_dir;
|
|
825
|
+
}
|
|
826
|
+
}
|
|
827
|
+
const fallback = new Date(0);
|
|
828
|
+
tasks.push({
|
|
829
|
+
task_name: taskName,
|
|
830
|
+
agent_count: teamAgents.length,
|
|
831
|
+
pending,
|
|
832
|
+
running,
|
|
833
|
+
completed,
|
|
834
|
+
failed,
|
|
835
|
+
stopped,
|
|
836
|
+
workspace_dir: workspaceDir,
|
|
837
|
+
created_at: (earliestStart || fallback).toISOString(),
|
|
838
|
+
modified_at: (latestActivity || earliestStart || fallback).toISOString(),
|
|
839
|
+
});
|
|
840
|
+
}
|
|
841
|
+
return tasks.sort((a, b) => new Date(b.modified_at).getTime() - new Date(a.modified_at).getTime());
|
|
842
|
+
}
|
|
843
|
+
export function buildTeamRowsFromSnapshots(registry, agents) {
|
|
844
|
+
const byTeam = new Map();
|
|
845
|
+
for (const agent of agents) {
|
|
846
|
+
const details = byTeam.get(agent.task_name) || [];
|
|
847
|
+
details.push(snapshotToStatusDetail(agent));
|
|
848
|
+
byTeam.set(agent.task_name, details);
|
|
849
|
+
}
|
|
850
|
+
const teams = mergeTeams(registry, buildTasksFromSnapshots(agents));
|
|
851
|
+
return {
|
|
852
|
+
teams,
|
|
853
|
+
rows: teams.map((team) => ({
|
|
854
|
+
team,
|
|
855
|
+
agents: byTeam.get(team.task_name) || [],
|
|
856
|
+
description: registry[team.task_name]?.description,
|
|
857
|
+
})),
|
|
858
|
+
names: teams.map((team) => team.task_name),
|
|
859
|
+
};
|
|
860
|
+
}
|
|
861
|
+
function snapshotFromMeta(meta) {
|
|
862
|
+
if (!meta || typeof meta !== 'object')
|
|
863
|
+
return null;
|
|
864
|
+
const agentId = typeof meta.agent_id === 'string' ? meta.agent_id : '';
|
|
865
|
+
const taskName = typeof meta.task_name === 'string' ? meta.task_name : '';
|
|
866
|
+
const agentType = typeof meta.agent_type === 'string' ? meta.agent_type : '';
|
|
867
|
+
if (!agentId || !taskName || !agentType)
|
|
868
|
+
return null;
|
|
869
|
+
return {
|
|
870
|
+
agent_id: agentId,
|
|
871
|
+
task_name: taskName,
|
|
872
|
+
agent_type: agentType,
|
|
873
|
+
status: normalizeTeamListStatus(meta.status),
|
|
874
|
+
prompt: typeof meta.prompt === 'string' ? meta.prompt : '',
|
|
875
|
+
started_at: parseTimestamp(meta.started_at)?.toISOString() || new Date(0).toISOString(),
|
|
876
|
+
completed_at: parseTimestamp(meta.completed_at)?.toISOString() || null,
|
|
877
|
+
workspace_dir: typeof meta.workspace_dir === 'string' ? meta.workspace_dir : null,
|
|
878
|
+
version: typeof meta.version === 'string' ? meta.version : null,
|
|
879
|
+
remote_session_id: typeof meta.remote_session_id === 'string' ? meta.remote_session_id : null,
|
|
880
|
+
name: typeof meta.name === 'string' ? meta.name : null,
|
|
881
|
+
after: Array.isArray(meta.after) ? meta.after.filter((name) => typeof name === 'string') : [],
|
|
882
|
+
task_type: typeof meta.task_type === 'string' && VALID_TASK_TYPES.includes(meta.task_type)
|
|
883
|
+
? meta.task_type
|
|
884
|
+
: null,
|
|
885
|
+
host: typeof meta.host_name === 'string' ? meta.host_name : null,
|
|
886
|
+
mode: typeof meta.mode === 'string' ? meta.mode : null,
|
|
887
|
+
cloud_session_id: typeof meta.cloud_session_id === 'string' ? meta.cloud_session_id : null,
|
|
888
|
+
cloud_provider: typeof meta.cloud_provider === 'string' ? meta.cloud_provider : null,
|
|
889
|
+
pr_url: typeof meta.pr_url === 'string' ? meta.pr_url : null,
|
|
890
|
+
};
|
|
891
|
+
}
|
|
892
|
+
async function loadTeamAgentSnapshots() {
|
|
893
|
+
const agentsDir = await getAgentsDir();
|
|
894
|
+
const entries = await fs.readdir(agentsDir).catch(() => []);
|
|
895
|
+
const snapshots = await Promise.all(entries.map(async (entry) => {
|
|
896
|
+
const metaPath = path.join(agentsDir, entry, 'meta.json');
|
|
724
897
|
try {
|
|
725
|
-
const
|
|
726
|
-
|
|
898
|
+
const raw = await fs.readFile(metaPath, 'utf-8');
|
|
899
|
+
return snapshotFromMeta(JSON.parse(raw));
|
|
727
900
|
}
|
|
728
901
|
catch {
|
|
729
|
-
|
|
902
|
+
return null;
|
|
730
903
|
}
|
|
731
|
-
return { team, agents, description: registry[team.task_name]?.description };
|
|
732
904
|
}));
|
|
733
|
-
return
|
|
905
|
+
return snapshots.filter((snapshot) => snapshot !== null);
|
|
906
|
+
}
|
|
907
|
+
// Build cached rows for the `list` picker. Shared between `list` and picker
|
|
908
|
+
// fallbacks for `status` / `start`; full status stays lazy until a team is picked.
|
|
909
|
+
async function loadTeamRows(_mgr) {
|
|
910
|
+
const [registry, agents] = await Promise.all([loadTeams(), loadTeamAgentSnapshots()]);
|
|
911
|
+
return buildTeamRowsFromSnapshots(registry, agents);
|
|
734
912
|
}
|
|
735
913
|
// Picker fallback for `teams logs` when the teammate ref is omitted. Shows a
|
|
736
914
|
// flat list of every teammate with their team context; Enter picks one.
|
|
@@ -900,25 +1078,23 @@ export function registerTeamsCommands(program) {
|
|
|
900
1078
|
.option('-n, --limit <n>', 'Show at most this many teams (default: 20)', '20')
|
|
901
1079
|
.option('--json', 'Output machine-readable JSON instead of formatted table')
|
|
902
1080
|
.action(async (query, opts) => {
|
|
903
|
-
const mgr = mkManager();
|
|
904
1081
|
const limit = Math.max(1, parseInt(opts.limit, 10) || 20);
|
|
905
|
-
const [
|
|
906
|
-
handleTasks(mgr, 1000),
|
|
1082
|
+
const [registry, everyAgent] = await Promise.all([
|
|
907
1083
|
loadTeams(),
|
|
908
|
-
|
|
1084
|
+
loadTeamAgentSnapshots(),
|
|
909
1085
|
]);
|
|
910
1086
|
// Group agents by team so we can filter on agent-type / version.
|
|
911
1087
|
const byTeam = new Map();
|
|
912
1088
|
for (const a of everyAgent) {
|
|
913
|
-
const arr = byTeam.get(a.
|
|
914
|
-
arr.push(
|
|
915
|
-
byTeam.set(a.
|
|
1089
|
+
const arr = byTeam.get(a.task_name) || [];
|
|
1090
|
+
arr.push(a);
|
|
1091
|
+
byTeam.set(a.task_name, arr);
|
|
916
1092
|
}
|
|
917
|
-
let
|
|
1093
|
+
let rows = buildTeamRowsFromSnapshots(registry, everyAgent).rows;
|
|
918
1094
|
// --- query: substring match on team name ---
|
|
919
1095
|
if (query) {
|
|
920
1096
|
const q = query.toLowerCase();
|
|
921
|
-
|
|
1097
|
+
rows = rows.filter((row) => row.team.task_name.toLowerCase().includes(q));
|
|
922
1098
|
}
|
|
923
1099
|
// --- --agent: filter teams containing a matching teammate ---
|
|
924
1100
|
if (opts.agent) {
|
|
@@ -926,8 +1102,8 @@ export function registerTeamsCommands(program) {
|
|
|
926
1102
|
const wantVersion = VALID_AGENTS.includes(wantType)
|
|
927
1103
|
? resolveVersionAliasLoose(wantType, rawVersion)
|
|
928
1104
|
: rawVersion;
|
|
929
|
-
|
|
930
|
-
const teammates = byTeam.get(
|
|
1105
|
+
rows = rows.filter((row) => {
|
|
1106
|
+
const teammates = byTeam.get(row.team.task_name) || [];
|
|
931
1107
|
return teammates.some((m) => m.agent_type === wantType && (!wantVersion || m.version === wantVersion));
|
|
932
1108
|
});
|
|
933
1109
|
}
|
|
@@ -938,27 +1114,27 @@ export function registerTeamsCommands(program) {
|
|
|
938
1114
|
if (!validStatuses.includes(want)) {
|
|
939
1115
|
die(`Invalid --status '${opts.status}'. Use one of: ${validStatuses.join(', ')}`);
|
|
940
1116
|
}
|
|
941
|
-
|
|
1117
|
+
rows = rows.filter((row) => classifyTeamStatus(row.team) === want);
|
|
942
1118
|
}
|
|
943
1119
|
// --- --since / --until: filter by activity window ---
|
|
944
1120
|
if (opts.since) {
|
|
945
1121
|
const cutoff = parseTimeFilter(opts.since);
|
|
946
1122
|
if (!cutoff)
|
|
947
1123
|
die(`Could not parse --since '${opts.since}'`);
|
|
948
|
-
|
|
1124
|
+
rows = rows.filter((row) => new Date(row.team.modified_at).getTime() >= cutoff);
|
|
949
1125
|
}
|
|
950
1126
|
if (opts.until) {
|
|
951
1127
|
const cutoff = parseTimeFilter(opts.until);
|
|
952
1128
|
if (!cutoff)
|
|
953
1129
|
die(`Could not parse --until '${opts.until}'`);
|
|
954
|
-
|
|
1130
|
+
rows = rows.filter((row) => new Date(row.team.modified_at).getTime() <= cutoff);
|
|
955
1131
|
}
|
|
956
|
-
|
|
1132
|
+
rows = rows.slice(0, limit);
|
|
957
1133
|
if (isJsonMode(opts)) {
|
|
958
|
-
console.log(JSON.stringify({ teams:
|
|
1134
|
+
console.log(JSON.stringify({ teams: rows.map((row) => row.team) }, null, 2));
|
|
959
1135
|
return;
|
|
960
1136
|
}
|
|
961
|
-
if (
|
|
1137
|
+
if (rows.length === 0) {
|
|
962
1138
|
if (query || opts.agent || opts.status || opts.since || opts.until) {
|
|
963
1139
|
console.log(chalk.gray('No teams match those filters.'));
|
|
964
1140
|
}
|
|
@@ -968,24 +1144,12 @@ export function registerTeamsCommands(program) {
|
|
|
968
1144
|
}
|
|
969
1145
|
return;
|
|
970
1146
|
}
|
|
971
|
-
// Enrich teams with teammate details for the picker's preview pane.
|
|
972
|
-
const rows = await Promise.all(merged.map(async (team) => {
|
|
973
|
-
let agents = [];
|
|
974
|
-
try {
|
|
975
|
-
const res = await handleStatus(mgr, team.task_name, 'all');
|
|
976
|
-
agents = res.agents;
|
|
977
|
-
}
|
|
978
|
-
catch {
|
|
979
|
-
// Empty teams (no live agents) throw in some code paths — preview
|
|
980
|
-
// will just show "no teammates yet".
|
|
981
|
-
}
|
|
982
|
-
return { team, agents, description: registry[team.task_name]?.description };
|
|
983
|
-
}));
|
|
984
1147
|
if (isInteractiveTerminal()) {
|
|
985
1148
|
try {
|
|
986
1149
|
const picked = await teamPicker(rows, query);
|
|
987
1150
|
if (picked) {
|
|
988
1151
|
// Fall through to the status subcommand's action for the picked team.
|
|
1152
|
+
const mgr = mkManager();
|
|
989
1153
|
const result = await handleStatus(mgr, picked.team, 'all');
|
|
990
1154
|
await printTeamStatus(picked.team, result);
|
|
991
1155
|
}
|
|
@@ -4,7 +4,7 @@ import ora from 'ora';
|
|
|
4
4
|
import * as fs from 'fs';
|
|
5
5
|
import * as path from 'path';
|
|
6
6
|
import { select, confirm, checkbox } from '@inquirer/prompts';
|
|
7
|
-
import { AGENTS,
|
|
7
|
+
import { AGENTS, MANAGED_AGENT_IDS, accountOrgBadge, getAccountEmail, getAccountInfo, agentLabel, warnAgentDeprecated, isAgentHardDeprecated, hardDeprecationError, isSelfUpdatingAgent, } from '../lib/agents.js';
|
|
8
8
|
import { formatUsageSummary, getUsageInfoForIdentity, getUsageInfoByIdentity, getUsageLookupKey, } from '../lib/usage.js';
|
|
9
9
|
import { viewAction } from './view.js';
|
|
10
10
|
import { resolveConfiguredModel, formatAgentIdentity } from '../lib/models.js';
|
|
@@ -128,7 +128,7 @@ async function versionPruneAction(specs, options, commandName) {
|
|
|
128
128
|
const parsed = parseAgentSpec(spec);
|
|
129
129
|
if (!parsed) {
|
|
130
130
|
console.log(chalk.red(`Invalid agent: ${spec}`));
|
|
131
|
-
console.log(chalk.gray(`Format: <agent>[@version]. Available: ${
|
|
131
|
+
console.log(chalk.gray(`Format: <agent>[@version]. Available: ${MANAGED_AGENT_IDS.join(', ')}`));
|
|
132
132
|
continue;
|
|
133
133
|
}
|
|
134
134
|
const { agent, version } = parsed;
|
|
@@ -333,11 +333,16 @@ export function registerVersionsCommands(program) {
|
|
|
333
333
|
const parsed = parseAgentSpec(spec);
|
|
334
334
|
if (!parsed) {
|
|
335
335
|
console.log(chalk.red(`Invalid agent: ${spec}`));
|
|
336
|
-
console.log(chalk.gray(`Format: <agent>[@version]. Available: ${
|
|
336
|
+
console.log(chalk.gray(`Format: <agent>[@version]. Available: ${MANAGED_AGENT_IDS.join(', ')}`));
|
|
337
337
|
continue;
|
|
338
338
|
}
|
|
339
339
|
const { agent, version } = parsed;
|
|
340
340
|
const agentConfig = AGENTS[agent];
|
|
341
|
+
if (isAgentHardDeprecated(agent)) {
|
|
342
|
+
console.error(chalk.red(hardDeprecationError(agent)));
|
|
343
|
+
process.exitCode = 1;
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
341
346
|
warnAgentDeprecated(agent);
|
|
342
347
|
// Isolation relies on a config-dir env var to redirect the copy away
|
|
343
348
|
// from the user's real ~/.<agent>. Agents without one isolate only by
|
|
@@ -631,7 +636,7 @@ export function registerVersionsCommands(program) {
|
|
|
631
636
|
const parsed = parseAgentSpec(agentArg);
|
|
632
637
|
if (!parsed) {
|
|
633
638
|
console.log(chalk.red(`Invalid agent: ${agentArg}`));
|
|
634
|
-
console.log(chalk.gray(`Format: <agent>[@version]. Available: ${
|
|
639
|
+
console.log(chalk.gray(`Format: <agent>[@version]. Available: ${MANAGED_AGENT_IDS.join(', ')}`));
|
|
635
640
|
return;
|
|
636
641
|
}
|
|
637
642
|
agent = parsed.agent;
|
|
@@ -641,7 +646,7 @@ export function registerVersionsCommands(program) {
|
|
|
641
646
|
const agentLower = agentArg.toLowerCase();
|
|
642
647
|
if (!AGENTS[agentLower]) {
|
|
643
648
|
console.log(chalk.red(`Invalid agent: ${agentArg}`));
|
|
644
|
-
console.log(chalk.gray(`Available: ${
|
|
649
|
+
console.log(chalk.gray(`Available: ${MANAGED_AGENT_IDS.join(', ')}`));
|
|
645
650
|
return;
|
|
646
651
|
}
|
|
647
652
|
agent = agentLower;
|
package/dist/commands/view.d.ts
CHANGED
|
@@ -129,6 +129,7 @@ export declare function viewAction(agentArg?: string, options?: {
|
|
|
129
129
|
detailed?: boolean;
|
|
130
130
|
refresh?: boolean;
|
|
131
131
|
live?: boolean;
|
|
132
|
+
merged?: boolean;
|
|
132
133
|
} & ViewSectionFilter): Promise<void>;
|
|
133
134
|
/** Register the `agents view` command. */
|
|
134
135
|
export declare function registerViewCommand(program: Command): void;
|
package/dist/commands/view.js
CHANGED
|
@@ -13,6 +13,7 @@ import { readManifest } from '../lib/manifest.js';
|
|
|
13
13
|
import { listInstalledVersions, listInstalledVersionDirs, getGlobalDefault, getVersionHomePath, getVersionDir, getAvailableResources, getActuallySyncedResources, getNewResources, getProjectOnlyResources, hasNewResources, promptNewResourceSelection, syncResourcesToVersion, removeVersion, printTrashFooter, reconcileStaleLatestForAgent, isGlobalBinaryAgent, getLiveVersion, isVersionIsolated, getIsolatedDefault, } from '../lib/versions.js';
|
|
14
14
|
import { ensureVersionedAliasCurrent, removeShim, } from '../lib/shims.js';
|
|
15
15
|
import { getAgentResources } from '../lib/resources.js';
|
|
16
|
+
import { renderMergedResources } from '../lib/merged-resources.js';
|
|
16
17
|
import { resolveVersionFilter, AgentSpecError } from '../lib/agent-spec/index.js';
|
|
17
18
|
import { listCliStatus } from '../lib/cli-resources.js';
|
|
18
19
|
import { isCapable } from '../lib/capabilities.js';
|
|
@@ -1468,6 +1469,12 @@ export async function pruneDuplicates(filterAgentId, yes, dryRun) {
|
|
|
1468
1469
|
* Exported for use by deprecated aliases.
|
|
1469
1470
|
*/
|
|
1470
1471
|
export async function viewAction(agentArg, options) {
|
|
1472
|
+
// --merged renders the cross-layer, first-wins resource surface (the former
|
|
1473
|
+
// `agents resources`), independent of the per-version detail view below.
|
|
1474
|
+
if (options?.merged) {
|
|
1475
|
+
renderMergedResources();
|
|
1476
|
+
return;
|
|
1477
|
+
}
|
|
1471
1478
|
// --live is a shorter-to-type alias of --refresh; both force a live probe.
|
|
1472
1479
|
const forceRefresh = options?.refresh === true || options?.live === true;
|
|
1473
1480
|
// --resources / --detailed imply --json (they only shape structured output).
|
|
@@ -1595,6 +1602,7 @@ export function registerViewCommand(program) {
|
|
|
1595
1602
|
.option('--hooks', 'Show only hooks in the detail view.')
|
|
1596
1603
|
.option('--promptcuts', 'Show only promptcuts in the detail view.')
|
|
1597
1604
|
.option('--cli', 'Show only host CLIs (declared in cli/, installed to PATH).')
|
|
1605
|
+
.option('--merged', 'Show the merged, first-wins resource surface across all layers (project, user, extras, system) in one table with the winning layer per row.')
|
|
1598
1606
|
.addHelpText('after', `
|
|
1599
1607
|
Examples:
|
|
1600
1608
|
# Show all installed agents with versions, accounts, and usage
|
|
@@ -1625,6 +1633,9 @@ Examples:
|
|
|
1625
1633
|
agents view claude@default --plugins --workflows
|
|
1626
1634
|
agents view claude --commands # implicitly the default version
|
|
1627
1635
|
|
|
1636
|
+
# Merged, first-wins resource surface across all layers, with the winning layer
|
|
1637
|
+
agents view --merged
|
|
1638
|
+
|
|
1628
1639
|
When to use:
|
|
1629
1640
|
- Checking which agents are installed and what their default versions are
|
|
1630
1641
|
- Seeing which account each version is logged into (useful for multi-account setups)
|
package/dist/index.js
CHANGED
|
@@ -94,7 +94,7 @@ if (IS_DEV_BUILD) {
|
|
|
94
94
|
// module on each invocation (which loaded the whole ~50-module tree before the
|
|
95
95
|
// first byte of output), the registry maps a command name to a thunk that
|
|
96
96
|
// imports only what that command needs. See src/lib/startup/command-registry.ts.
|
|
97
|
-
import { COMMAND_LOADERS, LAZY_COMMAND_NAMES, loadView, loadInspect,
|
|
97
|
+
import { COMMAND_LOADERS, LAZY_COMMAND_NAMES, loadView, loadInspect, loadFeedback, loadCommands, loadHooks, loadSkills, loadRules, loadMemory, loadPermissions, loadMcp, loadCli, loadSubagents, loadPlugins, loadWorkflows, loadWorktree, loadVersions, loadImport, loadExport, loadPackages, loadRoutines, loadMonitors, loadRun, loadFork, loadDefaults, loadSet, loadModels, loadPrune, loadTrash, loadRestore, loadDoctor, loadApply, loadStatus, loadProfiles, loadHarness, loadSecrets, loadLogin, loadWallet, loadHelper, loadMenubar, loadBeta, loadSync, loadLock, loadRefreshRules, loadDrive, loadFactory, loadUsage, loadCost, loadOutput, loadBudget, loadAlias, loadMine, loadPty, loadTmux, loadWatchdog, loadBrowser, loadComputer, loadHosts, loadLogs, loadEvents, loadAudit, loadWebhook, loadFunnel, loadSsh, loadPull, loadPush, loadRepo, loadSetup, loadUninstall, loadShare, loadSend, loadHq, loadFeed, loadActivity, loadMailboxes, } from './lib/startup/command-registry.js';
|
|
98
98
|
import { applyGlobalHelpConventions } from './lib/help.js';
|
|
99
99
|
import { renderWhatsNew } from './lib/whats-new.js';
|
|
100
100
|
import { getCliLaunch } from './lib/cli-entry.js';
|
|
@@ -215,7 +215,7 @@ program.helpInformation = function () {
|
|
|
215
215
|
return brandRootHelp(`Usage: agents [command] [options]
|
|
216
216
|
|
|
217
217
|
Install, configure, run, and dispatch AI coding agents from one place.
|
|
218
|
-
Works with Claude, Codex,
|
|
218
|
+
Works with Claude, Codex, Antigravity, Cursor, OpenCode, OpenClaw, and Droid.
|
|
219
219
|
|
|
220
220
|
Quick start:
|
|
221
221
|
agents setup First-time setup (interactive)
|
|
@@ -231,9 +231,8 @@ Agent versions:
|
|
|
231
231
|
use <agent>@<version> Set the default version
|
|
232
232
|
prune cleanup [target] Remove orphan resources and older duplicate version installs
|
|
233
233
|
trash Inspect and restore soft-deleted version directories
|
|
234
|
-
view [agent[@version]] List versions,
|
|
234
|
+
view [agent[@version]] List versions, inspect one in detail, or --merged for the cross-layer resource surface
|
|
235
235
|
inspect <target> Deep details for one agent+version, or a DotAgents repo (user|system|project|alias|path)
|
|
236
|
-
resources Show merged DotAgents resources with their winning layer
|
|
237
236
|
|
|
238
237
|
Agent configuration (synced across versions):
|
|
239
238
|
rules Instructions given to agents (CLAUDE.md, etc.)
|
|
@@ -268,8 +267,7 @@ Credentials and profiles:
|
|
|
268
267
|
secrets Keychain-backed env bundles; use 'secrets exec <bundle> -- <cmd>' to inject into a subprocess
|
|
269
268
|
|
|
270
269
|
Diagnostics:
|
|
271
|
-
doctor [agent[@version]] Diagnose CLI availability, sync status, and resource divergence
|
|
272
|
-
check CI drift gate: exit non-zero when resources are out of sync
|
|
270
|
+
doctor [agent[@version]] Diagnose CLI availability, sync status, and resource divergence; --check for the CI drift gate
|
|
273
271
|
usage [agent] Show rate-limit and quota usage per agent
|
|
274
272
|
|
|
275
273
|
Config sync:
|
|
@@ -764,7 +762,6 @@ async function registerAllEagerCommands() {
|
|
|
764
762
|
await reg(loadShare);
|
|
765
763
|
await reg(loadSend);
|
|
766
764
|
await reg(loadInspect);
|
|
767
|
-
await reg(loadResources);
|
|
768
765
|
await reg(loadFeedback);
|
|
769
766
|
await reg(loadCommands);
|
|
770
767
|
await reg(loadHooks);
|
|
@@ -788,13 +785,13 @@ async function registerAllEagerCommands() {
|
|
|
788
785
|
await reg(loadRun);
|
|
789
786
|
await reg(loadFork);
|
|
790
787
|
await reg(loadDefaults);
|
|
788
|
+
await reg(loadSet);
|
|
791
789
|
await reg(loadModels);
|
|
792
790
|
await reg(loadPrune);
|
|
793
791
|
await reg(loadTrash);
|
|
794
792
|
await reg(loadRestore);
|
|
795
793
|
await reg(loadDoctor);
|
|
796
794
|
await reg(loadApply);
|
|
797
|
-
await reg(loadCheck);
|
|
798
795
|
await reg(loadStatus);
|
|
799
796
|
registerExecAliasCommand(program);
|
|
800
797
|
await reg(loadProfiles);
|
|
@@ -8,13 +8,6 @@
|
|
|
8
8
|
* Sources: https://agentclientprotocol.com/get-started/agents + vendor docs.
|
|
9
9
|
*/
|
|
10
10
|
export const ACP_HARNESSES = {
|
|
11
|
-
gemini: {
|
|
12
|
-
command: 'gemini',
|
|
13
|
-
args: ['--experimental-acp'],
|
|
14
|
-
installHint: 'npm i -g @google/gemini-cli',
|
|
15
|
-
confidence: 'documented',
|
|
16
|
-
source: 'https://agentclientprotocol.com/get-started/agents',
|
|
17
|
-
},
|
|
18
11
|
claude: {
|
|
19
12
|
command: 'npx',
|
|
20
13
|
args: ['-y', '@zed-industries/claude-agent-acp'],
|