@atlasharness/atlascode 0.1.91 → 0.1.93

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.
Files changed (2) hide show
  1. package/dist/cli.js +1656 -500
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -742,7 +742,15 @@ var init_fs_operations = __esm(() => {
742
742
  });
743
743
 
744
744
  // src/shared/debug.ts
745
- function logForDebugging(_message, _options) {}
745
+ function setDebugSink(sink) {
746
+ _sink = sink;
747
+ }
748
+ function logForDebugging(message, options) {
749
+ if (_sink !== null) {
750
+ _sink(message, options);
751
+ }
752
+ }
753
+ var _sink = null;
746
754
 
747
755
  // src/shared/platform.ts
748
756
  function memoizeNoArg(fn) {
@@ -1017,6 +1025,89 @@ var init_pdfReference = __esm(() => {
1017
1025
  };
1018
1026
  });
1019
1027
 
1028
+ // src/shared/agentSwarmsEnabled.ts
1029
+ function isAgentTeamsFlagSet() {
1030
+ return process.argv.includes("--agent-teams");
1031
+ }
1032
+ function isAgentSwarmsEnabled() {
1033
+ return isEnvTruthy(process.env.ATLAS_EXPERIMENTAL_AGENT_TEAMS) || isAgentTeamsFlagSet();
1034
+ }
1035
+ var init_agentSwarmsEnabled = () => {};
1036
+
1037
+ // src/shared/swarmSchemaFilter.ts
1038
+ function filterSwarmFieldsFromSchema(toolName, schema, swarmEnabled) {
1039
+ if (swarmEnabled)
1040
+ return schema;
1041
+ const fieldsToRemove = SWARM_FIELDS_BY_TOOL[toolName];
1042
+ if (!fieldsToRemove || fieldsToRemove.length === 0)
1043
+ return schema;
1044
+ if (!schema || typeof schema !== "object")
1045
+ return schema;
1046
+ const props = schema.properties;
1047
+ if (!props || typeof props !== "object")
1048
+ return schema;
1049
+ const nextProps = { ...props };
1050
+ for (const f of fieldsToRemove)
1051
+ delete nextProps[f];
1052
+ return { ...schema, properties: nextProps };
1053
+ }
1054
+ var SWARM_FIELDS_BY_TOOL;
1055
+ var init_swarmSchemaFilter = __esm(() => {
1056
+ SWARM_FIELDS_BY_TOOL = {
1057
+ Agent: ["name", "team_name", "mode"],
1058
+ ExitPlanMode: ["launchSwarm", "teammateCount"]
1059
+ };
1060
+ });
1061
+
1062
+ // src/shared/agentRoleTemplates.ts
1063
+ function getAgentRoleTemplate(role) {
1064
+ return roleTemplates.get(role);
1065
+ }
1066
+ function renderTeammatePrompt(parts) {
1067
+ const sections = [];
1068
+ sections.push(`You are the team member "${parts.name}".`);
1069
+ const template = parts.role ? getAgentRoleTemplate(parts.role) : undefined;
1070
+ if (template?.systemPromptFragment) {
1071
+ sections.push(template.systemPromptFragment);
1072
+ }
1073
+ if (parts.role)
1074
+ sections.push(`Role: ${parts.role}`);
1075
+ if (parts.goal)
1076
+ sections.push(`Goal: ${parts.goal}`);
1077
+ if (parts.backstory)
1078
+ sections.push(`Backstory: ${parts.backstory}`);
1079
+ sections.push(parts.prompt);
1080
+ return sections.join(`
1081
+
1082
+ `);
1083
+ }
1084
+ var roleTemplates;
1085
+ var init_agentRoleTemplates = __esm(() => {
1086
+ roleTemplates = new Map;
1087
+ });
1088
+
1089
+ // src/shared/teammateContext.ts
1090
+ import { AsyncLocalStorage } from "async_hooks";
1091
+ function getTeammateContext() {
1092
+ return teammateContextStorage.getStore();
1093
+ }
1094
+ function runWithTeammateContext(context, fn) {
1095
+ return teammateContextStorage.run(context, fn);
1096
+ }
1097
+ function isInProcessTeammate() {
1098
+ return teammateContextStorage.getStore() !== undefined;
1099
+ }
1100
+ function createTeammateContext(config) {
1101
+ return {
1102
+ ...config,
1103
+ isInProcess: true
1104
+ };
1105
+ }
1106
+ var teammateContextStorage;
1107
+ var init_teammateContext = __esm(() => {
1108
+ teammateContextStorage = new AsyncLocalStorage;
1109
+ });
1110
+
1020
1111
  // src/shared/index.ts
