@tmustier/pi-agent-teams 0.4.0-beta.3 → 0.5.0
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 +26 -0
- package/README.md +72 -9
- package/WORKFLOW.md +110 -0
- package/docs/claude-parity.md +18 -13
- package/docs/hook-contract.md +183 -0
- package/docs/smoke-test-plan.md +26 -7
- package/extensions/teams/activity-tracker.ts +296 -8
- package/extensions/teams/cleanup.ts +216 -3
- package/extensions/teams/hooks.ts +57 -5
- package/extensions/teams/leader-attach-commands.ts +8 -4
- package/extensions/teams/leader-inbox.ts +162 -4
- package/extensions/teams/leader-info-commands.ts +105 -3
- package/extensions/teams/leader-lifecycle-commands.ts +205 -3
- package/extensions/teams/leader-messaging-commands.ts +19 -7
- package/extensions/teams/leader-spawn-command.ts +5 -1
- package/extensions/teams/leader-team-command.ts +51 -2
- package/extensions/teams/leader-teams-tool.ts +387 -11
- package/extensions/teams/leader.ts +126 -52
- package/extensions/teams/mailbox.ts +6 -1
- package/extensions/teams/model-policy.ts +117 -0
- package/extensions/teams/spawn-types.ts +4 -0
- package/extensions/teams/teammate-rpc.ts +14 -0
- package/extensions/teams/teams-panel.ts +117 -19
- package/extensions/teams/teams-ui-shared.ts +205 -2
- package/extensions/teams/teams-widget.ts +67 -14
- package/extensions/teams/worker.ts +18 -6
- package/extensions/teams/worktree.ts +143 -0
- package/package.json +4 -2
- package/scripts/integration-cleanup-test.mts +419 -0
- package/scripts/integration-hooks-remediation-test.mts +382 -0
- package/scripts/integration-spawn-overrides-test.mts +10 -0
- package/scripts/smoke-test.mts +701 -3
- package/skills/agent-teams/SKILL.md +28 -7
|
@@ -73,10 +73,14 @@ export async function handleTeamDmCommand(opts: {
|
|
|
73
73
|
}): Promise<void> {
|
|
74
74
|
const { ctx, rest, teamId, leadName, style } = opts;
|
|
75
75
|
|
|
76
|
-
|
|
77
|
-
const
|
|
76
|
+
// Parse --urgent flag from anywhere in the args
|
|
77
|
+
const isUrgent = rest.includes("--urgent");
|
|
78
|
+
const filtered = rest.filter((a) => a !== "--urgent");
|
|
79
|
+
|
|
80
|
+
const nameRaw = filtered[0];
|
|
81
|
+
const msg = filtered.slice(1).join(" ").trim();
|
|
78
82
|
if (!nameRaw || !msg) {
|
|
79
|
-
ctx.ui.notify("Usage: /team dm <name> <msg...>", "error");
|
|
83
|
+
ctx.ui.notify("Usage: /team dm <name> [--urgent] <msg...>", "error");
|
|
80
84
|
return;
|
|
81
85
|
}
|
|
82
86
|
const name = sanitizeName(nameRaw);
|
|
@@ -84,8 +88,10 @@ export async function handleTeamDmCommand(opts: {
|
|
|
84
88
|
from: leadName,
|
|
85
89
|
text: msg,
|
|
86
90
|
timestamp: new Date().toISOString(),
|
|
91
|
+
...(isUrgent ? { urgent: true } : {}),
|
|
87
92
|
});
|
|
88
|
-
|
|
93
|
+
const verb = isUrgent ? "Urgent DM" : "DM";
|
|
94
|
+
ctx.ui.notify(`${verb} queued for ${formatMemberDisplayName(style, name)}`, "info");
|
|
89
95
|
}
|
|
90
96
|
|
|
91
97
|
export async function handleTeamBroadcastCommand(opts: {
|
|
@@ -102,9 +108,13 @@ export async function handleTeamBroadcastCommand(opts: {
|
|
|
102
108
|
const { ctx, rest, teamId, teammates, leadName, style, refreshTasks, getTasks, getTaskListId } = opts;
|
|
103
109
|
const strings = getTeamsStrings(style);
|
|
104
110
|
|
|
105
|
-
|
|
111
|
+
// Parse --urgent flag from anywhere in the args
|
|
112
|
+
const isUrgent = rest.includes("--urgent");
|
|
113
|
+
const filtered = rest.filter((a) => a !== "--urgent");
|
|
114
|
+
|
|
115
|
+
const msg = filtered.join(" ").trim();
|
|
106
116
|
if (!msg) {
|
|
107
|
-
ctx.ui.notify("Usage: /team broadcast <msg...>", "error");
|
|
117
|
+
ctx.ui.notify("Usage: /team broadcast [--urgent] <msg...>", "error");
|
|
108
118
|
return;
|
|
109
119
|
}
|
|
110
120
|
|
|
@@ -137,12 +147,14 @@ export async function handleTeamBroadcastCommand(opts: {
|
|
|
137
147
|
from: leadName,
|
|
138
148
|
text: msg,
|
|
139
149
|
timestamp: ts,
|
|
150
|
+
...(isUrgent ? { urgent: true } : {}),
|
|
140
151
|
}),
|
|
141
152
|
),
|
|
142
153
|
);
|
|
143
154
|
|
|
155
|
+
const verb = isUrgent ? "Urgent broadcast" : "Broadcast";
|
|
144
156
|
ctx.ui.notify(
|
|
145
|
-
|
|
157
|
+
`${verb} queued for ${names.length} ${strings.memberTitle.toLowerCase()}(s): ${names.map((n) => formatMemberDisplayName(style, n)).join(", ")}`,
|
|
146
158
|
"info",
|
|
147
159
|
);
|
|
148
160
|
}
|
|
@@ -142,8 +142,12 @@ export async function handleTeamSpawnCommand(opts: {
|
|
|
142
142
|
|
|
143
143
|
for (const w of res.warnings) ctx.ui.notify(w, "warning");
|
|
144
144
|
const displayName = formatMemberDisplayName(style, res.name);
|
|
145
|
+
const extras: string[] = [];
|
|
146
|
+
if (res.model) extras.push(res.model);
|
|
147
|
+
if (res.thinking) extras.push(`thinking:${res.thinking}`);
|
|
148
|
+
const extrasStr = extras.length > 0 ? ` \u00b7 ${extras.join(" \u00b7 ")}` : "";
|
|
145
149
|
ctx.ui.notify(
|
|
146
|
-
`${displayName} ${strings.joinedVerb} (${res.mode}${res.note ? ", " + res.note : ""} \u00b7 ${res.workspaceMode})`,
|
|
150
|
+
`${displayName} ${strings.joinedVerb} (${res.mode}${res.note ? ", " + res.note : ""} \u00b7 ${res.workspaceMode}${extrasStr})`,
|
|
147
151
|
"info",
|
|
148
152
|
);
|
|
149
153
|
}
|
|
@@ -4,11 +4,14 @@ import {
|
|
|
4
4
|
handleTeamEnvCommand,
|
|
5
5
|
handleTeamIdCommand,
|
|
6
6
|
handleTeamListCommand,
|
|
7
|
+
handleTeamStatusCommand,
|
|
7
8
|
} from "./leader-info-commands.js";
|
|
8
9
|
import { handleTeamAttachCommand, handleTeamDetachCommand } from "./leader-attach-commands.js";
|
|
9
10
|
import {
|
|
10
11
|
handleTeamCleanupCommand,
|
|
11
12
|
handleTeamDelegateCommand,
|
|
13
|
+
handleTeamDoneCommand,
|
|
14
|
+
handleTeamGcCommand,
|
|
12
15
|
handleTeamKillCommand,
|
|
13
16
|
handleTeamPruneCommand,
|
|
14
17
|
handleTeamShutdownCommand,
|
|
@@ -28,6 +31,7 @@ import type { SpawnTeammateFn } from "./spawn-types.js";
|
|
|
28
31
|
import type { TeamConfig } from "./team-config.js";
|
|
29
32
|
import type { TeamTask } from "./task-store.js";
|
|
30
33
|
import type { TeammateRpc } from "./teammate-rpc.js";
|
|
34
|
+
import type { ActivityTracker } from "./activity-tracker.js";
|
|
31
35
|
import type { TeamsStyle } from "./teams-style.js";
|
|
32
36
|
|
|
33
37
|
const TEAM_HELP_TEXT = [
|
|
@@ -38,10 +42,11 @@ const TEAM_HELP_TEXT = [
|
|
|
38
42
|
" /team attach <teamId> [--claim]",
|
|
39
43
|
" /team detach",
|
|
40
44
|
" /team spawn <name> [fresh|branch] [shared|worktree] [plan] [--model <provider>/<modelId>] [--thinking <level>]",
|
|
45
|
+
" /team status [name] # real-time worker state (stall detection, time in state, activity)",
|
|
41
46
|
" /team panel",
|
|
42
47
|
" /team send <name> <msg...>",
|
|
43
|
-
" /team dm <name> <msg...>",
|
|
44
|
-
" /team broadcast <msg...>",
|
|
48
|
+
" /team dm <name> [--urgent] <msg...>",
|
|
49
|
+
" /team broadcast [--urgent] <msg...>",
|
|
45
50
|
" /team steer <name> <msg...>",
|
|
46
51
|
" /team stop <name> [reason...]",
|
|
47
52
|
" /team kill <name>",
|
|
@@ -54,7 +59,9 @@ const TEAM_HELP_TEXT = [
|
|
|
54
59
|
" /team style init <name> [extends <base>]",
|
|
55
60
|
" /team plan approve <name>",
|
|
56
61
|
" /team plan reject <name> [feedback...]",
|
|
62
|
+
" /team done [--force] # end run: stop teammates + hide widget",
|
|
57
63
|
" /team cleanup [--force]",
|
|
64
|
+
" /team gc [--dry-run] [--force] [--max-age-hours=N] # remove old team dirs",
|
|
58
65
|
" /team prune [--all] # hide stale manual teammates (mark offline)",
|
|
59
66
|
" /team task add <text...>",
|
|
60
67
|
" /team task assign <id> <agent>",
|
|
@@ -77,9 +84,12 @@ export async function handleTeamCommand(opts: {
|
|
|
77
84
|
ctx: ExtensionCommandContext;
|
|
78
85
|
teammates: Map<string, TeammateRpc>;
|
|
79
86
|
getTeamConfig: () => TeamConfig | null;
|
|
87
|
+
getTracker: () => ActivityTracker;
|
|
80
88
|
getTasks: () => TeamTask[];
|
|
81
89
|
refreshTasks: () => Promise<void>;
|
|
82
90
|
renderWidget: () => void;
|
|
91
|
+
hideWidget: () => void;
|
|
92
|
+
restoreWidget: () => void;
|
|
83
93
|
getTaskListId: () => string | null;
|
|
84
94
|
setTaskListId: (id: string) => void;
|
|
85
95
|
getActiveTeamId: () => string;
|
|
@@ -101,9 +111,12 @@ export async function handleTeamCommand(opts: {
|
|
|
101
111
|
ctx,
|
|
102
112
|
teammates,
|
|
103
113
|
getTeamConfig,
|
|
114
|
+
getTracker,
|
|
104
115
|
getTasks,
|
|
105
116
|
refreshTasks,
|
|
106
117
|
renderWidget,
|
|
118
|
+
hideWidget,
|
|
119
|
+
restoreWidget,
|
|
107
120
|
getTaskListId,
|
|
108
121
|
setTaskListId,
|
|
109
122
|
getActiveTeamId,
|
|
@@ -140,6 +153,7 @@ export async function handleTeamCommand(opts: {
|
|
|
140
153
|
ctx,
|
|
141
154
|
teammates,
|
|
142
155
|
getTeamConfig,
|
|
156
|
+
getTracker,
|
|
143
157
|
style,
|
|
144
158
|
refreshTasks,
|
|
145
159
|
renderWidget,
|
|
@@ -181,6 +195,7 @@ export async function handleTeamCommand(opts: {
|
|
|
181
195
|
setTaskListId,
|
|
182
196
|
refreshTasks,
|
|
183
197
|
renderWidget,
|
|
198
|
+
restoreWidget,
|
|
184
199
|
});
|
|
185
200
|
},
|
|
186
201
|
|
|
@@ -194,6 +209,23 @@ export async function handleTeamCommand(opts: {
|
|
|
194
209
|
setTaskListId,
|
|
195
210
|
refreshTasks,
|
|
196
211
|
renderWidget,
|
|
212
|
+
restoreWidget,
|
|
213
|
+
});
|
|
214
|
+
},
|
|
215
|
+
|
|
216
|
+
done: async () => {
|
|
217
|
+
await handleTeamDoneCommand({
|
|
218
|
+
ctx,
|
|
219
|
+
rest,
|
|
220
|
+
teamId: activeTeamId,
|
|
221
|
+
teammates,
|
|
222
|
+
getTeamConfig,
|
|
223
|
+
leadName,
|
|
224
|
+
style,
|
|
225
|
+
stopAllTeammates,
|
|
226
|
+
refreshTasks,
|
|
227
|
+
getTasks,
|
|
228
|
+
hideWidget,
|
|
197
229
|
});
|
|
198
230
|
},
|
|
199
231
|
|
|
@@ -210,6 +242,10 @@ export async function handleTeamCommand(opts: {
|
|
|
210
242
|
});
|
|
211
243
|
},
|
|
212
244
|
|
|
245
|
+
gc: async () => {
|
|
246
|
+
await handleTeamGcCommand({ ctx, rest });
|
|
247
|
+
},
|
|
248
|
+
|
|
213
249
|
prune: async () => {
|
|
214
250
|
await handleTeamPruneCommand({
|
|
215
251
|
ctx,
|
|
@@ -256,6 +292,19 @@ export async function handleTeamCommand(opts: {
|
|
|
256
292
|
await handleTeamSpawnCommand({ ctx, rest, teammates, style, spawnTeammate });
|
|
257
293
|
},
|
|
258
294
|
|
|
295
|
+
status: async () => {
|
|
296
|
+
await handleTeamStatusCommand({
|
|
297
|
+
ctx,
|
|
298
|
+
rest,
|
|
299
|
+
teammates,
|
|
300
|
+
getTeamConfig,
|
|
301
|
+
getTracker,
|
|
302
|
+
teamId: activeTeamId,
|
|
303
|
+
taskListId,
|
|
304
|
+
style,
|
|
305
|
+
});
|
|
306
|
+
},
|
|
307
|
+
|
|
259
308
|
style: async () => {
|
|
260
309
|
const teamDir = getTeamDir(activeTeamId);
|
|
261
310
|
await handleTeamStyleCommand({
|