@team-agent/installer 0.5.66 → 0.5.68
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/Cargo.lock +8 -1
- package/Cargo.toml +1 -1
- package/crates/team-agent/Cargo.toml +1 -0
- package/crates/team-agent/src/cli/adapters.rs +5 -0
- package/crates/team-agent/src/cli/diagnose.rs +82 -0
- package/crates/team-agent/src/cli/emit.rs +3 -3
- package/crates/team-agent/src/cli/grok_slot.rs +299 -0
- package/crates/team-agent/src/cli/leader.rs +21 -7
- package/crates/team-agent/src/cli/leaders.rs +125 -1
- package/crates/team-agent/src/cli/mod.rs +20 -0
- package/crates/team-agent/src/cli/send/presentation.rs +7 -1
- package/crates/team-agent/src/cli/spec.rs +2 -0
- package/crates/team-agent/src/cli/status_port/compact.rs +28 -0
- package/crates/team-agent/src/cli/status_port/snapshot.rs +25 -1
- package/crates/team-agent/src/cli/tests/base.rs +26 -3
- package/crates/team-agent/src/cli/tests/missing_subcommands.rs +129 -19
- package/crates/team-agent/src/cli/tests/shutdown_kill_plan.rs +387 -6
- package/crates/team-agent/src/cli/tests/status_send.rs +79 -10
- package/crates/team-agent/src/communication_mode/mod.rs +6 -4
- package/crates/team-agent/src/compiler.rs +59 -0
- package/crates/team-agent/src/coordinator/backoff.rs +55 -0
- package/crates/team-agent/src/coordinator/conpty_shim.rs +82 -0
- package/crates/team-agent/src/coordinator/health.rs +173 -0
- package/crates/team-agent/src/coordinator/mod.rs +31 -0
- package/crates/team-agent/src/coordinator/orphan.rs +31 -0
- package/crates/team-agent/src/coordinator/runtime_detectors.rs +30 -0
- package/crates/team-agent/src/coordinator/runtime_observation.rs +25 -0
- package/crates/team-agent/src/coordinator/steps/abnormal.rs +59 -0
- package/crates/team-agent/src/coordinator/steps/delivery.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/health_sync.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/mod.rs +22 -0
- package/crates/team-agent/src/coordinator/steps/persist.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/runtime_prompts.rs +10 -0
- package/crates/team-agent/src/coordinator/steps/session_gate.rs +10 -0
- package/crates/team-agent/src/coordinator/tick.rs +133 -22
- package/crates/team-agent/src/coordinator/types.rs +49 -0
- package/crates/team-agent/src/db/message_store.rs +39 -5
- package/crates/team-agent/src/layout/worker_env.rs +20 -3
- package/crates/team-agent/src/layout/worker_window_helpers.rs +2 -0
- package/crates/team-agent/src/leader/provider_attribution.rs +53 -0
- package/crates/team-agent/src/leader/registry.rs +65 -0
- package/crates/team-agent/src/leader/start.rs +920 -63
- package/crates/team-agent/src/lifecycle/display.rs +56 -0
- package/crates/team-agent/src/lifecycle/helpers.rs +57 -0
- package/crates/team-agent/src/lifecycle/launch/add_agent.rs +332 -12
- package/crates/team-agent/src/lifecycle/launch/add_agent_state.rs +62 -0
- package/crates/team-agent/src/lifecycle/launch/agent_state.rs +59 -0
- package/crates/team-agent/src/lifecycle/launch/clone_agent.rs +101 -11
- package/crates/team-agent/src/lifecycle/launch/cursor_create_chat.rs +229 -0
- package/crates/team-agent/src/lifecycle/launch/cursor_mcp.rs +332 -0
- package/crates/team-agent/src/lifecycle/launch/fork_agent.rs +204 -456
- package/crates/team-agent/src/lifecycle/launch/fork_entry.rs +24 -0
- package/crates/team-agent/src/lifecycle/launch/grok_per_seat.rs +260 -0
- package/crates/team-agent/src/lifecycle/launch/identity.rs +146 -0
- package/crates/team-agent/src/lifecycle/launch/layout.rs +60 -0
- package/crates/team-agent/src/lifecycle/launch/leader_context.rs +112 -0
- package/crates/team-agent/src/lifecycle/launch/mcp_config.rs +530 -0
- package/crates/team-agent/src/lifecycle/launch/ownership.rs +40 -0
- package/crates/team-agent/src/lifecycle/launch/plan.rs +31 -0
- package/crates/team-agent/src/lifecycle/launch/quick_start.rs +66 -0
- package/crates/team-agent/src/lifecycle/launch/quick_start_transport.rs +78 -0
- package/crates/team-agent/src/lifecycle/launch/readiness.rs +85 -38
- package/crates/team-agent/src/lifecycle/launch/role_source.rs +44 -44
- package/crates/team-agent/src/lifecycle/launch/spawn.rs +62 -2
- package/crates/team-agent/src/lifecycle/launch/spec_state.rs +139 -0
- package/crates/team-agent/src/lifecycle/launch/state_projection.rs +109 -0
- package/crates/team-agent/src/lifecycle/launch/worker_env.rs +214 -1
- package/crates/team-agent/src/lifecycle/launch.rs +99 -29
- package/crates/team-agent/src/lifecycle/lock.rs +42 -1
- package/crates/team-agent/src/lifecycle/mod.rs +11 -0
- package/crates/team-agent/src/lifecycle/pane_input_lock.rs +161 -0
- package/crates/team-agent/src/lifecycle/profile_launch.rs +98 -0
- package/crates/team-agent/src/lifecycle/profile_smoke.rs +51 -1
- package/crates/team-agent/src/lifecycle/restart/agent.rs +124 -0
- package/crates/team-agent/src/lifecycle/restart/common.rs +369 -11
- package/crates/team-agent/src/lifecycle/restart/orchestrator.rs +27 -0
- package/crates/team-agent/src/lifecycle/restart/preflight.rs +25 -0
- package/crates/team-agent/src/lifecycle/restart/rebuild.rs +106 -0
- package/crates/team-agent/src/lifecycle/restart/remove.rs +196 -5
- package/crates/team-agent/src/lifecycle/restart/selection.rs +72 -0
- package/crates/team-agent/src/lifecycle/restart/team_state.rs +22 -0
- package/crates/team-agent/src/lifecycle/restart.rs +29 -0
- package/crates/team-agent/src/lifecycle/tests/agent_ops.rs +2 -3
- package/crates/team-agent/src/lifecycle/tests/clone_agent_preserves_source_tools.rs +309 -0
- package/crates/team-agent/src/lifecycle/tests/clone_fork_copilot_perms_red.rs +150 -157
- package/crates/team-agent/src/lifecycle/tests/copilot_provider_red.rs +2 -2
- package/crates/team-agent/src/lifecycle/tests/core.rs +4 -0
- package/crates/team-agent/src/lifecycle/tests/cursor_mcp_overlay.rs +287 -0
- package/crates/team-agent/src/lifecycle/tests/cursor_require_explicit_model_red.rs +229 -0
- package/crates/team-agent/src/lifecycle/tests/cursor_restart_resume_red.rs +353 -0
- package/crates/team-agent/src/lifecycle/tests/g1_silent_faces.rs +784 -0
- package/crates/team-agent/src/lifecycle/tests/gate_fixtures.rs +562 -0
- package/crates/team-agent/src/lifecycle/tests/grok_effort_argv_red.rs +239 -0
- package/crates/team-agent/src/lifecycle/tests/grok_mcp_overlay_red.rs +498 -0
- package/crates/team-agent/src/lifecycle/tests/grok_require_explicit_model_red.rs +250 -0
- package/crates/team-agent/src/lifecycle/tests/grok_restart_resume_red.rs +293 -0
- package/crates/team-agent/src/lifecycle/tests/lane_ops.rs +63 -38
- package/crates/team-agent/src/lifecycle/tests/launch_spawn.rs +3 -2
- package/crates/team-agent/src/lifecycle/tests/lifecycle_rollback_red.rs +16 -8
- package/crates/team-agent/src/lifecycle/tests/mcp_tool_name_format_red.rs +69 -0
- package/crates/team-agent/src/lifecycle/tests/phase_b_contracts.rs +20 -19
- package/crates/team-agent/src/lifecycle/tests/phase_golden.rs +97 -61
- package/crates/team-agent/src/lifecycle/tests/restart_rebind_hotfix_252_red.rs +2 -0
- package/crates/team-agent/src/lifecycle/tests/startup_latency_contract.rs +40 -7
- package/crates/team-agent/src/lifecycle/tests/test_isolation_escape_contract.rs +59 -1
- package/crates/team-agent/src/lifecycle/tests/worker_spawn_env_red.rs +69 -26
- package/crates/team-agent/src/lifecycle/tests.rs +23 -13
- package/crates/team-agent/src/lifecycle/types.rs +61 -0
- package/crates/team-agent/src/lifecycle/worker_command_context.rs +85 -11
- package/crates/team-agent/src/mcp_server/tests/scoped.rs +100 -1
- package/crates/team-agent/src/mcp_server/tests.rs +196 -2
- package/crates/team-agent/src/messaging/delivery.rs +405 -40
- package/crates/team-agent/src/messaging/helpers.rs +2 -0
- package/crates/team-agent/src/messaging/leader_receiver.rs +53 -1
- package/crates/team-agent/src/messaging/results.rs +4 -0
- package/crates/team-agent/src/messaging/send.rs +34 -0
- package/crates/team-agent/src/messaging/tests/dup_inject.rs +406 -0
- package/crates/team-agent/src/messaging/tests/e23.rs +9 -0
- package/crates/team-agent/src/messaging/tests/leader_inject_acceptance.rs +66 -0
- package/crates/team-agent/src/messaging/tests/mod.rs +1 -0
- package/crates/team-agent/src/messaging/types.rs +4 -1
- package/crates/team-agent/src/model/enums.rs +14 -5
- package/crates/team-agent/src/model/permissions.rs +3 -0
- package/crates/team-agent/src/os_probe.rs +73 -2
- package/crates/team-agent/src/provider/adapter.rs +231 -4
- package/crates/team-agent/src/provider/adapters/cursor_agent.rs +86 -0
- package/crates/team-agent/src/provider/adapters/grok.rs +157 -0
- package/crates/team-agent/src/provider/adapters/mod.rs +2 -0
- package/crates/team-agent/src/provider/bypass_flags.rs +46 -2
- package/crates/team-agent/src/provider/classify.rs +4 -2
- package/crates/team-agent/src/provider/faults.rs +2 -1
- package/crates/team-agent/src/provider/mod.rs +11 -0
- package/crates/team-agent/src/provider/session/capture.rs +158 -20
- package/crates/team-agent/src/provider/session/context_fork/claude.rs +38 -1
- package/crates/team-agent/src/provider/session/context_fork/codex.rs +72 -1
- package/crates/team-agent/src/provider/session/context_fork/outcome.rs +57 -1
- package/crates/team-agent/src/provider/session/context_fork.rs +77 -3
- package/crates/team-agent/src/provider/session/mod.rs +18 -0
- package/crates/team-agent/src/provider/session/resume.rs +57 -0
- package/crates/team-agent/src/provider/session_scan/claude.rs +125 -1
- package/crates/team-agent/src/provider/session_scan/codex.rs +94 -1
- package/crates/team-agent/src/provider/session_scan/common.rs +204 -2
- package/crates/team-agent/src/provider/session_scan/copilot.rs +33 -1
- package/crates/team-agent/src/provider/session_scan/cursor.rs +538 -0
- package/crates/team-agent/src/provider/session_scan/grok.rs +288 -0
- package/crates/team-agent/src/provider/session_scan.rs +8 -0
- package/crates/team-agent/src/provider/submit_now.rs +94 -0
- package/crates/team-agent/src/provider/tests/adapter.rs +304 -0
- package/crates/team-agent/src/provider/types.rs +4 -2
- package/crates/team-agent/src/provider/wire.rs +23 -1
- package/crates/team-agent/src/state/persist.rs +301 -8
- package/crates/team-agent/src/state/repository.rs +5 -0
- package/crates/team-agent/src/tmux_backend/tests.rs +1737 -42
- package/crates/team-agent/src/tmux_backend.rs +1064 -75
- package/crates/team-agent/src/transport/tests/wire.rs +28 -2
- package/crates/team-agent/src/transport.rs +248 -1
- package/npm/install.mjs +129 -73
- package/package.json +4 -4
- package/skills/team-agent/SKILL.md +33 -238
- package/skills/team-agent/command-coverage.json +31 -0
- package/crates/team-agent/src/lifecycle/launch/fork_agent/completion.rs +0 -59
- package/crates/team-agent/src/lifecycle/launch/fork_finalize.rs +0 -488
- package/crates/team-agent/src/lifecycle/launch/fork_pending.rs +0 -109
- package/crates/team-agent/src/lifecycle/launch/fork_state.rs +0 -447
package/npm/install.mjs
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* purpose: place the Team Agent runtime and login wrappers via the npx installer
|
|
4
|
+
* contract: wrappers land only in the declared bin dir (~/.local/bin or --prefix/bin); installer-managed wrappers recorded in the manifest or recognized by marker are rewritten onto this install's runtime; a non-writable declared dir fails closed with ACTION
|
|
5
|
+
* boundary: never selects a PATH entry as the install target; never creates wrappers in third-party package dirs; does not treat host login PATH order as a landing picker
|
|
6
|
+
*/
|
|
2
7
|
import { spawnSync } from "node:child_process";
|
|
3
8
|
import fs from "node:fs";
|
|
4
9
|
import { createRequire } from "node:module";
|
|
@@ -119,7 +124,7 @@ Usage:
|
|
|
119
124
|
npx @team-agent/installer@latest uninstall
|
|
120
125
|
|
|
121
126
|
Options:
|
|
122
|
-
--prefix <dir>
|
|
127
|
+
--prefix <dir> declared wrapper prefix (wrappers go in <dir>/bin), default ~/.local
|
|
123
128
|
--runtime-dir <dir> stable runtime root, default ~/.team-agent/runtime
|
|
124
129
|
--purge-runtime uninstall also removes the runtime root
|
|
125
130
|
`);
|
|
@@ -128,6 +133,7 @@ Options:
|
|
|
128
133
|
function install(argv) {
|
|
129
134
|
const opts = parseOptions(argv);
|
|
130
135
|
const runtimeRoot = path.resolve(expandHome(opts.runtimeDir || path.join(os.homedir(), ".team-agent", "runtime")));
|
|
136
|
+
const prevManifest = readInstallManifest(runtimeRoot);
|
|
131
137
|
const installTarget = resolveInstallBinDir({ env: process.env, home: os.homedir(), prefix: opts.prefix });
|
|
132
138
|
const binDir = installTarget.binDir;
|
|
133
139
|
const version = packageJson.version || "dev";
|
|
@@ -161,6 +167,7 @@ function install(argv) {
|
|
|
161
167
|
home: os.homedir(),
|
|
162
168
|
binDir,
|
|
163
169
|
runtimeBinary,
|
|
170
|
+
recordedBinDirs: recordedManagedBinDirs(prevManifest),
|
|
164
171
|
log: (line) => console.log(line),
|
|
165
172
|
});
|
|
166
173
|
installSkills(runtimeBinary);
|
|
@@ -172,6 +179,11 @@ function install(argv) {
|
|
|
172
179
|
installedAt: new Date().toISOString(),
|
|
173
180
|
installTargetKind: installTarget.kind,
|
|
174
181
|
pathShadowRepairs: shadowRepairs.map((repair) => repair.file),
|
|
182
|
+
managedBinDirs: uniqueDirs([
|
|
183
|
+
binDir,
|
|
184
|
+
...recordedManagedBinDirs(prevManifest),
|
|
185
|
+
...shadowRepairs.map((repair) => repair.binDir),
|
|
186
|
+
]),
|
|
175
187
|
});
|
|
176
188
|
|
|
177
189
|
const teamAgent = path.join(binDir, "team-agent");
|
|
@@ -299,33 +311,71 @@ function parseOptions(argv) {
|
|
|
299
311
|
return opts;
|
|
300
312
|
}
|
|
301
313
|
|
|
314
|
+
export function declaredInstallBinDir(options = {}) {
|
|
315
|
+
const home = options.home || os.homedir();
|
|
316
|
+
const prefix = options.prefix
|
|
317
|
+
? path.resolve(expandHomeFor(options.prefix, home))
|
|
318
|
+
: path.join(home, ".local");
|
|
319
|
+
return path.join(prefix, "bin");
|
|
320
|
+
}
|
|
321
|
+
|
|
302
322
|
export function resolveInstallBinDir(options = {}) {
|
|
303
323
|
const env = options.env || process.env;
|
|
304
324
|
const home = options.home || os.homedir();
|
|
305
|
-
const
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
return { binDir: entry, kind: "path", readyNow: true, rc: null };
|
|
325
|
+
const binDir = path.resolve(declaredInstallBinDir(options));
|
|
326
|
+
try {
|
|
327
|
+
fs.mkdirSync(binDir, { recursive: true });
|
|
328
|
+
} catch (error) {
|
|
329
|
+
throw declaredBinDirUnwritableError(binDir, "create", error);
|
|
311
330
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (isVersionManagedPath(entry) || !isReasonableUserBinDir(entry, home) || !canWriteDir(entry) || hasForeignWrapper(entry)) {
|
|
315
|
-
continue;
|
|
316
|
-
}
|
|
317
|
-
return { binDir: entry, kind: "path_user", readyNow: true, rc: null };
|
|
331
|
+
if (!canWriteDir(binDir)) {
|
|
332
|
+
throw declaredBinDirUnwritableError(binDir, "write");
|
|
318
333
|
}
|
|
319
334
|
|
|
320
|
-
const
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
fs.mkdirSync(binDir, { recursive: true });
|
|
335
|
+
const onPath = uniquePathEntries(env.PATH || "", home).includes(binDir);
|
|
336
|
+
if (onPath) {
|
|
337
|
+
return { binDir, kind: "declared", readyNow: true, rc: null };
|
|
338
|
+
}
|
|
325
339
|
const rc = ensureBinDirOnShellRc(binDir, { env, home });
|
|
326
340
|
return { binDir, kind: "shell_rc", readyNow: false, rc };
|
|
327
341
|
}
|
|
328
342
|
|
|
343
|
+
function declaredBinDirUnwritableError(binDir, op, cause) {
|
|
344
|
+
const detail = cause instanceof Error ? cause.message : cause ? String(cause) : "permission denied";
|
|
345
|
+
return new Error(
|
|
346
|
+
[
|
|
347
|
+
`ERROR: cannot ${op} Team Agent wrapper directory ${binDir}`,
|
|
348
|
+
`ACTION: make it writable (\`mkdir -p ${binDir} && chmod u+w ${binDir}\`), or rerun with --prefix <writable-dir>`,
|
|
349
|
+
`LOG: declared wrapper dir is the only landing; installer does not fall back to a PATH entry (${detail})`,
|
|
350
|
+
].join("\n"),
|
|
351
|
+
);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
export function recordedManagedBinDirs(manifest) {
|
|
355
|
+
const dirs = [];
|
|
356
|
+
if (!manifest || typeof manifest !== "object") {
|
|
357
|
+
return dirs;
|
|
358
|
+
}
|
|
359
|
+
if (typeof manifest.binDir === "string" && manifest.binDir) {
|
|
360
|
+
dirs.push(manifest.binDir);
|
|
361
|
+
}
|
|
362
|
+
if (Array.isArray(manifest.managedBinDirs)) {
|
|
363
|
+
for (const dir of manifest.managedBinDirs) {
|
|
364
|
+
if (typeof dir === "string" && dir) {
|
|
365
|
+
dirs.push(dir);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
if (Array.isArray(manifest.pathShadowRepairs)) {
|
|
370
|
+
for (const file of manifest.pathShadowRepairs) {
|
|
371
|
+
if (typeof file === "string" && file) {
|
|
372
|
+
dirs.push(path.dirname(file));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
return uniqueDirs(dirs);
|
|
377
|
+
}
|
|
378
|
+
|
|
329
379
|
export function repairPathShadowingTeamAgentCommands(options = {}) {
|
|
330
380
|
const env = options.env || process.env;
|
|
331
381
|
const home = options.home || os.homedir();
|
|
@@ -337,42 +387,50 @@ export function repairPathShadowingTeamAgentCommands(options = {}) {
|
|
|
337
387
|
}
|
|
338
388
|
const installedWrapper = path.join(binDir, "team-agent");
|
|
339
389
|
const repairs = [];
|
|
340
|
-
const
|
|
341
|
-
|
|
390
|
+
const recordedBinDirs = options.recordedBinDirs || recordedManagedBinDirs(options.manifest);
|
|
391
|
+
const candidates = pathShadowRepairCandidates(env.PATH || "", home, binDir, recordedBinDirs);
|
|
392
|
+
log?.(`path-shadow: scanning ${candidates.length} candidate bin dirs for managed wrappers`);
|
|
342
393
|
for (const candidateDir of candidates) {
|
|
343
394
|
const entry = candidateDir.dir;
|
|
344
|
-
const candidate = path.join(entry, "team-agent");
|
|
345
395
|
if (isVersionManagedPath(entry)) {
|
|
346
|
-
log?.(`path-shadow: skip ${
|
|
396
|
+
log?.(`path-shadow: skip ${path.join(entry, "team-agent")} source=${candidateDir.source} reason=version-managed-path`);
|
|
347
397
|
continue;
|
|
348
398
|
}
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
399
|
+
for (const name of WRAPPER_NAMES) {
|
|
400
|
+
const candidate = path.join(entry, name);
|
|
401
|
+
if (!fs.existsSync(candidate)) {
|
|
402
|
+
if (name === "team-agent" && candidateDir.source === "home-local-bin") {
|
|
403
|
+
log?.(`path-shadow: checked ${candidate} source=${candidateDir.source} reason=not-found`);
|
|
404
|
+
}
|
|
405
|
+
continue;
|
|
352
406
|
}
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
407
|
+
log?.(`path-shadow: found ${candidate} source=${candidateDir.source}`);
|
|
408
|
+
if (!isExecutableFile(candidate)) {
|
|
409
|
+
log?.(`path-shadow: skip ${candidate} source=${candidateDir.source} reason=not-executable-file`);
|
|
410
|
+
continue;
|
|
411
|
+
}
|
|
412
|
+
if (sameFile(candidate, installedWrapper) && name === "team-agent") {
|
|
413
|
+
log?.(`path-shadow: skip ${candidate} source=${candidateDir.source} reason=installed-wrapper`);
|
|
414
|
+
continue;
|
|
415
|
+
}
|
|
416
|
+
if (sameFile(candidate, runtimeBinary)) {
|
|
417
|
+
log?.(`path-shadow: skip ${candidate} source=${candidateDir.source} reason=runtime-binary`);
|
|
418
|
+
continue;
|
|
419
|
+
}
|
|
420
|
+
if (!isInstallerManagedWrapper(candidate)) {
|
|
421
|
+
log?.(`path-shadow: skip ${candidate} source=${candidateDir.source} reason=not-installer-managed`);
|
|
422
|
+
continue;
|
|
423
|
+
}
|
|
424
|
+
const extraArgs = name === "team_orchestrator" ? ["mcp-server"] : name === "team-agent-coordinator" ? ["coordinator"] : [];
|
|
425
|
+
try {
|
|
426
|
+
writeExecWrapper(candidate, runtimeBinary, extraArgs, { allowForeign: true });
|
|
427
|
+
} catch (error) {
|
|
428
|
+
const detail = error instanceof Error ? error.message : String(error);
|
|
429
|
+
throw new Error(`failed to update PATH-shadowing team-agent at ${candidate}: ${detail}`);
|
|
430
|
+
}
|
|
431
|
+
log?.(`path-shadow: updated ${candidate} source=${candidateDir.source} to runtime shim`);
|
|
432
|
+
repairs.push({ file: candidate, binDir: entry, source: candidateDir.source });
|
|
373
433
|
}
|
|
374
|
-
log?.(`path-shadow: updated ${candidate} source=${candidateDir.source} to runtime shim`);
|
|
375
|
-
repairs.push({ file: candidate, binDir: entry, source: candidateDir.source });
|
|
376
434
|
}
|
|
377
435
|
if (repairs.length === 0) {
|
|
378
436
|
log?.("path-shadow: no stale team-agent command repaired");
|
|
@@ -434,16 +492,7 @@ export function parseTeamAgentVersion(output) {
|
|
|
434
492
|
return bare ? bare[1] : null;
|
|
435
493
|
}
|
|
436
494
|
|
|
437
|
-
function
|
|
438
|
-
const entries = uniquePathEntries(searchPath, home);
|
|
439
|
-
const installedIndex = entries.findIndex((entry) => path.resolve(entry) === path.resolve(binDir));
|
|
440
|
-
if (installedIndex === -1) {
|
|
441
|
-
return entries;
|
|
442
|
-
}
|
|
443
|
-
return entries.slice(0, installedIndex);
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
function pathShadowRepairCandidates(searchPath, home, binDir) {
|
|
495
|
+
function pathShadowRepairCandidates(searchPath, home, binDir, recordedBinDirs = []) {
|
|
447
496
|
const candidates = [];
|
|
448
497
|
const seen = new Set();
|
|
449
498
|
const add = (dir, source) => {
|
|
@@ -454,17 +503,36 @@ function pathShadowRepairCandidates(searchPath, home, binDir) {
|
|
|
454
503
|
seen.add(resolved);
|
|
455
504
|
candidates.push({ dir: resolved, source });
|
|
456
505
|
};
|
|
457
|
-
for (const entry of
|
|
458
|
-
add(entry, "path
|
|
506
|
+
for (const entry of uniquePathEntries(searchPath, home)) {
|
|
507
|
+
add(entry, "path");
|
|
459
508
|
}
|
|
460
509
|
|
|
461
510
|
const homeLocalBin = path.join(home, ".local", "bin");
|
|
462
|
-
|
|
463
|
-
|
|
511
|
+
add(homeLocalBin, "home-local-bin");
|
|
512
|
+
add(binDir, "declared-bin");
|
|
513
|
+
for (const dir of recordedBinDirs) {
|
|
514
|
+
add(dir, "manifest-recorded");
|
|
464
515
|
}
|
|
465
516
|
return candidates;
|
|
466
517
|
}
|
|
467
518
|
|
|
519
|
+
function uniqueDirs(dirs) {
|
|
520
|
+
const seen = new Set();
|
|
521
|
+
const out = [];
|
|
522
|
+
for (const dir of dirs) {
|
|
523
|
+
if (typeof dir !== "string" || !dir) {
|
|
524
|
+
continue;
|
|
525
|
+
}
|
|
526
|
+
const resolved = path.resolve(dir);
|
|
527
|
+
if (seen.has(resolved)) {
|
|
528
|
+
continue;
|
|
529
|
+
}
|
|
530
|
+
seen.add(resolved);
|
|
531
|
+
out.push(resolved);
|
|
532
|
+
}
|
|
533
|
+
return out;
|
|
534
|
+
}
|
|
535
|
+
|
|
468
536
|
function isExecutableFile(file) {
|
|
469
537
|
try {
|
|
470
538
|
fs.accessSync(file, fs.constants.X_OK);
|
|
@@ -513,11 +581,6 @@ function isVersionManagedPath(dir) {
|
|
|
513
581
|
].some((marker) => value.includes(marker));
|
|
514
582
|
}
|
|
515
583
|
|
|
516
|
-
function isReasonableUserBinDir(dir, home) {
|
|
517
|
-
const relative = path.relative(home, dir);
|
|
518
|
-
return Boolean(relative && !relative.startsWith("..") && !path.isAbsolute(relative));
|
|
519
|
-
}
|
|
520
|
-
|
|
521
584
|
function canWriteDir(dir) {
|
|
522
585
|
try {
|
|
523
586
|
const probe = path.join(dir, `.team-agent-write-test-${process.pid}-${Date.now()}`);
|
|
@@ -529,13 +592,6 @@ function canWriteDir(dir) {
|
|
|
529
592
|
}
|
|
530
593
|
}
|
|
531
594
|
|
|
532
|
-
function hasForeignWrapper(binDir) {
|
|
533
|
-
return WRAPPER_NAMES.some((name) => {
|
|
534
|
-
const file = path.join(binDir, name);
|
|
535
|
-
return fs.existsSync(file) && !isInstallerManagedWrapper(file);
|
|
536
|
-
});
|
|
537
|
-
}
|
|
538
|
-
|
|
539
595
|
function isInstallerManagedWrapper(file) {
|
|
540
596
|
try {
|
|
541
597
|
const text = fs.readFileSync(file, "utf8");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@team-agent/installer",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.68",
|
|
4
4
|
"description": "npx installer for Team Agent",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"codex",
|
|
@@ -20,9 +20,9 @@
|
|
|
20
20
|
"team-agent-installer": "npm/install.mjs"
|
|
21
21
|
},
|
|
22
22
|
"optionalDependencies": {
|
|
23
|
-
"@team-agent/cli-darwin-arm64": "0.5.
|
|
24
|
-
"@team-agent/cli-darwin-x64": "0.5.
|
|
25
|
-
"@team-agent/cli-linux-x64": "0.5.
|
|
23
|
+
"@team-agent/cli-darwin-arm64": "0.5.68",
|
|
24
|
+
"@team-agent/cli-darwin-x64": "0.5.68",
|
|
25
|
+
"@team-agent/cli-linux-x64": "0.5.68"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"postinstall": "node npm/bincheck.mjs",
|
|
@@ -1,272 +1,67 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: team-agent
|
|
3
3
|
description: Use only when the user explicitly asks to start, operate, inspect, shutdown, or restart a Team Agent team. Treat the team-agent CLI as a sealed appliance.
|
|
4
|
+
requires_team_agent: ">=0.5.0"
|
|
5
|
+
last_verified_against: "0.5.66"
|
|
4
6
|
---
|
|
5
7
|
|
|
6
8
|
# Team Agent
|
|
7
9
|
|
|
8
|
-
|
|
10
|
+
Sealed appliance for someone who just got the CLI. Operator handbook (permissions, models, routing, recovery): `docs/reference/team-agent-operator.md`.
|
|
9
11
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
Real Team Agent teams require the current leader to run inside a tmux-managed pane. Prefer the short launchers:
|
|
12
|
+
If `team-agent --version` does not match `last_verified_against`, do not copy examples as current truth. Learn from the live CLI:
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
team-agent
|
|
16
|
-
team-agent
|
|
15
|
+
team-agent --version
|
|
16
|
+
team-agent --help
|
|
17
|
+
team-agent doctor --help
|
|
17
18
|
```
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
## Leader Role
|
|
22
|
-
|
|
23
|
-
Invoking this skill turns the current agent into the team leader. The leader **orchestrates**: read reports, set direction, decompose work, dispatch tasks to teammates, review results, and decide. The leader does **not** execute hands-on work — no `cargo test`, no product-code edits, no `git push`, no build/verify cycles. Those belong to teammates. If the leader catches themselves running tests, editing source files, or pushing commits, they have stepped out of role; stop and re-dispatch.
|
|
24
|
-
|
|
25
|
-
When the user has been communicating in Chinese throughout the conversation, all leader↔teammate messaging (`send`, `report_result`, MCP messages, task descriptions) must also be in Chinese. The leader dispatches in Chinese, the worker reports back in Chinese. Switch back to the user's language only at the user-facing boundary.
|
|
26
|
-
|
|
27
|
-
## Minimal Copy-Paste Team
|
|
28
|
-
|
|
29
|
-
```bash
|
|
30
|
-
mkdir -p .team/current/agents
|
|
31
|
-
team-agent profile init codex-default --auth-mode subscription --workspace .
|
|
32
|
-
cat > .team/current/TEAM.md <<'EOF'
|
|
33
|
-
---
|
|
34
|
-
name: demo-team
|
|
35
|
-
objective: One worker handles bounded tasks and reports through Team Agent MCP.
|
|
36
|
-
dangerous_auto_approve: false
|
|
37
|
-
fast: false
|
|
38
|
-
provider_models:
|
|
39
|
-
codex: gpt-5.5
|
|
40
|
-
claude: claude-sonnet-4-6
|
|
41
|
-
claude_code: claude-sonnet-4-6
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
Team config only. This is not a worker role.
|
|
45
|
-
EOF
|
|
46
|
-
cat > .team/current/agents/coder.md <<'EOF'
|
|
47
|
-
---
|
|
48
|
-
name: coder
|
|
49
|
-
role: Implementation Worker
|
|
50
|
-
provider: codex
|
|
51
|
-
auth_mode: subscription
|
|
52
|
-
profile: codex-default
|
|
53
|
-
tools:
|
|
54
|
-
- fs_read
|
|
55
|
-
- fs_list
|
|
56
|
-
- fs_write
|
|
57
|
-
- execute_bash
|
|
58
|
-
- mcp_team
|
|
59
|
-
- provider_builtin
|
|
60
|
-
---
|
|
61
|
-
|
|
62
|
-
Handle one bounded task at a time. Send progress to leader only when needed. Final completion must call report_result exactly once; MCP fills task ids and result envelope fields.
|
|
63
|
-
EOF
|
|
64
|
-
team-agent quick-start .team/current
|
|
65
|
-
```
|
|
66
|
-
|
|
67
|
-
YAML lists must be block style. Use `tools:\n - fs_read`; do not use `tools: [fs_read, mcp_team]`.
|
|
68
|
-
|
|
69
|
-
Display choices (set `display_backend:` in `TEAM.md` to opt in):
|
|
70
|
-
|
|
71
|
-
- `none` (default): headless / no GUI window manager. The team runs entirely in the per-workspace tmux server; this is what the demo above uses.
|
|
72
|
-
- `adaptive`: framework picks an available GUI layout for the local platform.
|
|
73
|
-
- `ghostty_workspace`: one Ghostty window. Workers are shown in tmux tabs/windows, up to 3 side-by-side panes per tab. Four workers become `3 + 1`; eight become `3 + 3 + 2`.
|
|
74
|
-
- `ghostty_window`: one Ghostty window per worker.
|
|
20
|
+
**Launch** from a tmux-addressable pane: `team-agent claude` or `team-agent codex`, then `team-agent quick-start .team/current`. Do not start a real team from a naked terminal. Existing tmux/Ghostty layouts are valid if `quick-start` runs from the leader pane.
|
|
75
21
|
|
|
76
|
-
**
|
|
22
|
+
**Operate**
|
|
77
23
|
|
|
78
|
-
|
|
24
|
+
- Dispatch: `team-agent send TO MESSAGE` (positional TO; `--watch-result` is deprecated). After success, do not poll with `sleep` / `status` / `inbox` / `collect`.
|
|
25
|
+
TO has two co-equal logical forms: an **in-team short name** (`team-agent send reviewer "..."`) and a fully qualified `<workspace>::<team>/<agent>`. Use the qualified form across workspaces.
|
|
26
|
+
- Inspect: `team-agent status` / `status --json`. `ok: true` plus `ready: false` is not a crash.
|
|
27
|
+
- Lifecycle: `restart .` resumes a stopped team; `add-agent NAME --role-file FILE` adds or `--force` recreates one worker; `shutdown --workspace .` stops. Do not shutdown the whole team to add a worker.
|
|
28
|
+
- Roles: every `agents/*.md` must declare boolean `dangerously_skip_permissions`. Never rewrite a user-supplied model id. Never read `.env` files.
|
|
79
29
|
|
|
80
|
-
|
|
30
|
+
**On failure:** if the CLI prints a structured `action`, run that `action` first, then stop. Do not guess flags. `coordinator.session_missing` is a self-healing transient — re-check `status --json`; do not shutdown because of it.
|
|
81
31
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
Use `team-agent attach-leader` / `team-agent claim-leader` to bind the leader pane to a team. Do not invent socket paths by hand.
|
|
32
|
+
The current user-facing agent is the leader (orchestrate only). Workers call `report_result` exactly once. Nested teams: `skills/team-agent/references/team-in-team.md`.
|
|
85
33
|
|
|
86
34
|
## Provider Capability Matrix
|
|
87
35
|
|
|
36
|
+
Claude / Codex / Copilot / Gemini / fake: `docs/reference/team-agent-operator.md`. These two are in the runtime but were missing from that table:
|
|
37
|
+
|
|
88
38
|
| Provider | Resume | Turn-state detection | Per-worker model override | Native session fork |
|
|
89
39
|
|---|---|---|---|---|
|
|
90
|
-
| `
|
|
91
|
-
| `
|
|
92
|
-
| `copilot` | yes (`copilot --resume <id|name>`, sqlite `sessions` row) | not yet (phase 1: `provider.classify.unsupported` event) | yes (role `model`) | yes (isolated `COPILOT_HOME` store fork) |
|
|
93
|
-
| `gemini_cli` | no | no | yes | no |
|
|
94
|
-
| `fake` (testing only) | no | no | n/a | no |
|
|
40
|
+
| `grok` | yes (`--resume <id>`, archive-gated) | no | yes (role `model` required) | yes (`--fork-session` + new `--session-id`) |
|
|
41
|
+
| `cursor_agent` | yes (argv `--resume <chatId>`, archive-gated) | no | required on role; same-family catalog id can take effect; unknown id silent-fallback; pane chrome ≠ proven live | **no — `CapabilityUnsupported`** |
|
|
95
42
|
|
|
96
|
-
|
|
97
|
-
- Per-worker model override means a role-doc `model:` value wins over `TEAM.md` `provider_models.<provider>`; subscription defaults still fill blanks.
|
|
98
|
-
- Copilot fork copies the source session into an isolated `COPILOT_HOME` and rekeys its SQLite session references atomically. Missing or incomplete backing fails closed; it never falls back to a fresh spawn.
|
|
99
|
-
- Copilot phase-1 idle/turn detection is intentionally Unknown; tick emits a single explicit `provider.classify.unsupported` event per state change (P4 dedup), never a silent default.
|
|
43
|
+
Grok / `cursor_agent` have no JSONL turn-state reader (classify → Unknown).
|
|
100
44
|
|
|
101
45
|
## Provider Prep
|
|
102
46
|
|
|
103
|
-
###
|
|
104
|
-
|
|
105
|
-
Before workers can use a subscription provider, create a named subscription profile in the workspace and reference it from role docs:
|
|
106
|
-
|
|
107
|
-
```bash
|
|
108
|
-
team-agent profile init codex-default --auth-mode subscription --workspace .
|
|
109
|
-
team-agent profile init claude-default --auth-mode subscription --workspace .
|
|
110
|
-
```
|
|
111
|
-
|
|
112
|
-
Then in `agents/<role>.md` frontmatter, set `auth_mode: subscription` and `profile: codex-default` (or `claude-default`). The demo above uses `profile: codex-default`; that name only works after `profile init` has created it in the same workspace.
|
|
113
|
-
|
|
114
|
-
Common errors:
|
|
115
|
-
|
|
116
|
-
- `profile already exists`: a profile by that name is already in `.team/current/profiles/`. Either reuse it (skip `init`) or pick a new name.
|
|
117
|
-
- `profile not found` during quick-start: the role doc references a profile that was never `profile init`-ed in this workspace. Run `team-agent profile init <name> --auth-mode subscription --workspace .` and retry.
|
|
118
|
-
|
|
119
|
-
### Codex provider notes
|
|
120
|
-
|
|
121
|
-
Codex: run `codex login` first. Optional `~/.codex/config.toml` profile:
|
|
122
|
-
|
|
123
|
-
```toml
|
|
124
|
-
[profiles.team-agent]
|
|
125
|
-
model = "gpt-5.5"
|
|
126
|
-
approval_policy = "on-request"
|
|
127
|
-
sandbox_mode = "workspace-write"
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
Use exact provider model ids, not display names. For Codex workers, the model must match a `slug` from `codex debug models`; for example use `gpt-5.3-codex-spark`, not `GPT-5.3-Codex-Spark`.
|
|
131
|
-
Role docs may omit `model` for subscription workers. Team Agent fills subscription defaults from `TEAM.md` `provider_models`, then built-in provider defaults (`codex: gpt-5.5`, `claude/claude_code: claude-sonnet-4-6`). Use role-level `model` only for intentional per-worker overrides.
|
|
132
|
-
|
|
133
|
-
Claude: run `claude auth status`; if missing, run `claude auth login`. Team Agent stores Claude worker sessions by passing `--session-id` and resumes with `--resume`.
|
|
134
|
-
Use `provider: claude` or `provider: claude_code` for Claude workers.
|
|
135
|
-
|
|
136
|
-
If the current leader process was started with `claude --dangerously-skip-permissions` or `codex --dangerously-bypass-approvals-and-sandbox`, Team Agent inherits that permission mode for worker launch, restart, and single-agent repair.
|
|
137
|
-
Role `profile` values are secret-safe references. Do not put API keys in role docs or `TEAM.md`.
|
|
138
|
-
Never read raw provider profile files into model context. Do not use `Read`, `cat`, `sed`, `grep`, editors, or screenshots on `.team/current/profiles/*.env` or `.team/runtime/provider-env/*.env`. Those files may contain live API keys. Use only `team-agent profile show <name> --workspace . --json` or `team-agent profile doctor <name> --workspace . --json` for redacted diagnostics; if a value is missing, ask the human user to edit the local profile file.
|
|
139
|
-
When the user asks for a third-party or compatible API, do not ask them to paste keys into the chat. Generate a local blank profile instead, for example:
|
|
140
|
-
|
|
141
|
-
```bash
|
|
142
|
-
team-agent profile init deepseek --auth-mode compatible_api --workspace .
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
Tell the user to fill `.team/current/profiles/deepseek.env` locally:
|
|
146
|
-
|
|
147
|
-
```env
|
|
148
|
-
AUTH_MODE=compatible_api
|
|
149
|
-
PROFILE_NAME=deepseek
|
|
150
|
-
BASE_URL=
|
|
151
|
-
API_KEY=
|
|
152
|
-
MODEL=
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
Then reference only `auth_mode: compatible_api` and `profile: deepseek` in role docs. Do not invent or duplicate a role `model` when the profile already has `MODEL=`; if both places define a model they must match exactly. Team Agent loads the profile automatically during quick-start, launch, restart, and start-agent. Compatible API workers inherit the current shell proxy/CA environment by default. Claude compatible API workers use Team Agent managed `CLAUDE_CONFIG_DIR` so user-level Claude subscription settings cannot re-inject Anthropic proxy variables into third-party API sessions. If quick-start reports an ambient proxy blocker, do not silently unset proxy for the whole team; tell the user to choose one path: fix that proxy for `BASE_URL`, put `HTTPS_PROXY=`/`HTTP_PROXY=` in the profile, or put `PROXY_MODE=direct` in the profile to bypass proxy only for that worker. Subscription workers keep their native provider settings and environment. Startup runs a redacted smoke check for compatible API profiles before worker windows are created, so a bad URL/key/model or proxy/base URL connectivity failure is reported to the leader command instead of producing idle workers.
|
|
156
|
-
For diagnosis, run `team-agent profile show deepseek --workspace . --json`; never open the `.env` file to check whether `API_KEY` or `MODEL` is filled.
|
|
157
|
-
|
|
158
|
-
## Commands
|
|
159
|
-
|
|
160
|
-
- `team-agent codex ...` starts or attaches a tmux-managed Codex leader in the current directory; arguments after `codex` pass through to Codex.
|
|
161
|
-
- `team-agent claude ...` starts or attaches a tmux-managed Claude leader in the current directory; arguments after `claude` pass through to Claude.
|
|
162
|
-
- `team-agent quick-start .team/current` starts workers from `TEAM.md` and `agents/*.md`. When it prints `ready:` and `ready_signal`, startup is complete; do not run sleep/status/wait loops afterward unless diagnosing a failure.
|
|
163
|
-
- For real workers, `quick-start` requires a current tmux leader pane. If it says the leader must run inside tmux, restart the leader with `team-agent codex`/`team-agent claude` or use an existing tmux-managed layout, then run quick-start again.
|
|
164
|
-
- Quick-start generated files stay inside the selected team directory, for example `.team/current/` or `.team/alpha/`; do not create or expect root `team.spec.yaml` or `team_state.md`.
|
|
165
|
-
- Use `team-agent quick-start ./roles --team-id alpha` to create a second generated team under `.team/alpha/`, or pass an existing team directory directly such as `team-agent quick-start .team/alpha`.
|
|
166
|
-
- `quick-start` is only for first-time team creation from role docs. If that team already has runtime state, use `team-agent restart . --team <session_name_or_team_name>` to resume it. If restart cannot recover context, explain the loss and wait for explicit user consent before using `team-agent restart . --allow-fresh`; never reset context through quick-start.
|
|
167
|
-
- If the user explicitly asks a worker to create or operate a nested child team, first read `references/team-in-team.md`. Child teams must use an independent child workspace, never the parent `.team/current`.
|
|
168
|
-
- `team-agent send --watch-result coder "Do the bounded task"` sends a direct worker message, returns after delivery, and lets the coordinator collect/report completion asynchronously.
|
|
169
|
-
- Positional `TO` has two co-equal forms: an in-team short name, for example `team-agent send reviewer "Review this change"`, and a fully-qualified logical name, `<workspace>::<team>/<agent>`. Use the fully-qualified form across workspaces or when the local team scope is ambiguous.
|
|
170
|
-
- Advanced orchestration callers may add `--presentation-sink leader|casefile|silent --message-class CLASS [--case-id CASE]`. All sinks remain durable and pullable; `casefile`/`silent` suppress only live leader injection. Missing presentation metadata preserves the normal leader-visible behavior.
|
|
171
|
-
- After `send --watch-result` succeeds, do not run `sleep`, `status`, `inbox`, or `collect` polling loops unless the user explicitly asks for diagnosis; the coordinator will notify the leader when the result arrives.
|
|
172
|
-
- `team-agent send --task task_initial "Start"` routes by task.
|
|
173
|
-
- `team-agent status` shows team, worker health, result-store counts, `session_id`, `captured_via`, and attribution confidence. `team-agent status --json` is compact and context-safe by default; use `team-agent status --detail --json` only for raw runtime-state diagnostics.
|
|
174
|
-
- `team-agent status coder` shows one worker.
|
|
175
|
-
- `team-agent approvals [coder]` shows structured pending approval prompts without copying worker terminal pages.
|
|
176
|
-
- `team-agent inbox coder` shows message history only. Final results are not in inbox.
|
|
177
|
-
- `team-agent shutdown --workspace . --keep-logs` stops the tmux session after a final session capture attempt.
|
|
178
|
-
- `team-agent restart .` restarts a stopped team from stored worker sessions. If one workspace has multiple restartable teams, use `team-agent restart . --team <session_name_or_team_name>`.
|
|
179
|
-
- `team-agent start-agent coder --workspace .` repairs one missing worker window without interrupting other workers.
|
|
180
|
-
- `team-agent doctor` checks local dependencies and provider auth hints.
|
|
181
|
-
|
|
182
|
-
## Restart Semantics
|
|
47
|
+
### Cursor provider notes
|
|
183
48
|
|
|
184
|
-
`
|
|
49
|
+
Frontmatter: `provider: cursor_agent` (not `cursor`; launcher verb is `team-agent cursor`), `auth_mode: subscription`, `name:` required (omit → `missing front matter field name`). Also required: `role:`, `tools:`, `dangerously_skip_permissions:` (bool). Subscription needs no `profile`.
|
|
185
50
|
|
|
186
|
-
|
|
51
|
+
`model:` is required (omit compile-fails; blocks a silent builtin `sonnet-4-thinking`). The flag stays on argv. Same-family catalog ids can change pane chrome. An id not in that provider's catalog silent-falls back (landing not stable; no events/stderr/pane warning). Pick names from the catalog; after spawn, `capture-pane` once for chrome. Do not treat the role field or pane chrome as proof of the live model.
|
|
187
52
|
|
|
188
|
-
|
|
53
|
+
One `cursor_agent` per workspace. A second seat (including `add-agent --force` of a different id) fail-closes:
|
|
189
54
|
|
|
190
|
-
## Adding A New Worker At Runtime
|
|
191
|
-
|
|
192
|
-
To add a new worker to a running team, write the role doc and run **one command** — do not shutdown/restart, do not regenerate the compiled spec, and do not quick-start an existing team:
|
|
193
|
-
|
|
194
|
-
```bash
|
|
195
|
-
cat > .team/current/agents/reviewer.md <<'EOF'
|
|
196
|
-
---
|
|
197
|
-
name: reviewer
|
|
198
|
-
role: Code Reviewer
|
|
199
|
-
provider: codex
|
|
200
|
-
auth_mode: subscription
|
|
201
|
-
profile: codex-default
|
|
202
|
-
tools:
|
|
203
|
-
- fs_read
|
|
204
|
-
- fs_list
|
|
205
|
-
- mcp_team
|
|
206
|
-
---
|
|
207
|
-
|
|
208
|
-
Review changed files and report findings to leader.
|
|
209
|
-
EOF
|
|
210
|
-
team-agent add-agent reviewer --role-file .team/current/agents/reviewer.md --workspace .
|
|
211
55
|
```
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
Semantic distinction:
|
|
216
|
-
|
|
217
|
-
- `team-agent add-agent <agent> --role-file <file>` — add a **new** worker not yet in team state.
|
|
218
|
-
- `team-agent clone-agent <source> --as <new>` — reread the source worker's latest role file and start a fresh provider seat. It never copies conversation context. Success is initially honest `capture_state: pending_first_turn` with `session_id`, `new_session_id`, and `backing_path` all null; after the first turn, canonical capture changes the state to `captured` and fills the backing tuple.
|
|
219
|
-
- `team-agent fork-agent <source> --as <new>` — reread the same latest role file and create a distinct, verified provider session that forks the source context. If the provider backing cannot be verified, the command fails and rolls back instead of silently cloning fresh.
|
|
220
|
-
- `team-agent start-agent <agent>` — (re)launch a worker that **already exists** in team state but whose window is missing.
|
|
221
|
-
- `team-agent reset-agent <agent> --discard-session` — keep the same seat and deliberately start it with fresh context.
|
|
222
|
-
- `team-agent restart .` — resume a fully **stopped** team from stored worker sessions.
|
|
223
|
-
- `team-agent quick-start <dir>` — first-time team creation from role docs; for existing teams use `restart`, and use `restart --allow-fresh` only after explicit user consent to discard context.
|
|
224
|
-
|
|
225
|
-
Clone/fork names are always explicit: run concurrent calls with a different `--as` value for each new seat. Fork success includes a verified new `session_id` and independent backing; a tmux window alone is not fork success. Clone success uses the honest `pending_first_turn` state above until first-turn capture, never a fabricated verified tuple. Updating the source role file affects the next clone/fork without requiring a full-team rebuild. Automatic knowledge write-back from a clone/fork into the source role file is not provided.
|
|
226
|
-
|
|
227
|
-
Removing a worker at runtime is the symmetric `team-agent remove-agent <agent> --workspace . --confirm`.
|
|
228
|
-
|
|
229
|
-
## Worker Protocol
|
|
230
|
-
|
|
231
|
-
Workers normally do not run nested Team Agent teams. When the user or leader explicitly asks for a child team, follow `references/team-in-team.md`; otherwise workers only provide the target and content for progress, and a short completion summary at the end:
|
|
232
|
-
|
|
233
|
-
```text
|
|
234
|
-
team_orchestrator.send_message(to="leader", content="short progress or blocker")
|
|
235
|
-
# to another teammate:
|
|
236
|
-
team_orchestrator.send_message(to="<agent_id>", content="short coordination note")
|
|
237
|
-
# to every other team member:
|
|
238
|
-
team_orchestrator.send_message(to="*", content="short broadcast")
|
|
239
|
-
team_orchestrator.report_result(summary="short completion", status="success", tests=[{"command":"command","status":"passed"}])
|
|
56
|
+
error: cursor_agent seat already occupies this workspace
|
|
57
|
+
reason: <workspace>/.cursor/mcp.json is directory-scoped; a second seat overwrites TEAM_AGENT_ID (last-writer)
|
|
58
|
+
action: do not add another CursorAgent in this workspace until per-seat MCP identity is isolated
|
|
240
59
|
```
|
|
241
60
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
Do not pass `sender`, `task_id`, `requires_ack`, `schema_version`, or `agent_id` unless doing a low-level compatibility diagnostic. The MCP runtime fills those fields and keeps delivery metadata in runtime state and event logs. If provider env loses the worker id, MCP infers it from active task/message state and falls back to an explicit `unknown` sender instead of treating the worker as leader.
|
|
245
|
-
|
|
246
|
-
Message targets are team-scoped. Use `leader`, another teammate agent id, or `*` for all other team members. The runtime excludes the sender from `*` broadcasts and never scans unrelated terminal windows for recipients.
|
|
247
|
-
|
|
248
|
-
`report_result` stores final completion and immediately attempts a leader notification through the verified/fallback delivery path. `team-agent collect` remains the authoritative state-update path. Do not wait for final results through `team-agent inbox`, message ack counts, or repeated plain status polling. `acknowledged_count` only means prior task messages were acknowledged by the worker; it is not a missing-result signal.
|
|
249
|
-
For normal leader dispatch, prefer `team-agent send --watch-result ...`; when it returns a registered watcher notice, the framework will notify the leader at completion.
|
|
250
|
-
|
|
251
|
-
For long processes, workers must write logs, keep a pid, provide a health check, and stop after a bounded number of retries. QA/reviewer roles must stay within their authorized files and stop on service unavailable, approval prompts, or repeated startup failure.
|
|
252
|
-
|
|
253
|
-
## Failure Rules
|
|
254
|
-
|
|
255
|
-
For any non-zero `team-agent` exit, report the command, exit code, last about 20 stderr lines, and affected task or agent when known. Then stop and wait for the user.
|
|
256
|
-
|
|
257
|
-
Do not retry with changed flags. Do not inspect source code or private runtime state. Do not operate tmux directly except when the user asks for a manual diagnostic. Do not answer provider approval prompts for the user.
|
|
258
|
-
|
|
259
|
-
If `quick-start` reports `tmux session already exists`, treat it as a team-name collision. The existing session may be an active team; do not terminate it and do not suggest `shutdown` as the normal fix. Change `name:` in `TEAM.md` so the next launch uses a different tmux session name, then run `team-agent quick-start .team/current` again.
|
|
260
|
-
|
|
261
|
-
Known Team Agent control-plane MCP prompts such as `team_orchestrator.report_result` and `team_orchestrator.send_message` are handled by the coordinator. It uses session-scoped approval, verifies the prompt cleared, retries boundedly, and logs the result. Do not ask the user to approve those routine internal prompts.
|
|
262
|
-
|
|
263
|
-
When `status` still shows `AWAITING_APPROVAL`, run `team-agent approvals <agent_id>`, show the structured prompt summary and choices, ask the user to decide, and wait.
|
|
264
|
-
|
|
265
|
-
Do not inspect raw worker terminal output during normal operation. Use `team-agent status`, `team-agent approvals`, `team-agent inbox`, `team-agent collect`, and event logs instead. Raw-screen diagnostics are outside this skill's normal workflow, require explicit user authorization, and are guarded by the CLI; use them only as a one-shot bounded diagnostic, never as a routine workflow step.
|
|
61
|
+
Several cursor seats → one workspace directory each. Same seat, fresh context → `reset-agent --discard-session`.
|
|
266
62
|
|
|
267
|
-
|
|
63
|
+
`clone-agent` copies the source role (provider unchanged). Runtime add: `clone-agent` → `stop-agent` → `remove-agent --confirm` (deletes `.team/dynamic-role-files/`) → write the role file → `add-agent --role-file` → dispatch.
|
|
268
64
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
4. Do not loop on `team-agent inbox` or ack/status counts; that burns context and cannot consume final results.
|
|
65
|
+
- Restart emits `--resume <chatId>` when `store.db`/`meta.json` exist; the gate does not read chat text. Persist anything that must survive restart.
|
|
66
|
+
- Delivery sends one Enter; a second Enter interrupts the turn.
|
|
67
|
+
- After spawn, the pane footer should show `Cursor Agent v<version>`. Do not use `strings` to probe the binary.
|