1021
1112
  var init_shared = __esm(() => {
1022
1113
  init_feature();
@@ -1034,6 +1125,10 @@ var init_shared = __esm(() => {
1034
1125
  init_fs_operations();
1035
1126
  init_types();
1036
1127
  init_pdfReference();
1128
+ init_agentSwarmsEnabled();
1129
+ init_swarmSchemaFilter();
1130
+ init_agentRoleTemplates();
1131
+ init_teammateContext();
1037
1132
  });
1038
1133
 
1039
1134
  // node_modules/openai/internal/tslib.mjs
@@ -27524,16 +27619,21 @@ async function buildOpenAITools(tools, options, emptyPermissionContext) {
27524
27619
  let desc;
27525
27620
  try {
27526
27621
  desc = await tool.description({}, {
27527
- isNonInteractiveSession: options.isNonInteractiveSession,
27622
+ isNonInteractiveSession: options?.isNonInteractiveSession,
27528
27623
  toolPermissionContext,
27529
27624
  tools: tools ?? []
27530
27625
  });
27531
27626
  } catch {
27532
27627
  desc = tool.name;
27533
27628
  }
27629
+ const filteredSchema = filterSwarmFieldsFromSchema(tool.name, schema, isAgentSwarmsEnabled());
27534
27630
  out.push({
27535
27631
  type: "function",
27536
- function: { name: tool.name, description: desc, parameters: schema }
27632
+ function: {
27633
+ name: tool.name,
27634
+ description: desc,
27635
+ parameters: filteredSchema
27636
+ }
27537
27637
  });
27538
27638
  }
27539
27639
  for (const s of options?.extraToolSchemas ?? []) {
@@ -27620,6 +27720,7 @@ async function buildOpenAIParams(args, role = "small", entry, opts) {
27620
27720
  var init_params = __esm(() => {
27621
27721
  init_roles7();
27622
27722
  init_shared();
27723
+ init_shared();
27623
27724
  init_attachmentProjection();
27624
27725
  init_toolPairing();
27625
27726
  init_schema();
@@ -29563,7 +29664,7 @@ var init_state = __esm(() => {
29563
29664
  });
29564
29665
 
29565
29666
  // src/bootstrap/cwd.ts
29566
- import { AsyncLocalStorage } from "async_hooks";
29667
+ import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
29567
29668
  function runWithCwdOverride(cwd, fn) {
29568
29669
  return cwdOverrideStorage.run(cwd, fn);
29569
29670
  }
@@ -29580,7 +29681,7 @@ function getCwd() {
29580
29681
  var cwdOverrideStorage;
29581
29682
  var init_cwd = __esm(() => {
29582
29683
  init_state();
29583
- cwdOverrideStorage = new AsyncLocalStorage;
29684
+ cwdOverrideStorage = new AsyncLocalStorage2;
29584
29685
  });
29585
29686
 
29586
29687
  // src/bootstrap/index.ts
@@ -34620,7 +34721,7 @@ var init_project = __esm(() => {
34620
34721
  var AGENT_TOOL_NAME = "Agent", MAX_WORKER_SPAWN_DEPTH = 2;
34621
34722
 
34622
34723
  // src/engine/tools/toolNames.ts
34623
- var FILE_READ_TOOL_NAME = "Read", WEB_SEARCH_TOOL_NAME = "WebSearch", TODO_WRITE_TOOL_NAME = "TodoWrite", GREP_TOOL_NAME = "Grep", WEB_FETCH_TOOL_NAME = "WebFetch", GLOB_TOOL_NAME = "Glob", BASH_TOOL_NAME2 = "Bash", POWERSHELL_TOOL_NAME = "PowerShell", FILE_EDIT_TOOL_NAME = "Edit", FILE_WRITE_TOOL_NAME = "Write", NOTEBOOK_EDIT_TOOL_NAME = "NotebookEdit", SKILL_TOOL_NAME = "Skill", SYNTHETIC_OUTPUT_TOOL_NAME = "StructuredOutput", TOOL_SEARCH_TOOL_NAME = "ToolSearch", ENTER_WORKTREE_TOOL_NAME = "EnterWorktree", EXIT_WORKTREE_TOOL_NAME = "ExitWorktree", TEAM_CREATE_TOOL_NAME = "TeamCreate", TEAM_DELETE_TOOL_NAME = "TeamDelete", SNIP_TOOL_NAME = "Snip", SEND_MESSAGE_TOOL_NAME = "SendMessage", TASK_STOP_TOOL_NAME = "TaskStop", TASK_OUTPUT_TOOL_NAME = "TaskOutput", ENTER_PLAN_MODE_TOOL_NAME = "EnterPlanMode", EXIT_PLAN_MODE_V2_TOOL_NAME = "ExitPlanMode", ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion", TASK_CREATE_TOOL_NAME = "TaskCreate", TASK_GET_TOOL_NAME = "TaskGet", TASK_LIST_TOOL_NAME = "TaskList", TASK_UPDATE_TOOL_NAME = "TaskUpdate", CRON_CREATE_TOOL_NAME = "CronCreate", CRON_DELETE_TOOL_NAME = "CronDelete", CRON_LIST_TOOL_NAME = "CronList", CONFIG_TOOL_NAME = "Config", WORKFLOW_TOOL_NAME = "Workflow", REPL_TOOL_NAME = "REPL", LIST_MCP_RESOURCES_TOOL_NAME = "ListMcpResourcesTool", READ_MCP_RESOURCE_TOOL_NAME = "ReadMcpResourceTool", LSP_TOOL_NAME = "LSP", PROPOSE_GOAL_TOOL_NAME = "ProposeGoal", SHELL_TOOL_NAMES, ASYNC_AGENT_ALLOWED_TOOLS, INTERNAL_WORKER_TOOLS, ALL_AGENT_DISALLOWED_TOOLS, CUSTOM_AGENT_DISALLOWED_TOOLS, IN_PROCESS_TEAMMATE_ALLOWED_TOOLS, COORDINATOR_MODE_ALLOWED_TOOLS;
34724
+ var FILE_READ_TOOL_NAME = "Read", WEB_SEARCH_TOOL_NAME = "WebSearch", TODO_WRITE_TOOL_NAME = "TodoWrite", GREP_TOOL_NAME = "Grep", WEB_FETCH_TOOL_NAME = "WebFetch", GLOB_TOOL_NAME = "Glob", BASH_TOOL_NAME2 = "Bash", POWERSHELL_TOOL_NAME = "PowerShell", FILE_EDIT_TOOL_NAME = "Edit", FILE_WRITE_TOOL_NAME = "Write", NOTEBOOK_EDIT_TOOL_NAME = "NotebookEdit", SKILL_TOOL_NAME = "Skill", SYNTHETIC_OUTPUT_TOOL_NAME = "StructuredOutput", TOOL_SEARCH_TOOL_NAME = "ToolSearch", ENTER_WORKTREE_TOOL_NAME = "EnterWorktree", EXIT_WORKTREE_TOOL_NAME = "ExitWorktree", TEAM_CREATE_TOOL_NAME = "TeamCreate", TEAM_DELETE_TOOL_NAME = "TeamDelete", WAIT_FOR_TEAMMATES_TOOL_NAME = "WaitForTeammates", SNIP_TOOL_NAME = "Snip", SEND_MESSAGE_TOOL_NAME = "SendMessage", TASK_STOP_TOOL_NAME = "TaskStop", TASK_OUTPUT_TOOL_NAME = "TaskOutput", ENTER_PLAN_MODE_TOOL_NAME = "EnterPlanMode", EXIT_PLAN_MODE_V2_TOOL_NAME = "ExitPlanMode", ASK_USER_QUESTION_TOOL_NAME = "AskUserQuestion", TASK_CREATE_TOOL_NAME = "TaskCreate", TASK_GET_TOOL_NAME = "TaskGet", TASK_LIST_TOOL_NAME = "TaskList", TASK_UPDATE_TOOL_NAME = "TaskUpdate", CRON_CREATE_TOOL_NAME = "CronCreate", CRON_DELETE_TOOL_NAME = "CronDelete", CRON_LIST_TOOL_NAME = "CronList", CONFIG_TOOL_NAME = "Config", WORKFLOW_TOOL_NAME = "Workflow", REPL_TOOL_NAME = "REPL", LIST_MCP_RESOURCES_TOOL_NAME = "ListMcpResourcesTool", READ_MCP_RESOURCE_TOOL_NAME = "ReadMcpResourceTool", LSP_TOOL_NAME = "LSP", PROPOSE_GOAL_TOOL_NAME = "ProposeGoal", SHELL_TOOL_NAMES, ASYNC_AGENT_ALLOWED_TOOLS, INTERNAL_WORKER_TOOLS, ALL_AGENT_DISALLOWED_TOOLS, CUSTOM_AGENT_DISALLOWED_TOOLS, IN_PROCESS_TEAMMATE_ALLOWED_TOOLS, COORDINATOR_MODE_ALLOWED_TOOLS;
34624
34725
  var init_toolNames = __esm(() => {
34625
34726
  SHELL_TOOL_NAMES = [BASH_TOOL_NAME2, POWERSHELL_TOOL_NAME];
34626
34727
  ASYNC_AGENT_ALLOWED_TOOLS = new Set([
@@ -35711,9 +35812,22 @@ var init_diskOutput = __esm(() => {
35711
35812
  });
35712
35813
 
35713
35814
  // src/task/task.ts
35815
+ import { randomBytes } from "crypto";
35714
35816
  function isTerminalTaskStatus(status) {
35715
35817
  return status === "completed" || status === "failed" || status === "killed";
35716
35818
  }
35819
+ function getTaskIdPrefix(type) {
35820
+ return TASK_ID_PREFIXES[type] ?? "x";
35821
+ }
35822
+ function generateTaskId(type) {
35823
+ const prefix = getTaskIdPrefix(type);
35824
+ const bytes = randomBytes(8);
35825
+ let id = prefix;
35826
+ for (let i = 0;i < 8; i++) {
35827
+ id += TASK_ID_ALPHABET[bytes[i] % TASK_ID_ALPHABET.length];
35828
+ }
35829
+ return id;
35830
+ }
35717
35831
  function createTaskStateBase(id, type, description, toolUseId) {
35718
35832
  return {
35719
35833
  id,
@@ -35727,14 +35841,79 @@ function createTaskStateBase(id, type, description, toolUseId) {
35727
35841
  notified: false
35728
35842
  };
35729
35843
  }
35844
+ var TASK_ID_PREFIXES, TASK_ID_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
35730
35845
  var init_task = __esm(() => {
35731
35846
  init_diskOutput();
35847
+ TASK_ID_PREFIXES = {
35848
+ local_bash: "b",
35849
+ local_agent: "a",
35850
+ remote_agent: "r",
35851
+ in_process_teammate: "t",
35852
+ local_workflow: "w",
35853
+ monitor_mcp: "m",
35854
+ dream: "d"
35855
+ };
35732
35856
  });
35733
35857
 
35734
35858
  // src/task/inProcessTeammate.ts
35735
35859
  function isInProcessTeammateTask(task) {
35736
35860
  return task.type === "in_process_teammate";
35737
35861
  }
35862
+ function asInProcessTeammate(task) {
35863
+ if (typeof task === "object" && task !== null && isInProcessTeammateTask(task)) {
35864
+ return task;
35865
+ }
35866
+ return;
35867
+ }
35868
+ function isInProcessTeammateLive(task) {
35869
+ const t = asInProcessTeammate(task);
35870
+ return t !== undefined && t.status === "running";
35871
+ }
35872
+ function isInProcessTeammateWorking(task) {
35873
+ const t = asInProcessTeammate(task);
35874
+ return t !== undefined && t.status === "running" && !t.isIdle;
35875
+ }
35876
+ function isInProcessTeammateActiveOrUnknown(task) {
35877
+ const t = asInProcessTeammate(task);
35878
+ const status = t !== undefined ? t.status : task?.status;
35879
+ return status === undefined || status === "running";
35880
+ }
35881
+ function findInProcessTeammateTaskByAgentId(tasks, agentId) {
35882
+ for (const task of Object.values(tasks ?? {})) {
35883
+ const t = asInProcessTeammate(task);
35884
+ if (t !== undefined && t.identity.agentId === agentId)
35885
+ return t;
35886
+ }
35887
+ return;
35888
+ }
35889
+ function probeStampAbortController(ac) {
35890
+ let id = probeControllerIds.get(ac);
35891
+ if (id === undefined) {
35892
+ probeControllerSeq += 1;
35893
+ id = `ac-${probeControllerSeq}`;
35894
+ probeControllerIds.set(ac, id);
35895
+ }
35896
+ return id;
35897
+ }
35898
+ function probeReadAbortControllerId(ac) {
35899
+ if (!ac)
35900
+ return "none";
35901
+ return probeControllerIds.get(ac) ?? "untagged";
35902
+ }
35903
+ function probeStampTaskRecord(record) {
35904
+ let id = probeTaskRecordIds.get(record);
35905
+ if (id === undefined) {
35906
+ probeTaskRecordSeq += 1;
35907
+ id = `task-${probeTaskRecordSeq}`;
35908
+ probeTaskRecordIds.set(record, id);
35909
+ }
35910
+ return id;
35911
+ }
35912
+ function probeReadTaskRecordId(record) {
35913
+ if (typeof record !== "object" || record === null)
35914
+ return "none";
35915
+ return probeTaskRecordIds.get(record) ?? "untagged";
35916
+ }
35738
35917
  function appendCappedMessage(messages, message, cap = MAX_TEAMMATE_DISPLAY_MESSAGES) {
35739
35918
  const next = [...messages ?? [], message];
35740
35919
  if (next.length > cap) {
@@ -35742,7 +35921,11 @@ function appendCappedMessage(messages, message, cap = MAX_TEAMMATE_DISPLAY_MESSA
35742
35921
  }
35743
35922
  return next;
35744
35923
  }
35745
- var MAX_TEAMMATE_DISPLAY_MESSAGES = 100;
35924
+ var probeControllerIds, probeControllerSeq = 0, probeTaskRecordIds, probeTaskRecordSeq = 0, MAX_TEAMMATE_DISPLAY_MESSAGES = 100;
35925
+ var init_inProcessTeammate = __esm(() => {
35926
+ probeControllerIds = new WeakMap;
35927
+ probeTaskRecordIds = new WeakMap;
35928
+ });
35746
35929
 
35747
35930
  // src/task/outputLimits.ts
35748
35931
  function getMaxOutputLength() {
@@ -36024,6 +36207,7 @@ var init_outputFormatting = __esm(() => {
36024
36207
  // src/task/index.ts
36025
36208
  var init_task2 = __esm(() => {
36026
36209
  init_task();
36210
+ init_inProcessTeammate();
36027
36211
  init_TaskOutput();
36028
36212
  init_fsRange();
36029
36213
  init_outputLimits();
@@ -36274,28 +36458,6 @@ function isLocalShellTask(task) {
36274
36458
  return typeof task === "object" && task !== null && "type" in task && task.type === "local_bash";
36275
36459
  }
36276
36460
 
36277
- // src/engine/messaging/teammateContext.ts
36278
- import { AsyncLocalStorage as AsyncLocalStorage2 } from "async_hooks";
36279
- function getTeammateContext() {
36280
- return teammateContextStorage.getStore();
36281
- }
36282
- function runWithTeammateContext(context, fn) {
36283
- return teammateContextStorage.run(context, fn);
36284
- }
36285
- function isInProcessTeammate() {
36286
- return teammateContextStorage.getStore() !== undefined;
36287
- }
36288
- function createTeammateContext(config) {
36289
- return {
36290
- ...config,
36291
- isInProcess: true
36292
- };
36293
- }
36294
- var teammateContextStorage;
36295
- var init_teammateContext = __esm(() => {
36296
- teammateContextStorage = new AsyncLocalStorage2;
36297
- });
36298
-
36299
36461
  // src/engine/messaging/teammate.ts
36300
36462
  function getParentSessionId() {
36301
36463
  const inProcessCtx = getTeammateContext();
@@ -36426,7 +36588,7 @@ var init_teammate = __esm(() => {
36426
36588
  init_teammateContext();
36427
36589
  init_shared();
36428
36590
  init_task2();
36429
- init_teammateContext();
36591
+ init_shared();
36430
36592
  });
36431
36593
 
36432
36594
  // src/engine/messaging/agentId.ts
@@ -37411,14 +37573,8 @@ var init_queueManager = __esm(() => {
37411
37573
  });
37412
37574
 
37413
37575
  // src/engine/messaging/agentSwarmsEnabled.ts
37414
- function isAgentTeamsFlagSet() {
37415
- return process.argv.includes("--agent-teams");
37416
- }
37417
- function isAgentSwarmsEnabled() {
37418
- return isEnvTruthy(process.env.ATLAS_EXPERIMENTAL_AGENT_TEAMS) || isAgentTeamsFlagSet();
37419
- }
37420
- var init_agentSwarmsEnabled = __esm(() => {
37421
- init_shared();
37576
+ var init_agentSwarmsEnabled2 = __esm(() => {
37577
+ init_agentSwarmsEnabled();
37422
37578
  });
37423
37579
 
37424
37580
  // src/engine/messaging/index.ts
@@ -37428,7 +37584,7 @@ var init_messaging = __esm(() => {
37428
37584
  init_lockfile();
37429
37585
  init_constants4();
37430
37586
  init_queueManager();
37431
- init_agentSwarmsEnabled();
37587
+ init_agentSwarmsEnabled2();
37432
37588
  });
37433
37589
 
37434
37590
  // src/engine/coordinator/tasks/killShellTasks.ts
@@ -37805,7 +37961,8 @@ async function runAgent(args) {
37805
37961
  spawnDepth,
37806
37962
  signal,
37807
37963
  forkContextMessages,
37808
- checkPermission
37964
+ checkPermission,
37965
+ toolContext
37809
37966
  } = args;
37810
37967
  const role = resolveRole(overrideRole, agentDefinition, parentRole);
37811
37968
  const startTime = Date.now();
@@ -37815,7 +37972,7 @@ async function runAgent(args) {
37815
37972
  ...forkContextMessages ?? [],
37816
37973
  { type: "user", role: "user", content: prompt }
37817
37974
  ];
37818
- const loopResult = await queryAgentLoop({ modelProvider, role, signal, checkPermission }, { messages, tools });
37975
+ const loopResult = await queryAgentLoop({ modelProvider, role, signal, checkPermission, toolContext }, { messages, tools });
37819
37976
  const result = finalizeAgentTool(loopResult.messages, agentId, {
37820
37977
  agentType: agentDefinition.agentType,
37821
37978
  startTime
@@ -37922,6 +38079,65 @@ var init_backgroundTracker = __esm(() => {
37922
38079
  pendingBackgroundAgents = new Set;
37923
38080
  });
37924
38081
 
38082
+ // src/engine/tools/agent/teammateSpawnPort.ts
38083
+ function setTeammateSpawnTrigger(fn) {
38084
+ trigger = fn;
38085
+ }
38086
+ function resetTeammateSpawnTrigger() {
38087
+ trigger = null;
38088
+ }
38089
+ function requireTeammateSpawnTrigger() {
38090
+ if (!trigger) {
38091
+ throw new Error("TeammateSpawnTrigger not wired — call setTeammateSpawnTrigger at composition root first (0.1.93 W-D-A spawn seam)");
38092
+ }
38093
+ return trigger;
38094
+ }
38095
+ var trigger = null;
38096
+
38097
+ // src/engine/tools/team/teamServices.ts
38098
+ function setTeamServices(services) {
38099
+ active = services;
38100
+ }
38101
+ function resetTeamServices() {
38102
+ active = undefined;
38103
+ }
38104
+ function requireTeamServices() {
38105
+ if (!active) {
38106
+ throw new Error("TeamServices not wired — call setTeamServices at composition root first (swarm team-file seam, C 桶 ③ S-E2d)");
38107
+ }
38108
+ return active;
38109
+ }
38110
+ function peekTeamContext() {
38111
+ return active?.getTeamContext();
38112
+ }
38113
+ function createDefaultTeamContextStore() {
38114
+ return {
38115
+ getTeamContext: () => teamContext,
38116
+ setTeamContext: (ctx) => {
38117
+ teamContext = ctx;
38118
+ }
38119
+ };
38120
+ }
38121
+ function registerSpawnedTeammate(input) {
38122
+ const services = requireTeamServices();
38123
+ const ctx = services.getTeamContext();
38124
+ if (!ctx) {
38125
+ throw new Error("registerSpawnedTeammate: no active team — call TeamCreate before spawning teammates");
38126
+ }
38127
+ ctx.teammates[input.agentId] = {
38128
+ name: input.name,
38129
+ agentType: input.agentType,
38130
+ color: services.assignTeammateColor(input.agentId),
38131
+ tmuxSessionName: "",
38132
+ tmuxPaneId: "",
38133
+ cwd: input.cwd ?? "",
38134
+ spawnedAt: Date.now(),
38135
+ ...input.taskId ? { taskId: input.taskId } : {}
38136
+ };
38137
+ services.setTeamContext(ctx);
38138
+ }
38139
+ var active, teamContext;
38140
+
37925
38141
  // src/engine/tools/agent/AgentTool.ts
37926
38142
  import { randomUUID as randomUUID5 } from "crypto";
37927
38143
  function isAgentBackgroundByDefault() {
@@ -37945,6 +38161,45 @@ function resolveAgentDefinition(subagentType, agents) {
37945
38161
  whenToUse: "Custom agent type: " + subagentType
37946
38162
  };
37947
38163
  }
38164
+ async function spawnTeammateFromRoster(args) {
38165
+ const services = requireTeamServices();
38166
+ const teamCtx = services.getTeamContext();
38167
+ if (!teamCtx) {
38168
+ throw new Error(`No active team — call TeamCreate before spawning teammates (wanted team "${args.teamName}")`);
38169
+ }
38170
+ if (teamCtx.teamName !== args.teamName) {
38171
+ throw new Error(`Team "${args.teamName}" is not the active team (leading "${teamCtx.teamName}") — one team per leader`);
38172
+ }
38173
+ if (!args.name || args.name.trim().length === 0) {
38174
+ throw new Error("name (the teammate identity) is required for team-based delegation");
38175
+ }
38176
+ const rosterEntry = teamCtx.roster?.find((r) => r.name === args.name);
38177
+ const composedPrompt = renderTeammatePrompt({
38178
+ name: args.name,
38179
+ role: rosterEntry?.role,
38180
+ goal: rosterEntry?.goal,
38181
+ backstory: rosterEntry?.backstory,
38182
+ prompt: args.prompt
38183
+ });
38184
+ const trigger = requireTeammateSpawnTrigger();
38185
+ const result = await trigger({
38186
+ name: args.name,
38187
+ teamName: args.teamName,
38188
+ prompt: composedPrompt,
38189
+ ...args.model ? { model: args.model } : {},
38190
+ allowPermissionPrompts: false
38191
+ });
38192
+ if (!result.success) {
38193
+ throw new Error(result.error ?? `teammate spawn failed for "${args.name}"`);
38194
+ }
38195
+ registerSpawnedTeammate({
38196
+ name: args.name,
38197
+ agentId: result.agentId,
38198
+ agentType: rosterEntry?.role,
38199
+ ...result.taskId ? { taskId: result.taskId } : {}
38200
+ });
38201
+ return result;
38202
+ }
37948
38203
  var AGENT_TOOL_INPUT_SCHEMA, AgentTool;
37949
38204
  var init_AgentTool = __esm(() => {
37950
38205
  init_modelprovider2();
@@ -37958,6 +38213,7 @@ var init_AgentTool = __esm(() => {
37958
38213
  init_localAgentTask();
37959
38214
  init_shared();
37960
38215
  init_backgroundTracker();
38216
+ init_shared();
37961
38217
  AGENT_TOOL_INPUT_SCHEMA = {
37962
38218
  type: "object",
37963
38219
  properties: {
@@ -37980,6 +38236,18 @@ var init_AgentTool = __esm(() => {
37980
38236
  run_in_background: {
37981
38237
  type: "boolean",
37982
38238
  description: "Set to true to run this agent in the background. You will be notified when it completes."
38239
+ },
38240
+ name: {
38241
+ type: "string",
38242
+ description: "Teammate name for team-based delegation. Provide together with team_name to spawn a teammate into that team (TeamCreate first)."
38243
+ },
38244
+ team_name: {
38245
+ type: "string",
38246
+ description: "Name of the team to spawn the teammate into (must match an active TeamCreate team)."
38247
+ },
38248
+ mode: {
38249
+ type: "string",
38250
+ description: "Teammate mode (upstream contract field)."
37983
38251
  }
37984
38252
  },
37985
38253
  required: ["description", "prompt"]
@@ -37997,6 +38265,25 @@ var init_AgentTool = __esm(() => {
37997
38265
  behavior: "passthrough",
37998
38266
  message: "Agent tool requires permission."
37999
38267
  }),
38268
+ async validateInput(input, _context) {
38269
+ const i = input ?? {};
38270
+ const hasTeammateFields = !!(i.name || i.team_name || i.mode);
38271
+ if (hasTeammateFields && !isAgentSwarmsEnabled()) {
38272
+ return {
38273
+ result: false,
38274
+ message: "Agent teammate parameters (name/team_name/mode) require the agent-teams gate (ATLAS_EXPERIMENTAL_AGENT_TEAMS=1 or --agent-teams)",
38275
+ errorCode: 9
38276
+ };
38277
+ }
38278
+ if (i.team_name && !i.name) {
38279
+ return {
38280
+ result: false,
38281
+ message: "team_name requires name (the teammate identity) for team-based delegation",
38282
+ errorCode: 9
38283
+ };
38284
+ }
38285
+ return { result: true };
38286
+ },
38000
38287
  toAutoClassifierInput: (input) => input,
38001
38288
  description: async () => getPrompt(getBuiltInAgents()),
38002
38289
  userFacingName: (input) => {
@@ -38032,6 +38319,30 @@ var init_AgentTool = __esm(() => {
38032
38319
  async call(args, context) {
38033
38320
  const input = args ?? {};
38034
38321
  const ctx = context ?? {};
38322
+ if (input.name || input.team_name) {
38323
+ if (!isAgentSwarmsEnabled()) {
38324
+ throw new Error("Agent teammate spawn requires the agent-teams gate (ATLAS_EXPERIMENTAL_AGENT_TEAMS=1 or --agent-teams)");
38325
+ }
38326
+ const teamName = input.team_name;
38327
+ if (!teamName) {
38328
+ throw new Error("team_name is required when spawning a teammate (name alone is ambiguous)");
38329
+ }
38330
+ const spawnResult = await spawnTeammateFromRoster({
38331
+ name: input.name ?? "",
38332
+ teamName,
38333
+ prompt: input.prompt,
38334
+ model: input.model
38335
+ });
38336
+ return {
38337
+ data: {
38338
+ status: "teammate_spawned",
38339
+ agentId: spawnResult.agentId,
38340
+ ...spawnResult.taskId ? { taskId: spawnResult.taskId } : {},
38341
+ name: input.name,
38342
+ team_name: teamName
38343
+ }
38344
+ };
38345
+ }
38035
38346
  const parentRole = ctx.parentRole ?? "small";
38036
38347
  const modelProvider = ctx.modelProvider ?? getModelProvider();
38037
38348
  const agentDefinition = resolveAgentDefinition(input.subagent_type, getBuiltInAgents());
@@ -43588,9 +43899,9 @@ function createSubcommandPrefixExtractor(getPrefix, splitCommand) {
43588
43899
  }
43589
43900
 
43590
43901
  // src/engine/tools/bash/heredoc.ts
43591
- import { randomBytes } from "crypto";
43902
+ import { randomBytes as randomBytes2 } from "crypto";
43592
43903
  function generatePlaceholderSalt() {
43593
- return randomBytes(8).toString("hex");
43904
+ return randomBytes2(8).toString("hex");
43594
43905
  }
43595
43906
  function extractHeredocs(command, options) {
43596
43907
  const heredocs = new Map;
@@ -44380,9 +44691,9 @@ var init_shellQuote = __esm(() => {
44380
44691
  });
44381
44692
 
44382
44693
  // src/engine/tools/bash/commands.ts
44383
- import { randomBytes as randomBytes2 } from "crypto";
44694
+ import { randomBytes as randomBytes3 } from "crypto";
44384
44695
  function generatePlaceholders() {
44385
- const salt = randomBytes2(8).toString("hex");
44696
+ const salt = randomBytes3(8).toString("hex");
44386
44697
  return {
44387
44698
  SINGLE_QUOTE: `__SINGLE_QUOTE_${salt}__`,
44388
44699
  DOUBLE_QUOTE: `__DOUBLE_QUOTE_${salt}__`,
@@ -50771,13 +51082,13 @@ function getExecutorSandboxPort() {
50771
51082
  var activePort3 = null;
50772
51083
 
50773
51084
  // src/executor/shell/ShellCommand.ts
50774
- import { randomBytes as randomBytes3 } from "crypto";
51085
+ import { randomBytes as randomBytes4 } from "crypto";
50775
51086
  import { stat as stat5 } from "fs/promises";
50776
51087
  function generateLocalTaskId() {
50777
- const bytes = randomBytes3(8);
51088
+ const bytes = randomBytes4(8);
50778
51089
  let id = "b";
50779
51090
  for (let i = 0;i < 8; i++) {
50780
- id += TASK_ID_ALPHABET[bytes[i] % TASK_ID_ALPHABET.length];
51091
+ id += TASK_ID_ALPHABET2[bytes[i] % TASK_ID_ALPHABET2.length];
50781
51092
  }
50782
51093
  return id;
50783
51094
  }
@@ -51043,7 +51354,7 @@ function createFailedCommand(preSpawnError) {
51043
51354
  cleanup() {}
51044
51355
  };
51045
51356
  }
51046
- var SIGKILL = 137, SIGTERM = 143, SIZE_WATCHDOG_INTERVAL_MS = 5000, TASK_ID_ALPHABET = "0123456789abcdefghijklmnopqrstuvwxyz";
51357
+ var SIGKILL = 137, SIGTERM = 143, SIZE_WATCHDOG_INTERVAL_MS = 5000, TASK_ID_ALPHABET2 = "0123456789abcdefghijklmnopqrstuvwxyz";
51047
51358
  var init_ShellCommand = __esm(() => {
51048
51359
  init_shared();
51049
51360
  });
@@ -53872,9 +54183,9 @@ Remember: DO NOT write or edit any files yet. This is a read-only exploration an
53872
54183
  });
53873
54184
 
53874
54185
  // src/engine/tools/plan/planWords.ts
53875
- import { randomBytes as randomBytes4 } from "crypto";
54186
+ import { randomBytes as randomBytes5 } from "crypto";
53876
54187
  function randomInt(max) {
53877
- const bytes = randomBytes4(4);
54188
+ const bytes = randomBytes5(4);
53878
54189
  const value = bytes.readUInt32BE(0);
53879
54190
  return value % max;
53880
54191
  }
@@ -70157,15 +70468,21 @@ function parseAddress(to) {
70157
70468
  return { scheme: "uds", target: to };
70158
70469
  return { scheme: "other", target: to };
70159
70470
  }
70160
- // src/swarm/teammateContext.ts
70161
- import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
70162
- function runWithTeammateContext2(context, fn) {
70163
- return teammateContextStorage2.run(context, fn);
70471
+
70472
+ // src/swarm/agentId.ts
70473
+ function formatAgentId2(agentName, teamName) {
70474
+ return `${agentName}@${teamName}`;
70475
+ }
70476
+ function parseAgentId2(agentId) {
70477
+ const atIndex = agentId.indexOf("@");
70478
+ if (atIndex === -1) {
70479
+ return null;
70480
+ }
70481
+ return {
70482
+ agentName: agentId.slice(0, atIndex),
70483
+ teamName: agentId.slice(atIndex + 1)
70484
+ };
70164
70485
  }
70165
- var teammateContextStorage2;
70166
- var init_teammateContext2 = __esm(() => {
70167
- teammateContextStorage2 = new AsyncLocalStorage3;
70168
- });
70169
70486
 
70170
70487
  // src/swarm/standaloneAgent.ts
70171
70488
  var init_standaloneAgent = __esm(() => {
@@ -70260,6 +70577,10 @@ var init_types5 = __esm(() => {
70260
70577
  });
70261
70578
 
70262
70579
  // src/swarm/cleanupRegistry.ts
70580
+ function registerCleanup(cleanupFn) {
70581
+ cleanupFunctions.add(cleanupFn);
70582
+ return () => cleanupFunctions.delete(cleanupFn);
70583
+ }
70263
70584
  var cleanupFunctions;
70264
70585
  var init_cleanupRegistry = __esm(() => {
70265
70586
  cleanupFunctions = new Set;
@@ -70323,11 +70644,30 @@ async function readTeamFileAsync(teamName) {
70323
70644
  return null;
70324
70645
  }
70325
70646
  }
70647
+ function writeTeamFile(teamName, teamFile) {
70648
+ const teamDir = getTeamDir(teamName);
70649
+ mkdirSync3(teamDir, { recursive: true });
70650
+ writeFileSync2(getTeamFilePath(teamName), jsonStringify(teamFile, 2));
70651
+ }
70326
70652
  async function writeTeamFileAsync(teamName, teamFile) {
70327
70653
  const teamDir = getTeamDir(teamName);
70328
70654
  await mkdir5(teamDir, { recursive: true });
70329
70655
  await writeFile4(getTeamFilePath(teamName), jsonStringify(teamFile, 2));
70330
70656
  }
70657
+ function removeMemberByAgentId(teamName, agentId) {
70658
+ const teamFile = readTeamFile(teamName);
70659
+ if (!teamFile) {
70660
+ return false;
70661
+ }
70662
+ const memberIndex = teamFile.members.findIndex((m) => m.agentId === agentId);
70663
+ if (memberIndex === -1) {
70664
+ return false;
70665
+ }
70666
+ teamFile.members.splice(memberIndex, 1);
70667
+ writeTeamFile(teamName, teamFile);
70668
+ logForDebugging(`[TeammateTool] Removed member ${agentId} from team ${teamName}`);
70669
+ return true;
70670
+ }
70331
70671
  async function destroyWorktree(worktreePath) {
70332
70672
  const gitFilePath = join25(worktreePath, ".git");
70333
70673
  let mainRepoPath = null;
@@ -70424,17 +70764,152 @@ var init_teamMemoryOps = __esm(() => {
70424
70764
  });
70425
70765
 
70426
70766
  // src/swarm/spawnInProcess.ts
70767
+ async function spawnInProcessTeammate(config, context) {
70768
+ const { name, teamName, prompt, color, planModeRequired, model } = config;
70769
+ const { setAppState } = context;
70770
+ const agentId = formatAgentId2(name, teamName);
70771
+ const taskId = generateTaskId("in_process_teammate");
70772
+ logForDebugging(`[spawnInProcessTeammate] Spawning ${agentId} (taskId: ${taskId})`);
70773
+ try {
70774
+ const abortController = createAbortController();
70775
+ logForDebugging(`[probe-R1][spawn] agent=${agentId} taskId=${taskId} controller=${probeStampAbortController(abortController)}`);
70776
+ const parentSessionId = getSessionId();
70777
+ const identity = {
70778
+ agentId,
70779
+ agentName: name,
70780
+ teamName,
70781
+ color,
70782
+ planModeRequired,
70783
+ parentSessionId
70784
+ };
70785
+ const teammateContext = createTeammateContext({
70786
+ agentId,
70787
+ agentName: name,
70788
+ teamName,
70789
+ color,
70790
+ planModeRequired,
70791
+ parentSessionId,
70792
+ abortController
70793
+ });
70794
+ const description = `${name}: ${prompt.substring(0, 50)}${prompt.length > 50 ? "..." : ""}`;
70795
+ const taskState = {
70796
+ ...createTaskStateBase(taskId, "in_process_teammate", description, context.toolUseId),
70797
+ type: "in_process_teammate",
70798
+ status: "running",
70799
+ identity,
70800
+ prompt,
70801
+ model,
70802
+ abortController,
70803
+ awaitingPlanApproval: false,
70804
+ permissionMode: planModeRequired ? "plan" : "default",
70805
+ isIdle: false,
70806
+ shutdownRequested: false,
70807
+ lastReportedToolCount: 0,
70808
+ lastReportedTokenCount: 0,
70809
+ pendingUserMessages: [],
70810
+ messages: []
70811
+ };
70812
+ logForDebugging(`[probe-R6][spawn-record] agent=${agentId} taskId=${taskId} record=${probeStampTaskRecord(taskState)}`);
70813
+ const unregisterCleanup = registerCleanup(async () => {
70814
+ logForDebugging(`[spawnInProcessTeammate] Cleanup called for ${agentId}`);
70815
+ abortController.abort();
70816
+ });
70817
+ taskState.unregisterCleanup = unregisterCleanup;
70818
+ registerTask(taskState, setAppState);
70819
+ logForDebugging(`[spawnInProcessTeammate] Registered ${agentId} in AppState`);
70820
+ return {
70821
+ success: true,
70822
+ agentId,
70823
+ taskId,
70824
+ abortController,
70825
+ teammateContext
70826
+ };
70827
+ } catch (error) {
70828
+ const errorMessage = error instanceof Error ? error.message : "Unknown error during spawn";
70829
+ logForDebugging(`[spawnInProcessTeammate] Failed to spawn ${agentId}: ${errorMessage}`);
70830
+ return {
70831
+ success: false,
70832
+ agentId,
70833
+ error: errorMessage
70834
+ };
70835
+ }
70836
+ }
70837
+ function killInProcessTeammate(taskId, setAppState) {
70838
+ let killed = false;
70839
+ let teamName = null;
70840
+ let agentId = null;
70841
+ let toolUseId;
70842
+ let description;
70843
+ setAppState((prev) => {
70844
+ const task = prev.tasks[taskId];
70845
+ if (!task || !isInProcessTeammateTask(task)) {
70846
+ return prev;
70847
+ }
70848
+ const teammateTask = task;
70849
+ if (teammateTask.status !== "running") {
70850
+ return prev;
70851
+ }
70852
+ teamName = teammateTask.identity.teamName;
70853
+ agentId = teammateTask.identity.agentId;
70854
+ toolUseId = teammateTask.toolUseId;
70855
+ description = teammateTask.description;
70856
+ teammateTask.abortController?.abort();
70857
+ teammateTask.unregisterCleanup?.();
70858
+ killed = true;
70859
+ teammateTask.onIdleCallbacks?.forEach((cb) => cb());
70860
+ return {
70861
+ ...prev,
70862
+ tasks: {
70863
+ ...prev.tasks,
70864
+ [taskId]: {
70865
+ ...teammateTask,
70866
+ status: "killed",
70867
+ notified: true,
70868
+ endTime: Date.now(),
70869
+ onIdleCallbacks: [],
70870
+ messages: teammateTask.messages?.length ? [teammateTask.messages[teammateTask.messages.length - 1]] : undefined,
70871
+ pendingUserMessages: [],
70872
+ abortController: undefined,
70873
+ unregisterCleanup: undefined
70874
+ }
70875
+ }
70876
+ };
70877
+ });
70878
+ if (teamName && agentId) {
70879
+ removeMemberByAgentId(teamName, agentId);
70880
+ }
70881
+ if (killed) {
70882
+ evictTaskOutput(taskId);
70883
+ emitTaskTerminatedSdk(taskId, "stopped", {
70884
+ toolUseId,
70885
+ summary: description
70886
+ });
70887
+ setTimeout(evictTerminalTask.bind(null, taskId, setAppState), STOPPED_DISPLAY_MS);
70888
+ }
70889
+ return killed;
70890
+ }
70427
70891
  var init_spawnInProcess = __esm(() => {
70428
70892
  init_bootstrap();
70429
70893
  init_task2();
70430
70894
  init_engine();
70431
70895
  init_shared();
70432
- init_teammateContext2();
70896
+ init_shared();
70433
70897
  init_cleanupRegistry();
70434
70898
  init_teamHelpers();
70435
70899
  });
70436
70900
 
70437
70901
  // src/swarm/inProcessTeammateTask.ts
70902
+ function requestTeammateShutdown(taskId, setAppState) {
70903
+ updateTaskState(taskId, setAppState, (task) => {
70904
+ if (task.status !== "running" || task.shutdownRequested) {
70905
+ return task;
70906
+ }
70907
+ return {
70908
+ ...task,
70909
+ shutdownRequested: true
70910
+ };
70911
+ });
70912
+ }
70438
70913
  function appendTeammateMessage(taskId, message, setAppState) {
70439
70914
  updateTaskState(taskId, setAppState, (task) => {
70440
70915
  if (task.status !== "running") {
@@ -70446,6 +70921,83 @@ function appendTeammateMessage(taskId, message, setAppState) {
70446
70921
  };
70447
70922
  });
70448
70923
  }
70924
+ function findTeammateTaskByAgentId(agentId, tasks) {
70925
+ let fallback;
70926
+ for (const task of Object.values(tasks)) {
70927
+ if (isInProcessTeammateTask(task) && task.identity.agentId === agentId) {
70928
+ if (task.status === "running") {
70929
+ return task;
70930
+ }
70931
+ if (!fallback) {
70932
+ fallback = task;
70933
+ }
70934
+ }
70935
+ }
70936
+ return fallback;
70937
+ }
70938
+ function getAllInProcessTeammateTasks(tasks) {
70939
+ return Object.values(tasks).filter(isInProcessTeammateTask);
70940
+ }
70941
+ async function gracefulShutdownInProcessTeammates(deps) {
70942
+ const running = getAllInProcessTeammateTasks(deps.getAppState().tasks ?? {}).filter((t) => t.status === "running");
70943
+ if (running.length === 0) {
70944
+ return { requested: 0, drained: 0, forced: 0, hardTerminated: 0 };
70945
+ }
70946
+ const toRequest = running.filter((t) => !t.shutdownRequested);
70947
+ const requestIdBase = Date.now();
70948
+ for (const teammate of toRequest) {
70949
+ const shutdownRequest = createShutdownRequestMessage({
70950
+ requestId: `shutdown-${teammate.identity.agentId}-session-end-${requestIdBase}`,
70951
+ from: TEAM_LEAD_NAME2,
70952
+ reason: "session end (headless terminal state)"
70953
+ });
70954
+ await writeToMailbox(teammate.identity.agentName, {
70955
+ from: TEAM_LEAD_NAME2,
70956
+ text: jsonStringify(shutdownRequest),
70957
+ timestamp: new Date().toISOString()
70958
+ }, teammate.identity.teamName);
70959
+ requestTeammateShutdown(teammate.id, deps.setAppState);
70960
+ }
70961
+ const freshTasks = () => getAllInProcessTeammateTasks(deps.getAppState().tasks ?? {});
70962
+ const countStillRunning = () => freshTasks().filter((t) => t.status === "running" && running.some((prev) => prev.id === t.id)).length;
70963
+ const waitForDrain = async (timeoutMs) => {
70964
+ const deadline = Date.now() + timeoutMs;
70965
+ for (;; ) {
70966
+ if (countStillRunning() === 0 || Date.now() >= deadline)
70967
+ return;
70968
+ await new Promise((resolve) => setTimeout(resolve, TEAMMATE_GRACEFUL_SHUTDOWN_POLL_MS));
70969
+ }
70970
+ };
70971
+ await waitForDrain(deps.timeoutMs ?? TEAMMATE_GRACEFUL_SHUTDOWN_TIMEOUT_MS);
70972
+ let drained = running.length - countStillRunning();
70973
+ if (drained === running.length) {
70974
+ return { requested: toRequest.length, drained, forced: 0, hardTerminated: 0 };
70975
+ }
70976
+ let forced = 0;
70977
+ for (const prev of running) {
70978
+ const now = freshTasks().find((t) => t.id === prev.id);
70979
+ if (now?.status === "running" && now.abortController) {
70980
+ now.abortController.abort();
70981
+ forced++;
70982
+ }
70983
+ }
70984
+ if (forced > 0) {
70985
+ await waitForDrain(deps.forcedTimeoutMs ?? TEAMMATE_FORCED_SHUTDOWN_TIMEOUT_MS);
70986
+ drained = running.length - countStillRunning();
70987
+ if (drained === running.length) {
70988
+ return { requested: toRequest.length, drained, forced, hardTerminated: 0 };
70989
+ }
70990
+ }
70991
+ let hardTerminated = 0;
70992
+ for (const prev of running) {
70993
+ const now = freshTasks().find((t) => t.id === prev.id);
70994
+ if (now?.status === "running" && killInProcessTeammate(now.id, deps.setAppState)) {
70995
+ hardTerminated++;
70996
+ }
70997
+ }
70998
+ return { requested: toRequest.length, drained, forced, hardTerminated };
70999
+ }
71000
+ var TEAMMATE_GRACEFUL_SHUTDOWN_TIMEOUT_MS = 15000, TEAMMATE_FORCED_SHUTDOWN_TIMEOUT_MS = 5000, TEAMMATE_GRACEFUL_SHUTDOWN_POLL_MS = 250;
70449
71001
  var init_inProcessTeammateTask = __esm(() => {
70450
71002
  init_task2();
70451
71003
  init_task2();
@@ -70559,9 +71111,159 @@ var init_it2Setup = __esm(() => {
70559
71111
  function setStartInProcessTeammate(fn) {
70560
71112
  startFn = fn;
70561
71113
  }
71114
+ function requireStartInProcessTeammate() {
71115
+ if (!startFn) {
71116
+ throw new Error("StartInProcessTeammate not wired — call setStartInProcessTeammate at composition root first (swarm inProcessRunner seam ②)");
71117
+ }
71118
+ return startFn;
71119
+ }
70562
71120
  var startFn = null;
70563
71121
 
70564
71122
  // src/swarm/backends/InProcessBackend.ts
71123
+ class InProcessBackend {
71124
+ type = "in-process";
71125
+ context = null;
71126
+ setContext(context) {
71127
+ this.context = context;
71128
+ }
71129
+ async isAvailable() {
71130
+ return true;
71131
+ }
71132
+ async spawn(config) {
71133
+ if (!this.context) {
71134
+ logForDebugging(`[InProcessBackend] spawn() called without context for ${config.name}`);
71135
+ return {
71136
+ success: false,
71137
+ agentId: `${config.name}@${config.teamName}`,
71138
+ error: "InProcessBackend not initialized. Call setContext() before spawn()."
71139
+ };
71140
+ }
71141
+ logForDebugging(`[InProcessBackend] spawn() called for ${config.name}`);
71142
+ const result = await spawnInProcessTeammate({
71143
+ name: config.name,
71144
+ teamName: config.teamName,
71145
+ prompt: config.prompt,
71146
+ color: config.color,
71147
+ planModeRequired: config.planModeRequired ?? false
71148
+ }, this.context);
71149
+ if (result.success && result.taskId && result.teammateContext && result.abortController) {
71150
+ requireStartInProcessTeammate()({
71151
+ identity: {
71152
+ agentId: result.agentId,
71153
+ agentName: config.name,
71154
+ teamName: config.teamName,
71155
+ color: config.color,
71156
+ planModeRequired: config.planModeRequired ?? false,
71157
+ parentSessionId: result.teammateContext.parentSessionId
71158
+ },
71159
+ taskId: result.taskId,
71160
+ prompt: config.prompt,
71161
+ teammateContext: result.teammateContext,
71162
+ toolUseContext: { ...this.context, messages: [] },
71163
+ abortController: result.abortController,
71164
+ model: config.model,
71165
+ systemPrompt: config.systemPrompt,
71166
+ systemPromptMode: config.systemPromptMode,
71167
+ allowedTools: config.permissions,
71168
+ allowPermissionPrompts: config.allowPermissionPrompts,
71169
+ ...config.termination ? { termination: config.termination } : {}
71170
+ });
71171
+ logForDebugging(`[InProcessBackend] Started agent execution for ${result.agentId}`);
71172
+ }
71173
+ return {
71174
+ success: result.success,
71175
+ agentId: result.agentId,
71176
+ taskId: result.taskId,
71177
+ abortController: result.abortController,
71178
+ error: result.error
71179
+ };
71180
+ }
71181
+ async sendMessage(agentId, message) {
71182
+ logForDebugging(`[InProcessBackend] sendMessage() to ${agentId}: ${message.text.substring(0, 50)}...`);
71183
+ const parsed = parseAgentId2(agentId);
71184
+ if (!parsed) {
71185
+ logForDebugging(`[InProcessBackend] Invalid agentId format: ${agentId}`);
71186
+ throw new Error(`Invalid agentId format: ${agentId}. Expected format: agentName@teamName`);
71187
+ }
71188
+ const { agentName, teamName } = parsed;
71189
+ await writeToMailbox(agentName, {
71190
+ text: message.text,
71191
+ from: message.from,
71192
+ color: message.color,
71193
+ timestamp: message.timestamp ?? new Date().toISOString()
71194
+ }, teamName);
71195
+ logForDebugging(`[InProcessBackend] sendMessage() completed for ${agentId}`);
71196
+ }
71197
+ async terminate(agentId, reason) {
71198
+ logForDebugging(`[InProcessBackend] terminate() called for ${agentId}: ${reason}`);
71199
+ if (!this.context) {
71200
+ logForDebugging(`[InProcessBackend] terminate() failed: no context set for ${agentId}`);
71201
+ return false;
71202
+ }
71203
+ const state = this.context.getAppState();
71204
+ const task = findTeammateTaskByAgentId(agentId, state.tasks);
71205
+ if (!task) {
71206
+ logForDebugging(`[InProcessBackend] terminate() failed: task not found for ${agentId}`);
71207
+ return false;
71208
+ }
71209
+ if (task.shutdownRequested) {
71210
+ logForDebugging(`[InProcessBackend] terminate(): shutdown already requested for ${agentId}`);
71211
+ return true;
71212
+ }
71213
+ const requestId = `shutdown-${agentId}-${Date.now()}`;
71214
+ const shutdownRequest = createShutdownRequestMessage({
71215
+ requestId,
71216
+ from: "team-lead",
71217
+ reason
71218
+ });
71219
+ const teammateAgentName = task.identity.agentName;
71220
+ await writeToMailbox(teammateAgentName, {
71221
+ from: "team-lead",
71222
+ text: jsonStringify(shutdownRequest),
71223
+ timestamp: new Date().toISOString()
71224
+ }, task.identity.teamName);
71225
+ requestTeammateShutdown(task.id, this.context.setAppState);
71226
+ logForDebugging(`[InProcessBackend] terminate() sent shutdown request to ${agentId}`);
71227
+ return true;
71228
+ }
71229
+ async kill(agentId) {
71230
+ logForDebugging(`[InProcessBackend] kill() called for ${agentId}`);
71231
+ if (!this.context) {
71232
+ logForDebugging(`[InProcessBackend] kill() failed: no context set for ${agentId}`);
71233
+ return false;
71234
+ }
71235
+ const state = this.context.getAppState();
71236
+ const task = findTeammateTaskByAgentId(agentId, state.tasks);
71237
+ if (!task) {
71238
+ logForDebugging(`[InProcessBackend] kill() failed: task not found for ${agentId}`);
71239
+ return false;
71240
+ }
71241
+ const killed = killInProcessTeammate(task.id, this.context.setAppState);
71242
+ logForDebugging(`[InProcessBackend] kill() ${killed ? "succeeded" : "failed"} for ${agentId}`);
71243
+ return killed;
71244
+ }
71245
+ async isActive(agentId) {
71246
+ logForDebugging(`[InProcessBackend] isActive() called for ${agentId}`);
71247
+ if (!this.context) {
71248
+ logForDebugging(`[InProcessBackend] isActive() failed: no context set for ${agentId}`);
71249
+ return false;
71250
+ }
71251
+ const state = this.context.getAppState();
71252
+ const task = findTeammateTaskByAgentId(agentId, state.tasks);
71253
+ if (!task) {
71254
+ logForDebugging(`[InProcessBackend] isActive(): task not found for ${agentId}`);
71255
+ return false;
71256
+ }
71257
+ const isRunning = task.status === "running";
71258
+ const isAborted = task.abortController?.signal.aborted ?? true;
71259
+ const active = isRunning && !isAborted;
71260
+ logForDebugging(`[InProcessBackend] isActive() for ${agentId}: ${active} (running=${isRunning}, aborted=${isAborted})`);
71261
+ return active;
71262
+ }
71263
+ }
71264
+ function createInProcessBackend() {
71265
+ return new InProcessBackend;
71266
+ }
70565
71267
  var init_InProcessBackend = __esm(() => {
70566
71268
  init_engine();
70567
71269
  init_shared();
@@ -71317,7 +72019,13 @@ function getBackendByType(type) {
71317
72019
  return createITermBackend();
71318
72020
  }
71319
72021
  }
71320
- var cachedBackend = null, cachedDetectionResult = null, backendsRegistered = false, TmuxBackendClass = null, ITermBackendClass = null;
72022
+ function getInProcessBackend() {
72023
+ if (!cachedInProcessBackend) {
72024
+ cachedInProcessBackend = createInProcessBackend();
72025
+ }
72026
+ return cachedInProcessBackend;
72027
+ }
72028
+ var cachedBackend = null, cachedDetectionResult = null, backendsRegistered = false, cachedInProcessBackend = null, TmuxBackendClass = null, ITermBackendClass = null;
71321
72029
  var init_registry = __esm(() => {
71322
72030
  init_bootstrap();
71323
72031
  init_shared();
@@ -71454,6 +72162,110 @@ var init_permissionSync = __esm(() => {
71454
72162
  });
71455
72163
  });
71456
72164
 
72165
+ // src/swarm/teammateTermination.ts
72166
+ function resolveTerminationSpec(spec) {
72167
+ return spec ?? DEFAULT_TEAMMATE_TERMINATION_SPEC;
72168
+ }
72169
+ function validateTerminationSpec(spec) {
72170
+ if (spec.op !== "or" && spec.op !== "and") {
72171
+ throw new Error(`teammate-termination config: op must be "or" or "and" (got ${String(spec.op)})`);
72172
+ }
72173
+ if (!Array.isArray(spec.conditions) || spec.conditions.length === 0) {
72174
+ throw new Error("teammate-termination config: conditions must be a non-empty array");
72175
+ }
72176
+ for (const c of spec.conditions) {
72177
+ switch (c.kind) {
72178
+ case "max-turns":
72179
+ if (!Number.isInteger(c.maxTurns) || c.maxTurns < 1) {
72180
+ throw new Error(`teammate-termination config: maxTurns must be an integer >= 1 (got ${String(c.maxTurns)})`);
72181
+ }
72182
+ break;
72183
+ case "text-confirm":
72184
+ if (!Array.isArray(c.phrases) || c.phrases.length === 0 || c.phrases.some((p) => typeof p !== "string" || p.length === 0)) {
72185
+ throw new Error("teammate-termination config: text-confirm phrases must be a non-empty array of non-empty strings");
72186
+ }
72187
+ break;
72188
+ case "stall":
72189
+ if (!Number.isInteger(c.maxConsecutive) || c.maxConsecutive < 2) {
72190
+ throw new Error(`teammate-termination config: stall maxConsecutive must be an integer >= 2 (got ${String(c.maxConsecutive)})`);
72191
+ }
72192
+ break;
72193
+ case "external-kill":
72194
+ break;
72195
+ default:
72196
+ throw new Error(`teammate-termination config: unknown condition kind (got ${JSON.stringify(c)})`);
72197
+ }
72198
+ }
72199
+ }
72200
+ function createInitialTerminationLoopState() {
72201
+ return { turns: 0, stallConsecutive: 0 };
72202
+ }
72203
+ function advanceTerminationLoopState(state, outcome) {
72204
+ const finalText = outcome.finalText;
72205
+ const stalled = typeof finalText === "string" && finalText.length > 0 && finalText === state.lastFinalText;
72206
+ return {
72207
+ turns: state.turns + 1,
72208
+ lastFinalText: finalText,
72209
+ stallConsecutive: stalled ? state.stallConsecutive + 1 : 0
72210
+ };
72211
+ }
72212
+ function evaluateCondition(c, state) {
72213
+ switch (c.kind) {
72214
+ case "max-turns":
72215
+ return state.turns >= c.maxTurns ? { type: "max-turns", turns: state.turns } : undefined;
72216
+ case "text-confirm": {
72217
+ const text = (state.lastFinalText ?? "").toLowerCase();
72218
+ const matched = c.phrases.find((p) => text.includes(p.toLowerCase()));
72219
+ return matched !== undefined ? { type: "text-confirm", matched } : undefined;
72220
+ }
72221
+ case "external-kill":
72222
+ return state.aborted ? { type: "external-kill" } : undefined;
72223
+ case "stall":
72224
+ return state.stallConsecutive >= c.maxConsecutive ? { type: "stall", consecutive: state.stallConsecutive } : undefined;
72225
+ }
72226
+ }
72227
+ function evaluateTerminationSpec(spec, state) {
72228
+ const reasons = spec.conditions.map((c) => evaluateCondition(c, state)).filter((r) => r !== undefined);
72229
+ if (spec.op === "or") {
72230
+ if (reasons.length === 0)
72231
+ return { terminate: false };
72232
+ return {
72233
+ terminate: true,
72234
+ reason: spec.conditions.length === 1 ? reasons[0] : { type: "or", satisfied: reasons }
72235
+ };
72236
+ }
72237
+ if (reasons.length !== spec.conditions.length)
72238
+ return { terminate: false };
72239
+ return {
72240
+ terminate: true,
72241
+ reason: spec.conditions.length === 1 ? reasons[0] : { type: "and", satisfied: reasons }
72242
+ };
72243
+ }
72244
+ function extractFinalAssistantText(messages) {
72245
+ for (let i = messages.length - 1;i >= 0; i--) {
72246
+ const m = messages[i];
72247
+ if (m?.role !== "assistant")
72248
+ continue;
72249
+ const content = m.content;
72250
+ if (typeof content === "string") {
72251
+ return content.length > 0 ? content : undefined;
72252
+ }
72253
+ if (Array.isArray(content)) {
72254
+ const text = content.map((b) => b && typeof b === "object" && b.type === "text" ? b.text : "").filter((t) => typeof t === "string").join("").trim();
72255
+ return text.length > 0 ? text : undefined;
72256
+ }
72257
+ return;
72258
+ }
72259
+ return;
72260
+ }
72261
+ var DEFAULT_TEAMMATE_MAX_TURNS = 200, DEFAULT_TEAMMATE_TERMINATION_SPEC;
72262
+ var init_teammateTermination = __esm(() => {
72263
+ DEFAULT_TEAMMATE_TERMINATION_SPEC = {
72264
+ op: "or",
72265
+ conditions: [{ kind: "max-turns", maxTurns: DEFAULT_TEAMMATE_MAX_TURNS }]
72266
+ };
72267
+ });
72268
+
71457
72269
  // src/swarm/inProcessRunner.ts
71458
72270
  import { randomUUID as randomUUID9 } from "node:crypto";
71459
72271
  function buildTeammateToolPermissionContext(narrow) {
@@ -71804,7 +72616,7 @@ async function tryClaimNextTask(taskListId, agentName) {
71804
72616
  }
71805
72617
  async function waitForNextPromptOrShutdown(identity, abortController, taskId, getAppState, setAppState, taskListId) {
71806
72618
  const POLL_INTERVAL_MS = 500;
71807
- logForDebugging(`[inProcessRunner] ${identity.agentName} starting poll loop (abort=${abortController.signal.aborted})`);
72619
+ logForDebugging(`[probe-R2][anchor3-poll-start] [inProcessRunner] ${identity.agentName} starting poll loop (abort=${abortController.signal.aborted}, controller=${probeReadAbortControllerId(abortController)})`);
71808
72620
  let pollCount = 0;
71809
72621
  while (!abortController.signal.aborted) {
71810
72622
  const appState = getAppState();
@@ -71923,6 +72735,7 @@ async function runInProcessTeammate(config) {
71923
72735
  const modelProvider = getModelProvider();
71924
72736
  const contextWindow = getProviderContextWindow(getRoleModel(role) ?? "") ?? HARD_DEFAULT_CONTEXT_WINDOW;
71925
72737
  logForDebugging(`[inProcessRunner] Starting agent loop for ${identity.agentId}`);
72738
+ logForDebugging(`[probe-R1][runner] agent=${identity.agentId} taskId=${taskId} controller=${probeReadAbortControllerId(abortController)}`);
71926
72739
  const teammateSystemPrompt = await buildTeammateSystemPrompt({
71927
72740
  systemPrompt,
71928
72741
  systemPromptMode,
@@ -71950,6 +72763,10 @@ async function runInProcessTeammate(config) {
71950
72763
  turnCounter: 0,
71951
72764
  turnId: "turn-0"
71952
72765
  };
72766
+ let termState = createInitialTerminationLoopState();
72767
+ let terminationReason;
72768
+ const effectiveTermination = resolveTerminationSpec(config.termination);
72769
+ validateTerminationSpec(effectiveTermination);
71953
72770
  try {
71954
72771
  updateTaskState(taskId, setAppState, (task) => ({
71955
72772
  ...task,
@@ -71998,7 +72815,7 @@ async function runInProcessTeammate(config) {
71998
72815
  const forkContextMessages = contextMessages.length > 0 ? [...contextMessages] : undefined;
71999
72816
  allMessages.push(userMessage);
72000
72817
  let workWasAborted = false;
72001
- await runWithTeammateContext2(teammateContext, async () => {
72818
+ await runWithTeammateContext(teammateContext, async () => {
72002
72819
  updateTaskState(taskId, setAppState, (task) => ({ ...task, status: "running", isIdle: false }));
72003
72820
  const agentResult = await runAgent({
72004
72821
  agentDefinition: resolvedAgentDefinition,
@@ -72010,11 +72827,16 @@ async function runInProcessTeammate(config) {
72010
72827
  agentId: identity.agentId,
72011
72828
  signal: currentWorkAbortController.signal,
72012
72829
  forkContextMessages,
72013
- checkPermission: createInProcessPermissionGate(identity, currentWorkAbortController, tools, getAppState, buildTeammateTpc)
72830
+ checkPermission: createInProcessPermissionGate(identity, currentWorkAbortController, tools, getAppState, buildTeammateTpc),
72831
+ toolContext: { getAppState, setAppState }
72014
72832
  });
72833
+ logForDebugging(`[probe-R2][anchor1-runagent-returned] agent=${identity.agentId} lifecycleAborted=${abortController.signal.aborted}`);
72015
72834
  const prefixLen = 2 + (forkContextMessages?.length ?? 0);
72016
72835
  const newMessages = agentResult.messages.slice(prefixLen);
72017
72836
  allMessages.push(...newMessages);
72837
+ termState = advanceTerminationLoopState(termState, {
72838
+ finalText: extractFinalAssistantText(newMessages)
72839
+ });
72018
72840
  updateTaskState(taskId, setAppState, (task) => ({
72019
72841
  ...task,
72020
72842
  messages: allMessages.slice(-MAX_TEAMMATE_DISPLAY_MESSAGES)
@@ -72047,13 +72869,24 @@ async function runInProcessTeammate(config) {
72047
72869
  return { ...task, isIdle: true, onIdleCallbacks: [] };
72048
72870
  });
72049
72871
  if (!wasAlreadyIdle) {
72872
+ logForDebugging(`[probe-R2][anchor2-idle-in] agent=${identity.agentName} lifecycleAborted=${abortController.signal.aborted}`);
72050
72873
  await sendIdleNotification(identity.agentName, identity.color, identity.teamName, {
72051
72874
  idleReason: workWasAborted ? "interrupted" : "available",
72052
72875
  summary: getLastPeerDmSummary(allMessages)
72053
72876
  });
72877
+ logForDebugging(`[probe-R2][anchor2-idle-out] agent=${identity.agentName} lifecycleAborted=${abortController.signal.aborted}`);
72054
72878
  } else {
72055
72879
  logForDebugging(`[inProcessRunner] Skipping duplicate idle notification for ${identity.agentName}`);
72056
72880
  }
72881
+ const terminationVerdict = evaluateTerminationSpec(effectiveTermination, {
72882
+ ...termState,
72883
+ aborted: abortController.signal.aborted
72884
+ });
72885
+ if (terminationVerdict.terminate) {
72886
+ logForDebugging(`[inProcessRunner] ${identity.agentId} termination condition met (${JSON.stringify(terminationVerdict.reason)}) — graceful exit`);
72887
+ terminationReason = terminationVerdict.reason;
72888
+ shouldExit = true;
72889
+ }
72057
72890
  logForDebugging(`[inProcessRunner] ${identity.agentId} finished prompt, waiting for next`);
72058
72891
  const waitResult = await waitForNextPromptOrShutdown(identity, abortController, taskId, getAppState, setAppState, identity.parentSessionId);
72059
72892
  switch (waitResult.type) {
@@ -72079,26 +72912,37 @@ async function runInProcessTeammate(config) {
72079
72912
  }
72080
72913
  let alreadyTerminal = false;
72081
72914
  let toolUseId;
72915
+ logForDebugging(`[probe-R6][completed-in] agent=${identity.agentId} taskId=${taskId}`);
72082
72916
  updateTaskState(taskId, setAppState, (task) => {
72083
- if (task.status !== "running") {
72084
- alreadyTerminal = true;
72085
- return task;
72917
+ logForDebugging(`[probe-R6][completed-updater-enter] agent=${identity.agentId} status=${task.status} recordId=${probeReadTaskRecordId(task)}`);
72918
+ try {
72919
+ if (!isInProcessTeammateLive(task)) {
72920
+ logForDebugging(`[probe-R6][completed-updater-notlive] agent=${identity.agentId}`);
72921
+ alreadyTerminal = true;
72922
+ return task;
72923
+ }
72924
+ toolUseId = task.toolUseId;
72925
+ task.onIdleCallbacks?.forEach((cb) => cb());
72926
+ task.unregisterCleanup?.();
72927
+ const completed = {
72928
+ ...task,
72929
+ status: "completed",
72930
+ notified: true,
72931
+ endTime: Date.now(),
72932
+ messages: task.messages?.length ? [task.messages.at(-1)] : undefined,
72933
+ pendingUserMessages: [],
72934
+ abortController: undefined,
72935
+ unregisterCleanup: undefined,
72936
+ onIdleCallbacks: []
72937
+ };
72938
+ logForDebugging(`[probe-R6][completed-updater-apply] agent=${identity.agentId} recordId=${probeReadTaskRecordId(completed)}`);
72939
+ return completed;
72940
+ } catch (error) {
72941
+ logForDebugging(`[probe-R6][completed-updater-throw] agent=${identity.agentId} ${error instanceof Error ? error.stack ?? error.message : String(error)}`);
72942
+ throw error;
72086
72943
  }
72087
- toolUseId = task.toolUseId;
72088
- task.onIdleCallbacks?.forEach((cb) => cb());
72089
- task.unregisterCleanup?.();
72090
- return {
72091
- ...task,
72092
- status: "completed",
72093
- notified: true,
72094
- endTime: Date.now(),
72095
- messages: task.messages?.length ? [task.messages.at(-1)] : undefined,
72096
- pendingUserMessages: [],
72097
- abortController: undefined,
72098
- unregisterCleanup: undefined,
72099
- onIdleCallbacks: []
72100
- };
72101
72944
  });
72945
+ logForDebugging(`[probe-R6][completed-out] agent=${identity.agentId}`);
72102
72946
  evictTaskOutput(taskId);
72103
72947
  if (!alreadyTerminal) {
72104
72948
  emitTaskTerminatedSdk(taskId, "completed", {
@@ -72106,14 +72950,18 @@ async function runInProcessTeammate(config) {
72106
72950
  summary: identity.agentId
72107
72951
  });
72108
72952
  }
72109
- return { success: true, messages: allMessages };
72953
+ return {
72954
+ success: true,
72955
+ messages: allMessages,
72956
+ ...terminationReason ? { terminationReason } : {}
72957
+ };
72110
72958
  } catch (error) {
72111
72959
  const errorMessage = error instanceof Error ? error.message : "Unknown error";
72112
72960
  logForDebugging(`[inProcessRunner] Agent ${identity.agentId} failed: ${errorMessage}`);
72113
72961
  let alreadyTerminal = false;
72114
72962
  let toolUseId;
72115
72963
  updateTaskState(taskId, setAppState, (task) => {
72116
- if (task.status !== "running") {
72964
+ if (!isInProcessTeammateLive(task)) {
72117
72965
  alreadyTerminal = true;
72118
72966
  return task;
72119
72967
  }
@@ -72167,15 +73015,16 @@ var init_inProcessRunner = __esm(() => {
72167
73015
  init_task2();
72168
73016
  init_engine();
72169
73017
  init_permissions3();
72170
- init_teammateContext2();
73018
+ init_shared();
72171
73019
  init_inProcessTeammateTask();
72172
73020
  init_permissionPoller();
72173
73021
  init_permissionSync();
73022
+ init_teammateTermination();
72174
73023
  });
72175
73024
 
72176
73025
  // src/swarm/index.ts
72177
73026
  var init_swarm = __esm(() => {
72178
- init_teammateContext2();
73027
+ init_teammateContext();
72179
73028
  init_standaloneAgent();
72180
73029
  init_teammateModel();
72181
73030
  init_permissionPoller();
@@ -72202,6 +73051,7 @@ var init_swarm = __esm(() => {
72202
73051
  init_PaneBackendExecutor();
72203
73052
  init_wireBackends();
72204
73053
  init_inProcessRunner();
73054
+ init_teammateTermination();
72205
73055
  init_shared();
72206
73056
  init_permissionSync();
72207
73057
  });
@@ -72238,6 +73088,18 @@ var init_remote = __esm(() => {
72238
73088
  init_udsInboxEnabled();
72239
73089
  });
72240
73090
 
73091
+ // src/engine/session/sessionContextPort.ts
73092
+ function setSessionContextPort(port) {
73093
+ _sessionContextPort = port;
73094
+ }
73095
+ function getSessionContextPort() {
73096
+ return _sessionContextPort;
73097
+ }
73098
+ function resetSessionContextPort() {
73099
+ _sessionContextPort = null;
73100
+ }
73101
+ var _sessionContextPort = null;
73102
+
72241
73103
  // src/engine/tools/team/sendMessagePrompt.ts
72242
73104
  function buildPrompt(udsRow, udsSection) {
72243
73105
  return `
@@ -72265,7 +73127,9 @@ If you receive a JSON message with \`type: "shutdown_request"\` or \`type: "plan
72265
73127
  {"to": "researcher", "message": {"type": "plan_approval_response", "request_id": "...", "approve": false, "feedback": "add error handling"}}
72266
73128
  \`\`\`
72267
73129
 
72268
- Approving shutdown terminates your process. Rejecting plan sends the teammate back to revise. Don't originate \`shutdown_request\` unless asked. Don't send structured JSON status messages — use TaskUpdate.`.trim();
73130
+ Approving shutdown terminates your process. Rejecting plan sends the teammate back to revise. Don't originate \`shutdown_request\` unless asked. Don't send structured JSON status messages — use TaskUpdate.
73131
+
73132
+ Always send protocol responses as JSON **objects** in the \`message\` field, exactly as shown above — never stringify them into a string. (String-encoded JSON of the three protocol types is tolerated as a fallback, but the object form is authoritative.)`.trim();
72269
73133
  }
72270
73134
  function getSendMessagePrompt() {
72271
73135
  const on = isUdsInboxEnabled();
@@ -72291,12 +73155,34 @@ var init_sendMessagePrompt = __esm(() => {
72291
73155
  });
72292
73156
 
72293
73157
  // src/engine/tools/team/sendMessageTool.ts
73158
+ function tryParseStructuredMessage(text) {
73159
+ let parsed;
73160
+ try {
73161
+ parsed = JSON.parse(text);
73162
+ } catch {
73163
+ return;
73164
+ }
73165
+ if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
73166
+ return;
73167
+ }
73168
+ const type = parsed.type;
73169
+ if (type === "shutdown_request" || type === "shutdown_response" || type === "plan_approval_response") {
73170
+ return parsed;
73171
+ }
73172
+ return;
73173
+ }
72294
73174
  function setTeamFileLoader(loader) {
72295
73175
  teamFileLoader = loader;
72296
73176
  }
72297
73177
  function resetTeamFileLoader() {
72298
73178
  teamFileLoader = async () => null;
72299
73179
  }
73180
+ function resolveOutgoingTeamName(teamContext) {
73181
+ return getTeamName(teamContext) ?? peekTeamContext()?.teamName;
73182
+ }
73183
+ function unresolvedTeamMailboxError(recipient) {
73184
+ return new Error(`Cannot route message to "${recipient}": no team mailbox is resolvable ` + "(no teamContext in appState, no in-process teammate context, and no team " + "registered via TeamCreate). Create a team with TeamCreate first; the " + "message was NOT delivered.");
73185
+ }
72300
73186
  function truncatePreview(text, maxWidth) {
72301
73187
  if (text.length <= maxWidth)
72302
73188
  return text;
@@ -72304,7 +73190,9 @@ function truncatePreview(text, maxWidth) {
72304
73190
  }
72305
73191
  async function handleMessage(recipientName, content, summary, context) {
72306
73192
  const appState = context.getAppState();
72307
- const teamName = getTeamName(appState.teamContext);
73193
+ const teamName = resolveOutgoingTeamName(appState.teamContext);
73194
+ if (!teamName)
73195
+ throw unresolvedTeamMailboxError(recipientName);
72308
73196
  const senderName = getAgentName() || (isTeammate() ? "teammate" : TEAM_LEAD_NAME);
72309
73197
  const senderColor = getTeammateColor();
72310
73198
  await writeToMailbox(recipientName, {
@@ -72331,13 +73219,49 @@ async function handleMessage(recipientName, content, summary, context) {
72331
73219
  }
72332
73220
  async function handleBroadcast(content, summary, context) {
72333
73221
  const appState = context.getAppState();
72334
- const teamName = getTeamName(appState.teamContext);
73222
+ const teamName = resolveOutgoingTeamName(appState.teamContext);
72335
73223
  if (!teamName) {
72336
73224
  throw new Error("Not in a team context. Create a team with Teammate spawnTeam first, or set ATLAS_TEAM_NAME.");
72337
73225
  }
72338
- const teamFile = await teamFileLoader(teamName);
72339
- if (!teamFile) {
72340
- throw new Error(`Team "${teamName}" does not exist`);
73226
+ const memberNames = [];
73227
+ const seenNames = new Set;
73228
+ const pushMember = (raw) => {
73229
+ if (!raw)
73230
+ return;
73231
+ const key = raw.toLowerCase();
73232
+ if (!seenNames.has(key)) {
73233
+ seenNames.add(key);
73234
+ memberNames.push(raw);
73235
+ }
73236
+ };
73237
+ const servicesCtx = peekTeamContext();
73238
+ if (servicesCtx && servicesCtx.teamName === teamName) {
73239
+ for (const [agentId, m] of Object.entries(servicesCtx.teammates ?? {})) {
73240
+ pushMember(m.name || agentId);
73241
+ }
73242
+ for (const r of servicesCtx.roster ?? []) {
73243
+ pushMember(r.name);
73244
+ }
73245
+ } else if (appState.teamContext && appState.teamContext.teamName === teamName) {
73246
+ for (const [agentId, m] of Object.entries(appState.teamContext.teammates ?? {})) {
73247
+ pushMember(m.name || agentId);
73248
+ }
73249
+ }
73250
+ let teamFile = null;
73251
+ if (memberNames.length === 0) {
73252
+ teamFile = await teamFileLoader(teamName);
73253
+ if (!teamFile) {
73254
+ return {
73255
+ data: {
73256
+ success: true,
73257
+ message: "No teammates to broadcast to (team has no members yet)",
73258
+ recipients: []
73259
+ }
73260
+ };
73261
+ }
73262
+ for (const member of teamFile.members) {
73263
+ pushMember(member.name);
73264
+ }
72341
73265
  }
72342
73266
  const senderName = getAgentName() || (isTeammate() ? "teammate" : TEAM_LEAD_NAME);
72343
73267
  if (!senderName) {
@@ -72345,11 +73269,11 @@ async function handleBroadcast(content, summary, context) {
72345
73269
  }
72346
73270
  const senderColor = getTeammateColor();
72347
73271
  const recipients = [];
72348
- for (const member of teamFile.members) {
72349
- if (member.name.toLowerCase() === senderName.toLowerCase()) {
73272
+ for (const name of memberNames) {
73273
+ if (name.toLowerCase() === senderName.toLowerCase()) {
72350
73274
  continue;
72351
73275
  }
72352
- recipients.push(member.name);
73276
+ recipients.push(name);
72353
73277
  }
72354
73278
  if (recipients.length === 0) {
72355
73279
  return {
@@ -72386,7 +73310,9 @@ async function handleBroadcast(content, summary, context) {
72386
73310
  }
72387
73311
  async function handleShutdownRequest(targetName, reason, context) {
72388
73312
  const appState = context.getAppState();
72389
- const teamName = getTeamName(appState.teamContext);
73313
+ const teamName = resolveOutgoingTeamName(appState.teamContext);
73314
+ if (!teamName)
73315
+ throw unresolvedTeamMailboxError(targetName);
72390
73316
  const senderName = getAgentName() || TEAM_LEAD_NAME;
72391
73317
  const requestId = generateRequestId("shutdown", targetName);
72392
73318
  const shutdownMessage = createShutdownRequestMessage({
@@ -72410,7 +73336,9 @@ async function handleShutdownRequest(targetName, reason, context) {
72410
73336
  };
72411
73337
  }
72412
73338
  async function handleShutdownApproval(requestId, _context) {
72413
- const teamName = getTeamName();
73339
+ const teamName = resolveOutgoingTeamName();
73340
+ if (!teamName)
73341
+ throw unresolvedTeamMailboxError(TEAM_LEAD_NAME);
72414
73342
  const agentId = getAgentId();
72415
73343
  const agentName = getAgentName() || "teammate";
72416
73344
  logForDebugging(`[SendMessageTool] handleShutdownApproval: teamName=${teamName}, agentId=${agentId}, agentName=${agentName}`);
@@ -72424,16 +73352,32 @@ async function handleShutdownApproval(requestId, _context) {
72424
73352
  timestamp: new Date().toISOString(),
72425
73353
  color: getTeammateColor()
72426
73354
  }, teamName);
73355
+ let exitTriggered = false;
73356
+ try {
73357
+ const port = getSessionContextPort();
73358
+ const memberTask = port ? findInProcessTeammateTaskByAgentId(port.get().tasks, agentId ?? "") : undefined;
73359
+ if (port) {
73360
+ const tasksAll = port.get().tasks ?? {};
73361
+ const sameAgentEntries = Object.entries(tasksAll).filter(([, t]) => t?.identity?.agentId === agentId);
73362
+ logForDebugging(`[probe-R1][trigger] agent=${agentId} taskEntries=${Object.keys(tasksAll).length} sameAgentId=${sameAgentEntries.map(([k, t]) => `${k}:${t.status ?? "unknown"}`).join("|") || "none"} firstHit=${memberTask ? "yes" : "no"} controller=${probeReadAbortControllerId(memberTask?.abortController)} live=${isInProcessTeammateLive(memberTask)} recordId=${probeReadTaskRecordId(memberTask)}`);
73363
+ }
73364
+ if (isInProcessTeammateLive(memberTask) && memberTask.abortController) {
73365
+ memberTask.abortController.abort();
73366
+ exitTriggered = true;
73367
+ }
73368
+ } catch {}
72427
73369
  return {
72428
73370
  data: {
72429
73371
  success: true,
72430
- message: `Shutdown approved. Sent confirmation to team-lead. Agent ${agentName} is now exiting.`,
73372
+ message: exitTriggered ? `Shutdown approved. Confirmation sent to team-lead; exit sequence triggered for agent ${agentName}.` : `Shutdown approved. Confirmation sent to team-lead; agent ${agentName} will exit on its next lifecycle check.`,
72431
73373
  request_id: requestId
72432
73374
  }
72433
73375
  };
72434
73376
  }
72435
73377
  async function handleShutdownRejection(requestId, reason) {
72436
- const teamName = getTeamName();
73378
+ const teamName = resolveOutgoingTeamName();
73379
+ if (!teamName)
73380
+ throw unresolvedTeamMailboxError(TEAM_LEAD_NAME);
72437
73381
  const agentName = getAgentName() || "teammate";
72438
73382
  const rejectedMessage = createShutdownRejectedMessage({
72439
73383
  requestId,
@@ -72456,7 +73400,9 @@ async function handleShutdownRejection(requestId, reason) {
72456
73400
  }
72457
73401
  async function handlePlanApproval(recipientName, requestId, context) {
72458
73402
  const appState = context.getAppState();
72459
- const teamName = appState.teamContext?.teamName;
73403
+ const teamName = resolveOutgoingTeamName(appState.teamContext);
73404
+ if (!teamName)
73405
+ throw unresolvedTeamMailboxError(recipientName);
72460
73406
  if (!isTeamLead(appState.teamContext)) {
72461
73407
  throw new Error("Only the team lead can approve plans. Teammates cannot approve their own or other plans.");
72462
73408
  }
@@ -72484,7 +73430,9 @@ async function handlePlanApproval(recipientName, requestId, context) {
72484
73430
  }
72485
73431
  async function handlePlanRejection(recipientName, requestId, feedback, context) {
72486
73432
  const appState = context.getAppState();
72487
- const teamName = appState.teamContext?.teamName;
73433
+ const teamName = resolveOutgoingTeamName(appState.teamContext);
73434
+ if (!teamName)
73435
+ throw unresolvedTeamMailboxError(recipientName);
72488
73436
  if (!isTeamLead(appState.teamContext)) {
72489
73437
  throw new Error("Only the team lead can reject plans. Teammates cannot reject their own or other plans.");
72490
73438
  }
@@ -72508,12 +73456,29 @@ async function handlePlanRejection(recipientName, requestId, feedback, context)
72508
73456
  }
72509
73457
  };
72510
73458
  }
73459
+ async function dispatchStructuredMessage(message, to, ctx) {
73460
+ switch (message.type) {
73461
+ case "shutdown_request":
73462
+ return handleShutdownRequest(to, message.reason, ctx);
73463
+ case "shutdown_response":
73464
+ if (message.approve) {
73465
+ return handleShutdownApproval(message.request_id, ctx);
73466
+ }
73467
+ return handleShutdownRejection(message.request_id, message.reason);
73468
+ case "plan_approval_response":
73469
+ if (message.approve) {
73470
+ return handlePlanApproval(to, message.request_id, ctx);
73471
+ }
73472
+ return handlePlanRejection(to, message.request_id, message.feedback ?? "Plan needs revision", ctx);
73473
+ }
73474
+ }
72511
73475
  var SEND_MESSAGE_TOOL_INPUT_SCHEMA, teamFileLoader = async () => null, SendMessageTool;
72512
73476
  var init_sendMessageTool = __esm(() => {
72513
73477
  init_shared();
72514
73478
  init_remote();
72515
73479
  init_messaging();
72516
73480
  init_json();
73481
+ init_task2();
72517
73482
  init_toolNames();
72518
73483
  init_sendMessagePrompt();
72519
73484
  SEND_MESSAGE_TOOL_INPUT_SCHEMA = {
@@ -72611,6 +73576,8 @@ var init_sendMessageTool = __esm(() => {
72611
73576
  },
72612
73577
  async validateInput(input, _context) {
72613
73578
  const i = input;
73579
+ const sniffedMessage = typeof i.message === "string" ? tryParseStructuredMessage(i.message) : undefined;
73580
+ const message = sniffedMessage ?? i.message;
72614
73581
  if (i.to.trim().length === 0) {
72615
73582
  return {
72616
73583
  result: false,
@@ -72634,7 +73601,7 @@ var init_sendMessageTool = __esm(() => {
72634
73601
  };
72635
73602
  }
72636
73603
  if (isUdsInboxEnabled() && parseAddress(i.to).scheme === "bridge") {
72637
- if (typeof i.message !== "string") {
73604
+ if (typeof message !== "string") {
72638
73605
  return {
72639
73606
  result: false,
72640
73607
  message: "structured messages cannot be sent cross-session — only plain text",
@@ -72650,10 +73617,10 @@ var init_sendMessageTool = __esm(() => {
72650
73617
  }
72651
73618
  return { result: true };
72652
73619
  }
72653
- if (isUdsInboxEnabled() && parseAddress(i.to).scheme === "uds" && typeof i.message === "string") {
73620
+ if (isUdsInboxEnabled() && parseAddress(i.to).scheme === "uds" && typeof message === "string") {
72654
73621
  return { result: true };
72655
73622
  }
72656
- if (typeof i.message === "string") {
73623
+ if (typeof message === "string") {
72657
73624
  if (!i.summary || i.summary.trim().length === 0) {
72658
73625
  return {
72659
73626
  result: false,
@@ -72677,14 +73644,14 @@ var init_sendMessageTool = __esm(() => {
72677
73644
  errorCode: 9
72678
73645
  };
72679
73646
  }
72680
- if (i.message.type === "shutdown_response" && i.to !== TEAM_LEAD_NAME) {
73647
+ if (message.type === "shutdown_response" && i.to !== TEAM_LEAD_NAME) {
72681
73648
  return {
72682
73649
  result: false,
72683
73650
  message: `shutdown_response must be sent to "${TEAM_LEAD_NAME}"`,
72684
73651
  errorCode: 9
72685
73652
  };
72686
73653
  }
72687
- if (i.message.type === "shutdown_response" && !i.message.approve && (!i.message.reason || i.message.reason.trim().length === 0)) {
73654
+ if (message.type === "shutdown_response" && !message.approve && (!message.reason || message.reason.trim().length === 0)) {
72688
73655
  return {
72689
73656
  result: false,
72690
73657
  message: "reason is required when rejecting a shutdown request",
@@ -72751,6 +73718,13 @@ var init_sendMessageTool = __esm(() => {
72751
73718
  }
72752
73719
  }
72753
73720
  }
73721
+ const sniffed = typeof input.message === "string" ? tryParseStructuredMessage(input.message) : undefined;
73722
+ if (sniffed !== undefined) {
73723
+ if (input.to === "*") {
73724
+ throw new Error("structured messages cannot be broadcast");
73725
+ }
73726
+ return dispatchStructuredMessage(sniffed, input.to, ctx);
73727
+ }
72754
73728
  if (typeof input.message === "string") {
72755
73729
  if (input.to === "*") {
72756
73730
  return handleBroadcast(input.message, input.summary, ctx);
@@ -72760,20 +73734,7 @@ var init_sendMessageTool = __esm(() => {
72760
73734
  if (input.to === "*") {
72761
73735
  throw new Error("structured messages cannot be broadcast");
72762
73736
  }
72763
- switch (input.message.type) {
72764
- case "shutdown_request":
72765
- return handleShutdownRequest(input.to, input.message.reason, ctx);
72766
- case "shutdown_response":
72767
- if (input.message.approve) {
72768
- return handleShutdownApproval(input.message.request_id, ctx);
72769
- }
72770
- return handleShutdownRejection(input.message.request_id, input.message.reason);
72771
- case "plan_approval_response":
72772
- if (input.message.approve) {
72773
- return handlePlanApproval(input.to, input.message.request_id, ctx);
72774
- }
72775
- return handlePlanRejection(input.to, input.message.request_id, input.message.feedback ?? "Plan needs revision", ctx);
72776
- }
73737
+ return dispatchStructuredMessage(input.message, input.to, ctx);
72777
73738
  },
72778
73739
  renderToolUseMessage(input) {
72779
73740
  const { message, to } = input ?? {};
@@ -73365,29 +74326,6 @@ var init_tasks2 = __esm(() => {
73365
74326
  init_tasks();
73366
74327
  });
73367
74328
 
73368
- // src/engine/tools/team/teamServices.ts
73369
- function setTeamServices(services) {
73370
- active = services;
73371
- }
73372
- function resetTeamServices() {
73373
- active = undefined;
73374
- }
73375
- function requireTeamServices() {
73376
- if (!active) {
73377
- throw new Error("TeamServices not wired — call setTeamServices at composition root first (swarm team-file seam, C 桶 ③ S-E2d)");
73378
- }
73379
- return active;
73380
- }
73381
- function createDefaultTeamContextStore() {
73382
- return {
73383
- getTeamContext: () => teamContext,
73384
- setTeamContext: (ctx) => {
73385
- teamContext = ctx;
73386
- }
73387
- };
73388
- }
73389
- var active, teamContext;
73390
-
73391
74329
  // src/engine/tools/team/teamCreatePrompt.ts
73392
74330
  var PROMPT4;
73393
74331
  var init_teamCreatePrompt = __esm(() => {
@@ -73423,7 +74361,7 @@ Create a new team to coordinate multiple agents working on a project. Teams have
73423
74361
  \`\`\`
73424
74362
 
73425
74363
  This creates:
73426
- - A team file at \`~/.atlas/teams/{team-name}/config.json\`
74364
+ - An in-memory team context on the leader (Form A is zero-persistence — no team file is written to \`~/.atlas/teams/\`; the member roster lives in the leader's team context)
73427
74365
  - A corresponding task list directory at \`~/.atlas/tasks/{team-name}/\`
73428
74366
 
73429
74367
  ## Team Workflow
@@ -73465,23 +74403,14 @@ Teammates go idle after every turn—this is completely normal and expected. A t
73465
74403
 
73466
74404
  ## Discovering Team Members
73467
74405
 
73468
- Teammates can read the team config file to discover other team members:
73469
- - **Team config location**: \`~/.atlas/teams/{team-name}/config.json\`
73470
-
73471
- The config file contains a \`members\` array with each teammate's:
74406
+ Form A teams are zero-persistence: no team config file is written to disk. Team members come from the \`members\` roster passed to TeamCreate (carried in the leader's team context). Each roster entry has:
73472
74407
  - \`name\`: Human-readable name (**always use this** for messaging and task assignment)
73473
- - \`agentId\`: Unique identifier (for reference only - do not use for communication)
73474
- - \`agentType\`: Role/type of the agent
74408
+ - \`role\`/\`goal\`/\`backstory\`: Role triplet used to compose the member's prompt when spawned via Agent(name, team_name)
73475
74409
 
73476
74410
  **IMPORTANT**: Always refer to teammates by their NAME (e.g., "team-lead", "researcher", "tester"). Names are used for:
73477
74411
  - \`to\` when sending messages
73478
74412
  - Identifying task owners
73479
74413
 
73480
- Example of reading team config:
73481
- \`\`\`
73482
- Use the Read tool to read ~/.atlas/teams/{team-name}/config.json
73483
- \`\`\`
73484
-
73485
74414
  ## Task List Coordination
73486
74415
 
73487
74416
  Teams share a task list that all teammates can access at \`~/.atlas/tasks/{team-name}/\`.
@@ -73515,7 +74444,6 @@ function generateUniqueTeamName(providedName) {
73515
74444
  var TEAM_CREATE_TOOL_INPUT_SCHEMA, TeamCreateTool;
73516
74445
  var init_teamCreateTool = __esm(() => {
73517
74446
  init_bootstrap();
73518
- init_modelprovider2();
73519
74447
  init_tasks2();
73520
74448
  init_messaging();
73521
74449
  init_json();
@@ -73536,6 +74464,33 @@ var init_teamCreateTool = __esm(() => {
73536
74464
  agent_type: {
73537
74465
  type: "string",
73538
74466
  description: 'Type/role of the team lead (e.g., "researcher", "test-runner"). ' + "Used for team file and inter-agent coordination."
74467
+ },
74468
+ members: {
74469
+ type: "array",
74470
+ description: "Optional roster of team members to plan for this team. Each entry " + "carries an optional role/goal/backstory triplet used to compose the " + "member's prompt when spawned via Agent(name, team_name).",
74471
+ items: {
74472
+ type: "object",
74473
+ properties: {
74474
+ name: {
74475
+ type: "string",
74476
+ description: "Member name (used as the spawn identity)."
74477
+ },
74478
+ role: {
74479
+ type: "string",
74480
+ description: "Role label resolved against the role template registry."
74481
+ },
74482
+ goal: {
74483
+ type: "string",
74484
+ description: "This member's goal for the team's current task."
74485
+ },
74486
+ backstory: {
74487
+ type: "string",
74488
+ description: "This member's background/context for prompt composition."
74489
+ }
74490
+ },
74491
+ required: ["name"],
74492
+ additionalProperties: false
74493
+ }
73539
74494
  }
73540
74495
  },
73541
74496
  required: ["team_name"],
@@ -73569,6 +74524,17 @@ var init_teamCreateTool = __esm(() => {
73569
74524
  errorCode: 9
73570
74525
  };
73571
74526
  }
74527
+ if (i.members) {
74528
+ for (const m of i.members) {
74529
+ if (!m || typeof m !== "object" || !m.name || m.name.trim().length === 0) {
74530
+ return {
74531
+ result: false,
74532
+ message: "each team member requires a non-empty name",
74533
+ errorCode: 9
74534
+ };
74535
+ }
74536
+ }
74537
+ }
73572
74538
  return { result: true };
73573
74539
  },
73574
74540
  async description() {
@@ -73596,29 +74562,8 @@ var init_teamCreateTool = __esm(() => {
73596
74562
  const finalTeamName = generateUniqueTeamName(input.team_name);
73597
74563
  const leadAgentId = formatAgentId(TEAM_LEAD_NAME, finalTeamName);
73598
74564
  const leadAgentType = input.agent_type || TEAM_LEAD_NAME;
73599
- const leadModel = getRoleModel("premium");
73600
74565
  const teamFilePath = services.getTeamFilePath(finalTeamName);
73601
- const teamFile = {
73602
- name: finalTeamName,
73603
- description: input.description,
73604
- createdAt: Date.now(),
73605
- leadAgentId,
73606
- leadSessionId: getSessionId(),
73607
- members: [
73608
- {
73609
- agentId: leadAgentId,
73610
- name: TEAM_LEAD_NAME,
73611
- agentType: leadAgentType,
73612
- model: leadModel,
73613
- joinedAt: Date.now(),
73614
- tmuxPaneId: "",
73615
- cwd: getCwd(),
73616
- subscriptions: []
73617
- }
73618
- ]
73619
- };
73620
- await services.writeTeamFileAsync(finalTeamName, teamFile);
73621
- services.registerTeamForSessionCleanup(finalTeamName);
74566
+ const roster = input.members && input.members.length > 0 ? input.members : undefined;
73622
74567
  const taskListId = services.sanitizeName(finalTeamName);
73623
74568
  await resetTaskList(taskListId);
73624
74569
  await ensureTasksDir(taskListId);
@@ -73627,6 +74572,7 @@ var init_teamCreateTool = __esm(() => {
73627
74572
  teamName: finalTeamName,
73628
74573
  teamFilePath,
73629
74574
  leadAgentId,
74575
+ roster,
73630
74576
  teammates: {
73631
74577
  [leadAgentId]: {
73632
74578
  name: TEAM_LEAD_NAME,
@@ -73679,6 +74625,7 @@ var init_teamDeleteTool = __esm(() => {
73679
74625
  init_tasks2();
73680
74626
  init_messaging();
73681
74627
  init_json();
74628
+ init_task2();
73682
74629
  init_toolNames();
73683
74630
  init_teamDeletePrompt();
73684
74631
  TEAM_DELETE_TOOL_INPUT_SCHEMA = {
@@ -73720,7 +74667,8 @@ var init_teamDeleteTool = __esm(() => {
73720
74667
  },
73721
74668
  async call(_args, _context) {
73722
74669
  const services = requireTeamServices();
73723
- const teamName = services.getTeamContext()?.teamName;
74670
+ const teamContext = services.getTeamContext();
74671
+ const teamName = teamContext?.teamName;
73724
74672
  if (teamName) {
73725
74673
  const teamFile = services.readTeamFile(teamName);
73726
74674
  if (teamFile) {
@@ -73731,7 +74679,22 @@ var init_teamDeleteTool = __esm(() => {
73731
74679
  return {
73732
74680
  data: {
73733
74681
  success: false,
73734
- message: `Cannot cleanup team with ${activeMembers.length} active member(s): ${memberNames}. Use requestShutdown to gracefully terminate teammates first.`,
74682
+ message: `Cannot cleanup team with ${activeMembers.length} active member(s): ${memberNames}. Send each active member a shutdown request via SendMessage first (message: {"type":"shutdown_request","request_id":"<id>","reason":"<why>"}), and wait for their shutdown approval and exit before retrying TeamDelete.`,
74683
+ team_name: teamName
74684
+ }
74685
+ };
74686
+ }
74687
+ }
74688
+ const teammateEntries = Object.entries(teamContext?.teammates ?? {}).filter(([, member]) => member.name !== TEAM_LEAD_NAME);
74689
+ if (teammateEntries.length > 0) {
74690
+ const tasks = getSessionContextPort()?.get().tasks;
74691
+ const alive = teammateEntries.filter(([, member]) => isInProcessTeammateActiveOrUnknown(tasks?.[member.taskId ?? ""]));
74692
+ if (alive.length > 0) {
74693
+ const memberNames = alive.map(([, member]) => member.name).join(", ");
74694
+ return {
74695
+ data: {
74696
+ success: false,
74697
+ message: `Cannot cleanup team with ${alive.length} active member(s): ${memberNames}. Send each active member a shutdown request via SendMessage first (message: {"type":"shutdown_request","request_id":"<id>","reason":"<why>"}), and wait for their shutdown approval and exit before retrying TeamDelete.`,
73735
74698
  team_name: teamName
73736
74699
  }
73737
74700
  };
@@ -73757,6 +74720,171 @@ var init_teamDeleteTool = __esm(() => {
73757
74720
  };
73758
74721
  });
73759
74722
 
74723
+ // src/engine/tools/team/waitForTeammatesPrompt.ts
74724
+ var PROMPT6 = `Wait for all currently working in-process teammates to become idle, then return.
74725
+
74726
+ Use this tool instead of repeatedly polling with other tools when you are waiting for teammates to finish their work, to acknowledge a shutdown request, or to exit after you sent them instructions. One call replaces many polling rounds.
74727
+
74728
+ The call blocks (event-driven, no busy-waiting) until every working teammate is idle, or until the timeout expires:
74729
+
74730
+ - On success it returns { status: 'idle', waited_ms, idle }.
74731
+ - On timeout it returns { status: 'timeout', waited_ms, still_working } listing the teammates that are still working — it never blocks forever. You may call again with a longer timeout, or proceed without those teammates.
74732
+
74733
+ This tool never aborts or kills teammates; it only waits. Graceful termination is driven by shutdown requests via SendMessage, and cleanup remains TeamDelete's responsibility. When no teammates are working, it returns immediately with status 'idle'.
74734
+
74735
+ Parameters:
74736
+ - timeout: Maximum time to wait in milliseconds (default 120000, maximum 600000).
74737
+ `;
74738
+
74739
+ // src/engine/tools/team/waitForTeammatesTool.ts
74740
+ function sessionStateUnavailableError() {
74741
+ return new Error("No session state is available in the current context " + "(SessionContextPort is not injected). WaitForTeammates requires the " + "engine composition root (in-process teammates live in the session " + "task registry). Create a team with TeamCreate and spawn teammates first.");
74742
+ }
74743
+ function listWorkingTeammateNames(appState) {
74744
+ const names = [];
74745
+ for (const task of Object.values(appState.tasks)) {
74746
+ if (isInProcessTeammateWorking(task)) {
74747
+ names.push(task.identity.agentName);
74748
+ }
74749
+ }
74750
+ return names;
74751
+ }
74752
+ var WAIT_FOR_TEAMMATES_TOOL_INPUT_SCHEMA, WAIT_FOR_TEAMMATES_DEFAULT_TIMEOUT_MS = 120000, WAIT_FOR_TEAMMATES_MAX_TIMEOUT_MS = 600000, WaitForTeammatesTool;
74753
+ var init_waitForTeammatesTool = __esm(() => {
74754
+ init_messaging();
74755
+ init_task2();
74756
+ init_json();
74757
+ init_toolNames();
74758
+ WAIT_FOR_TEAMMATES_TOOL_INPUT_SCHEMA = {
74759
+ type: "object",
74760
+ properties: {
74761
+ timeout: {
74762
+ type: "number",
74763
+ minimum: 0,
74764
+ maximum: 600000,
74765
+ default: 120000,
74766
+ description: "Max time to wait in milliseconds (default 120000)"
74767
+ }
74768
+ },
74769
+ additionalProperties: false
74770
+ };
74771
+ WaitForTeammatesTool = {
74772
+ name: WAIT_FOR_TEAMMATES_TOOL_NAME,
74773
+ inputSchema: WAIT_FOR_TEAMMATES_TOOL_INPUT_SCHEMA,
74774
+ inputJSONSchema: WAIT_FOR_TEAMMATES_TOOL_INPUT_SCHEMA,
74775
+ strict: true,
74776
+ searchHint: "wait for teammates to finish or acknowledge",
74777
+ maxResultSizeChars: 1e5,
74778
+ shouldDefer: true,
74779
+ isEnabled: () => isAgentSwarmsEnabled(),
74780
+ isReadOnly: () => true,
74781
+ isDestructive: () => false,
74782
+ isConcurrencySafe: () => true,
74783
+ userFacingName: () => "Wait For Teammates",
74784
+ toAutoClassifierInput: () => "",
74785
+ async checkPermissions(input) {
74786
+ return { behavior: "allow", updatedInput: input };
74787
+ },
74788
+ async description() {
74789
+ return PROMPT6;
74790
+ },
74791
+ mapToolResultToToolResultBlockParam(data, toolUseID) {
74792
+ return {
74793
+ tool_use_id: toolUseID,
74794
+ type: "tool_result",
74795
+ content: [
74796
+ {
74797
+ type: "text",
74798
+ text: jsonStringify(data)
74799
+ }
74800
+ ]
74801
+ };
74802
+ },
74803
+ renderToolUseMessage(input) {
74804
+ const { timeout } = input ?? {};
74805
+ if (timeout !== undefined) {
74806
+ return `waiting for teammates (up to ${timeout}ms)`;
74807
+ }
74808
+ return "waiting for teammates";
74809
+ },
74810
+ async call(args) {
74811
+ const { timeout = WAIT_FOR_TEAMMATES_DEFAULT_TIMEOUT_MS } = args;
74812
+ const effectiveTimeout = Math.min(Math.max(0, timeout), WAIT_FOR_TEAMMATES_MAX_TIMEOUT_MS);
74813
+ const port = getSessionContextPort();
74814
+ if (!port) {
74815
+ throw sessionStateUnavailableError();
74816
+ }
74817
+ const snapshot = port.get();
74818
+ const appState = {
74819
+ tasks: snapshot.tasks ?? {}
74820
+ };
74821
+ const startedAt = Date.now();
74822
+ const workingNames = listWorkingTeammateNames(appState);
74823
+ if (workingNames.length === 0) {
74824
+ return {
74825
+ data: { status: "idle", waited_ms: 0, idle: [], still_working: [] }
74826
+ };
74827
+ }
74828
+ const setAppState = (updater) => {
74829
+ port.set((prev) => {
74830
+ const next = updater({
74831
+ tasks: prev.tasks ?? {}
74832
+ });
74833
+ return {
74834
+ ...prev,
74835
+ tasks: next.tasks
74836
+ };
74837
+ });
74838
+ };
74839
+ let timer;
74840
+ try {
74841
+ const outcome = await Promise.race([
74842
+ waitForTeammatesToBecomeIdle(setAppState, appState).then(() => "idle"),
74843
+ new Promise((resolve) => {
74844
+ timer = setTimeout(() => resolve("timeout"), effectiveTimeout);
74845
+ })
74846
+ ]);
74847
+ const waitedMs = Date.now() - startedAt;
74848
+ const nowWorking = listWorkingTeammateNames({
74849
+ tasks: port.get().tasks ?? {}
74850
+ });
74851
+ const idleNames = workingNames.filter((name) => !nowWorking.includes(name));
74852
+ if (outcome === "timeout" && nowWorking.length === 0) {
74853
+ return {
74854
+ data: {
74855
+ status: "idle",
74856
+ waited_ms: waitedMs,
74857
+ idle: idleNames,
74858
+ still_working: []
74859
+ }
74860
+ };
74861
+ }
74862
+ if (outcome === "idle") {
74863
+ return {
74864
+ data: {
74865
+ status: "idle",
74866
+ waited_ms: waitedMs,
74867
+ idle: idleNames,
74868
+ still_working: []
74869
+ }
74870
+ };
74871
+ }
74872
+ return {
74873
+ data: {
74874
+ status: "timeout",
74875
+ waited_ms: waitedMs,
74876
+ idle: idleNames,
74877
+ still_working: nowWorking
74878
+ }
74879
+ };
74880
+ } finally {
74881
+ if (timer)
74882
+ clearTimeout(timer);
74883
+ }
74884
+ }
74885
+ };
74886
+ });
74887
+
73760
74888
  // src/engine/tools/team/index.ts
73761
74889
  var init_team = __esm(() => {
73762
74890
  init_sendMessageTool();
@@ -73767,6 +74895,7 @@ var init_team = __esm(() => {
73767
74895
  init_teamCreatePrompt();
73768
74896
  init_teamDeleteTool();
73769
74897
  init_teamDeletePrompt();
74898
+ init_waitForTeammatesTool();
73770
74899
  });
73771
74900
 
73772
74901
  // src/engine/scheduler/cron.ts
@@ -75009,7 +76138,7 @@ var init_taskCreateTool = __esm(() => {
75009
76138
  });
75010
76139
 
75011
76140
  // src/engine/tools/tasks/taskGetPrompt.ts
75012
- var PROMPT6 = `Use this tool to retrieve a task by its ID from the task list.
76141
+ var PROMPT7 = `Use this tool to retrieve a task by its ID from the task list.
75013
76142
 
75014
76143
  ## When to Use This Tool
75015
76144
 
@@ -75064,7 +76193,7 @@ var init_taskGetTool = __esm(() => {
75064
76193
  behavior: "allow",
75065
76194
  updatedInput: input
75066
76195
  }),
75067
- description: async () => PROMPT6,
76196
+ description: async () => PROMPT7,
75068
76197
  async call(args) {
75069
76198
  const { taskId } = args;
75070
76199
  const taskListId = getTaskListId();
@@ -75231,7 +76360,7 @@ var init_taskListTool = __esm(() => {
75231
76360
  });
75232
76361
 
75233
76362
  // src/engine/tools/tasks/taskUpdatePrompt.ts
75234
- var PROMPT7 = `Use this tool to update a task in the task list.
76363
+ var PROMPT8 = `Use this tool to update a task in the task list.
75235
76364
 
75236
76365
  ## When to Use This Tool
75237
76366
 
@@ -75385,7 +76514,7 @@ var init_taskUpdateTool = __esm(() => {
75385
76514
  behavior: "allow",
75386
76515
  updatedInput: input
75387
76516
  }),
75388
- description: async () => PROMPT7,
76517
+ description: async () => PROMPT8,
75389
76518
  async call(args, context) {
75390
76519
  const {
75391
76520
  taskId,
@@ -75556,7 +76685,7 @@ Task completed. Call TaskList now to find your next available task or see if you
75556
76685
  });
75557
76686
 
75558
76687
  // src/engine/tools/tasks/taskStopPrompt.ts
75559
- var DESCRIPTION10 = `
76688
+ var DESCRIPTION11 = `
75560
76689
  - Stops a running background task by its ID
75561
76690
  - Takes a task_id parameter identifying the task to stop
75562
76691
  - Returns a success or failure status
@@ -75602,7 +76731,7 @@ var init_taskStopTool = __esm(() => {
75602
76731
  behavior: "allow",
75603
76732
  updatedInput: input
75604
76733
  }),
75605
- description: async () => DESCRIPTION10,
76734
+ description: async () => DESCRIPTION11,
75606
76735
  async validateInput(input, context) {
75607
76736
  const { task_id, shell_id } = input;
75608
76737
  const ctx = context;
@@ -75665,10 +76794,10 @@ var init_taskStopTool = __esm(() => {
75665
76794
  });
75666
76795
 
75667
76796
  // src/engine/tools/tasks/todoWritePrompt.ts
75668
- var PROMPT8;
76797
+ var PROMPT9;
75669
76798
  var init_todoWritePrompt = __esm(() => {
75670
76799
  init_toolNames();
75671
- PROMPT8 = `Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
76800
+ PROMPT9 = `Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
75672
76801
  It also helps the user understand the progress of the task and overall progress of their requests.
75673
76802
 
75674
76803
  ## When to Use This Tool
@@ -75906,7 +77035,7 @@ var init_todoWriteTool = __esm(() => {
75906
77035
  behavior: "allow",
75907
77036
  updatedInput: input
75908
77037
  }),
75909
- description: async () => PROMPT8,
77038
+ description: async () => PROMPT9,
75910
77039
  async call(args, context) {
75911
77040
  const { todos } = args;
75912
77041
  const ctx = context;
@@ -75941,7 +77070,7 @@ var init_todoWriteTool = __esm(() => {
75941
77070
  });
75942
77071
 
75943
77072
  // src/engine/tools/tasks/taskOutputPrompt.ts
75944
- var PROMPT9 = `DEPRECATED: Prefer using the Read tool on the task's output file path instead. Background tasks return their output file path in the tool result, and you receive a <task-notification> with the same path when the task completes — Read that file directly.
77073
+ var PROMPT10 = `DEPRECATED: Prefer using the Read tool on the task's output file path instead. Background tasks return their output file path in the tool result, and you receive a <task-notification> with the same path when the task completes — Read that file directly.
75945
77074
 
75946
77075
  - Retrieves output from a running or completed task (background shell, agent, or remote session)
75947
77076
  - Takes a task_id parameter identifying the task
@@ -76068,7 +77197,7 @@ var init_taskOutputTool = __esm(() => {
76068
77197
  behavior: "allow",
76069
77198
  updatedInput: input
76070
77199
  }),
76071
- description: async () => PROMPT9,
77200
+ description: async () => PROMPT10,
76072
77201
  async validateInput(input, context) {
76073
77202
  const { task_id } = input;
76074
77203
  const ctx = context;
@@ -76080,6 +77209,13 @@ var init_taskOutputTool = __esm(() => {
76080
77209
  };
76081
77210
  }
76082
77211
  const appState = ctx.getAppState();
77212
+ if (!appState?.tasks) {
77213
+ return {
77214
+ result: false,
77215
+ message: `No task registry is available in the current context ` + `(task_id: ${task_id}). For in-process teammates, communicate via ` + "SendMessage (the mailbox is the coordination channel) instead of " + "polling TaskOutput.",
77216
+ errorCode: 2
77217
+ };
77218
+ }
76083
77219
  const task = appState.tasks[task_id];
76084
77220
  if (!task) {
76085
77221
  return {
@@ -76094,6 +77230,9 @@ var init_taskOutputTool = __esm(() => {
76094
77230
  const { task_id, block = true, timeout = 30000 } = args;
76095
77231
  const ctx = context;
76096
77232
  const appState = ctx.getAppState();
77233
+ if (!appState?.tasks) {
77234
+ throw new Error(`No task registry is available in the current context ` + `(task_id: ${task_id}). For in-process teammates, communicate via ` + "SendMessage (the mailbox is the coordination channel) instead of " + "polling TaskOutput.");
77235
+ }
76097
77236
  const task = appState.tasks[task_id];
76098
77237
  if (!task) {
76099
77238
  throw new Error(`No task found with ID: ${task_id}`);
@@ -82643,18 +83782,6 @@ var init_restore = __esm(() => {
82643
83782
  init_goalState();
82644
83783
  });
82645
83784
 
82646
- // src/engine/session/sessionContextPort.ts
82647
- function setSessionContextPort(port) {
82648
- _sessionContextPort = port;
82649
- }
82650
- function getSessionContextPort() {
82651
- return _sessionContextPort;
82652
- }
82653
- function resetSessionContextPort() {
82654
- _sessionContextPort = null;
82655
- }
82656
- var _sessionContextPort = null;
82657
-
82658
83785
  // src/engine/session/index.ts
82659
83786
  var init_session = __esm(() => {
82660
83787
  init_env();
@@ -84565,6 +85692,7 @@ async function queryAgentLoop(deps, args) {
84565
85692
  assistantMessage: lastRound.messages[roundInputLen],
84566
85693
  toolResultMessages: lastRound.messages.slice(roundInputLen + 1)
84567
85694
  });
85695
+ await deps.afterRound?.();
84568
85696
  break;
84569
85697
  }
84570
85698
  if (lastRound.deferred) {
@@ -84870,6 +85998,7 @@ async function createAgentLoopDeps(config = {}) {
84870
85998
  SnipTool,
84871
85999
  TeamCreateTool,
84872
86000
  TeamDeleteTool,
86001
+ WaitForTeammatesTool,
84873
86002
  ProposeGoalTool
84874
86003
  ],
84875
86004
  mcpTools: [...config.toolRegistryDeps?.mcpTools ?? [], ...mcpTools],
@@ -84916,6 +86045,8 @@ async function createAgentLoopDeps(config = {}) {
84916
86045
  messages: [...compactMsgs, prompt],
84917
86046
  role,
84918
86047
  sessionModel,
86048
+ systemPrompt: config.systemPrompt,
86049
+ tools: tools.length > 0 ? tools : undefined,
84919
86050
  signal: config.signal
84920
86051
  });
84921
86052
  const content = resp.message?.content;
@@ -84964,6 +86095,7 @@ var init_loopDeps = __esm(() => {
84964
86095
  init_snipTool();
84965
86096
  init_teamCreateTool();
84966
86097
  init_teamDeleteTool();
86098
+ init_waitForTeammatesTool();
84967
86099
  init_ProposeGoal();
84968
86100
  init_context();
84969
86101
  });
@@ -84979,6 +86111,7 @@ class EngineState {
84979
86111
  set(f) {
84980
86112
  return new Promise((resolve, reject) => {
84981
86113
  this.queue.push({ f, resolve, reject });
86114
+ logForDebugging(`[probe-R6][es-enqueue] q=${this.queue.length} processing=${this.processing}`);
84982
86115
  this.process();
84983
86116
  });
84984
86117
  }
@@ -84989,6 +86122,7 @@ class EngineState {
84989
86122
  try {
84990
86123
  while (this.queue.length > 0) {
84991
86124
  const item = this.queue.shift();
86125
+ logForDebugging(`[probe-R6][es-apply] q=${this.queue.length}`);
84992
86126
  await Promise.resolve();
84993
86127
  try {
84994
86128
  this.state = item.f(this.state);
@@ -85005,9 +86139,14 @@ class EngineState {
85005
86139
  return this.state;
85006
86140
  }
85007
86141
  }
86142
+ var init_EngineState = __esm(() => {
86143
+ init_shared();
86144
+ });
85008
86145
 
85009
86146
  // src/engine/state/index.ts
85010
- var init_state2 = () => {};
86147
+ var init_state2 = __esm(() => {
86148
+ init_EngineState();
86149
+ });
85011
86150
 
85012
86151
  // src/engine/hooks/index.ts
85013
86152
  var init_hooks2 = __esm(() => {
@@ -87614,6 +88753,8 @@ function initDebugSink() {
87614
88753
  if (initialized)
87615
88754
  return;
87616
88755
  initialized = true;
88756
+ sharedDebugSinkRegistered = true;
88757
+ setDebugSink(sharedLogForDebugging);
87617
88758
  toStderr = argvHas("--debug-to-stderr") || argvHas("-d2e");
87618
88759
  const file = argvValue("--debug-file");
87619
88760
  if (file)
@@ -87656,7 +88797,9 @@ function logForDebugging2(message, { level } = {}) {
87656
88797
  function flushDebugSink() {
87657
88798
  return pendingWrite;
87658
88799
  }
87659
- var LEVEL_ORDER, initialized = false, enabled = false, toStderr = false, sinkFile = null, minLevel = "debug", filter = null, pendingWrite;
88800
+ var LEVEL_ORDER, initialized = false, enabled = false, toStderr = false, sinkFile = null, minLevel = "debug", filter = null, pendingWrite, sharedDebugSinkRegistered = false, sharedLogForDebugging = (message, options) => {
88801
+ logForDebugging2(message, options);
88802
+ };
87660
88803
  var init_debugSink = __esm(() => {
87661
88804
  init_bootstrap();
87662
88805
  init_shared();
@@ -88745,7 +89888,7 @@ function handleControlRequestLocal(request, structuredIO, sessionId) {
88745
89888
  logForDebugging2(`[headless] unknown control_request subtype: ${String(request.request.subtype)}`);
88746
89889
  }
88747
89890
  }
88748
- function extractFinalAssistantText(loopResult) {
89891
+ function extractFinalAssistantText2(loopResult) {
88749
89892
  const contentOf = (m) => {
88750
89893
  const msg = m.message;
88751
89894
  return m.content !== undefined ? m.content : msg?.content;
@@ -89052,6 +90195,8 @@ async function runHeadless(inputPrompt, options) {
89052
90195
  const resp = await modelProvider.chat({
89053
90196
  messages: [...msgs, prompt],
89054
90197
  role: "small",
90198
+ systemPrompt: bundle.deps.systemPrompt,
90199
+ tools,
89055
90200
  signal: abortController.signal
89056
90201
  });
89057
90202
  return resp.message.content.filter((block) => block.type === "text" && typeof block.text === "string").map((block) => block.text).join("");
@@ -89062,6 +90207,7 @@ async function runHeadless(inputPrompt, options) {
89062
90207
  const loopDeps = {
89063
90208
  ...bundle.deps,
89064
90209
  signal: abortController.signal,
90210
+ afterRound: () => drainToOutput(),
89065
90211
  checkPermission,
89066
90212
  toolContext: makeCtx()
89067
90213
  };
@@ -89082,7 +90228,10 @@ async function runHeadless(inputPrompt, options) {
89082
90228
  return queryAgentLoop(loopDeps, {
89083
90229
  messages: turnMessages,
89084
90230
  tools,
89085
- context: { autoCompact, maxTurns: options.maxTurns }
90231
+ context: {
90232
+ autoCompact,
90233
+ maxTurns: options.maxTurns ?? DEFAULT_AGENT_LOOP_MAX_TURNS
90234
+ }
89086
90235
  }).then((r) => {
89087
90236
  logForDebugging2(turnEndLine(n, r));
89088
90237
  return r;
@@ -89096,7 +90245,7 @@ async function runHeadless(inputPrompt, options) {
89096
90245
  }
89097
90246
  };
89098
90247
  const buildResultMessage = (loopResult, isError) => {
89099
- const resultText = extractFinalAssistantText(loopResult);
90248
+ const resultText = extractFinalAssistantText2(loopResult);
89100
90249
  return {
89101
90250
  type: "result",
89102
90251
  subtype: loopResult.terminated ? "success" : "error_max_turns",
@@ -89194,6 +90343,7 @@ async function runHeadless(inputPrompt, options) {
89194
90343
  dir: getSchedulerEnv().getProjectRoot()
89195
90344
  });
89196
90345
  cronScheduler.start();
90346
+ let teammateDrainRequested = 0;
89197
90347
  try {
89198
90348
  const deferredState = findDeferredToolUseState(conversation);
89199
90349
  let reSuspended = false;
@@ -89275,7 +90425,7 @@ async function runHeadless(inputPrompt, options) {
89275
90425
  process.stdout.write(`Execution error`);
89276
90426
  break;
89277
90427
  case "error_max_turns":
89278
- process.stdout.write(`Error: Reached max turns (${String(options.maxTurns)})`);
90428
+ process.stdout.write(`Error: Reached max turns (${String(options.maxTurns ?? DEFAULT_AGENT_LOOP_MAX_TURNS)})`);
89279
90429
  break;
89280
90430
  default:
89281
90431
  break;
@@ -89306,6 +90456,19 @@ async function runHeadless(inputPrompt, options) {
89306
90456
  cronScheduler.stop();
89307
90457
  await drainToOutput();
89308
90458
  await drainPendingBackgroundAgents(abortController.signal);
90459
+ {
90460
+ const sessionPort = getSessionContextPort();
90461
+ if (sessionPort) {
90462
+ const drain = await gracefulShutdownInProcessTeammates({
90463
+ getAppState: () => sessionPort.get(),
90464
+ setAppState: (f) => sessionPort.set(f)
90465
+ });
90466
+ teammateDrainRequested = drain.requested;
90467
+ if (drain.requested > 0) {
90468
+ logForDebugging2(`[headless] teammate shutdown ladder: requested=${drain.requested} drained=${drain.drained} forced=${drain.forced} hardTerminated=${drain.hardTerminated}`);
90469
+ }
90470
+ }
90471
+ }
89309
90472
  await runHeadlessSessionEndHooks("prompt_input_exit");
89310
90473
  } catch (error) {
89311
90474
  cronScheduler.stop();
@@ -89325,10 +90488,32 @@ async function runHeadless(inputPrompt, options) {
89325
90488
  });
89326
90489
  } catch {}
89327
90490
  abortController.abort();
90491
+ {
90492
+ const sessionPort = getSessionContextPort();
90493
+ if (sessionPort) {
90494
+ try {
90495
+ const drain = await gracefulShutdownInProcessTeammates({
90496
+ getAppState: () => sessionPort.get(),
90497
+ setAppState: (f) => sessionPort.set(f)
90498
+ });
90499
+ teammateDrainRequested = drain.requested;
90500
+ if (drain.requested > 0) {
90501
+ logForDebugging2(`[headless] teammate shutdown ladder (error path): requested=${drain.requested} drained=${drain.drained} forced=${drain.forced} hardTerminated=${drain.hardTerminated}`);
90502
+ }
90503
+ } catch {}
90504
+ }
90505
+ }
89328
90506
  await runHeadlessSessionEndHooks("other");
89329
90507
  process.exitCode = 1;
89330
90508
  }
90509
+ if (teammateDrainRequested > 0) {
90510
+ logForDebugging2(`[headless] teammate lifecycle exit guard: forcing process exit after drain (requested=${teammateDrainRequested})`);
90511
+ }
89331
90512
  await flushDebugSink();
90513
+ if (teammateDrainRequested > 0) {
90514
+ await new Promise((resolve) => setTimeout(resolve, 2000));
90515
+ process.exit(process.exitCode ?? 0);
90516
+ }
89332
90517
  }
89333
90518
  async function loadResumedMessages(options) {
89334
90519
  await Promise.resolve().then(() => init_engine());
@@ -89368,6 +90553,7 @@ async function loadResumedMessages(options) {
89368
90553
  }
89369
90554
  var init_print = __esm(() => {
89370
90555
  init_engine();
90556
+ init_swarm();
89371
90557
  init_mcp3();
89372
90558
  init_modelprovider2();
89373
90559
  init_structuredIO();
@@ -124809,7 +125995,7 @@ var init_teamMemPaths = __esm(() => {
124809
125995
  });
124810
125996
 
124811
125997
  // src/tui/utils/config.ts
124812
- import { randomBytes as randomBytes5 } from "crypto";
125998
+ import { randomBytes as randomBytes6 } from "crypto";
124813
125999
  import { unwatchFile as unwatchFile2, watchFile as watchFile2 } from "fs";
124814
126000
  import { basename as basename10, dirname as dirname29, join as join57, resolve as resolve23 } from "path";
124815
126001
  function createDefaultGlobalConfig() {
@@ -125399,7 +126585,7 @@ function getOrCreateUserID() {
125399
126585
  if (config.userID) {
125400
126586
  return config.userID;
125401
126587
  }
125402
- const userID = randomBytes5(32).toString("hex");
126588
+ const userID = randomBytes6(32).toString("hex");
125403
126589
  saveGlobalConfig((current) => ({ ...current, userID }));
125404
126590
  return userID;
125405
126591
  }
@@ -126523,7 +127709,7 @@ var init_constants6 = __esm(() => {
126523
127709
  var TASK_OUTPUT_TOOL_NAME2 = "TaskOutput";
126524
127710
 
126525
127711
  // src/tui/tools/TaskStopTool/prompt.ts
126526
- var TASK_STOP_TOOL_NAME2 = "TaskStop", DESCRIPTION17 = `
127712
+ var TASK_STOP_TOOL_NAME2 = "TaskStop", DESCRIPTION18 = `
126527
127713
  - Stops a running background task by its ID
126528
127714
  - Takes a task_id parameter identifying the task to stop
126529
127715
  - Returns a success or failure status
@@ -135324,7 +136510,7 @@ ${lineFormat}
135324
136510
  - You will regularly be asked to read screenshots. If the user provides a path to a screenshot, ALWAYS use this tool to view the file at the path. This tool will work with all temporary file paths.
135325
136511
  - If you read a file that exists but has empty contents you will receive a system reminder warning in place of file contents.`;
135326
136512
  }
135327
- var FILE_READ_TOOL_NAME2 = "Read", FILE_UNCHANGED_STUB2 = "File unchanged since last read. The content from the earlier Read tool_result in this conversation is still current — refer to that instead of re-reading.", MAX_LINES_TO_READ2 = 2000, DESCRIPTION18 = "Read a file from the local filesystem.", LINE_FORMAT_INSTRUCTION2 = "- Results are returned using cat -n format, with line numbers starting at 1", OFFSET_INSTRUCTION_DEFAULT2 = "- You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters", OFFSET_INSTRUCTION_TARGETED2 = "- When you already know which part of the file you need, only read that part. This can be important for larger files.";
136513
+ var FILE_READ_TOOL_NAME2 = "Read", FILE_UNCHANGED_STUB2 = "File unchanged since last read. The content from the earlier Read tool_result in this conversation is still current — refer to that instead of re-reading.", MAX_LINES_TO_READ2 = 2000, DESCRIPTION19 = "Read a file from the local filesystem.", LINE_FORMAT_INSTRUCTION2 = "- Results are returned using cat -n format, with line numbers starting at 1", OFFSET_INSTRUCTION_DEFAULT2 = "- You can optionally specify a line offset and limit (especially handy for long files), but it's recommended to read the whole file by not providing these parameters", OFFSET_INSTRUCTION_TARGETED2 = "- When you already know which part of the file you need, only read that part. This can be important for larger files.";
135328
136514
  var init_prompt2 = __esm(() => {
135329
136515
  init_pdfUtils2();
135330
136516
  init_toolName();
@@ -135347,9 +136533,9 @@ var init_outputsScanner = __esm(() => {
135347
136533
  });
135348
136534
 
135349
136535
  // src/tui/utils/words.ts
135350
- import { randomBytes as randomBytes6 } from "crypto";
136536
+ import { randomBytes as randomBytes7 } from "crypto";
135351
136537
  function randomInt2(max) {
135352
- const bytes = randomBytes6(4);
136538
+ const bytes = randomBytes7(4);
135353
136539
  const value = bytes.readUInt32BE(0);
135354
136540
  return value % max;
135355
136541
  }
@@ -153304,28 +154490,28 @@ function getEventPriority(eventType) {
153304
154490
  case "focus":
153305
154491
  case "blur":
153306
154492
  case "paste":
153307
- return import_constants56.DiscreteEventPriority;
154493
+ return import_constants57.DiscreteEventPriority;
153308
154494
  case "resize":
153309
154495
  case "scroll":
153310
154496
  case "mousemove":
153311
- return import_constants56.ContinuousEventPriority;
154497
+ return import_constants57.ContinuousEventPriority;
153312
154498
  default:
153313
- return import_constants56.DefaultEventPriority;
154499
+ return import_constants57.DefaultEventPriority;
153314
154500
  }
153315
154501
  }
153316
154502
 
153317
154503
  class Dispatcher {
153318
154504
  currentEvent = null;
153319
- currentUpdatePriority = import_constants56.DefaultEventPriority;
154505
+ currentUpdatePriority = import_constants57.DefaultEventPriority;
153320
154506
  discreteUpdates = null;
153321
154507
  resolveEventPriority() {
153322
- if (this.currentUpdatePriority !== import_constants56.NoEventPriority) {
154508
+ if (this.currentUpdatePriority !== import_constants57.NoEventPriority) {
153323
154509
  return this.currentUpdatePriority;
153324
154510
  }
153325
154511
  if (this.currentEvent) {
153326
154512
  return getEventPriority(this.currentEvent.type);
153327
154513
  }
153328
- return import_constants56.DefaultEventPriority;
154514
+ return import_constants57.DefaultEventPriority;
153329
154515
  }
153330
154516
  dispatch(target, event) {
153331
154517
  const previousEvent = this.currentEvent;
@@ -153350,18 +154536,18 @@ class Dispatcher {
153350
154536
  dispatchContinuous(target, event) {
153351
154537
  const previousPriority = this.currentUpdatePriority;
153352
154538
  try {
153353
- this.currentUpdatePriority = import_constants56.ContinuousEventPriority;
154539
+ this.currentUpdatePriority = import_constants57.ContinuousEventPriority;
153354
154540
  return this.dispatch(target, event);
153355
154541
  } finally {
153356
154542
  this.currentUpdatePriority = previousPriority;
153357
154543
  }
153358
154544
  }
153359
154545
  }
153360
- var import_constants56;
154546
+ var import_constants57;
153361
154547
  var init_dispatcher = __esm(() => {
153362
154548
  init_log5();
153363
154549
  init_event_handlers();
153364
- import_constants56 = __toESM(require_constants2(), 1);
154550
+ import_constants57 = __toESM(require_constants2(), 1);
153365
154551
  });
153366
154552
 
153367
154553
  // src/tui/ink/events/terminal-event.ts
@@ -162168,7 +163354,7 @@ function applyPositionedHighlight(screen, stylePool, positions, rowOffset, curre
162168
163354
  }
162169
163355
  return true;
162170
163356
  }
162171
- var import_constants58, timing;
163357
+ var import_constants59, timing;
162172
163358
  var init_render_to_screen = __esm(() => {
162173
163359
  init_debug();
162174
163360
  init_dom();
@@ -162177,7 +163363,7 @@ var init_render_to_screen = __esm(() => {
162177
163363
  init_reconciler();
162178
163364
  init_render_node_to_output();
162179
163365
  init_screen();
162180
- import_constants58 = __toESM(require_constants2(), 1);
163366
+ import_constants59 = __toESM(require_constants2(), 1);
162181
163367
  timing = { reconcile: 0, yoga: 0, paint: 0, scan: 0, calls: 0 };
162182
163368
  });
162183
163369
 
@@ -162483,7 +163669,7 @@ class Ink {
162483
163669
  };
162484
163670
  }
162485
163671
  };
162486
- this.container = reconciler_default.createContainer(this.rootNode, import_constants59.ConcurrentRoot, null, false, null, "id", noop_default, noop_default, noop_default, noop_default);
163672
+ this.container = reconciler_default.createContainer(this.rootNode, import_constants60.ConcurrentRoot, null, false, null, "id", noop_default, noop_default, noop_default, noop_default);
162487
163673
  if (false) {}
162488
163674
  }
162489
163675
  handleResume = () => {
@@ -163296,7 +164482,7 @@ function drainStdin(stdin = process.stdin) {
163296
164482
  }
163297
164483
  }
163298
164484
  }
163299
- var import_constants59, jsx_dev_runtime8, ALT_SCREEN_ANCHOR_CURSOR, CURSOR_HOME_PATCH, ERASE_THEN_HOME_PATCH, CONSOLE_STDOUT_METHODS, CONSOLE_STDERR_METHODS;
164485
+ var import_constants60, jsx_dev_runtime8, ALT_SCREEN_ANCHOR_CURSOR, CURSOR_HOME_PATCH, ERASE_THEN_HOME_PATCH, CONSOLE_STDOUT_METHODS, CONSOLE_STDERR_METHODS;
163300
164486
  var init_ink = __esm(() => {
163301
164487
  init_noop();
163302
164488
  init_throttle2();
@@ -163329,7 +164515,7 @@ var init_ink = __esm(() => {
163329
164515
  init_dec();
163330
164516
  init_osc();
163331
164517
  init_useTerminalNotification();
163332
- import_constants59 = __toESM(require_constants2(), 1);
164518
+ import_constants60 = __toESM(require_constants2(), 1);
163333
164519
  jsx_dev_runtime8 = __toESM(require_jsx_dev_runtime(), 1);
163334
164520
  ALT_SCREEN_ANCHOR_CURSOR = Object.freeze({
163335
164521
  x: 0,
@@ -173089,7 +174275,7 @@ var init_agentMemorySnapshot = __esm(() => {
173089
174275
  });
173090
174276
 
173091
174277
  // src/tui/tools/GlobTool/prompt.ts
173092
- var GLOB_TOOL_NAME2 = "Glob", DESCRIPTION19 = `- Fast file pattern matching tool that works with any codebase size
174278
+ var GLOB_TOOL_NAME2 = "Glob", DESCRIPTION20 = `- Fast file pattern matching tool that works with any codebase size
173093
174279
  - Supports glob patterns like "**/*.js" or "src/**/*.ts"
173094
174280
  - Returns matching file paths sorted by modification time
173095
174281
  - Use this tool when you need to find files by name patterns
@@ -173136,7 +174322,7 @@ ${prompt}
173136
174322
  ${guidelines}
173137
174323
  `;
173138
174324
  }
173139
- var WEB_FETCH_TOOL_NAME2 = "WebFetch", DESCRIPTION20 = `
174325
+ var WEB_FETCH_TOOL_NAME2 = "WebFetch", DESCRIPTION21 = `
173140
174326
  - Fetches content from a specified URL and processes it using an AI model
173141
174327
  - Takes a URL and a prompt as input
173142
174328
  - Fetches the URL content, converts HTML to markdown
@@ -182359,7 +183545,7 @@ var TODO_WRITE_TOOL_NAME2 = "TodoWrite";
182359
183545
  var TASK_CREATE_TOOL_NAME2 = "TaskCreate";
182360
183546
 
182361
183547
  // src/tui/tools/AskUserQuestionTool/prompt.ts
182362
- var ASK_USER_QUESTION_TOOL_NAME2 = "AskUserQuestion", ASK_USER_QUESTION_TOOL_CHIP_WIDTH2 = 12, DESCRIPTION21 = "Asks the user multiple choice questions to gather information, clarify ambiguity, understand preferences, make decisions or offer them choices.", PREVIEW_FEATURE_PROMPT2, ASK_USER_QUESTION_TOOL_PROMPT2;
183548
+ var ASK_USER_QUESTION_TOOL_NAME2 = "AskUserQuestion", ASK_USER_QUESTION_TOOL_CHIP_WIDTH2 = 12, DESCRIPTION22 = "Asks the user multiple choice questions to gather information, clarify ambiguity, understand preferences, make decisions or offer them choices.", PREVIEW_FEATURE_PROMPT2, ASK_USER_QUESTION_TOOL_PROMPT2;
182363
183549
  var init_prompt8 = __esm(() => {
182364
183550
  PREVIEW_FEATURE_PROMPT2 = {
182365
183551
  markdown: `
@@ -182900,6 +184086,7 @@ __export(exports_engineCompat, {
182900
184086
  WEB_SEARCH_TOOL_NAME: () => WEB_SEARCH_TOOL_NAME,
182901
184087
  WORKER_AGENT: () => WORKER_AGENT,
182902
184088
  WORKFLOW_TOOL_NAME: () => WORKFLOW_TOOL_NAME,
184089
+ WaitForTeammatesTool: () => WaitForTeammatesTool,
182903
184090
  WebFetchTool: () => WebFetchTool,
182904
184091
  WebSearchTool: () => WebSearchTool,
182905
184092
  WriteTool: () => WriteTool,
@@ -183362,6 +184549,7 @@ __export(exports_engineCompat, {
183362
184549
  removeExtraFields: () => removeExtraFields,
183363
184550
  renderableSearchText: () => renderableSearchText,
183364
184551
  reportAutoCompactCircuitFailures: () => reportAutoCompactCircuitFailures,
184552
+ requireTeammateSpawnTrigger: () => requireTeammateSpawnTrigger,
183365
184553
  resetAutoCompactCircuitForTesting: () => resetAutoCompactCircuitForTesting,
183366
184554
  resetBackgroundAgentTracker: () => resetBackgroundAgentTracker,
183367
184555
  resetBuiltinCommandNamesSourceForTesting: () => resetBuiltinCommandNamesSourceForTesting,
@@ -183389,6 +184577,7 @@ __export(exports_engineCompat, {
183389
184577
  resetTaskNotificationHandler: () => resetTaskNotificationHandler,
183390
184578
  resetTeamFileLoader: () => resetTeamFileLoader,
183391
184579
  resetTeamServices: () => resetTeamServices,
184580
+ resetTeammateSpawnTrigger: () => resetTeammateSpawnTrigger,
183392
184581
  resetWorktreeGitCaches: () => resetWorktreeGitCaches,
183393
184582
  resolveAgentTools: () => resolveAgentTools,
183394
184583
  resolveAutoCompactWindow: () => resolveAutoCompactWindow,
@@ -183451,6 +184640,7 @@ __export(exports_engineCompat, {
183451
184640
  setTaskNotificationHandler: () => setTaskNotificationHandler,
183452
184641
  setTeamFileLoader: () => setTeamFileLoader,
183453
184642
  setTeamServices: () => setTeamServices,
184643
+ setTeammateSpawnTrigger: () => setTeammateSpawnTrigger,
183454
184644
  setTimeBasedMCConfigSource: () => setTimeBasedMCConfigSource,
183455
184645
  setWebSearchSettingsKeyProvider: () => setWebSearchSettingsKeyProvider,
183456
184646
  setWebSearchTransportForTesting: () => setWebSearchTransportForTesting,
@@ -192614,14 +193804,14 @@ var init_terminal2 = __esm(() => {
192614
193804
  });
192615
193805
 
192616
193806
  // src/tui/tools/ListMcpResourcesTool/prompt.ts
192617
- var LIST_MCP_RESOURCES_TOOL_NAME2 = "ListMcpResourcesTool", DESCRIPTION22 = `
193807
+ var LIST_MCP_RESOURCES_TOOL_NAME2 = "ListMcpResourcesTool", DESCRIPTION23 = `
192618
193808
  Lists available resources from configured MCP servers.
192619
193809
  Each resource object includes a 'server' field indicating which server it's from.
192620
193810
 
192621
193811
  Usage examples:
192622
193812
  - List all resources from all servers: \`listMcpResources\`
192623
193813
  - List resources from a specific server: \`listMcpResources({ server: "myserver" })\`
192624
- `, PROMPT10 = `
193814
+ `, PROMPT11 = `
192625
193815
  List available resources from configured MCP servers.
192626
193816
  Each returned resource will include all standard MCP resource fields plus a 'server' field
192627
193817
  indicating which server the resource belongs to.
@@ -192860,10 +194050,10 @@ var init_ListMcpResourcesTool = __esm(() => {
192860
194050
  searchHint: "list resources from connected MCP servers",
192861
194051
  maxResultSizeChars: 1e5,
192862
194052
  async description() {
192863
- return DESCRIPTION22;
194053
+ return DESCRIPTION23;
192864
194054
  },
192865
194055
  async prompt() {
192866
- return PROMPT10;
194056
+ return PROMPT11;
192867
194057
  },
192868
194058
  get inputSchema() {
192869
194059
  return inputSchema4();
@@ -192916,7 +194106,7 @@ var init_ListMcpResourcesTool = __esm(() => {
192916
194106
  });
192917
194107
 
192918
194108
  // src/tui/tools/MCPTool/prompt.ts
192919
- var PROMPT11 = "", DESCRIPTION23 = "";
194109
+ var PROMPT12 = "", DESCRIPTION24 = "";
192920
194110
 
192921
194111
  // src/tui/components/Spinner/utils.ts
192922
194112
  function getDefaultCharacters() {
@@ -194217,10 +195407,10 @@ var init_MCPTool = __esm(() => {
194217
195407
  name: "mcp",
194218
195408
  maxResultSizeChars: 1e5,
194219
195409
  async description() {
194220
- return DESCRIPTION23;
195410
+ return DESCRIPTION24;
194221
195411
  },
194222
195412
  async prompt() {
194223
- return PROMPT11;
195413
+ return PROMPT12;
194224
195414
  },
194225
195415
  get inputSchema() {
194226
195416
  return inputSchema5();
@@ -197597,7 +198787,7 @@ var init_xaa = __esm(() => {
197597
198787
  });
197598
198788
 
197599
198789
  // src/tui/services/mcp/xaaIdpLogin.ts
197600
- import { randomBytes as randomBytes7 } from "crypto";
198790
+ import { randomBytes as randomBytes8 } from "crypto";
197601
198791
  import { createServer as createServer2 } from "http";
197602
198792
  import { parse as parse10 } from "url";
197603
198793
  function isXaaEnabled() {
@@ -197822,7 +199012,7 @@ async function acquireIdpIdToken(opts) {
197822
199012
  const metadata = await discoverOidc(idpIssuer);
197823
199013
  const port = opts.callbackPort ?? await findAvailablePort();
197824
199014
  const redirectUri = buildRedirectUri(port);
197825
- const state = randomBytes7(32).toString("base64url");
199015
+ const state = randomBytes8(32).toString("base64url");
197826
199016
  const clientInformation = {
197827
199017
  client_id: idpClientId,
197828
199018
  ...opts.idpClientSecret ? { client_secret: opts.idpClientSecret } : {}
@@ -197881,7 +199071,7 @@ var init_xaaIdpLogin = __esm(() => {
197881
199071
  });
197882
199072
 
197883
199073
  // src/tui/services/mcp/auth.ts
197884
- import { createHash as createHash5, randomBytes as randomBytes8, randomUUID as randomUUID24 } from "crypto";
199074
+ import { createHash as createHash5, randomBytes as randomBytes9, randomUUID as randomUUID24 } from "crypto";
197885
199075
  import { mkdir as mkdir17 } from "fs/promises";
197886
199076
  import { createServer as createServer3 } from "http";
197887
199077
  import { join as join80 } from "path";
@@ -198664,7 +199854,7 @@ class ClaudeAuthProvider {
198664
199854
  }
198665
199855
  async state() {
198666
199856
  if (!this._state) {
198667
- this._state = randomBytes8(32).toString("base64url");
199857
+ this._state = randomBytes9(32).toString("base64url");
198668
199858
  logMCPDebug(this.serverName, "Generated new OAuth state");
198669
199859
  }
198670
199860
  return this._state;
@@ -199853,14 +201043,14 @@ var init_mcpOutputStorage = __esm(() => {
199853
201043
  });
199854
201044
 
199855
201045
  // src/tui/tools/ReadMcpResourceTool/prompt.ts
199856
- var DESCRIPTION24 = `
201046
+ var DESCRIPTION25 = `
199857
201047
  Reads a specific resource from an MCP server.
199858
201048
  - server: The name of the MCP server to read from
199859
201049
  - uri: The URI of the resource to read
199860
201050
 
199861
201051
  Usage examples:
199862
201052
  - Read a resource from a server: \`readMcpResource({ server: "myserver", uri: "my-resource-uri" })\`
199863
- `, PROMPT12 = `
201053
+ `, PROMPT13 = `
199864
201054
  Reads a specific resource from an MCP server, identified by server name and resource URI.
199865
201055
 
199866
201056
  Parameters:
@@ -199948,10 +201138,10 @@ var init_ReadMcpResourceTool = __esm(() => {
199948
201138
  searchHint: "read a specific MCP resource by URI",
199949
201139
  maxResultSizeChars: 1e5,
199950
201140
  async description() {
199951
- return DESCRIPTION24;
201141
+ return DESCRIPTION25;
199952
201142
  },
199953
201143
  async prompt() {
199954
- return PROMPT12;
201144
+ return PROMPT13;
199955
201145
  },
199956
201146
  get inputSchema() {
199957
201147
  return inputSchema7();
@@ -200552,7 +201742,7 @@ var init_auth4 = __esm(() => {
200552
201742
  });
200553
201743
 
200554
201744
  // src/tui/utils/workloadContext.ts
200555
- import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
201745
+ import { AsyncLocalStorage as AsyncLocalStorage3 } from "async_hooks";
200556
201746
  function getWorkload() {
200557
201747
  return workloadStorage.getStore()?.workload;
200558
201748
  }
@@ -200561,7 +201751,7 @@ function runWithWorkload(workload, fn) {
200561
201751
  }
200562
201752
  var WORKLOAD_CRON = "cron", workloadStorage;
200563
201753
  var init_workloadContext = __esm(() => {
200564
- workloadStorage = new AsyncLocalStorage4;
201754
+ workloadStorage = new AsyncLocalStorage3;
200565
201755
  });
200566
201756
 
200567
201757
  // src/tui/utils/http.ts
@@ -203273,10 +204463,10 @@ function parseProxyResponse(socket) {
203273
204463
  read();
203274
204464
  });
203275
204465
  }
203276
- var import_debug54, debug;
204466
+ var import_debug55, debug;
203277
204467
  var init_parse_proxy_response = __esm(() => {
203278
- import_debug54 = __toESM(require_src(), 1);
203279
- debug = import_debug54.default("https-proxy-agent:parse-proxy-response");
204468
+ import_debug55 = __toESM(require_src(), 1);
204469
+ debug = import_debug55.default("https-proxy-agent:parse-proxy-response");
203280
204470
  });
203281
204471
 
203282
204472
  // node_modules/proxy-agent-negotiate/dist/index.js
@@ -203329,7 +204519,7 @@ function omit2(obj, ...keys) {
203329
204519
  }
203330
204520
  return ret;
203331
204521
  }
203332
- var import_debug55, debug2, setServernameFromNonIpHost = (options) => {
204522
+ var import_debug56, debug2, setServernameFromNonIpHost = (options) => {
203333
204523
  if (options.servername === undefined && options.host && !net2.isIP(options.host)) {
203334
204524
  return {
203335
204525
  ...options,
@@ -203341,8 +204531,8 @@ var import_debug55, debug2, setServernameFromNonIpHost = (options) => {
203341
204531
  var init_dist7 = __esm(() => {
203342
204532
  init_dist6();
203343
204533
  init_parse_proxy_response();
203344
- import_debug55 = __toESM(require_src(), 1);
203345
- debug2 = import_debug55.default("https-proxy-agent");
204534
+ import_debug56 = __toESM(require_src(), 1);
204535
+ debug2 = import_debug56.default("https-proxy-agent");
203346
204536
  HttpsProxyAgent2 = class HttpsProxyAgent2 extends Agent2 {
203347
204537
  constructor(proxy, opts) {
203348
204538
  super(opts);
@@ -204462,7 +205652,7 @@ var init_use_declared_cursor = __esm(() => {
204462
205652
  });
204463
205653
 
204464
205654
  // src/tui/utils/imagePaste.ts
204465
- import { randomBytes as randomBytes9 } from "crypto";
205655
+ import { randomBytes as randomBytes10 } from "crypto";
204466
205656
  import { basename as basename20, extname as extname8, isAbsolute as isAbsolute18, join as join86 } from "path";
204467
205657
  function getClipboardCommands() {
204468
205658
  const platform = process.platform;
@@ -204621,7 +205811,7 @@ function stripBackslashEscapes(path) {
204621
205811
  if (platform === "win32") {
204622
205812
  return path;
204623
205813
  }
204624
- const salt = randomBytes9(8).toString("hex");
205814
+ const salt = randomBytes10(8).toString("hex");
204625
205815
  const placeholder = `__DOUBLE_BACKSLASH_${salt}__`;
204626
205816
  const withPlaceholder = path.replace(/\\\\/g, placeholder);
204627
205817
  const withoutEscapes = withPlaceholder.replace(/\\(.)/g, "$1");
@@ -207029,7 +208219,7 @@ __export(exports_terminalSetup, {
207029
208219
  setupTerminal: () => setupTerminal,
207030
208220
  shouldOfferTerminalSetup: () => shouldOfferTerminalSetup
207031
208221
  });
207032
- import { randomBytes as randomBytes10 } from "crypto";
208222
+ import { randomBytes as randomBytes11 } from "crypto";
207033
208223
  import { copyFile as copyFile3, mkdir as mkdir20, readFile as readFile25, writeFile as writeFile14 } from "fs/promises";
207034
208224
  import { homedir as homedir27, platform as platform3 } from "os";
207035
208225
  import { dirname as dirname45, join as join89 } from "path";
@@ -207186,7 +208376,7 @@ async function installBindingsForVSCodeTerminal(editor = "VSCode", theme) {
207186
208376
  throw e;
207187
208377
  }
207188
208378
  if (fileExists) {
207189
- const randomSha = randomBytes10(4).toString("hex");
208379
+ const randomSha = randomBytes11(4).toString("hex");
207190
208380
  const backupPath = `${keybindingsPath}.${randomSha}.bak`;
207191
208381
  try {
207192
208382
  await copyFile3(keybindingsPath, backupPath);
@@ -207345,7 +208535,7 @@ chars = "\\u001B\\r"`;
207345
208535
  if (configContent.includes('mods = "Shift"') && configContent.includes('key = "Return"')) {
207346
208536
  return `${color("warning", theme)("Found existing Alacritty Shift+Enter key binding. Remove it to continue.")}${EOL}${source_default.dim(`See ${formatPathLink(configPath)}`)}${EOL}`;
207347
208537
  }
207348
- const randomSha = randomBytes10(4).toString("hex");
208538
+ const randomSha = randomBytes11(4).toString("hex");
207349
208539
  const backupPath = `${configPath}.${randomSha}.bak`;
207350
208540
  try {
207351
208541
  await copyFile3(configPath, backupPath);
@@ -207397,7 +208587,7 @@ async function installBindingsForZed(theme) {
207397
208587
  if (keymapContent.includes("shift-enter")) {
207398
208588
  return `${color("warning", theme)("Found existing Zed Shift+Enter key binding. Remove it to continue.")}${EOL}${source_default.dim(`See ${formatPathLink(keymapPath)}`)}${EOL}`;
207399
208589
  }
207400
- const randomSha = randomBytes10(4).toString("hex");
208590
+ const randomSha = randomBytes11(4).toString("hex");
207401
208591
  const backupPath = `${keymapPath}.${randomSha}.bak`;
207402
208592
  try {
207403
208593
  await copyFile3(keymapPath, backupPath);
@@ -261406,7 +262596,7 @@ var init_GlobTool = __esm(() => {
261406
262596
  searchHint: "find files by name pattern or wildcard",
261407
262597
  maxResultSizeChars: 1e5,
261408
262598
  async description() {
261409
- return DESCRIPTION19;
262599
+ return DESCRIPTION20;
261410
262600
  },
261411
262601
  userFacingName: userFacingName3,
261412
262602
  getToolUseSummary: getToolUseSummary3,
@@ -261478,7 +262668,7 @@ var init_GlobTool = __esm(() => {
261478
262668
  return checkReadPermissionForTool2(GlobTool2, input, appState.toolPermissionContext);
261479
262669
  },
261480
262670
  async prompt() {
261481
- return DESCRIPTION19;
262671
+ return DESCRIPTION20;
261482
262672
  },
261483
262673
  renderToolUseMessage: renderToolUseMessage6,
261484
262674
  renderToolUseErrorMessage: renderToolUseErrorMessage3,
@@ -262009,52 +263199,30 @@ function getMaxBashTimeoutMs2(env = process.env) {
262009
263199
  }
262010
263200
  var DEFAULT_TIMEOUT_MS2 = 120000, MAX_TIMEOUT_MS2 = 600000;
262011
263201
 
262012
- // src/tui/utils/teammateContext.ts
262013
- import { AsyncLocalStorage as AsyncLocalStorage5 } from "async_hooks";
262014
- function getTeammateContext3() {
262015
- return teammateContextStorage3.getStore();
262016
- }
262017
- function runWithTeammateContext3(context, fn) {
262018
- return teammateContextStorage3.run(context, fn);
262019
- }
262020
- function isInProcessTeammate3() {
262021
- return teammateContextStorage3.getStore() !== undefined;
262022
- }
262023
- function createTeammateContext3(config) {
262024
- return {
262025
- ...config,
262026
- isInProcess: true
262027
- };
262028
- }
262029
- var teammateContextStorage3;
262030
- var init_teammateContext3 = __esm(() => {
262031
- teammateContextStorage3 = new AsyncLocalStorage5;
262032
- });
262033
-
262034
263202
  // src/tui/utils/teammate.ts
262035
263203
  var exports_teammate = {};
262036
263204
  __export(exports_teammate, {
262037
263205
  clearDynamicTeamContext: () => clearDynamicTeamContext2,
262038
- createTeammateContext: () => createTeammateContext3,
263206
+ createTeammateContext: () => createTeammateContext,
262039
263207
  getAgentId: () => getAgentId2,
262040
263208
  getAgentName: () => getAgentName2,
262041
263209
  getDynamicTeamContext: () => getDynamicTeamContext2,
262042
263210
  getParentSessionId: () => getParentSessionId2,
262043
263211
  getTeamName: () => getTeamName2,
262044
263212
  getTeammateColor: () => getTeammateColor3,
262045
- getTeammateContext: () => getTeammateContext3,
263213
+ getTeammateContext: () => getTeammateContext,
262046
263214
  hasActiveInProcessTeammates: () => hasActiveInProcessTeammates2,
262047
263215
  hasWorkingInProcessTeammates: () => hasWorkingInProcessTeammates2,
262048
- isInProcessTeammate: () => isInProcessTeammate3,
263216
+ isInProcessTeammate: () => isInProcessTeammate,
262049
263217
  isPlanModeRequired: () => isPlanModeRequired2,
262050
263218
  isTeamLead: () => isTeamLead2,
262051
263219
  isTeammate: () => isTeammate2,
262052
- runWithTeammateContext: () => runWithTeammateContext3,
263220
+ runWithTeammateContext: () => runWithTeammateContext,
262053
263221
  setDynamicTeamContext: () => setDynamicTeamContext2,
262054
263222
  waitForTeammatesToBecomeIdle: () => waitForTeammatesToBecomeIdle2
262055
263223
  });
262056
263224
  function getParentSessionId2() {
262057
- const inProcessCtx = getTeammateContext3();
263225
+ const inProcessCtx = getTeammateContext();
262058
263226
  if (inProcessCtx)
262059
263227
  return inProcessCtx.parentSessionId;
262060
263228
  return dynamicTeamContext2?.parentSessionId;
@@ -262069,19 +263237,19 @@ function getDynamicTeamContext2() {
262069
263237
  return dynamicTeamContext2;
262070
263238
  }
262071
263239
  function getAgentId2() {
262072
- const inProcessCtx = getTeammateContext3();
263240
+ const inProcessCtx = getTeammateContext();
262073
263241
  if (inProcessCtx)
262074
263242
  return inProcessCtx.agentId;
262075
263243
  return dynamicTeamContext2?.agentId;
262076
263244
  }
262077
263245
  function getAgentName2() {
262078
- const inProcessCtx = getTeammateContext3();
263246
+ const inProcessCtx = getTeammateContext();
262079
263247
  if (inProcessCtx)
262080
263248
  return inProcessCtx.agentName;
262081
263249
  return dynamicTeamContext2?.agentName;
262082
263250
  }
262083
263251
  function getTeamName2(teamContext) {
262084
- const inProcessCtx = getTeammateContext3();
263252
+ const inProcessCtx = getTeammateContext();
262085
263253
  if (inProcessCtx)
262086
263254
  return inProcessCtx.teamName;
262087
263255
  if (dynamicTeamContext2?.teamName)
@@ -262089,19 +263257,19 @@ function getTeamName2(teamContext) {
262089
263257
  return teamContext?.teamName;
262090
263258
  }
262091
263259
  function isTeammate2() {
262092
- const inProcessCtx = getTeammateContext3();
263260
+ const inProcessCtx = getTeammateContext();
262093
263261
  if (inProcessCtx)
262094
263262
  return true;
262095
263263
  return !!(dynamicTeamContext2?.agentId && dynamicTeamContext2?.teamName);
262096
263264
  }
262097
263265
  function getTeammateColor3() {
262098
- const inProcessCtx = getTeammateContext3();
263266
+ const inProcessCtx = getTeammateContext();
262099
263267
  if (inProcessCtx)
262100
263268
  return inProcessCtx.color;
262101
263269
  return dynamicTeamContext2?.color;
262102
263270
  }
262103
263271
  function isPlanModeRequired2() {
262104
- const inProcessCtx = getTeammateContext3();
263272
+ const inProcessCtx = getTeammateContext();
262105
263273
  if (inProcessCtx)
262106
263274
  return inProcessCtx.planModeRequired;
262107
263275
  if (dynamicTeamContext2 !== null) {
@@ -262178,9 +263346,9 @@ function waitForTeammatesToBecomeIdle2(setAppState, appState) {
262178
263346
  }
262179
263347
  var dynamicTeamContext2 = null;
262180
263348
  var init_teammate2 = __esm(() => {
262181
- init_teammateContext3();
263349
+ init_teammateContext();
262182
263350
  init_envUtils2();
262183
- init_teammateContext3();
263351
+ init_shared();
262184
263352
  });
262185
263353
 
262186
263354
  // src/tui/utils/tasks.ts
@@ -262264,7 +263432,7 @@ function getTaskListId2() {
262264
263432
  if (process.env.ATLAS_TASK_LIST_ID) {
262265
263433
  return process.env.ATLAS_TASK_LIST_ID;
262266
263434
  }
262267
- const teammateCtx = getTeammateContext3();
263435
+ const teammateCtx = getTeammateContext();
262268
263436
  if (teammateCtx) {
262269
263437
  return teammateCtx.teamName;
262270
263438
  }
@@ -262488,7 +263656,7 @@ var init_tasks5 = __esm(() => {
262488
263656
  init_log5();
262489
263657
  init_slowOperations();
262490
263658
  init_teammate2();
262491
- init_teammateContext3();
263659
+ init_shared();
262492
263660
  tasksUpdated2 = createSignal3();
262493
263661
  onTasksUpdated2 = tasksUpdated2.subscribe;
262494
263662
  TaskStatusSchema2 = lazySchema2(() => _enum(["pending", "in_progress", "completed"]));
@@ -262526,10 +263694,10 @@ var init_types13 = __esm(() => {
262526
263694
  });
262527
263695
 
262528
263696
  // src/tui/tools/TodoWriteTool/prompt.ts
262529
- var PROMPT13, DESCRIPTION25 = "Update the todo list for the current session. To be used proactively and often to track progress and pending tasks. Make sure that at least one task is in_progress at all times. Always provide both content (imperative) and activeForm (present continuous) for each task.";
263697
+ var PROMPT14, DESCRIPTION26 = "Update the todo list for the current session. To be used proactively and often to track progress and pending tasks. Make sure that at least one task is in_progress at all times. Always provide both content (imperative) and activeForm (present continuous) for each task.";
262530
263698
  var init_prompt10 = __esm(() => {
262531
263699
  init_constants8();
262532
- PROMPT13 = `Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
263700
+ PROMPT14 = `Use this tool to create and manage a structured task list for your current coding session. This helps you track progress, organize complex tasks, and demonstrate thoroughness to the user.
262533
263701
  It also helps the user understand the progress of the task and overall progress of their requests.
262534
263702
 
262535
263703
  ## When to Use This Tool
@@ -262736,10 +263904,10 @@ var init_TodoWriteTool = __esm(() => {
262736
263904
  maxResultSizeChars: 1e5,
262737
263905
  strict: true,
262738
263906
  async description() {
262739
- return DESCRIPTION25;
263907
+ return DESCRIPTION26;
262740
263908
  },
262741
263909
  async prompt() {
262742
- return PROMPT13;
263910
+ return PROMPT14;
262743
263911
  },
262744
263912
  get inputSchema() {
262745
263913
  return inputSchema11();
@@ -263406,7 +264574,7 @@ function isAgentSwarmsEnabled2() {
263406
264574
  }
263407
264575
  return true;
263408
264576
  }
263409
- var init_agentSwarmsEnabled2 = __esm(() => {
264577
+ var init_agentSwarmsEnabled3 = __esm(() => {
263410
264578
  init_growthbook();
263411
264579
  init_envUtils2();
263412
264580
  });
@@ -264563,14 +265731,14 @@ var init_agent2 = __esm(() => {
264563
265731
  });
264564
265732
 
264565
265733
  // src/tui/utils/uuid.ts
264566
- import { randomBytes as randomBytes11 } from "crypto";
265734
+ import { randomBytes as randomBytes12 } from "crypto";
264567
265735
  function validateUuid2(maybeUuid) {
264568
265736
  if (typeof maybeUuid !== "string")
264569
265737
  return null;
264570
265738
  return uuidRegex2.test(maybeUuid) ? maybeUuid : null;
264571
265739
  }
264572
265740
  function createAgentId(label) {
264573
- const suffix = randomBytes11(8).toString("hex");
265741
+ const suffix = randomBytes12(8).toString("hex");
264574
265742
  return label ? `a${label}-${suffix}` : `a${suffix}`;
264575
265743
  }
264576
265744
  var uuidRegex2;
@@ -266580,7 +267748,7 @@ var init_notebook3 = __esm(() => {
266580
267748
  });
266581
267749
 
266582
267750
  // src/tui/tools/NotebookEditTool/prompt.ts
266583
- var DESCRIPTION26 = "Replace the contents of a specific cell in a Jupyter notebook.", PROMPT14 = `Completely replaces the contents of a specific cell in a Jupyter notebook (.ipynb file) with new source. Jupyter notebooks are interactive documents that combine code, text, and visualizations, commonly used for data analysis and scientific computing. The notebook_path parameter must be an absolute path, not a relative path. The cell_number is 0-indexed. Use edit_mode=insert to add a new cell at the index specified by cell_number. Use edit_mode=delete to delete the cell at the index specified by cell_number.`;
267751
+ var DESCRIPTION27 = "Replace the contents of a specific cell in a Jupyter notebook.", PROMPT15 = `Completely replaces the contents of a specific cell in a Jupyter notebook (.ipynb file) with new source. Jupyter notebooks are interactive documents that combine code, text, and visualizations, commonly used for data analysis and scientific computing. The notebook_path parameter must be an absolute path, not a relative path. The cell_number is 0-indexed. Use edit_mode=insert to add a new cell at the index specified by cell_number. Use edit_mode=delete to delete the cell at the index specified by cell_number.`;
266584
267752
 
266585
267753
  // src/tui/components/NotebookEditToolUseRejectedMessage.tsx
266586
267754
  import { relative as relative16 } from "path";
@@ -266871,10 +268039,10 @@ var init_NotebookEditTool = __esm(() => {
266871
268039
  maxResultSizeChars: 1e5,
266872
268040
  shouldDefer: true,
266873
268041
  async description() {
266874
- return DESCRIPTION26;
268042
+ return DESCRIPTION27;
266875
268043
  },
266876
268044
  async prompt() {
266877
- return PROMPT14;
268045
+ return PROMPT15;
266878
268046
  },
266879
268047
  userFacingName() {
266880
268048
  return "Edit Notebook";
@@ -274796,7 +275964,7 @@ var import_compiler_runtime85, jsx_dev_runtime93;
274796
275964
  var init_UserTextMessage = __esm(() => {
274797
275965
  init_shared();
274798
275966
  init_xml();
274799
- init_agentSwarmsEnabled2();
275967
+ init_agentSwarmsEnabled3();
274800
275968
  init_messages3();
274801
275969
  init_InterruptedByUser();
274802
275970
  init_MessageResponse();
@@ -275787,7 +276955,7 @@ var init_AttachmentMessage = __esm(() => {
275787
276955
  init_ink3();
275788
276956
  init_slowOperations();
275789
276957
  init_stringUtils2();
275790
- init_agentSwarmsEnabled2();
276958
+ init_agentSwarmsEnabled3();
275791
276959
  init_PlanApprovalMessage();
275792
276960
  init_figures2();
275793
276961
  init_UserTeammateMessage();
@@ -279972,7 +281140,7 @@ var init_UI9 = __esm(() => {
279972
281140
  });
279973
281141
 
279974
281142
  // src/tui/utils/agentContext.ts
279975
- import { AsyncLocalStorage as AsyncLocalStorage6 } from "async_hooks";
281143
+ import { AsyncLocalStorage as AsyncLocalStorage4 } from "async_hooks";
279976
281144
  function getAgentContext() {
279977
281145
  return agentContextStorage.getStore();
279978
281146
  }
@@ -279981,8 +281149,8 @@ function runWithAgentContext(context, fn) {
279981
281149
  }
279982
281150
  var agentContextStorage;
279983
281151
  var init_agentContext = __esm(() => {
279984
- init_agentSwarmsEnabled2();
279985
- agentContextStorage = new AsyncLocalStorage6;
281152
+ init_agentSwarmsEnabled3();
281153
+ agentContextStorage = new AsyncLocalStorage4;
279986
281154
  });
279987
281155
 
279988
281156
  // src/tui/utils/generators.ts
@@ -282930,7 +284098,7 @@ function filterToolsForAgent2({
282930
284098
  return false;
282931
284099
  }
282932
284100
  if (isAsync && !ASYNC_AGENT_ALLOWED_TOOLS.has(tool.name)) {
282933
- if (isAgentSwarmsEnabled2() && isInProcessTeammate3()) {
284101
+ if (isAgentSwarmsEnabled2() && isInProcessTeammate()) {
282934
284102
  if (toolMatchesName(tool, AGENT_TOOL_NAME2)) {
282935
284103
  return true;
282936
284104
  }
@@ -283274,7 +284442,7 @@ var init_agentToolUtils2 = __esm(() => {
283274
284442
  init_Tool();
283275
284443
  init_LocalAgentTask();
283276
284444
  init_ids();
283277
- init_agentSwarmsEnabled2();
284445
+ init_agentSwarmsEnabled3();
283278
284446
  init_debug();
283279
284447
  init_errors4();
283280
284448
  init_messages3();
@@ -283282,7 +284450,7 @@ var init_agentToolUtils2 = __esm(() => {
283282
284450
  init_mcpStringUtils();
283283
284451
  init_yoloClassifier();
283284
284452
  init_sdkProgress();
283285
- init_teammateContext3();
284453
+ init_shared();
283286
284454
  init_tokens();
283287
284455
  init_constants6();
283288
284456
  agentToolResultSchema = lazySchema2(() => object({
@@ -283478,7 +284646,7 @@ ${whenNotToUseSection}
283478
284646
 
283479
284647
  Usage notes:
283480
284648
  - Always include a short description (3-5 words) summarizing what the agent will do${concurrencyNote}
283481
- - When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.${!isEnvTruthy2(process.env.ATLAS_DISABLE_BACKGROUND_TASKS) && !isInProcessTeammate3() && !forkEnabled ? `
284649
+ - When the agent is done, it will return a single message back to you. The result returned by the agent is not visible to the user. To show the user the result, you should send a text message back to the user with a concise summary of the result.${!isEnvTruthy2(process.env.ATLAS_DISABLE_BACKGROUND_TASKS) && !isInProcessTeammate() && !forkEnabled ? `
283482
284650
  - Agents run in the background by default. When an agent runs in the background, you will be automatically notified when it completes — do NOT sleep, poll, or proactively check on its progress. Continue with other work or respond to the user instead.
283483
284651
  - **Foreground vs background**: Agents run in the background by default. Use foreground (set run_in_background to false) when you need the agent's results before you can proceed — e.g., research agents whose findings inform your next steps. Use background when you have genuinely independent work to do in parallel.` : ""}
283484
284652
  - To continue a previously spawned agent, use ${SEND_MESSAGE_TOOL_NAME3} with the agent's ID or name as the \`to\` field. The agent resumes with its full context preserved. ${forkEnabled ? "Each fresh Agent invocation with a subagent_type starts without context — provide a complete task description." : "Each Agent invocation starts fresh — provide a complete task description."}
@@ -283486,7 +284654,7 @@ Usage notes:
283486
284654
  - Clearly tell the agent whether you expect it to write code or just to do research (search, file reads, web fetches, etc.)${forkEnabled ? "" : ", since it is not aware of the user's intent"}
283487
284655
  - If the agent description mentions that it should be used proactively, then you should try your best to use it without the user having to ask for it first. Use your judgement.
283488
284656
  - If the user specifies that they want you to run agents "in parallel", you MUST send a single message with multiple ${AGENT_TOOL_NAME2} tool use content blocks. For example, if you need to launch both a build-validator agent and a test-runner agent in parallel, send a single message with both tool calls.
283489
- - You can optionally set \`isolation: "worktree"\` to run the agent in a temporary git worktree, giving it an isolated copy of the repository. The worktree is automatically cleaned up if the agent makes no changes; if changes are made, the worktree path and branch are returned in the result.${isInProcessTeammate3() ? `
284657
+ - You can optionally set \`isolation: "worktree"\` to run the agent in a temporary git worktree, giving it an isolated copy of the repository. The worktree is automatically cleaned up if the agent makes no changes; if changes are made, the worktree path and branch are returned in the result.${isInProcessTeammate() ? `
283490
284658
  - The run_in_background, name, team_name, and mode parameters are not available in this context. Only synchronous subagents are supported.` : isTeammate2() ? `
283491
284659
  - The name, team_name, and mode parameters are not available in this context — teammates cannot spawn other teammates. Omit them to spawn a subagent.` : ""}${whenToForkSection}${writingThePromptSection}
283492
284660
 
@@ -283497,7 +284665,7 @@ var init_prompt13 = __esm(() => {
283497
284665
  init_embeddedTools();
283498
284666
  init_envUtils2();
283499
284667
  init_teammate2();
283500
- init_teammateContext3();
284668
+ init_shared();
283501
284669
  init_prompt2();
283502
284670
  init_prompt3();
283503
284671
  init_constants6();
@@ -302427,7 +303595,7 @@ var init_WebFetchTool = __esm(() => {
302427
303595
  },
302428
303596
  async prompt(_options) {
302429
303597
  return `IMPORTANT: WebFetch WILL FAIL for authenticated or private URLs. Before using this tool, check if the URL points to an authenticated service (e.g. Google Docs, Confluence, Jira, GitHub). If so, look for a specialized MCP tool that provides authenticated access.
302430
- ${DESCRIPTION20}`;
303598
+ ${DESCRIPTION21}`;
302431
303599
  },
302432
303600
  async validateInput(input) {
302433
303601
  const { url } = input;
@@ -302903,7 +304071,7 @@ var init_TaskStopTool = __esm(() => {
302903
304071
  return `Stop a running background task by ID`;
302904
304072
  },
302905
304073
  async prompt() {
302906
- return DESCRIPTION17;
304074
+ return DESCRIPTION18;
302907
304075
  },
302908
304076
  mapToolResultToToolResultBlockParam(output, toolUseID) {
302909
304077
  return {
@@ -304126,7 +305294,7 @@ var init_ExitPlanModeV2Tool = __esm(() => {
304126
305294
  init_v4();
304127
305295
  init_bootstrapState();
304128
305296
  init_Tool();
304129
- init_agentSwarmsEnabled2();
305297
+ init_agentSwarmsEnabled3();
304130
305298
  init_debug();
304131
305299
  init_inProcessTeammateHelpers2();
304132
305300
  init_log5();
@@ -304609,7 +305777,7 @@ var init_AskUserQuestionTool = __esm(() => {
304609
305777
  maxResultSizeChars: 1e5,
304610
305778
  shouldDefer: true,
304611
305779
  async description() {
304612
- return DESCRIPTION21;
305780
+ return DESCRIPTION22;
304613
305781
  },
304614
305782
  async prompt() {
304615
305783
  const format = getQuestionPreviewFormat();
@@ -305105,7 +306273,7 @@ var init_formatters = __esm(() => {
305105
306273
  });
305106
306274
 
305107
306275
  // src/tui/tools/LSPTool/prompt.ts
305108
- var LSP_TOOL_NAME2 = "LSP", DESCRIPTION27 = `Interact with Language Server Protocol (LSP) servers to get code intelligence features.
306276
+ var LSP_TOOL_NAME2 = "LSP", DESCRIPTION28 = `Interact with Language Server Protocol (LSP) servers to get code intelligence features.
305109
306277
 
305110
306278
  Supported operations:
305111
306279
  - goToDefinition: Find where a symbol is defined
@@ -305852,7 +307020,7 @@ var init_LSPTool = __esm(() => {
305852
307020
  maxResultSizeChars: 1e5,
305853
307021
  isLsp: true,
305854
307022
  async description() {
305855
- return DESCRIPTION27;
307023
+ return DESCRIPTION28;
305856
307024
  },
305857
307025
  userFacingName: userFacingName5,
305858
307026
  shouldDefer: true,
@@ -305921,7 +307089,7 @@ var init_LSPTool = __esm(() => {
305921
307089
  return checkReadPermissionForTool2(LSPTool2, input, appState.toolPermissionContext);
305922
307090
  },
305923
307091
  async prompt() {
305924
- return DESCRIPTION27;
307092
+ return DESCRIPTION28;
305925
307093
  },
305926
307094
  renderToolUseMessage: renderToolUseMessage16,
305927
307095
  renderToolUseErrorMessage: renderToolUseErrorMessage7,
@@ -307854,7 +309022,7 @@ ${lines.join(`
307854
309022
  - model - Override the default model (sonnet, opus, haiku, best, or full model ID)`;
307855
309023
  }
307856
309024
  }
307857
- var DESCRIPTION28 = "Get or set Atlas configuration settings.";
309025
+ var DESCRIPTION29 = "Get or set Atlas configuration settings.";
307858
309026
  var init_prompt16 = __esm(() => {
307859
309027
  init_shared();
307860
309028
  init_modelOptions();
@@ -308380,7 +309548,7 @@ var init_ConfigTool = __esm(() => {
308380
309548
  searchHint: "get or set Atlas settings (theme, model)",
308381
309549
  maxResultSizeChars: 1e5,
308382
309550
  async description() {
308383
- return DESCRIPTION28;
309551
+ return DESCRIPTION29;
308384
309552
  },
308385
309553
  async prompt() {
308386
309554
  return generatePrompt2();
@@ -308676,9 +309844,9 @@ All tasks are created with status \`pending\`.
308676
309844
  ${teammateTips}- Check TaskList first to avoid creating duplicate tasks
308677
309845
  `;
308678
309846
  }
308679
- var DESCRIPTION29 = "Create a new task in the task list";
309847
+ var DESCRIPTION30 = "Create a new task in the task list";
308680
309848
  var init_prompt17 = __esm(() => {
308681
- init_agentSwarmsEnabled2();
309849
+ init_agentSwarmsEnabled3();
308682
309850
  });
308683
309851
 
308684
309852
  // src/tui/tools/TaskCreateTool/TaskCreateTool.ts
@@ -308707,7 +309875,7 @@ var init_TaskCreateTool = __esm(() => {
308707
309875
  searchHint: "create a task in the task list",
308708
309876
  maxResultSizeChars: 1e5,
308709
309877
  async description() {
308710
- return DESCRIPTION29;
309878
+ return DESCRIPTION30;
308711
309879
  },
308712
309880
  async prompt() {
308713
309881
  return getPrompt23();
@@ -308786,7 +309954,7 @@ var init_TaskCreateTool = __esm(() => {
308786
309954
  var TASK_GET_TOOL_NAME2 = "TaskGet";
308787
309955
 
308788
309956
  // src/tui/tools/TaskGetTool/prompt.ts
308789
- var DESCRIPTION30 = "Get a task by ID from the task list", PROMPT15 = `Use this tool to retrieve a task by its ID from the task list.
309957
+ var DESCRIPTION31 = "Get a task by ID from the task list", PROMPT16 = `Use this tool to retrieve a task by its ID from the task list.
308790
309958
 
308791
309959
  ## When to Use This Tool
308792
309960
 
@@ -308833,10 +310001,10 @@ var init_TaskGetTool = __esm(() => {
308833
310001
  searchHint: "retrieve a task by ID",
308834
310002
  maxResultSizeChars: 1e5,
308835
310003
  async description() {
308836
- return DESCRIPTION30;
310004
+ return DESCRIPTION31;
308837
310005
  },
308838
310006
  async prompt() {
308839
- return PROMPT15;
310007
+ return PROMPT16;
308840
310008
  },
308841
310009
  get inputSchema() {
308842
310010
  return inputSchema30();
@@ -308920,7 +310088,7 @@ var init_TaskGetTool = __esm(() => {
308920
310088
  var TASK_UPDATE_TOOL_NAME2 = "TaskUpdate";
308921
310089
 
308922
310090
  // src/tui/tools/TaskUpdateTool/prompt.ts
308923
- var DESCRIPTION31 = "Update a task in the task list", PROMPT16 = `Use this tool to update a task in the task list.
310091
+ var DESCRIPTION32 = "Update a task in the task list", PROMPT17 = `Use this tool to update a task in the task list.
308924
310092
 
308925
310093
  ## When to Use This Tool
308926
310094
 
@@ -309003,7 +310171,7 @@ var init_TaskUpdateTool = __esm(() => {
309003
310171
  init_v4();
309004
310172
  init_growthbook();
309005
310173
  init_Tool();
309006
- init_agentSwarmsEnabled2();
310174
+ init_agentSwarmsEnabled3();
309007
310175
  init_hooks7();
309008
310176
  init_tasks5();
309009
310177
  init_teammate2();
@@ -309039,10 +310207,10 @@ var init_TaskUpdateTool = __esm(() => {
309039
310207
  searchHint: "update a task",
309040
310208
  maxResultSizeChars: 1e5,
309041
310209
  async description() {
309042
- return DESCRIPTION31;
310210
+ return DESCRIPTION32;
309043
310211
  },
309044
310212
  async prompt() {
309045
- return PROMPT16;
310213
+ return PROMPT17;
309046
310214
  },
309047
310215
  get inputSchema() {
309048
310216
  return inputSchema31();
@@ -309307,9 +310475,9 @@ ${idDescription}
309307
310475
  Use TaskGet with a specific task ID to view full details including description and comments.
309308
310476
  ${teammateWorkflow}`;
309309
310477
  }
309310
- var DESCRIPTION32 = "List all tasks in the task list";
310478
+ var DESCRIPTION33 = "List all tasks in the task list";
309311
310479
  var init_prompt18 = __esm(() => {
309312
- init_agentSwarmsEnabled2();
310480
+ init_agentSwarmsEnabled3();
309313
310481
  });
309314
310482
 
309315
310483
  // src/tui/tools/TaskListTool/TaskListTool.ts
@@ -309334,7 +310502,7 @@ var init_TaskListTool = __esm(() => {
309334
310502
  searchHint: "list all tasks",
309335
310503
  maxResultSizeChars: 1e5,
309336
310504
  async description() {
309337
- return DESCRIPTION32;
310505
+ return DESCRIPTION33;
309338
310506
  },
309339
310507
  async prompt() {
309340
310508
  return getPrompt24();
@@ -309962,7 +311130,7 @@ var init_CronCreateTool = __esm(() => {
309962
311130
  init_cron2();
309963
311131
  init_cronTasks2();
309964
311132
  init_semanticBoolean();
309965
- init_teammateContext3();
311133
+ init_shared();
309966
311134
  init_prompt19();
309967
311135
  init_UI20();
309968
311136
  inputSchema33 = lazySchema2(() => strictObject({
@@ -310026,7 +311194,7 @@ var init_CronCreateTool = __esm(() => {
310026
311194
  errorCode: 3
310027
311195
  };
310028
311196
  }
310029
- if (input.durable && getTeammateContext3()) {
311197
+ if (input.durable && getTeammateContext()) {
310030
311198
  return {
310031
311199
  result: false,
310032
311200
  message: "durable crons are not supported for teammates (teammates do not persist across sessions)",
@@ -310037,7 +311205,7 @@ var init_CronCreateTool = __esm(() => {
310037
311205
  },
310038
311206
  async call({ cron, prompt, recurring = true, durable = false }) {
310039
311207
  const effectiveDurable = durable && isDurableCronEnabled2();
310040
- const id = await addCronTask2(cron, prompt, recurring, effectiveDurable, getTeammateContext3()?.agentId);
311208
+ const id = await addCronTask2(cron, prompt, recurring, effectiveDurable, getTeammateContext()?.agentId);
310041
311209
  setScheduledTasksEnabled(true);
310042
311210
  return {
310043
311211
  data: {
@@ -310071,7 +311239,7 @@ var init_CronDeleteTool = __esm(() => {
310071
311239
  init_v4();
310072
311240
  init_Tool();
310073
311241
  init_cronTasks2();
310074
- init_teammateContext3();
311242
+ init_shared();
310075
311243
  init_prompt19();
310076
311244
  init_UI20();
310077
311245
  inputSchema34 = lazySchema2(() => strictObject({
@@ -310116,7 +311284,7 @@ var init_CronDeleteTool = __esm(() => {
310116
311284
  errorCode: 1
310117
311285
  };
310118
311286
  }
310119
- const ctx = getTeammateContext3();
311287
+ const ctx = getTeammateContext();
310120
311288
  if (ctx && task.agentId !== ctx.agentId) {
310121
311289
  return {
310122
311290
  result: false,
@@ -310154,7 +311322,7 @@ var init_CronListTool = __esm(() => {
310154
311322
  init_cron2();
310155
311323
  init_cronTasks2();
310156
311324
  init_format2();
310157
- init_teammateContext3();
311325
+ init_shared();
310158
311326
  init_prompt19();
310159
311327
  init_UI20();
310160
311328
  inputSchema35 = lazySchema2(() => strictObject({}));
@@ -310196,7 +311364,7 @@ var init_CronListTool = __esm(() => {
310196
311364
  },
310197
311365
  async call() {
310198
311366
  const allTasks = await listAllCronTasks2();
310199
- const ctx = getTeammateContext3();
311367
+ const ctx = getTeammateContext();
310200
311368
  const tasks = ctx ? allTasks.filter((t) => t.agentId === ctx.agentId) : allTasks;
310201
311369
  const jobs = tasks.map((t) => ({
310202
311370
  id: t.id,
@@ -310454,7 +311622,7 @@ var init_spawnInProcess2 = __esm(() => {
310454
311622
  init_sdkEventQueue2();
310455
311623
  init_diskOutput2();
310456
311624
  init_framework2();
310457
- init_teammateContext3();
311625
+ init_shared();
310458
311626
  init_perfettoTracing();
310459
311627
  init_teamHelpers2();
310460
311628
  });
@@ -314750,9 +315918,9 @@ var init_ParsedCommand2 = __esm(() => {
314750
315918
  });
314751
315919
 
314752
315920
  // src/tui/utils/bash/heredoc.ts
314753
- import { randomBytes as randomBytes12 } from "crypto";
315921
+ import { randomBytes as randomBytes13 } from "crypto";
314754
315922
  function generatePlaceholderSalt2() {
314755
- return randomBytes12(8).toString("hex");
315923
+ return randomBytes13(8).toString("hex");
314756
315924
  }
314757
315925
  function extractHeredocs2(command, options) {
314758
315926
  const heredocs = new Map;
@@ -317183,7 +318351,7 @@ var init_inProcessRunner2 = __esm(() => {
317183
318351
  init_sdkEventQueue2();
317184
318352
  init_slowOperations();
317185
318353
  init_tasks5();
317186
- init_teammateContext3();
318354
+ init_shared();
317187
318355
  init_teammateMailbox();
317188
318356
  init_perfettoTracing();
317189
318357
  init_toolResultStorage();
@@ -318122,7 +319290,7 @@ async function readTeamFileAsync2(teamName) {
318122
319290
  return null;
318123
319291
  }
318124
319292
  }
318125
- function writeTeamFile(teamName, teamFile) {
319293
+ function writeTeamFile2(teamName, teamFile) {
318126
319294
  const teamDir = getTeamDir2(teamName);
318127
319295
  mkdirSync7(teamDir, { recursive: true });
318128
319296
  writeFileSync6(getTeamFilePath2(teamName), jsonStringify5(teamFile, null, 2));
@@ -318155,7 +319323,7 @@ function removeTeammateFromTeamFile2(teamName, identifier) {
318155
319323
  logForDebugging3(`[TeammateTool] Teammate ${identifierStr} not found in team file for "${teamName}"`);
318156
319324
  return false;
318157
319325
  }
318158
- writeTeamFile(teamName, teamFile);
319326
+ writeTeamFile2(teamName, teamFile);
318159
319327
  logForDebugging3(`[TeammateTool] Removed teammate from team file: ${identifierStr}`);
318160
319328
  return true;
318161
319329
  }
@@ -318175,7 +319343,7 @@ function removeMemberFromTeam2(teamName, tmuxPaneId) {
318175
319343
  teamFile.hiddenPaneIds.splice(hiddenIndex, 1);
318176
319344
  }
318177
319345
  }
318178
- writeTeamFile(teamName, teamFile);
319346
+ writeTeamFile2(teamName, teamFile);
318179
319347
  logForDebugging3(`[TeammateTool] Removed member with pane ${tmuxPaneId} from team ${teamName}`);
318180
319348
  return true;
318181
319349
  }
@@ -318189,7 +319357,7 @@ function removeMemberByAgentId2(teamName, agentId) {
318189
319357
  return false;
318190
319358
  }
318191
319359
  teamFile.members.splice(memberIndex, 1);
318192
- writeTeamFile(teamName, teamFile);
319360
+ writeTeamFile2(teamName, teamFile);
318193
319361
  logForDebugging3(`[TeammateTool] Removed member ${agentId} from team ${teamName}`);
318194
319362
  return true;
318195
319363
  }
@@ -318207,7 +319375,7 @@ function setMemberMode2(teamName, memberName, mode) {
318207
319375
  return true;
318208
319376
  }
318209
319377
  const updatedMembers = teamFile.members.map((m) => m.name === memberName ? { ...m, mode } : m);
318210
- writeTeamFile(teamName, { ...teamFile, members: updatedMembers });
319378
+ writeTeamFile2(teamName, { ...teamFile, members: updatedMembers });
318211
319379
  logForDebugging3(`[TeammateTool] Set member ${memberName} in team ${teamName} to mode: ${mode}`);
318212
319380
  return true;
318213
319381
  }
@@ -318236,7 +319404,7 @@ function setMultipleMemberModes2(teamName, modeUpdates) {
318236
319404
  return member;
318237
319405
  });
318238
319406
  if (anyChanged) {
318239
- writeTeamFile(teamName, { ...teamFile, members: updatedMembers });
319407
+ writeTeamFile2(teamName, { ...teamFile, members: updatedMembers });
318240
319408
  logForDebugging3(`[TeammateTool] Set ${modeUpdates.length} member modes in team ${teamName}`);
318241
319409
  }
318242
319410
  return true;
@@ -318290,9 +319458,6 @@ async function destroyWorktree2(worktreePath) {
318290
319458
  logForDebugging3(`[TeammateTool] Failed to remove worktree ${worktreePath}: ${errorMessage2(error)}`);
318291
319459
  }
318292
319460
  }
318293
- function registerTeamForSessionCleanup2(teamName) {
318294
- getSessionCreatedTeams().add(teamName);
318295
- }
318296
319461
  function unregisterTeamForSessionCleanup2(teamName) {
318297
319462
  getSessionCreatedTeams().delete(teamName);
318298
319463
  }
@@ -318412,7 +319577,7 @@ Create a new team to coordinate multiple agents working on a project. Teams have
318412
319577
  \`\`\`
318413
319578
 
318414
319579
  This creates:
318415
- - A team file at \`~/.atlas/teams/{team-name}/config.json\`
319580
+ - An in-memory team context on the leader (Form A is zero-persistence — no team file is written to \`~/.atlas/teams/\`; the member roster lives in the leader's team context)
318416
319581
  - A corresponding task list directory at \`~/.atlas/tasks/{team-name}/\`
318417
319582
 
318418
319583
  ## Team Workflow
@@ -318454,23 +319619,14 @@ Teammates go idle after every turn—this is completely normal and expected. A t
318454
319619
 
318455
319620
  ## Discovering Team Members
318456
319621
 
318457
- Teammates can read the team config file to discover other team members:
318458
- - **Team config location**: \`~/.atlas/teams/{team-name}/config.json\`
318459
-
318460
- The config file contains a \`members\` array with each teammate's:
319622
+ Form A teams are zero-persistence: no team config file is written to disk. Team members come from the \`members\` roster passed to TeamCreate (carried in the leader's team context). Each roster entry has:
318461
319623
  - \`name\`: Human-readable name (**always use this** for messaging and task assignment)
318462
- - \`agentId\`: Unique identifier (for reference only - do not use for communication)
318463
- - \`agentType\`: Role/type of the agent
319624
+ - \`role\`/\`goal\`/\`backstory\`: Role triplet used to compose the member's prompt when spawned via Agent(name, team_name)
318464
319625
 
318465
319626
  **IMPORTANT**: Always refer to teammates by their NAME (e.g., "team-lead", "researcher", "tester"). Names are used for:
318466
319627
  - \`to\` when sending messages
318467
319628
  - Identifying task owners
318468
319629
 
318469
- Example of reading team config:
318470
- \`\`\`
318471
- Use the Read tool to read ~/.atlas/teams/{team-name}/config.json
318472
- \`\`\`
318473
-
318474
319630
  ## Task List Coordination
318475
319631
 
318476
319632
  Teams share a task list that all teammates can access at \`~/.atlas/tasks/{team-name}/\`.
@@ -318512,11 +319668,9 @@ function generateUniqueTeamName2(providedName) {
318512
319668
  var inputSchema37, TeamCreateTool2;
318513
319669
  var init_TeamCreateTool = __esm(() => {
318514
319670
  init_v4();
318515
- init_bootstrap();
318516
319671
  init_Tool();
318517
- init_agentSwarmsEnabled2();
319672
+ init_agentSwarmsEnabled3();
318518
319673
  init_cwd3();
318519
- init_model();
318520
319674
  init_slowOperations();
318521
319675
  init_teamHelpers2();
318522
319676
  init_teammateLayoutManager2();
@@ -318525,7 +319679,13 @@ var init_TeamCreateTool = __esm(() => {
318525
319679
  inputSchema37 = lazySchema2(() => strictObject({
318526
319680
  team_name: string2().describe("Name for the new team to create."),
318527
319681
  description: string2().optional().describe("Team description/purpose."),
318528
- agent_type: string2().optional().describe('Type/role of the team lead (e.g., "researcher", "test-runner"). ' + "Used for team file and inter-agent coordination.")
319682
+ agent_type: string2().optional().describe('Type/role of the team lead (e.g., "researcher", "test-runner"). ' + "Used for team file and inter-agent coordination."),
319683
+ members: array(strictObject({
319684
+ name: string2().describe("Member name (used as the spawn identity)."),
319685
+ role: string2().optional().describe("Role label resolved against the role template registry."),
319686
+ goal: string2().optional().describe("This member's goal for the team's current task."),
319687
+ backstory: string2().optional().describe("This member's background/context for prompt composition.")
319688
+ })).optional().describe("Optional roster of team members to plan for this team. Each entry " + "carries an optional role/goal/backstory triplet used to compose the " + "member's prompt when spawned via Agent(name, team_name).")
318529
319689
  }));
318530
319690
  TeamCreateTool2 = buildTool({
318531
319691
  name: TEAM_CREATE_TOOL_NAME2,
@@ -318552,6 +319712,17 @@ var init_TeamCreateTool = __esm(() => {
318552
319712
  errorCode: 9
318553
319713
  };
318554
319714
  }
319715
+ if (input.members) {
319716
+ for (const m of input.members) {
319717
+ if (!m || typeof m !== "object" || !m.name || m.name.trim().length === 0) {
319718
+ return {
319719
+ result: false,
319720
+ message: "each team member requires a non-empty name",
319721
+ errorCode: 9
319722
+ };
319723
+ }
319724
+ }
319725
+ }
318555
319726
  return { result: true };
318556
319727
  },
318557
319728
  async description() {
@@ -318574,7 +319745,7 @@ var init_TeamCreateTool = __esm(() => {
318574
319745
  },
318575
319746
  async call(input, context) {
318576
319747
  const { setAppState, getAppState } = context;
318577
- const { team_name, description: _description, agent_type } = input;
319748
+ const { team_name, agent_type } = input;
318578
319749
  const appState = getAppState();
318579
319750
  const existingTeam = appState.teamContext?.teamName;
318580
319751
  if (existingTeam) {
@@ -318583,29 +319754,8 @@ var init_TeamCreateTool = __esm(() => {
318583
319754
  const finalTeamName = generateUniqueTeamName2(team_name);
318584
319755
  const leadAgentId = formatAgentId3(TEAM_LEAD_NAME3, finalTeamName);
318585
319756
  const leadAgentType = agent_type || TEAM_LEAD_NAME3;
318586
- const leadModel = parseUserSpecifiedModel2(appState.mainLoopModelForSession ?? appState.mainLoopModel ?? getDefaultMainLoopModel());
318587
319757
  const teamFilePath = getTeamFilePath2(finalTeamName);
318588
- const teamFile = {
318589
- name: finalTeamName,
318590
- description: _description,
318591
- createdAt: Date.now(),
318592
- leadAgentId,
318593
- leadSessionId: getSessionId(),
318594
- members: [
318595
- {
318596
- agentId: leadAgentId,
318597
- name: TEAM_LEAD_NAME3,
318598
- agentType: leadAgentType,
318599
- model: leadModel,
318600
- joinedAt: Date.now(),
318601
- tmuxPaneId: "",
318602
- cwd: getCwd(),
318603
- subscriptions: []
318604
- }
318605
- ]
318606
- };
318607
- await writeTeamFileAsync2(finalTeamName, teamFile);
318608
- registerTeamForSessionCleanup2(finalTeamName);
319758
+ const roster = input.members && input.members.length > 0 ? input.members : undefined;
318609
319759
  const taskListId = sanitizeName3(finalTeamName);
318610
319760
  await resetTaskList2(taskListId);
318611
319761
  await ensureTasksDir2(taskListId);
@@ -318616,6 +319766,7 @@ var init_TeamCreateTool = __esm(() => {
318616
319766
  teamName: finalTeamName,
318617
319767
  teamFilePath,
318618
319768
  leadAgentId,
319769
+ roster,
318619
319770
  teammates: {
318620
319771
  [leadAgentId]: {
318621
319772
  name: TEAM_LEAD_NAME3,
@@ -318685,7 +319836,7 @@ var inputSchema38, TeamDeleteTool2;
318685
319836
  var init_TeamDeleteTool = __esm(() => {
318686
319837
  init_v4();
318687
319838
  init_Tool();
318688
- init_agentSwarmsEnabled2();
319839
+ init_agentSwarmsEnabled3();
318689
319840
  init_slowOperations();
318690
319841
  init_teamHelpers2();
318691
319842
  init_teammateLayoutManager2();
@@ -318738,7 +319889,7 @@ var init_TeamDeleteTool = __esm(() => {
318738
319889
  return {
318739
319890
  data: {
318740
319891
  success: false,
318741
- message: `Cannot cleanup team with ${activeMembers.length} active member(s): ${memberNames}. Use requestShutdown to gracefully terminate teammates first.`,
319892
+ message: `Cannot cleanup team with ${activeMembers.length} active member(s): ${memberNames}. Send each active member a shutdown request via SendMessage first (message: {"type":"shutdown_request","request_id":"<id>","reason":"<why>"}), and wait for their shutdown approval and exit before retrying TeamDelete.`,
318742
319893
  team_name: teamName
318743
319894
  }
318744
319895
  };
@@ -318770,12 +319921,12 @@ var init_TeamDeleteTool = __esm(() => {
318770
319921
  });
318771
319922
 
318772
319923
  // src/tui/tasks/LocalMainSessionTask.ts
318773
- import { randomBytes as randomBytes13 } from "crypto";
319924
+ import { randomBytes as randomBytes14 } from "crypto";
318774
319925
  function generateMainSessionTaskId() {
318775
- const bytes = randomBytes13(8);
319926
+ const bytes = randomBytes14(8);
318776
319927
  let id = "s";
318777
319928
  for (let i = 0;i < 8; i++) {
318778
- id += TASK_ID_ALPHABET2[bytes[i] % TASK_ID_ALPHABET2.length];
319929
+ id += TASK_ID_ALPHABET3[bytes[i] % TASK_ID_ALPHABET3.length];
318779
319930
  }
318780
319931
  return id;
318781
319932
  }
@@ -318991,7 +320142,7 @@ function startBackgroundSession({
318991
320142
  });
318992
320143
  return taskId;
318993
320144
  }
318994
- var DEFAULT_MAIN_SESSION_AGENT, TASK_ID_ALPHABET2 = "0123456789abcdefghijklmnopqrstuvwxyz", MAX_RECENT_ACTIVITIES3 = 5;
320145
+ var DEFAULT_MAIN_SESSION_AGENT, TASK_ID_ALPHABET3 = "0123456789abcdefghijklmnopqrstuvwxyz", MAX_RECENT_ACTIVITIES3 = 5;
318995
320146
  var init_LocalMainSessionTask = __esm(() => {
318996
320147
  init_xml();
318997
320148
  init_loopEvents();
@@ -319519,7 +320670,7 @@ If you receive a JSON message with \`type: "shutdown_request"\` or \`type: "plan
319519
320670
  Approving shutdown terminates your process. Rejecting plan sends the teammate back to revise. Don't originate \`shutdown_request\` unless asked. Don't send structured JSON status messages — use TaskUpdate.
319520
320671
  `.trim();
319521
320672
  }
319522
- var DESCRIPTION33 = "Send a message to another agent";
320673
+ var DESCRIPTION34 = "Send a message to another agent";
319523
320674
  var init_prompt20 = __esm(() => {
319524
320675
  init_shared();
319525
320676
  });
@@ -319841,7 +320992,7 @@ var init_SendMessageTool = __esm(() => {
319841
320992
  init_LocalAgentTask();
319842
320993
  init_LocalMainSessionTask();
319843
320994
  init_ids();
319844
- init_agentSwarmsEnabled2();
320995
+ init_agentSwarmsEnabled3();
319845
320996
  init_debug();
319846
320997
  init_errors4();
319847
320998
  init_format2();
@@ -320034,7 +321185,7 @@ var init_SendMessageTool = __esm(() => {
320034
321185
  return { result: true };
320035
321186
  },
320036
321187
  async description() {
320037
- return DESCRIPTION33;
321188
+ return DESCRIPTION34;
320038
321189
  },
320039
321190
  async prompt() {
320040
321191
  return getPrompt27();
@@ -328991,7 +330142,7 @@ var init_tools3 = __esm(() => {
328991
330142
  init_embeddedTools();
328992
330143
  init_envUtils2();
328993
330144
  init_shellToolUtils();
328994
- init_agentSwarmsEnabled2();
330145
+ init_agentSwarmsEnabled3();
328995
330146
  init_constants9();
328996
330147
  IS_ATLAS_DEV = process.env.ATLAS_DEV === "1" || process.env.ATLAS_DEV === "true";
328997
330148
  REPLTool2 = IS_ATLAS_DEV ? __toCommonJS(exports_REPLTool).REPLTool : null;
@@ -329046,21 +330197,8 @@ var init_zodToJsonSchema2 = __esm(() => {
329046
330197
  });
329047
330198
 
329048
330199
  // src/tui/utils/api.ts
329049
- function filterSwarmFieldsFromSchema(toolName, schema) {
329050
- const fieldsToRemove = SWARM_FIELDS_BY_TOOL[toolName];
329051
- if (!fieldsToRemove || fieldsToRemove.length === 0) {
329052
- return schema;
329053
- }
329054
- const filtered = { ...schema };
329055
- const props = filtered.properties;
329056
- if (props && typeof props === "object") {
329057
- const filteredProps = { ...props };
329058
- for (const field of fieldsToRemove) {
329059
- delete filteredProps[field];
329060
- }
329061
- filtered.properties = filteredProps;
329062
- }
329063
- return filtered;
330200
+ function filterSwarmFieldsFromSchema2(toolName, schema) {
330201
+ return filterSwarmFieldsFromSchema(toolName, schema, !isAgentSwarmsEnabled2());
329064
330202
  }
329065
330203
  async function toolToAPISchema(tool, options) {
329066
330204
  const cacheKey = "inputJSONSchema" in tool && tool.inputJSONSchema ? `${tool.name}:${jsonStringify5(tool.inputJSONSchema)}` : tool.name;
@@ -329070,7 +330208,7 @@ async function toolToAPISchema(tool, options) {
329070
330208
  const strictToolsEnabled = checkStatsigFeatureGate_CACHED_MAY_BE_STALE("atlas_tool_pear");
329071
330209
  let input_schema = "inputJSONSchema" in tool && tool.inputJSONSchema ? tool.inputJSONSchema : zodToJsonSchema(tool.inputSchema);
329072
330210
  if (!isAgentSwarmsEnabled2()) {
329073
- input_schema = filterSwarmFieldsFromSchema(tool.name, input_schema);
330211
+ input_schema = filterSwarmFieldsFromSchema2(tool.name, input_schema);
329074
330212
  }
329075
330213
  base = {
329076
330214
  name: tool.name,
@@ -329219,7 +330357,7 @@ function normalizeToolInputForAPI(tool, input) {
329219
330357
  return input;
329220
330358
  }
329221
330359
  }
329222
- var SWARM_FIELDS_BY_TOOL, loggedStrip = false;
330360
+ var loggedStrip = false;
329223
330361
  var init_api2 = __esm(() => {
329224
330362
  init_prompts2();
329225
330363
  init_context5();
@@ -329233,8 +330371,7 @@ var init_api2 = __esm(() => {
329233
330371
  init_tools3();
329234
330372
  init_system();
329235
330373
  init_tokenEstimation();
329236
- init_constants6();
329237
- init_agentSwarmsEnabled2();
330374
+ init_agentSwarmsEnabled3();
329238
330375
  init_betas2();
329239
330376
  init_cwd3();
329240
330377
  init_debug();
@@ -329248,10 +330385,7 @@ var init_api2 = __esm(() => {
329248
330385
  init_toolSchemaCache();
329249
330386
  init_windowsPaths2();
329250
330387
  init_zodToJsonSchema2();
329251
- SWARM_FIELDS_BY_TOOL = {
329252
- [EXIT_PLAN_MODE_V2_TOOL_NAME2]: ["launchSwarm", "teammateCount"],
329253
- [AGENT_TOOL_NAME2]: ["name", "team_name", "mode"]
329254
- };
330388
+ init_shared();
329255
330389
  });
329256
330390
 
329257
330391
  // src/tui/loopPermissionBridge.ts
@@ -329894,7 +331028,7 @@ Format: 2-12 words, match the user's style. Or nothing.
329894
331028
  Reply with ONLY the suggestion, no quotes or explanation.`, SUGGESTION_PROMPTS;
329895
331029
  var init_promptSuggestion = __esm(() => {
329896
331030
  init_bootstrap();
329897
- init_agentSwarmsEnabled2();
331031
+ init_agentSwarmsEnabled3();
329898
331032
  init_envUtils2();
329899
331033
  init_errors4();
329900
331034
  init_forkedAgent2();
@@ -332336,7 +333470,7 @@ var init_LocalShellTask = __esm(() => {
332336
333470
  });
332337
333471
 
332338
333472
  // src/tui/tools/BashTool/sedEditParser.ts
332339
- import { randomBytes as randomBytes14 } from "crypto";
333473
+ import { randomBytes as randomBytes15 } from "crypto";
332340
333474
  function parseSedEditCommand2(command) {
332341
333475
  const trimmed = command.trim();
332342
333476
  const sedMatch = trimmed.match(/^\s*sed\s+/);
@@ -332488,7 +333622,7 @@ function applySedSubstitution2(content, sedInfo) {
332488
333622
  if (!sedInfo.extendedRegex) {
332489
333623
  jsPattern = jsPattern.replace(/\\\\/g, BACKSLASH_PLACEHOLDER2).replace(/\\\+/g, PLUS_PLACEHOLDER2).replace(/\\\?/g, QUESTION_PLACEHOLDER2).replace(/\\\|/g, PIPE_PLACEHOLDER2).replace(/\\\(/g, LPAREN_PLACEHOLDER2).replace(/\\\)/g, RPAREN_PLACEHOLDER2).replace(/\+/g, "\\+").replace(/\?/g, "\\?").replace(/\|/g, "\\|").replace(/\(/g, "\\(").replace(/\)/g, "\\)").replace(BACKSLASH_PLACEHOLDER_RE2, "\\\\").replace(PLUS_PLACEHOLDER_RE2, "+").replace(QUESTION_PLACEHOLDER_RE2, "?").replace(PIPE_PLACEHOLDER_RE2, "|").replace(LPAREN_PLACEHOLDER_RE2, "(").replace(RPAREN_PLACEHOLDER_RE2, ")");
332490
333624
  }
332491
- const salt = randomBytes14(8).toString("hex");
333625
+ const salt = randomBytes15(8).toString("hex");
332492
333626
  const ESCAPED_AMP_PLACEHOLDER = `___ESCAPED_AMPERSAND_${salt}___`;
332493
333627
  const jsReplacement = sedInfo.replacement.replace(/\\\//g, "/").replace(/\\&/g, ESCAPED_AMP_PLACEHOLDER).replace(/&/g, "$$&").replace(new RegExp(ESCAPED_AMP_PLACEHOLDER, "g"), "&");
332494
333628
  try {
@@ -335556,7 +336690,7 @@ var init_FileReadTool = __esm(() => {
335556
336690
  maxResultSizeChars: Infinity,
335557
336691
  strict: true,
335558
336692
  async description() {
335559
- return DESCRIPTION18;
336693
+ return DESCRIPTION19;
335560
336694
  },
335561
336695
  async prompt() {
335562
336696
  const limits = getDefaultFileReadingLimits2();
@@ -337463,7 +338597,7 @@ var init_attachments = __esm(() => {
337463
338597
  init_pdfUtils2();
337464
338598
  init_common();
337465
338599
  init_pdf2();
337466
- init_agentSwarmsEnabled2();
338600
+ init_agentSwarmsEnabled3();
337467
338601
  init_findRelevantMemories();
337468
338602
  init_paths3();
337469
338603
  init_factory();
@@ -338252,7 +339386,7 @@ var init_zip = __esm(() => {
338252
339386
  });
338253
339387
 
338254
339388
  // src/tui/utils/plugins/zipCache.ts
338255
- import { randomBytes as randomBytes15 } from "crypto";
339389
+ import { randomBytes as randomBytes16 } from "crypto";
338256
339390
  import {
338257
339391
  chmod as chmod5,
338258
339392
  lstat as lstat8,
@@ -338274,7 +339408,7 @@ async function getSessionPluginCachePath() {
338274
339408
  }
338275
339409
  if (!sessionPluginCachePromise) {
338276
339410
  sessionPluginCachePromise = (async () => {
338277
- const suffix = randomBytes15(8).toString("hex");
339411
+ const suffix = randomBytes16(8).toString("hex");
338278
339412
  const dir = join120(tmpdir7(), `atlas-plugin-session-${suffix}`);
338279
339413
  await getFsImplementation2().mkdir(dir);
338280
339414
  sessionPluginCachePath = dir;
@@ -338287,7 +339421,7 @@ async function getSessionPluginCachePath() {
338287
339421
  async function atomicWriteToZipCache(targetPath, data) {
338288
339422
  const dir = dirname62(targetPath);
338289
339423
  await getFsImplementation2().mkdir(dir);
338290
- const tmpName = `.${basename35(targetPath)}.tmp.${randomBytes15(4).toString("hex")}`;
339424
+ const tmpName = `.${basename35(targetPath)}.tmp.${randomBytes16(4).toString("hex")}`;
338291
339425
  const tmpPath = join120(dir, tmpName);
338292
339426
  try {
338293
339427
  if (typeof data === "string") {
@@ -340728,7 +341862,7 @@ function mtimeAwareMemoize(fn, watchFiles, options) {
340728
341862
  var init_mtimeAwareMemoize = () => {};
340729
341863
 
340730
341864
  // src/tui/utils/plugins/installCounts.ts
340731
- import { randomBytes as randomBytes16 } from "crypto";
341865
+ import { randomBytes as randomBytes17 } from "crypto";
340732
341866
  import { readFile as readFile46, rename as rename5, unlink as unlink19, writeFile as writeFile33 } from "fs/promises";
340733
341867
  import { join as join126 } from "path";
340734
341868
  function normalizeStatsBase(raw) {
@@ -340802,7 +341936,7 @@ async function loadInstallCountsCache() {
340802
341936
  }
340803
341937
  async function saveInstallCountsCache(cache) {
340804
341938
  const cachePath = getInstallCountsCachePath();
340805
- const tempPath = `${cachePath}.${randomBytes16(8).toString("hex")}.tmp`;
341939
+ const tempPath = `${cachePath}.${randomBytes17(8).toString("hex")}.tmp`;
340806
341940
  try {
340807
341941
  const pluginsDir = getPluginsDirectory();
340808
341942
  await getFsImplementation2().mkdir(pluginsDir);
@@ -340981,7 +342115,7 @@ var init_pluginVersioning = __esm(() => {
340981
342115
  });
340982
342116
 
340983
342117
  // src/tui/utils/plugins/pluginInstallationHelpers.ts
340984
- import { randomBytes as randomBytes17 } from "crypto";
342118
+ import { randomBytes as randomBytes18 } from "crypto";
340985
342119
  import { rename as rename6, rm as rm9 } from "fs/promises";
340986
342120
  import { dirname as dirname66, join as join127, resolve as resolve48, sep as sep28 } from "path";
340987
342121
  function getCurrentTimestamp() {
@@ -341012,7 +342146,7 @@ async function cacheAndRegisterPlugin(pluginId, entry, scope = "user", projectPa
341012
342146
  const normalizedCachePath = cacheResult.path.endsWith(sep28) ? cacheResult.path : cacheResult.path + sep28;
341013
342147
  const isSubdirectory = versionedPath.startsWith(normalizedCachePath);
341014
342148
  if (isSubdirectory) {
341015
- const tempPath = join127(dirname66(cacheResult.path), `.atlas-plugin-temp-${Date.now()}-${randomBytes17(4).toString("hex")}`);
342149
+ const tempPath = join127(dirname66(cacheResult.path), `.atlas-plugin-temp-${Date.now()}-${randomBytes18(4).toString("hex")}`);
341016
342150
  await rename6(cacheResult.path, tempPath);
341017
342151
  await getFsImplementation2().mkdir(dirname66(versionedPath));
341018
342152
  await rename6(tempPath, versionedPath);
@@ -346002,7 +347136,7 @@ var init_messages3 = __esm(() => {
346002
347136
  init_paths3();
346003
347137
  init_growthbook();
346004
347138
  init_modelprovider2();
346005
- init_agentSwarmsEnabled2();
347139
+ init_agentSwarmsEnabled3();
346006
347140
  init_attachments();
346007
347141
  init_shellQuote2();
346008
347142
  init_format2();
@@ -346219,9 +347353,9 @@ var init_prefix = __esm(() => {
346219
347353
  });
346220
347354
 
346221
347355
  // src/tui/utils/bash/commands.ts
346222
- import { randomBytes as randomBytes18 } from "crypto";
347356
+ import { randomBytes as randomBytes19 } from "crypto";
346223
347357
  function generatePlaceholders2() {
346224
- const salt = randomBytes18(8).toString("hex");
347358
+ const salt = randomBytes19(8).toString("hex");
346225
347359
  return {
346226
347360
  SINGLE_QUOTE: `__SINGLE_QUOTE_${salt}__`,
346227
347361
  DOUBLE_QUOTE: `__DOUBLE_QUOTE_${salt}__`,
@@ -360924,7 +362058,7 @@ var init_Config = __esm(() => {
360924
362058
  init_outputStyles();
360925
362059
  init_envUtils2();
360926
362060
  init_growthbook();
360927
- init_agentSwarmsEnabled2();
362061
+ init_agentSwarmsEnabled3();
360928
362062
  init_teammateModeSnapshot2();
360929
362063
  init_teammateModel2();
360930
362064
  init_modelprovider2();
@@ -370648,7 +371782,7 @@ var init_TaskListV2 = __esm(() => {
370648
371782
  init_AppState();
370649
371783
  init_types15();
370650
371784
  init_agentColorManager();
370651
- init_agentSwarmsEnabled2();
371785
+ init_agentSwarmsEnabled3();
370652
371786
  init_collapseReadSearch();
370653
371787
  init_format2();
370654
371788
  init_tasks5();
@@ -410478,7 +411612,7 @@ var init_ManageMarketplaces = __esm(() => {
410478
411612
  });
410479
411613
 
410480
411614
  // src/tui/utils/plugins/pluginFlagging.ts
410481
- import { randomBytes as randomBytes19 } from "crypto";
411615
+ import { randomBytes as randomBytes20 } from "crypto";
410482
411616
  import { readFile as readFile56, rename as rename10, unlink as unlink22, writeFile as writeFile42 } from "fs/promises";
410483
411617
  import { join as join149 } from "path";
410484
411618
  function getFlaggedPluginsPath() {
@@ -410516,7 +411650,7 @@ async function readFromDisk() {
410516
411650
  }
410517
411651
  async function writeToDisk(plugins) {
410518
411652
  const filePath = getFlaggedPluginsPath();
410519
- const tempPath = `${filePath}.${randomBytes19(8).toString("hex")}.tmp`;
411653
+ const tempPath = `${filePath}.${randomBytes20(8).toString("hex")}.tmp`;
410520
411654
  try {
410521
411655
  await getFsImplementation2().mkdir(getPluginsDirectory());
410522
411656
  const content = jsonStringify5({ plugins }, null, 2);
@@ -420010,7 +421144,7 @@ var require_asciichart = __commonJS(function(exports) {
420010
421144
  });
420011
421145
 
420012
421146
  // src/tui/utils/statsCache.ts
420013
- import { randomBytes as randomBytes20 } from "crypto";
421147
+ import { randomBytes as randomBytes21 } from "crypto";
420014
421148
  import { open as open18 } from "fs/promises";
420015
421149
  import { join as join159 } from "path";
420016
421150
  async function withStatsCacheLock(fn) {
@@ -420106,7 +421240,7 @@ async function loadStatsCache() {
420106
421240
  async function saveStatsCache(cache) {
420107
421241
  const fs = getFsImplementation2();
420108
421242
  const cachePath = getStatsCachePath();
420109
- const tempPath = `${cachePath}.${randomBytes20(8).toString("hex")}.tmp`;
421243
+ const tempPath = `${cachePath}.${randomBytes21(8).toString("hex")}.tmp`;
420110
421244
  try {
420111
421245
  const configDir = getAtlasConfigHomeDir3();
420112
421246
  try {
@@ -429091,7 +430225,7 @@ var init_plans = __esm(() => {
429091
430225
  });
429092
430226
 
429093
430227
  // src/tui/utils/permissions/filesystem.ts
429094
- import { randomBytes as randomBytes21 } from "crypto";
430228
+ import { randomBytes as randomBytes22 } from "crypto";
429095
430229
  import { homedir as homedir38, tmpdir as tmpdir11 } from "os";
429096
430230
  import { join as join165, normalize as normalize15, posix as posix9, resolve as resolve57, sep as sep37 } from "path";
429097
430231
  function normalizeCaseForComparison2(path) {
@@ -430019,7 +431153,7 @@ var init_filesystem2 = __esm(() => {
430019
431153
  return join165(resolvedBaseTmpDir, getAtlasTempDirName2()) + sep37;
430020
431154
  });
430021
431155
  getBundledSkillsRoot2 = memoize_default(function getBundledSkillsRoot() {
430022
- const nonce = randomBytes21(16).toString("hex");
431156
+ const nonce = randomBytes22(16).toString("hex");
430023
431157
  return join165(getAtlasTempDir2(), "bundled-skills", MACRO.VERSION, nonce);
430024
431158
  });
430025
431159
  worktreeCwdProbeCache2 = new Map;
@@ -430240,22 +431374,22 @@ var init_diskOutput2 = __esm(() => {
430240
431374
  });
430241
431375
 
430242
431376
  // src/tui/Task.ts
430243
- import { randomBytes as randomBytes22 } from "crypto";
431377
+ import { randomBytes as randomBytes23 } from "crypto";
430244
431378
  function isTerminalTaskStatus2(status) {
430245
431379
  return status === "completed" || status === "failed" || status === "killed";
430246
431380
  }
430247
431381
  function hasNonTerminalTasks(tasks) {
430248
431382
  return Object.values(tasks).some((t) => !isTerminalTaskStatus2(t.status));
430249
431383
  }
430250
- function getTaskIdPrefix(type) {
430251
- return TASK_ID_PREFIXES[type] ?? "x";
431384
+ function getTaskIdPrefix2(type) {
431385
+ return TASK_ID_PREFIXES2[type] ?? "x";
430252
431386
  }
430253
431387
  function generateTaskId2(type) {
430254
- const prefix = getTaskIdPrefix(type);
430255
- const bytes = randomBytes22(8);
431388
+ const prefix = getTaskIdPrefix2(type);
431389
+ const bytes = randomBytes23(8);
430256
431390
  let id = prefix;
430257
431391
  for (let i = 0;i < 8; i++) {
430258
- id += TASK_ID_ALPHABET3[bytes[i] % TASK_ID_ALPHABET3.length];
431392
+ id += TASK_ID_ALPHABET4[bytes[i] % TASK_ID_ALPHABET4.length];
430259
431393
  }
430260
431394
  return id;
430261
431395
  }
@@ -430272,10 +431406,10 @@ function createTaskStateBase2(id, type, description, toolUseId) {
430272
431406
  notified: false
430273
431407
  };
430274
431408
  }
430275
- var TASK_ID_PREFIXES, TASK_ID_ALPHABET3 = "0123456789abcdefghijklmnopqrstuvwxyz";
431409
+ var TASK_ID_PREFIXES2, TASK_ID_ALPHABET4 = "0123456789abcdefghijklmnopqrstuvwxyz";
430276
431410
  var init_Task = __esm(() => {
430277
431411
  init_diskOutput2();
430278
- TASK_ID_PREFIXES = {
431412
+ TASK_ID_PREFIXES2 = {
430279
431413
  local_bash: "b",
430280
431414
  local_agent: "a",
430281
431415
  remote_agent: "r",
@@ -432168,7 +433302,7 @@ var init_betaSessionTracing = __esm(() => {
432168
433302
  });
432169
433303
 
432170
433304
  // src/tui/utils/telemetry/sessionTracing.ts
432171
- import { AsyncLocalStorage as AsyncLocalStorage7 } from "async_hooks";
433305
+ import { AsyncLocalStorage as AsyncLocalStorage5 } from "async_hooks";
432172
433306
  function getSpanId(span) {
432173
433307
  return span.spanContext().spanId || "";
432174
433308
  }
@@ -432353,8 +433487,8 @@ var init_sessionTracing = __esm(() => {
432353
433487
  init_betaSessionTracing();
432354
433488
  init_perfettoTracing();
432355
433489
  import_api5 = __toESM(require_src3(), 1);
432356
- interactionContext = new AsyncLocalStorage7;
432357
- toolContext = new AsyncLocalStorage7;
433490
+ interactionContext = new AsyncLocalStorage5;
433491
+ toolContext = new AsyncLocalStorage5;
432358
433492
  activeSpans = new Map;
432359
433493
  strongSpans = new Map;
432360
433494
  SPAN_TTL_MS = 30 * 60 * 1000;
@@ -432604,7 +433738,7 @@ var init_hookInputMaterialize = __esm(() => {
432604
433738
  });
432605
433739
 
432606
433740
  // src/tui/utils/hooks/hookReentrancy.ts
432607
- import { AsyncLocalStorage as AsyncLocalStorage8 } from "async_hooks";
433741
+ import { AsyncLocalStorage as AsyncLocalStorage6 } from "async_hooks";
432608
433742
  function getCallbackId(fn) {
432609
433743
  let id = callbackIds.get(fn);
432610
433744
  if (id === undefined) {
@@ -432631,7 +433765,7 @@ function runWithHookReentrancy(hookEvent, hook, pluginRoot, fn) {
432631
433765
  }
432632
433766
  var hookReentrancyStorage, callbackIds, nextCallbackId = 1;
432633
433767
  var init_hookReentrancy = __esm(() => {
432634
- hookReentrancyStorage = new AsyncLocalStorage8;
433768
+ hookReentrancyStorage = new AsyncLocalStorage6;
432635
433769
  callbackIds = new WeakMap;
432636
433770
  });
432637
433771
 
@@ -437109,12 +438243,6 @@ async function streamCompactSummary({
437109
438243
  let hasStartedStreaming = false;
437110
438244
  let response;
437111
438245
  context.setResponseLength?.(() => 0);
437112
- const useToolSearch = await isToolSearchEnabled(compactModel, context.options.tools, async () => appState.toolPermissionContext, context.options.agentDefinitions.activeAgents, "compact");
437113
- const tools = useToolSearch ? uniqBy_default([
437114
- FileReadTool,
437115
- ToolSearchTool2,
437116
- ...context.options.tools.filter((t) => t.isMcp)
437117
- ], "name") : [FileReadTool];
437118
438246
  const compactMessages = normalizeMessagesForAPI(stripImagesFromMessages2(stripReinjectedAttachments([
437119
438247
  ...getMessagesAfterCompactBoundary(messages),
437120
438248
  summaryRequest
@@ -437122,11 +438250,9 @@ async function streamCompactSummary({
437122
438250
  const compactRole = modelToRole(compactModel);
437123
438251
  const params = await buildOpenAIParams({
437124
438252
  messages: compactMessages,
437125
- systemPrompt: asSystemPrompt2([
437126
- "You are a helpful AI assistant tasked with summarizing conversations."
437127
- ]),
438253
+ systemPrompt: asSystemPrompt2(appendSystemContext(cacheSafeParams.systemPrompt, cacheSafeParams.systemContext)),
437128
438254
  thinkingConfig: { type: "disabled" },
437129
- tools,
438255
+ tools: context.options.tools,
437130
438256
  options: {
437131
438257
  model: compactModel,
437132
438258
  async getToolPermissionContext() {
@@ -437356,14 +438482,12 @@ var POST_COMPACT_MAX_FILES_TO_RESTORE = 5, POST_COMPACT_TOKEN_BUDGET = 50000, PO
437356
438482
  var init_compact4 = __esm(() => {
437357
438483
  init_shared();
437358
438484
  init_shared();
437359
- init_uniqBy();
438485
+ init_api2();
437360
438486
  init_atlas();
437361
438487
  init_compactModelSwitch();
437362
438488
  init_bootstrapState();
437363
438489
  init_bootstrapState();
437364
- init_FileReadTool();
437365
438490
  init_prompt2();
437366
- init_ToolSearchTool();
437367
438491
  init_attachments();
437368
438492
  init_config6();
437369
438493
  init_context2();
@@ -441400,7 +442524,7 @@ function useLogMessages(messages, ignore = false) {
441400
442524
  var import_react178;
441401
442525
  var init_useLogMessages = __esm(() => {
441402
442526
  init_AppState();
441403
- init_agentSwarmsEnabled2();
442527
+ init_agentSwarmsEnabled3();
441404
442528
  init_sessionStorage();
441405
442529
  import_react178 = __toESM(require_react(), 1);
441406
442530
  });
@@ -450546,7 +451670,7 @@ var init_ExitPlanModePermissionRequest = __esm(() => {
450546
451670
  init_generateSessionName();
450547
451671
  init_ink2();
450548
451672
  init_constants6();
450549
- init_agentSwarmsEnabled2();
451673
+ init_agentSwarmsEnabled3();
450550
451674
  init_context2();
450551
451675
  init_editor();
450552
451676
  init_file();
@@ -461223,7 +462347,7 @@ var init_useTypeahead = __esm(() => {
461223
462347
  init_useKeybinding();
461224
462348
  init_useShortcutDisplay();
461225
462349
  init_AppState();
461226
- init_agentSwarmsEnabled2();
462350
+ init_agentSwarmsEnabled3();
461227
462351
  init_argumentSubstitution2();
461228
462352
  init_shellCompletion();
461229
462353
  init_format2();
@@ -466469,7 +467593,7 @@ var init_PromptInputFooterLeftSide = __esm(() => {
466469
467593
  init_BackgroundTaskStatus();
466470
467594
  init_types14();
466471
467595
  init_taskStatusUtils();
466472
- init_agentSwarmsEnabled2();
467596
+ init_agentSwarmsEnabled3();
466473
467597
  init_TeamStatus();
466474
467598
  init_registry3();
466475
467599
  init_AppState();
@@ -466747,7 +467871,7 @@ var init_PromptInputModeIndicator = __esm(() => {
466747
467871
  init_ink2();
466748
467872
  init_agentColorManager();
466749
467873
  init_teammate2();
466750
- init_agentSwarmsEnabled2();
467874
+ init_agentSwarmsEnabled3();
466751
467875
  import_compiler_runtime297 = __toESM(require_compiler_runtime(), 1);
466752
467876
  jsx_dev_runtime405 = __toESM(require_jsx_dev_runtime(), 1);
466753
467877
  });
@@ -467164,7 +468288,7 @@ function useSwarmBanner() {
467164
468288
  isInsideTmux3().then(setInsideTmux);
467165
468289
  }, []);
467166
468290
  const state = store.getState();
467167
- if (isTeammate2() && !isInProcessTeammate3()) {
468291
+ if (isTeammate2() && !isInProcessTeammate()) {
467168
468292
  const agentName = getAgentName2();
467169
468293
  if (agentName && getTeamName2()) {
467170
468294
  return {
@@ -467236,7 +468360,7 @@ var init_useSwarmBanner = __esm(() => {
467236
468360
  init_detection2();
467237
468361
  init_registry3();
467238
468362
  init_teammate2();
467239
- init_teammateContext3();
468363
+ init_shared();
467240
468364
  React127 = __toESM(require_react(), 1);
467241
468365
  });
467242
468366
 
@@ -468748,7 +469872,7 @@ function PromptInput({
468748
469872
  if (modeColors[mode]) {
468749
469873
  return modeColors[mode];
468750
469874
  }
468751
- if (isInProcessTeammate3()) {
469875
+ if (isInProcessTeammate()) {
468752
469876
  return "promptBorder";
468753
469877
  }
468754
469878
  const teammateColorName = getTeammateColor3();
@@ -468989,7 +470113,7 @@ var init_PromptInput = __esm(() => {
468989
470113
  init_InProcessTeammateTask();
468990
470114
  init_types14();
468991
470115
  init_agentColorManager();
468992
- init_agentSwarmsEnabled2();
470116
+ init_agentSwarmsEnabled3();
468993
470117
  init_Cursor();
468994
470118
  init_config6();
468995
470119
  init_debug();
@@ -469013,7 +470137,7 @@ var init_PromptInput = __esm(() => {
469013
470137
  init_registry3();
469014
470138
  init_teamHelpers2();
469015
470139
  init_teammate2();
469016
- init_teammateContext3();
470140
+ init_shared();
469017
470141
  init_teammateMailbox();
469018
470142
  init_thinking();
469019
470143
  init_tokenBudget();
@@ -471621,7 +472745,7 @@ function useSwarmInitialization(setAppState, initialMessages, { enabled = true }
471621
472745
  var import_react248;
471622
472746
  var init_useSwarmInitialization = __esm(() => {
471623
472747
  init_bootstrap();
471624
- init_agentSwarmsEnabled2();
472748
+ init_agentSwarmsEnabled3();
471625
472749
  init_reconnection2();
471626
472750
  init_teamHelpers2();
471627
472751
  init_teammateInit();
@@ -472416,7 +473540,7 @@ async function handleSwarmWorkerPermission(params) {
472416
473540
  }
472417
473541
  var init_swarmWorkerHandler = __esm(() => {
472418
473542
  init_shared();
472419
- init_agentSwarmsEnabled2();
473543
+ init_agentSwarmsEnabled3();
472420
473544
  init_errors4();
472421
473545
  init_log5();
472422
473546
  init_permissionSync2();
@@ -474930,7 +476054,7 @@ var init_sessionRestore = __esm(() => {
474930
476054
  // src/tui/hooks/useInboxPoller.ts
474931
476055
  import { randomUUID as randomUUID51 } from "crypto";
474932
476056
  function getAgentNameToPoll(appState) {
474933
- if (isInProcessTeammate3()) {
476057
+ if (isInProcessTeammate()) {
474934
476058
  return;
474935
476059
  }
474936
476060
  if (isTeammate2()) {
@@ -475509,7 +476633,7 @@ var init_useInboxPoller = __esm(() => {
475509
476633
  init_teamHelpers2();
475510
476634
  init_tasks5();
475511
476635
  init_teammate2();
475512
- init_teammateContext3();
476636
+ init_shared();
475513
476637
  init_teammateMailbox();
475514
476638
  init_useSwarmPermissionPoller();
475515
476639
  import_react257 = __toESM(require_react(), 1);
@@ -485412,7 +486536,7 @@ var init_REPL = __esm(() => {
485412
486536
  init_concurrentSessions2();
485413
486537
  init_types15();
485414
486538
  init_useInboxPoller();
485415
- init_agentSwarmsEnabled2();
486539
+ init_agentSwarmsEnabled3();
485416
486540
  init_ide();
485417
486541
  init_useIDEIntegration();
485418
486542
  init_exit2();
@@ -493237,7 +494361,7 @@ var init_setup4 = __esm(() => {
493237
494361
  init_commands5();
493238
494362
  init_sessionMemory2();
493239
494363
  init_ids();
493240
- init_agentSwarmsEnabled2();
494364
+ init_agentSwarmsEnabled3();
493241
494365
  init_appleTerminalBackup();
493242
494366
  init_auth4();
493243
494367
  init_memoryFiles();
@@ -498418,7 +499542,7 @@ var init_main3 = __esm(() => {
498418
499542
  init_growthbook();
498419
499543
  init_SyntheticOutputTool();
498420
499544
  init_tools3();
498421
- init_agentSwarmsEnabled2();
499545
+ init_agentSwarmsEnabled3();
498422
499546
  init_asciicast();
498423
499547
  init_auth4();
498424
499548
  init_config6();
@@ -498848,6 +499972,38 @@ function createCoreDependencies() {
498848
499972
  setTeammateToolRegistryDeps({
498849
499973
  baseTools: [SnipTool, TeamCreateTool, TeamDeleteTool]
498850
499974
  });
499975
+ getInProcessBackend().setContext({
499976
+ getAppState: () => appState.get(),
499977
+ setAppState: (f) => {
499978
+ appState.set(f);
499979
+ },
499980
+ messages: []
499981
+ });
499982
+ setTeammateSpawnTrigger(async (config) => {
499983
+ if (isTeammate()) {
499984
+ return {
499985
+ success: false,
499986
+ agentId: `${config.name}@${config.teamName}`,
499987
+ error: "nested teammate spawn is not supported (a teammate cannot spawn teammates)"
499988
+ };
499989
+ }
499990
+ const result = await getInProcessBackend().spawn({
499991
+ name: config.name,
499992
+ teamName: config.teamName,
499993
+ prompt: config.prompt,
499994
+ ...config.model ? { model: config.model } : {},
499995
+ ...config.allowedTools ? { permissions: config.allowedTools } : {},
499996
+ allowPermissionPrompts: config.allowPermissionPrompts ?? false,
499997
+ ...config.systemPrompt ? { systemPrompt: config.systemPrompt } : {},
499998
+ ...config.systemPromptMode ? { systemPromptMode: config.systemPromptMode } : {}
499999
+ });
500000
+ return {
500001
+ success: result.success,
500002
+ agentId: result.agentId,
500003
+ ...result.taskId ? { taskId: result.taskId } : {},
500004
+ ...result.error ? { error: result.error } : {}
500005
+ };
500006
+ });
498851
500007
  setAgentLoopDepsTeammatePoolSync(setTeammateToolRegistryDeps);
498852
500008
  setAgentLoopDepsMcpConnectionsProvider(() => buildMcpEngineConnections(getMcpConnectionManager()));
498853
500009
  setWebSearchSettingsKeyProvider(() => {