replicas-engine 0.1.1350 → 0.1.1352

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.
@@ -1116,17 +1116,17 @@ var require_luxon = __commonJS({
1116
1116
  constructor(dt, intl, opts) {
1117
1117
  this.opts = opts;
1118
1118
  this.originalZone = void 0;
1119
- let z29 = void 0;
1119
+ let z30 = void 0;
1120
1120
  if (this.opts.timeZone) {
1121
1121
  this.dt = dt;
1122
1122
  } else if (dt.zone.type === "fixed") {
1123
1123
  const gmtOffset = -1 * (dt.offset / 60);
1124
1124
  const offsetZ = gmtOffset >= 0 ? `Etc/GMT+${gmtOffset}` : `Etc/GMT${gmtOffset}`;
1125
1125
  if (dt.offset !== 0 && IANAZone.create(offsetZ).valid) {
1126
- z29 = offsetZ;
1126
+ z30 = offsetZ;
1127
1127
  this.dt = dt;
1128
1128
  } else {
1129
- z29 = "UTC";
1129
+ z30 = "UTC";
1130
1130
  this.dt = dt.offset === 0 ? dt : dt.setZone("UTC").plus({
1131
1131
  minutes: dt.offset
1132
1132
  });
@@ -1136,9 +1136,9 @@ var require_luxon = __commonJS({
1136
1136
  this.dt = dt;
1137
1137
  } else if (dt.zone.type === "iana") {
1138
1138
  this.dt = dt;
1139
- z29 = dt.zone.name;
1139
+ z30 = dt.zone.name;
1140
1140
  } else {
1141
- z29 = "UTC";
1141
+ z30 = "UTC";
1142
1142
  this.dt = dt.setZone("UTC").plus({
1143
1143
  minutes: dt.offset
1144
1144
  });
@@ -1147,7 +1147,7 @@ var require_luxon = __commonJS({
1147
1147
  const intlOpts = {
1148
1148
  ...this.opts
1149
1149
  };
1150
- intlOpts.timeZone = intlOpts.timeZone || z29;
1150
+ intlOpts.timeZone = intlOpts.timeZone || z30;
1151
1151
  this.dtf = getCachedDTF(intl, intlOpts);
1152
1152
  }
1153
1153
  format() {
@@ -11019,6 +11019,10 @@ var sendChatMessageResponseSchema = z4.object({
11019
11019
  chatId: z4.string().optional(),
11020
11020
  steered: z4.boolean().optional()
11021
11021
  });
11022
+ var respondToolInputRequestSchema = z4.object({
11023
+ requestId: z4.string().min(1),
11024
+ selectionId: z4.string().min(1)
11025
+ });
11022
11026
  function isLatestChatHistoryPage(params) {
11023
11027
  return params.beforeCursor === void 0 && params.beforeEvent === void 0 && params.beforeTurn === void 0;
11024
11028
  }
@@ -11087,6 +11091,12 @@ var SUBAGENT_MCP_TOOLS = {
11087
11091
  deleteAgent: "delete_agent"
11088
11092
  };
11089
11093
  var SUBAGENT_MCP_TOOL_NAMES = Object.values(SUBAGENT_MCP_TOOLS);
11094
+ function isSubagentMcpToolName(tool) {
11095
+ return SUBAGENT_MCP_TOOL_NAMES.some((name) => name === tool);
11096
+ }
11097
+ function isSubagentMcpServerName(server) {
11098
+ return server === SUBAGENT_MCP_SERVER_NAME;
11099
+ }
11090
11100
 
11091
11101
  // ../shared/src/workspace-identity.ts
11092
11102
  import { z as z5 } from "zod";
@@ -11619,7 +11629,7 @@ var reorderCredentialPoolSchema = z13.object({
11619
11629
  });
11620
11630
 
11621
11631
  // ../shared/src/mothership-events.ts
11622
- import { z as z20 } from "zod";
11632
+ import { z as z21 } from "zod";
11623
11633
 
11624
11634
  // ../shared/src/replicas-mcp.ts
11625
11635
  import { z as z17 } from "zod";
@@ -11734,6 +11744,7 @@ var terminalSocketServerMessageSchema = z16.discriminatedUnion("type", [
11734
11744
  var TERMINAL_RTC_ICE_SERVER = "stun:stun.l.google.com:19302";
11735
11745
 
11736
11746
  // ../shared/src/replicas-mcp.ts
11747
+ var REPLICAS_MCP_SERVER_NAME = "replicas-mcp";
11737
11748
  var REPLICAS_MCP_TOOLS = {
11738
11749
  listEnvironments: "list_environments",
11739
11750
  createAutomation: "create_automation",
@@ -11846,6 +11857,54 @@ var SCOUT_PRESET_ICONS = [
11846
11857
  "tag"
11847
11858
  ];
11848
11859
 
11860
+ // ../shared/src/routes/push.ts
11861
+ import { z as z18 } from "zod";
11862
+
11863
+ // ../shared/src/workspace-attention.ts
11864
+ var WORKSPACE_ATTENTION_REASONS = ["question", "plan", "variables", "blocked", "setup"];
11865
+ var CHAT_ATTENTION_REASONS = ["question", "blocked"];
11866
+
11867
+ // ../shared/src/routes/push.ts
11868
+ var registerPushDeviceRequestSchema = z18.discriminatedUnion("platform", [
11869
+ z18.object({
11870
+ platform: z18.literal("ios"),
11871
+ token: z18.string().regex(/^[0-9a-f]{64,200}$/i),
11872
+ appId: z18.string().min(1).max(255),
11873
+ apnsEnvironment: z18.enum(["sandbox", "production"])
11874
+ }),
11875
+ z18.object({
11876
+ platform: z18.literal("android"),
11877
+ token: z18.string().min(1).max(4096),
11878
+ appId: z18.string().min(1).max(255)
11879
+ })
11880
+ ]);
11881
+ var PUSH_HOLD_MINUTES = 5;
11882
+ var recordPushActivityRequestSchema = z18.object({
11883
+ organizationId: z18.string().uuid(),
11884
+ /** Seconds since the last keyboard or mouse input on this computer. A phone leaves it out: it only reports what it has open. */
11885
+ idleSeconds: z18.number().min(0).optional(),
11886
+ seenWorkspaceIds: z18.array(z18.string().uuid()).max(20)
11887
+ });
11888
+ var PUSH_NOTIFICATION_KINDS = [...WORKSPACE_ATTENTION_REASONS, "finished", "pull_request"];
11889
+ var pushQuestionSchema = z18.object({ id: z18.string().max(64), options: z18.array(z18.object({ id: z18.string().max(64), label: z18.string().min(1).max(60) })).min(1).max(4) });
11890
+ var pushNotificationDataSchema = z18.object({
11891
+ organizationId: z18.string(),
11892
+ workspaceId: z18.string(),
11893
+ chatId: z18.string().nullable(),
11894
+ kind: z18.enum(PUSH_NOTIFICATION_KINDS),
11895
+ completedAt: z18.string(),
11896
+ pullRequestUrl: z18.string().optional(),
11897
+ toolRequestId: z18.string().optional(),
11898
+ question: pushQuestionSchema.optional()
11899
+ });
11900
+ var registerLiveActivityRequestSchema = z18.object({
11901
+ deviceId: z18.string().uuid(),
11902
+ workspaceId: z18.string().uuid(),
11903
+ chatId: z18.string().min(1).max(100),
11904
+ /** The iOS activity's push token. Android leaves it out and gets FCM data messages on the device token. */
11905
+ pushToken: z18.string().regex(/^[0-9a-f]{64,400}$/i).optional()
11906
+ });
11907
+
11849
11908
  // ../shared/src/default-skills/replicas-agent/abilities/computer.ts
11850
11909
  var SECTION = `### Computer use (Linux desktop control)
11851
11910
  Drive the workspace's Linux desktop - open a browser, click, type, scroll, screenshot, record - via the \`replicas computer\` CLI. Every Replicas workspace boots with a live H.264 and Opus stream published as an authenticated preview, so a \`Desktop\` tab is always available in the dashboard. Use \`replicas computer info\` to get the viewer URL when you want to share it (e.g. point a user on Slack at the live stream).
@@ -12125,7 +12184,7 @@ var DOCKER_ABILITY = {
12125
12184
  };
12126
12185
 
12127
12186
  // ../shared/src/routes/environment-setups.ts
12128
- import { z as z18 } from "zod";
12187
+ import { z as z19 } from "zod";
12129
12188
  var ENVIRONMENT_SETUP_STEPS = [
12130
12189
  { key: "understand", label: "Understand the codebase" },
12131
12190
  { key: "install", label: "Install dependencies and run the app" },
@@ -12158,17 +12217,17 @@ var ENVIRONMENT_SETUP_LIMITS = {
12158
12217
  repositories: 20
12159
12218
  };
12160
12219
  var VARIABLE_KEY_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
12161
- var text2 = (max) => max === void 0 ? z18.string().trim() : z18.string().trim().max(max);
12220
+ var text2 = (max) => max === void 0 ? z19.string().trim() : z19.string().trim().max(max);
12162
12221
  var requiredText = (max) => text2(max).min(1, "must not be empty");
12163
12222
  var optionalText2 = (max) => text2(max).nullish().transform((value) => value || null);
12164
12223
  var clearableText = (max) => text2(max).nullish().transform((value) => value === void 0 ? void 0 : value || null);
12165
- var list = (item, max) => max === void 0 ? z18.array(item) : z18.array(item).max(max);
12224
+ var list = (item, max) => max === void 0 ? z19.array(item) : z19.array(item).max(max);
12166
12225
  var ENVIRONMENT_SETUP_AUTHORED_TRIGGER_TYPES = ["cron", "github", "gitlab"];
12167
12226
  function isEnvironmentSetupAuthoredTriggerType(type) {
12168
12227
  return ENVIRONMENT_SETUP_AUTHORED_TRIGGER_TYPES.some((authored) => authored === type);
12169
12228
  }
12170
- var proposalTriggerSchema = z18.discriminatedUnion("type", [cronTriggerSchema, githubTriggerSchema, gitlabTriggerSchema]);
12171
- var existingTriggerSchema = z18.custom(
12229
+ var proposalTriggerSchema = z19.discriminatedUnion("type", [cronTriggerSchema, githubTriggerSchema, gitlabTriggerSchema]);
12230
+ var existingTriggerSchema = z19.custom(
12172
12231
  (value) => isRecord(value) && typeof value.type === "string" && isRecord(value.config),
12173
12232
  "must be an automation trigger"
12174
12233
  );
@@ -12176,17 +12235,17 @@ var carriedTriggerSchema = existingTriggerSchema.refine(
12176
12235
  (trigger) => !isEnvironmentSetupAuthoredTriggerType(trigger.type)
12177
12236
  );
12178
12237
  function automationSchema(limits) {
12179
- const authored = z18.object({
12238
+ const authored = z19.object({
12180
12239
  name: text2(limits.nameChars),
12181
12240
  description: text2(limits.descriptionChars),
12182
12241
  prompt: text2(limits.automationPromptChars),
12183
12242
  triggers: list(proposalTriggerSchema, limits.automationTriggers)
12184
12243
  });
12185
- const updated = authored.extend({ triggers: list(z18.union([proposalTriggerSchema, carriedTriggerSchema]), limits.automationTriggers) });
12186
- return z18.object({
12244
+ const updated = authored.extend({ triggers: list(z19.union([proposalTriggerSchema, carriedTriggerSchema]), limits.automationTriggers) });
12245
+ return z19.object({
12187
12246
  key: requiredText(limits.automationKeyChars),
12188
- action: z18.enum(ENVIRONMENT_SETUP_AUTOMATION_ACTIONS).default("create"),
12189
- automation_id: z18.string().regex(UUID_RE, "must be an automation id").nullable().default(null),
12247
+ action: z19.enum(ENVIRONMENT_SETUP_AUTOMATION_ACTIONS).default("create"),
12248
+ automation_id: z19.string().regex(UUID_RE, "must be an automation id").nullable().default(null),
12190
12249
  name: text2().default(""),
12191
12250
  description: optionalText2().transform((value) => value ?? ""),
12192
12251
  prompt: text2().default(""),
@@ -12209,7 +12268,7 @@ function automationSchema(limits) {
12209
12268
  const content = (automation.action === "update" ? updated : authored).safeParse(automation);
12210
12269
  if (content.success) return { ...automation, ...content.data };
12211
12270
  for (const issue of content.error.issues) ctx.addIssue({ ...issue, code: "custom" });
12212
- return z18.NEVER;
12271
+ return z19.NEVER;
12213
12272
  });
12214
12273
  }
12215
12274
  function automationListSchema(limits) {
@@ -12227,7 +12286,7 @@ function automationListSchema(limits) {
12227
12286
  });
12228
12287
  }
12229
12288
  function environmentSchema(limits) {
12230
- return z18.object({
12289
+ return z19.object({
12231
12290
  name: optionalText2(limits.nameChars).transform((value) => value ?? void 0),
12232
12291
  description: clearableText(limits.descriptionChars),
12233
12292
  system_prompt: clearableText(limits.systemPromptChars),
@@ -12236,41 +12295,41 @@ function environmentSchema(limits) {
12236
12295
  });
12237
12296
  }
12238
12297
  function proposalSchema(limits) {
12239
- return z18.object({
12298
+ return z19.object({
12240
12299
  summary: requiredText(limits.summaryChars),
12241
12300
  stack: list(text2(), limits.stackItems).default([]).transform((items) => items.filter(Boolean)),
12242
12301
  environment: environmentSchema(limits),
12243
- variables: list(z18.object({
12244
- key: z18.string().regex(VARIABLE_KEY_RE, "must be a valid environment variable name").max(limits.variableKeyChars ?? Number.POSITIVE_INFINITY),
12302
+ variables: list(z19.object({
12303
+ key: z19.string().regex(VARIABLE_KEY_RE, "must be a valid environment variable name").max(limits.variableKeyChars ?? Number.POSITIVE_INFINITY),
12245
12304
  description: optionalText2(limits.variableDescriptionChars).transform((value) => value ?? ""),
12246
- required: z18.boolean().default(false)
12305
+ required: z19.boolean().default(false)
12247
12306
  }), limits.variables).default([]),
12248
12307
  automations: automationListSchema(limits),
12249
- verification: list(z18.object({
12308
+ verification: list(z19.object({
12250
12309
  label: requiredText(limits.nameChars),
12251
- status: z18.enum(ENVIRONMENT_SETUP_VERIFICATION_STATUSES),
12310
+ status: z19.enum(ENVIRONMENT_SETUP_VERIFICATION_STATUSES),
12252
12311
  detail: optionalText2(limits.verificationDetailChars).transform((value) => value ?? void 0)
12253
12312
  }), limits.verificationItems).default([]),
12254
- media: list(z18.object({
12255
- media_id: z18.string().regex(UUID_RE, "must be a media id"),
12313
+ media: list(z19.object({
12314
+ media_id: z19.string().regex(UUID_RE, "must be a media id"),
12256
12315
  title: requiredText(limits.nameChars)
12257
12316
  }), limits.mediaItems).default([])
12258
12317
  });
12259
12318
  }
12260
12319
  var environmentSetupProposalSchema = proposalSchema({});
12261
12320
  var environmentSetupProposalSubmissionSchema = proposalSchema(ENVIRONMENT_SETUP_LIMITS);
12262
- var environmentSetupRunStateSchema = z18.object({
12263
- status: z18.enum(ENVIRONMENT_SETUP_RUN_STATUSES),
12264
- steps: z18.partialRecord(z18.enum(ENVIRONMENT_SETUP_STEPS.map((step) => step.key)), z18.enum(ENVIRONMENT_SETUP_STEP_STATUSES)).default({}),
12321
+ var environmentSetupRunStateSchema = z19.object({
12322
+ status: z19.enum(ENVIRONMENT_SETUP_RUN_STATUSES),
12323
+ steps: z19.partialRecord(z19.enum(ENVIRONMENT_SETUP_STEPS.map((step) => step.key)), z19.enum(ENVIRONMENT_SETUP_STEP_STATUSES)).default({}),
12265
12324
  proposal: environmentSetupProposalSchema.nullable().default(null),
12266
- applied: z18.object({
12267
- applied_at: z18.string(),
12268
- automation_ids: z18.array(z18.string())
12325
+ applied: z19.object({
12326
+ applied_at: z19.string(),
12327
+ automation_ids: z19.array(z19.string())
12269
12328
  }).nullable().default(null)
12270
12329
  });
12271
- var applyEnvironmentSetupRequestSchema = z18.object({
12330
+ var applyEnvironmentSetupRequestSchema = z19.object({
12272
12331
  environment: environmentSchema(ENVIRONMENT_SETUP_LIMITS).extend({ name: requiredText(ENVIRONMENT_SETUP_LIMITS.nameChars) }),
12273
- variables: list(z18.object({ key: z18.string().regex(VARIABLE_KEY_RE), value: z18.string() }), ENVIRONMENT_SETUP_LIMITS.variables).default([]).refine((variables) => new Set(variables.map((variable) => variable.key)).size === variables.length, "must have unique keys").transform((variables) => variables.filter((variable) => variable.value.length > 0)),
12332
+ variables: list(z19.object({ key: z19.string().regex(VARIABLE_KEY_RE), value: z19.string() }), ENVIRONMENT_SETUP_LIMITS.variables).default([]).refine((variables) => new Set(variables.map((variable) => variable.key)).size === variables.length, "must have unique keys").transform((variables) => variables.filter((variable) => variable.value.length > 0)),
12274
12333
  automations: automationListSchema(ENVIRONMENT_SETUP_LIMITS)
12275
12334
  });
12276
12335
 
@@ -12745,7 +12804,7 @@ var GITLAB_ABILITY = {
12745
12804
  };
12746
12805
 
12747
12806
  // ../shared/src/routes/compute.ts
12748
- import { z as z19 } from "zod";
12807
+ import { z as z20 } from "zod";
12749
12808
  var COMPUTE_SANDBOX_KINDS = ["gpu"];
12750
12809
  var GPU_TYPES = ["T4", "L4", "A10G", "L40S", "A100", "A100-80GB", "H100", "H200", "B200"];
12751
12810
  var DEFAULT_GPU_TYPE = "L4";
@@ -12762,27 +12821,27 @@ var COMPUTE_SANDBOX_LIMITS = {
12762
12821
  maxIdleTimeoutMinutes: 60,
12763
12822
  maxTransferBytes: 1024 ** 3
12764
12823
  };
12765
- var computeEnvSchema = z19.record(z19.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(128), z19.string().max(32768)).refine((env) => Object.keys(env).length <= 64, "At most 64 environment variables are allowed");
12766
- var createComputeSandboxRequestSchema = z19.object({
12767
- kind: z19.enum(COMPUTE_SANDBOX_KINDS),
12768
- gpu: z19.string().trim().optional(),
12769
- image: z19.string().trim().min(1).max(256).regex(/^\S+$/, "Image must not contain whitespace").optional(),
12770
- timeoutMinutes: z19.number().int().min(1).max(COMPUTE_SANDBOX_LIMITS.maxTimeoutMinutes).optional(),
12771
- idleTimeoutMinutes: z19.number().int().min(1).max(COMPUTE_SANDBOX_LIMITS.maxIdleTimeoutMinutes).optional(),
12772
- ports: z19.array(z19.number().int().min(1).max(65535)).max(COMPUTE_SANDBOX_LIMITS.maxPorts).optional(),
12824
+ var computeEnvSchema = z20.record(z20.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/).max(128), z20.string().max(32768)).refine((env) => Object.keys(env).length <= 64, "At most 64 environment variables are allowed");
12825
+ var createComputeSandboxRequestSchema = z20.object({
12826
+ kind: z20.enum(COMPUTE_SANDBOX_KINDS),
12827
+ gpu: z20.string().trim().optional(),
12828
+ image: z20.string().trim().min(1).max(256).regex(/^\S+$/, "Image must not contain whitespace").optional(),
12829
+ timeoutMinutes: z20.number().int().min(1).max(COMPUTE_SANDBOX_LIMITS.maxTimeoutMinutes).optional(),
12830
+ idleTimeoutMinutes: z20.number().int().min(1).max(COMPUTE_SANDBOX_LIMITS.maxIdleTimeoutMinutes).optional(),
12831
+ ports: z20.array(z20.number().int().min(1).max(65535)).max(COMPUTE_SANDBOX_LIMITS.maxPorts).optional(),
12773
12832
  env: computeEnvSchema.optional()
12774
12833
  });
12775
- var computeExecRequestSchema = z19.object({
12776
- command: z19.string().min(1).max(1e5),
12777
- workdir: z19.string().min(1).max(4096).optional(),
12834
+ var computeExecRequestSchema = z20.object({
12835
+ command: z20.string().min(1).max(1e5),
12836
+ workdir: z20.string().min(1).max(4096).optional(),
12778
12837
  env: computeEnvSchema.optional(),
12779
- detach: z19.boolean().optional()
12838
+ detach: z20.boolean().optional()
12780
12839
  });
12781
- var computeUploadRequestSchema = z19.object({
12782
- size: z19.number().int().min(1).max(COMPUTE_SANDBOX_LIMITS.maxTransferBytes)
12840
+ var computeUploadRequestSchema = z20.object({
12841
+ size: z20.number().int().min(1).max(COMPUTE_SANDBOX_LIMITS.maxTransferBytes)
12783
12842
  });
12784
- var computeTransferPathSchema = z19.object({
12785
- path: z19.string().min(1).max(4096).optional()
12843
+ var computeTransferPathSchema = z20.object({
12844
+ path: z20.string().min(1).max(4096).optional()
12786
12845
  });
12787
12846
 
12788
12847
  // ../shared/src/default-skills/replicas-agent/abilities/gpu.ts
@@ -14344,6 +14403,11 @@ var ALERT_SOUND_FAMILIES = {
14344
14403
  wood: ["ready", "pluck", "knock", "bloom", "steps"]
14345
14404
  };
14346
14405
  var ALERT_SOUNDS = [...ALERT_SOUND_FAMILIES.glass, ...ALERT_SOUND_FAMILIES.wood];
14406
+ var PUSH_WHEN_ACTIVE_COPY = {
14407
+ wait: `Wait ${PUSH_HOLD_MINUTES} minutes`,
14408
+ skip: "Don\u2019t send",
14409
+ send: "Send right away"
14410
+ };
14347
14411
  var DEFAULT_USER_PREFERENCES = {
14348
14412
  default_agent: null,
14349
14413
  default_model: null,
@@ -14383,7 +14447,8 @@ var DEFAULT_USER_PREFERENCES = {
14383
14447
  alert_sound: null,
14384
14448
  workspace_alerts: {},
14385
14449
  automation_alerts: {},
14386
- push_types: { needs_you: true, finished: true, pull_requests: true, automations: true, usage_limit: true }
14450
+ push_types: { needs_you: true, finished: true, pull_requests: true, automations: true, usage_limit: true },
14451
+ push_when_active: "wait"
14387
14452
  };
14388
14453
  function defaultReplicasAgentAbilities() {
14389
14454
  const abilities = {};
@@ -14432,18 +14497,18 @@ var MOTHERSHIP_EVENT_KINDS = ["finished", "ready", "needs_attention", "merged",
14432
14497
  var MOTHERSHIP_TURN_ERROR_SUMMARY = "Turn ended with an error.";
14433
14498
  var MOTHERSHIP_EVENT_TYPE = "multitask-event";
14434
14499
  var MOTHERSHIP_EVENT_MESSAGE_TYPE = "multitask_event";
14435
- var mothershipEventSchema = z20.object({
14436
- id: z20.string(),
14437
- at: z20.string(),
14438
- kind: z20.enum(MOTHERSHIP_EVENT_KINDS),
14439
- agentId: z20.string(),
14440
- agentName: z20.string(),
14441
- summary: z20.string(),
14442
- detail: z20.string().optional(),
14500
+ var mothershipEventSchema = z21.object({
14501
+ id: z21.string(),
14502
+ at: z21.string(),
14503
+ kind: z21.enum(MOTHERSHIP_EVENT_KINDS),
14504
+ agentId: z21.string(),
14505
+ agentName: z21.string(),
14506
+ summary: z21.string(),
14507
+ detail: z21.string().optional(),
14443
14508
  // Set when the subagent is a chat in this workspace rather than a ship; agentId is then that chat's id.
14444
- chatId: z20.string().optional(),
14509
+ chatId: z21.string().optional(),
14445
14510
  // Set on events recorded before every kind woke the orchestrator, which were shown as a row when they happened.
14446
- noticed: z20.boolean().optional()
14511
+ noticed: z21.boolean().optional()
14447
14512
  });
14448
14513
  var TAG = "multitask_event";
14449
14514
  var BLOCK = new RegExp(`<${TAG}((?:\\s+\\w+="[^"]*")*)>\\n?([\\s\\S]*?)\\n?</${TAG}>`, "g");
@@ -15000,6 +15065,9 @@ function upsertDisplayMessage(messages, message2) {
15000
15065
  else messages[index] = message2;
15001
15066
  return message2;
15002
15067
  }
15068
+ function isToolInputQuestion(value) {
15069
+ return isRecord(value) && typeof value.id === "string" && typeof value.prompt === "string" && typeof value.multiSelect === "boolean" && Array.isArray(value.options) && value.options.every((option) => isRecord(option) && typeof option.id === "string" && typeof option.label === "string");
15070
+ }
15003
15071
  function applyToolInputEvent(event, messages, provider2, state, questionFilter) {
15004
15072
  if (event.type === "replicas-tool-input-request" && typeof event.payload.toolUseId === "string" && typeof event.payload.requestId === "string" && (Array.isArray(event.payload.options) || Array.isArray(event.payload.questions))) {
15005
15073
  const previous = state.resolutions.get(event.payload.toolUseId);
@@ -15099,6 +15167,16 @@ function planItemsFromMessage(message2) {
15099
15167
  function peerChatName(message2) {
15100
15168
  return message2.chat ?? "another chat";
15101
15169
  }
15170
+ function getDisplayMessageStatus(message2) {
15171
+ if (message2.type === "error" || message2.type === "quota_status") return "failed";
15172
+ if (message2.type === "auth_fallback") return message2.status === "switched" ? "completed" : "failed";
15173
+ if (message2.type === "interruption" || message2.type === "multitask_event" || message2.type === "harness_switch") return "completed";
15174
+ if (message2.type === "background_task") return message2.status === "stopped" ? "completed" : message2.status;
15175
+ if (message2.type === "command" || message2.type === "patch") {
15176
+ return message2.status ?? (message2.exitCode === void 0 ? "in_progress" : message2.exitCode === 0 ? "completed" : "failed");
15177
+ }
15178
+ return "status" in message2 ? message2.status : void 0;
15179
+ }
15102
15180
  function todoItemStatus(item) {
15103
15181
  return item.itemStatus ?? (item.completed ? "completed" : "pending");
15104
15182
  }
@@ -15135,6 +15213,17 @@ ${operation.diff}` : ""}`).join("\n\n");
15135
15213
  if (message2.type === "multitask_event") return { kind: "task", title: "Ship update", summary: message2.events.map((event) => `${event.agentName}: ${event.summary}`).join(" \xB7 "), content: "" };
15136
15214
  return { kind: "error", title: "Agent error", summary: "", content: message2.message };
15137
15215
  }
15216
+ function lineCountFromOutput(output) {
15217
+ if (!output) return null;
15218
+ let end = output.length;
15219
+ while (end > 0 && output[end - 1] === "\n") end--;
15220
+ if (end === 0) return null;
15221
+ let lines = 1;
15222
+ for (let i = 0; i < end; i++) {
15223
+ if (output[i] === "\n") lines++;
15224
+ }
15225
+ return lines;
15226
+ }
15138
15227
  function fileContentDiff(path, content, action) {
15139
15228
  const lines = content.replace(/\n$/, "").split("\n");
15140
15229
  return [
@@ -15144,7 +15233,81 @@ function fileContentDiff(path, content, action) {
15144
15233
  ...lines.map((line) => `${action === "add" ? "+" : "-"}${line}`)
15145
15234
  ].join("\n");
15146
15235
  }
15236
+ function isRawFileContent(diff, action) {
15237
+ const lines = diff.split("\n");
15238
+ return !lines[0].startsWith("diff --git ") && !(lines[0].startsWith("--- ") && lines[1]?.startsWith("+++ ")) && !(action === "add" && lines.every((line) => line === "" || line.startsWith("+")));
15239
+ }
15240
+ function operationDiffStats({ diff, action }) {
15241
+ if (!diff) return void 0;
15242
+ if (action === "update" || !isRawFileContent(diff, action)) return getDiffStats(diff);
15243
+ const lines = diff.replace(/\n$/, "").split("\n").length;
15244
+ return action === "add" ? { added: lines, removed: 0 } : { added: 0, removed: lines };
15245
+ }
15246
+ function getDiffStats(diff) {
15247
+ let added = 0;
15248
+ let removed = 0;
15249
+ let oldLeft = 0;
15250
+ let newLeft = 0;
15251
+ let lineStart = 0;
15252
+ for (let i = 0; i <= diff.length; i++) {
15253
+ if (i !== diff.length && diff[i] !== "\n") continue;
15254
+ const first = diff[lineStart];
15255
+ const hunk = first === "@" ? /^@@ -\d+(?:,(\d+))? \+\d+(?:,(\d+))? @@/.exec(diff.slice(lineStart, i)) : null;
15256
+ if (hunk) {
15257
+ oldLeft = Number(hunk[1] ?? 1);
15258
+ newLeft = Number(hunk[2] ?? 1);
15259
+ } else if (oldLeft > 0 || newLeft > 0) {
15260
+ if (first === "+") {
15261
+ added++;
15262
+ newLeft--;
15263
+ } else if (first === "-") {
15264
+ removed++;
15265
+ oldLeft--;
15266
+ } else if (first === " ") {
15267
+ oldLeft--;
15268
+ newLeft--;
15269
+ }
15270
+ } else if (!diff.startsWith("+++", lineStart) && !diff.startsWith("---", lineStart)) {
15271
+ if (first === "+") added++;
15272
+ else if (first === "-") removed++;
15273
+ }
15274
+ lineStart = i + 1;
15275
+ }
15276
+ return { added, removed };
15277
+ }
15278
+ var READ_COMMANDS = /* @__PURE__ */ new Set([
15279
+ "cat",
15280
+ "find",
15281
+ "grep",
15282
+ "head",
15283
+ "ls",
15284
+ "nl",
15285
+ "pwd",
15286
+ "rg",
15287
+ "sed",
15288
+ "tail",
15289
+ "tree",
15290
+ "wc"
15291
+ ]);
15147
15292
  var SEARCH_COMMANDS = /* @__PURE__ */ new Set(["grep", "rg"]);
15293
+ var PIPE_FILTERS = /* @__PURE__ */ new Set(["awk", "cat", "column", "cut", "grep", "head", "jq", "nl", "rg", "sed", "sort", "tail", "tr", "uniq", "wc"]);
15294
+ var NEUTRAL_COMMANDS = /* @__PURE__ */ new Set(["cd", "echo", "printf", "true"]);
15295
+ var GIT_READ_COMMANDS = /* @__PURE__ */ new Set([
15296
+ "branch",
15297
+ "diff",
15298
+ "grep",
15299
+ "log",
15300
+ "ls-files",
15301
+ "show",
15302
+ "status"
15303
+ ]);
15304
+ var GH_READ_COMMANDS = /* @__PURE__ */ new Set([
15305
+ "api",
15306
+ "issue",
15307
+ "pr",
15308
+ "repo",
15309
+ "run"
15310
+ ]);
15148
15311
  var LINE_COUNT_VALUE_FLAGS = /* @__PURE__ */ new Set(["-c", "-n", "--bytes", "--lines"]);
15149
15312
  var SEARCH_VALUE_FLAGS = ["-A", "-B", "-C", "-d", "-e", "-f", "-m", "--after-context", "--before-context", "--context", "--file", "--max-count", "--regexp"];
15150
15313
  var VALUE_FLAGS = {
@@ -15160,9 +15323,26 @@ var PATTERN_FLAGS = /* @__PURE__ */ new Set(["-e", "-f", "--file", "--regexp"]);
15160
15323
  var SCRIPT_ROOT = "/";
15161
15324
  var commandName = (argv) => argv[0].split("/").pop() ?? argv[0];
15162
15325
  var fileWrites = ({ writes }) => writes.filter(({ path }) => path !== "/dev/null");
15326
+ function displayPath(dir, path) {
15327
+ if (path.startsWith("~")) return path;
15328
+ const resolved = resolveShellPath(dir, path);
15329
+ if (resolved === null) return null;
15330
+ if (resolved === SCRIPT_ROOT) return ".";
15331
+ if (resolved.startsWith(`${SCRIPT_ROOT}/`)) return resolved.slice(SCRIPT_ROOT.length + 1);
15332
+ return path.startsWith("/") ? resolved : null;
15333
+ }
15163
15334
  function shellCommands(command) {
15164
15335
  return parseShellScript(command, SCRIPT_ROOT).filter(({ wrapper }) => !wrapper);
15165
15336
  }
15337
+ function simpleCommands(command) {
15338
+ const commands = shellCommands(command);
15339
+ const hasRedirectOrSubshell = commands.some((shellCommand) => shellCommand.subshell || shellCommand.stdinFile !== null || !shellCommand.piped && shellCommand.stdin !== void 0 || fileWrites(shellCommand).length > 0);
15340
+ if (commands.length === 0 || hasRedirectOrSubshell) return null;
15341
+ return commands.map((shellCommand) => {
15342
+ const argv = shellCommand.argv.map((word) => word.replaceAll(SHELL_OPAQUE, "\u2026"));
15343
+ return { ...shellCommand, argv, name: commandName(argv) };
15344
+ });
15345
+ }
15166
15346
  var SKILL_READ_COMMANDS = /* @__PURE__ */ new Set(["awk", "bat", "cat", "head", "less", "more", "nl", "sed", "tail"]);
15167
15347
  function skillNamesFromCommand(command) {
15168
15348
  return Array.from(new Set(shellCommands(command).flatMap((shellCommand) => {
@@ -15228,10 +15408,72 @@ function readCommandPaths(command, words) {
15228
15408
  }
15229
15409
  return pathArgs(command, words.slice(1));
15230
15410
  }
15411
+ function readTitle(search, output, paths) {
15412
+ const lines = lineCountFromOutput(output);
15413
+ if (lines) return `Read ${lines} line${lines === 1 ? "" : "s"}${paths.length > 1 ? ` from ${paths.length} files` : ""}`;
15414
+ return search ? "Search" : paths.length > 1 ? `Read ${paths.length} files` : "Read";
15415
+ }
15416
+ function writtenFile(command) {
15417
+ const [write, ...rest] = shellCommands(command).filter(({ argv }) => !["cd", "mkdir"].includes(commandName(argv)));
15418
+ if (!write || rest.length > 0 || write.piped || write.subshell || write.stdinFile !== null) return null;
15419
+ if (!["cat", "echo", "printf"].includes(commandName(write.argv))) return null;
15420
+ const writes = fileWrites(write);
15421
+ return writes.length === 1 && writes[0].path ? displayPath(write.dir, writes[0].target) : null;
15422
+ }
15231
15423
  function writesFiles(name, argv) {
15232
15424
  if (name === "sed") return argv.some((word) => /^(-[a-zA-Z]*i|--in-place)/.test(word));
15233
15425
  return name === "find" && argv.some((word) => /^-(exec|ok|delete|fprint|fls)/.test(word));
15234
15426
  }
15427
+ function commandDisplayFromCommand(command, output) {
15428
+ const written = writtenFile(command);
15429
+ if (written) return { title: "Write", paths: [written] };
15430
+ const commands = simpleCommands(command);
15431
+ if (!commands || commands.some(({ name, argv, piped }) => writesFiles(name, argv) || piped && !PIPE_FILTERS.has(name))) return null;
15432
+ const mainCommands = commands.filter(({ name, piped }) => !piped && !NEUTRAL_COMMANDS.has(name));
15433
+ if (mainCommands.length === 0) return null;
15434
+ if (mainCommands.length === 1) {
15435
+ const [{ name, argv: words }] = mainCommands;
15436
+ if (name === "git" && words[1] && GIT_READ_COMMANDS.has(words[1])) {
15437
+ return { title: `Git ${words[1]}`, paths: [] };
15438
+ }
15439
+ if (name === "gh" && words[1] && GH_READ_COMMANDS.has(words[1])) {
15440
+ return { title: words[1] === "pr" && words[2] ? `GitHub PR ${words[2]}` : "GitHub", paths: [] };
15441
+ }
15442
+ }
15443
+ if (!mainCommands.every(({ name }) => READ_COMMANDS.has(name))) return null;
15444
+ const paths = /* @__PURE__ */ new Set();
15445
+ for (const { name, argv, dir } of mainCommands) {
15446
+ for (const path of readCommandPaths(name, argv)) {
15447
+ const shown = displayPath(dir, path);
15448
+ if (shown === null) return null;
15449
+ paths.add(shown);
15450
+ }
15451
+ }
15452
+ const search = mainCommands.every(({ name }) => SEARCH_COMMANDS.has(name));
15453
+ return { title: readTitle(search, output, [...paths]), paths: [...paths] };
15454
+ }
15455
+
15456
+ // ../shared/src/display-message/tool-call.ts
15457
+ function parseToolCallInput(inputValue) {
15458
+ const input = typeof inputValue === "string" ? inputValue : inputValue ? JSON.stringify(inputValue, null, 2) : "";
15459
+ let inputObject = null;
15460
+ if (inputValue && typeof inputValue !== "string") inputObject = inputValue;
15461
+ else if (input)
15462
+ try {
15463
+ const parsed = JSON.parse(input);
15464
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed))
15465
+ inputObject = Object.fromEntries(Object.entries(parsed));
15466
+ } catch {
15467
+ }
15468
+ const filePath = inputObject ? [inputObject.file_path, inputObject.filePath, inputObject.path, inputObject.filename, inputObject.file].find(
15469
+ (value) => typeof value === "string" && value.trim().length > 0
15470
+ ) : void 0;
15471
+ return {
15472
+ input,
15473
+ inputObject,
15474
+ filePath: filePath ?? input.match(/^\*\*\* (?:Update|Add|Delete) File: (.+)$/m)?.[1]
15475
+ };
15476
+ }
15235
15477
 
15236
15478
  // ../shared/src/display-message/parsers/mcp.ts
15237
15479
  function parseMcpToolName(name) {
@@ -15246,8 +15488,30 @@ function parseMcpToolName(name) {
15246
15488
  return { server, tool };
15247
15489
  }
15248
15490
 
15491
+ // ../shared/src/display-message/subagent-tools.ts
15492
+ function chatIdFrom(input) {
15493
+ const value = parseToolCallInput(input).inputObject;
15494
+ if (!value) return null;
15495
+ if ("chatId" in value && typeof value.chatId === "string") return value.chatId;
15496
+ return "chat_id" in value && typeof value.chat_id === "string" ? value.chat_id : null;
15497
+ }
15498
+ function subagentToolName(message2) {
15499
+ const mcp = parseMcpToolName(message2.tool);
15500
+ const server = mcp?.server ?? message2.server;
15501
+ const tool = mcp?.tool ?? message2.tool;
15502
+ return isSubagentMcpServerName(server) ? tool : null;
15503
+ }
15504
+ function subagentChatId(message2) {
15505
+ const tool = subagentToolName(message2);
15506
+ if (!tool || tool === SUBAGENT_MCP_TOOLS.getProviders || !isSubagentMcpToolName(tool)) return null;
15507
+ const inputId = chatIdFrom(message2.input);
15508
+ if (inputId) return inputId;
15509
+ if (tool !== SUBAGENT_MCP_TOOLS.spawnAgent || !message2.output) return null;
15510
+ return chatIdFrom(message2.output);
15511
+ }
15512
+
15249
15513
  // ../shared/src/learned-skills.ts
15250
- import { z as z21 } from "zod";
15514
+ import { z as z22 } from "zod";
15251
15515
 
15252
15516
  // ../shared/src/frontmatter.ts
15253
15517
  import { parse as parseYaml } from "yaml";
@@ -15270,20 +15534,20 @@ function parseFrontmatter(content) {
15270
15534
  var LEARNED_SKILLS_ROOT = `${SANDBOX_PATHS.REPLICAS_DIR}/learned-skills`;
15271
15535
  var LEARNED_SKILLS_MANIFEST_PATH = `${LEARNED_SKILLS_ROOT}/manifest.json`;
15272
15536
  var LEARNED_SKILL_DIR_PREFIX = "replicas-learned__";
15273
- var learnedSkillsManifestSchema = z21.object({
15274
- skills: z21.array(z21.object({ name: z21.string(), sha256: z21.string() }))
15537
+ var learnedSkillsManifestSchema = z22.object({
15538
+ skills: z22.array(z22.object({ name: z22.string(), sha256: z22.string() }))
15275
15539
  });
15276
- var dreamVerdictChecksSchema = z21.object({
15277
- repeatable: z21.boolean(),
15278
- realInstruction: z21.boolean(),
15279
- noContradiction: z21.boolean(),
15280
- formatExact: z21.boolean(),
15281
- humanOnly: z21.boolean(),
15282
- actionable: z21.boolean(),
15283
- durable: z21.boolean()
15540
+ var dreamVerdictChecksSchema = z22.object({
15541
+ repeatable: z22.boolean(),
15542
+ realInstruction: z22.boolean(),
15543
+ noContradiction: z22.boolean(),
15544
+ formatExact: z22.boolean(),
15545
+ humanOnly: z22.boolean(),
15546
+ actionable: z22.boolean(),
15547
+ durable: z22.boolean()
15284
15548
  });
15285
15549
  var DREAM_VERDICT_CHECKS = dreamVerdictChecksSchema.keyof().options;
15286
- var dreamVerdictSchema = dreamVerdictChecksSchema.extend({ approve: z21.boolean(), reason: z21.string() });
15550
+ var dreamVerdictSchema = dreamVerdictChecksSchema.extend({ approve: z22.boolean(), reason: z22.string() });
15287
15551
  var learnedSkillFormatInstruction = (speaker) => `Write a SKILL.md whose frontmatter has a kebab-case \`name\` and a short \`description\` that starts with "Use when" and names the situations it applies to; the body records only what ${speaker} actually said, restated as a direct instruction, usually one to three lines. Every line of a learning is loaded into future sessions, so leave out anything an agent could infer on its own: no headings, explanations, rules, or examples unless ${speaker} stated those specifics themselves. For "from now on, use Conventional Commits", the body is just "Use Conventional Commits for every commit message and PR title."`;
15288
15552
 
15289
15553
  // ../shared/src/user-message-matching.ts
@@ -15303,7 +15567,152 @@ function areUserMessagesWithinMatchWindow(a, b) {
15303
15567
  return a.content === b.content && Math.abs(parseTimestampMs(a.timestamp) - parseTimestampMs(b.timestamp)) <= USER_MESSAGE_MATCH_GRACE_PERIOD_MS;
15304
15568
  }
15305
15569
 
15570
+ // ../shared/src/display-message/turns.ts
15571
+ function isCompaction(message2) {
15572
+ return message2.type === "reasoning" && message2.content === COMPACTION_CONTENT;
15573
+ }
15574
+ function isGoalUpdate(message2) {
15575
+ return message2.type === "tool_call" && message2.server === "claude" && message2.tool === GOAL_TOOL_NAME;
15576
+ }
15577
+
15306
15578
  // ../shared/src/display-message/steps.ts
15579
+ function inputString(input, ...keys) {
15580
+ for (const key of keys) {
15581
+ const value = input?.[key];
15582
+ if (typeof value === "string" && value.trim()) return value;
15583
+ }
15584
+ return void 0;
15585
+ }
15586
+ var COMMAND_PARSE_LIMIT = 4096;
15587
+ function shellPayload(command) {
15588
+ const [first] = parseShellScript(command, null);
15589
+ const flag = first?.wrapper ? first.argv.findIndex((arg, index) => index > 0 && /^-[A-Za-z]*c[A-Za-z]*$/.test(arg)) : -1;
15590
+ return (flag > 0 ? first.argv[flag + 1] : void 0)?.replaceAll(SHELL_OPAQUE, "\u2026") ?? command.trim();
15591
+ }
15592
+ function commandLabel(command) {
15593
+ const lines = shellPayload(command.slice(0, COMMAND_PARSE_LIMIT)).replace(/^cd\s+\S+\s*&&\s*/, "").split("\n").filter((line) => line.trim());
15594
+ const shown = lines.length > 1 && /(["']|<<-?\s*['"]?\w+['"]?)\s*$/.test(lines[0]) ? 2 : 1;
15595
+ const label = lines.slice(0, shown).map((line) => line.trim()).join(" ");
15596
+ return lines.length > shown ? `${label} \u2026` : label;
15597
+ }
15598
+ var BACKGROUND_META = {
15599
+ in_progress: "Running in background",
15600
+ completed: "Done in background",
15601
+ failed: "Failed in background",
15602
+ stopped: "Stopped in background"
15603
+ };
15604
+ var OPERATION_VERBS = {
15605
+ add: ["Creating", "Created", "file-plus"],
15606
+ delete: ["Deleting", "Deleted", "file-x"],
15607
+ update: ["Editing", "Edited", "file-pen"]
15608
+ };
15609
+ function skillStep(base, key, skillName) {
15610
+ return skillName.startsWith(LEARNED_SKILL_DIR_PREFIX) ? { ...base, key, category: "learning", icon: "lightbulb", live: "Using learning", done: "Used learning", target: { text: skillName.slice(LEARNED_SKILL_DIR_PREFIX.length) } } : { ...base, key, category: "skill", icon: "zap", live: "Using skill", done: "Used skill", target: { text: skillName } };
15611
+ }
15612
+ function describeMessageSteps(message2, durationMs, background) {
15613
+ const status = getDisplayMessageStatus(message2);
15614
+ const base = {
15615
+ message: message2,
15616
+ running: status === "in_progress",
15617
+ failed: status === "failed",
15618
+ durationMs
15619
+ };
15620
+ switch (message2.type) {
15621
+ case "reasoning":
15622
+ if (isCompaction(message2)) {
15623
+ return [{ ...base, key: message2.id, category: "compact", icon: "fold", live: "Compacting context", done: base.failed ? "Context compaction" : "Compacted context" }];
15624
+ }
15625
+ if (!message2.content.trim()) return [];
15626
+ return [{ ...base, key: message2.id, category: "think", icon: "brain", live: "Thinking", done: "Thought", failed: false, detail: "reasoning" }];
15627
+ case "command": {
15628
+ const policyBlocked = message2.status === "failed" && message2.exitCode == null && Boolean(message2.output?.toLowerCase().includes("blocked by organization policy"));
15629
+ const display = policyBlocked || message2.command.length > COMMAND_PARSE_LIMIT ? null : commandDisplayFromCommand(message2.command);
15630
+ const failed = policyBlocked || base.failed || message2.exitCode != null && message2.exitCode !== 0 || background?.status === "failed";
15631
+ const running = background ? background.status === "in_progress" : base.running;
15632
+ const meta = policyBlocked ? "Blocked by policy" : background ? BACKGROUND_META[background.status] : failed && message2.exitCode != null ? `Exit code ${message2.exitCode}` : void 0;
15633
+ const shell = { ...base, meta, running, failed, detail: "shell", background };
15634
+ const pathSkills = display?.paths.map(skillNameFromFilePath) ?? [];
15635
+ if ((display?.title.startsWith("Read") || display?.title === "Search" && pathSkills.every(Boolean)) && display.paths.length > 0) {
15636
+ return display.paths.map((path, index) => {
15637
+ const key = index ? `${message2.id}-${index}` : message2.id;
15638
+ const skillName = pathSkills[index];
15639
+ return skillName ? skillStep(shell, key, skillName) : { ...shell, key, category: "read", icon: "book", live: "Reading", done: "Read", target: { text: path, path } };
15640
+ });
15641
+ }
15642
+ if (display?.title === "Write") {
15643
+ return [{ ...shell, key: message2.id, category: "edit", icon: "file-pen", live: "Writing", done: "Wrote", target: { text: display.paths[0], path: display.paths[0] } }];
15644
+ }
15645
+ return [...(message2.skillNames ?? []).map((skillName) => skillStep(shell, `${message2.id}-${skillName}`, skillName)), {
15646
+ ...shell,
15647
+ key: message2.id,
15648
+ category: display?.title === "Search" ? "search" : "command",
15649
+ icon: "terminal",
15650
+ live: "Running",
15651
+ done: "Ran",
15652
+ target: { text: commandLabel(message2.command) }
15653
+ }];
15654
+ }
15655
+ case "patch":
15656
+ return message2.operations.map((operation, index) => {
15657
+ const [live, done, icon] = OPERATION_VERBS[operation.action] ?? OPERATION_VERBS.update;
15658
+ return {
15659
+ ...base,
15660
+ key: `${message2.id}-${index}`,
15661
+ category: "edit",
15662
+ icon,
15663
+ live,
15664
+ done,
15665
+ target: { text: operation.moveTo ?? operation.path, path: operation.moveTo ?? operation.path },
15666
+ detail: operation.diff ? "diff" : void 0,
15667
+ operation
15668
+ };
15669
+ });
15670
+ case "file_change":
15671
+ return message2.changes.map((change, index) => {
15672
+ const [live, done, icon] = OPERATION_VERBS[change.kind] ?? OPERATION_VERBS.update;
15673
+ return { ...base, key: `${message2.id}-${index}`, category: "edit", icon, live, done, target: { text: change.path, path: change.path } };
15674
+ });
15675
+ case "web_search":
15676
+ return [{ ...base, key: message2.id, category: "web", icon: "globe", live: "Searching the web for", done: "Searched the web for", target: { text: message2.query } }];
15677
+ case "skill":
15678
+ return [skillStep(base, message2.id, message2.skillName)];
15679
+ case "subagent":
15680
+ return [{
15681
+ ...base,
15682
+ // A foreground agent's spawning call returns only when it finishes, so its result settles the step even when the
15683
+ // task's own completion was never recorded. A backgrounded agent's call returns at launch.
15684
+ ...background?.isBackgrounded && { running: background.status === "in_progress", failed: background.status === "failed" },
15685
+ key: message2.id,
15686
+ category: "agent",
15687
+ icon: "bot",
15688
+ live: "Running",
15689
+ done: "Ran",
15690
+ target: { text: message2.description, plain: true },
15691
+ background
15692
+ }];
15693
+ case "background_task":
15694
+ if (message2.toolUseId) return [];
15695
+ return [{ ...base, key: message2.id, category: "task", icon: "bell", live: "Running", done: "Ran", target: { text: message2.description ?? message2.summary ?? "background task", plain: true } }];
15696
+ case "peer_message":
15697
+ return [message2.direction === "received" ? { ...base, key: message2.id, category: "message", icon: "message", live: "Message from", done: "Message from", target: { text: peerChatName(message2), plain: true }, detail: "peer" } : { ...base, key: message2.id, category: "message", icon: "send", live: "Messaging", done: "Messaged", target: { text: peerChatName(message2), plain: true }, detail: "peer" }];
15698
+ case "tool_call": {
15699
+ const step = describeToolCall(message2, base);
15700
+ return step ? [step] : [];
15701
+ }
15702
+ case "capacity_retry":
15703
+ return [{
15704
+ ...base,
15705
+ key: message2.id,
15706
+ category: "retry",
15707
+ icon: "clock",
15708
+ live: "Retrying",
15709
+ done: "Retried",
15710
+ target: { text: `(model at capacity, ${message2.attempt} of ${message2.maxAttempts})`, plain: true }
15711
+ }];
15712
+ default:
15713
+ return [];
15714
+ }
15715
+ }
15307
15716
  var SUBAGENT_STEPS = {
15308
15717
  [SUBAGENT_MCP_TOOLS.messageAgent]: { icon: "message", live: "Messaging", done: "Messaged" },
15309
15718
  [SUBAGENT_MCP_TOOLS.waitAgent]: { icon: "clock", live: "Waiting for", done: "Waited for" },
@@ -15340,6 +15749,130 @@ var REPLICAS_API_STEPS = {
15340
15749
  [REPLICAS_MCP_TOOLS.listEnvironments]: { icon: "list", live: "Listing environments", done: "Listed environments" },
15341
15750
  [REPLICAS_MCP_TOOLS.createAutomation]: { icon: "clock", live: "Creating automation", done: "Created automation" }
15342
15751
  };
15752
+ var INTERNAL_TOOLS = /* @__PURE__ */ new Set(["ToolSearch", "ListAgents", "ListMcpResourcesTool", "ReadMcpResourceTool", "TaskOutput", "BashOutput"]);
15753
+ function describeToolCall(message2, base) {
15754
+ const { inputObject: input, filePath } = parseToolCallInput(message2.input);
15755
+ const tool = message2.tool;
15756
+ const key = message2.id;
15757
+ if (INTERNAL_TOOLS.has(tool)) return null;
15758
+ if (isGoalUpdate(message2)) {
15759
+ const objective = inputString(input, "objective");
15760
+ return objective ? { ...base, key, category: "tool", icon: "target", live: "Setting goal", done: "Set goal", target: { text: objective, plain: true } } : { ...base, key, category: "tool", icon: "target", live: "Clearing goal", done: "Cleared goal" };
15761
+ }
15762
+ const subagentTool = subagentToolName(message2);
15763
+ if (subagentTool && isSubagentMcpToolName(subagentTool)) {
15764
+ const failed = base.failed || typeof parseToolCallInput(message2.output).inputObject?.error === "string";
15765
+ if (subagentTool === SUBAGENT_MCP_TOOLS.spawnAgent) {
15766
+ return { ...base, key, category: "agent", icon: "bot", live: "Running", done: "Started", failed, target: { text: inputString(input, "title", "prompt") ?? "subagent", plain: true } };
15767
+ }
15768
+ const chatId = subagentChatId(message2);
15769
+ const provider2 = typeof input?.provider === "string" && isValidAgentProvider(input.provider) ? input.provider : null;
15770
+ const agent = inputString(input, "title") ?? chatId?.slice(0, 8) ?? (provider2 ? getProviderDisplayName(provider2) : void 0);
15771
+ return { ...base, key, category: "tool", ...SUBAGENT_STEPS[subagentTool], failed, target: agent ? { text: agent, plain: true } : void 0, detail: "subagent" };
15772
+ }
15773
+ const mcp = parseMcpToolName(tool);
15774
+ const replicasTool = (mcp?.server ?? message2.server) === REPLICAS_MCP_SERVER_NAME ? mcp?.tool ?? tool : tool.startsWith(`${REPLICAS_MCP_SERVER_NAME}_`) ? tool.slice(REPLICAS_MCP_SERVER_NAME.length + 1) : void 0;
15775
+ const mothershipAction = replicasTool ? MOTHERSHIP_TOOL_ACTIONS[replicasTool] : void 0;
15776
+ if (mothershipAction) {
15777
+ const step = {
15778
+ ...base,
15779
+ key,
15780
+ failed: base.failed || Boolean(message2.output?.startsWith("Error:")),
15781
+ mothership: { action: mothershipAction, name: inputString(input, "name"), agentId: inputString(input, "agent_id"), chatId: inputString(input, "chat_id"), text: inputString(input, "prompt", "message") }
15782
+ };
15783
+ if (mothershipAction === "spawn") return { ...step, category: "agent", icon: "network", live: "Spawning", done: "Spawned", detail: "mothership" };
15784
+ if (mothershipAction === "send") return { ...step, category: "agent", icon: "message", live: "Messaging", done: "Messaged", detail: "mothership" };
15785
+ if (mothershipAction === "wait") {
15786
+ return { ...step, category: "agent", icon: "clock", live: "Waiting for ships", done: "Waited for ships", detail: "mothership", mothership: { ...step.mothership, events: extractMothershipEvents(message2.output ?? "") } };
15787
+ }
15788
+ if (mothershipAction === "archive") return { ...step, category: "tool", icon: "archive", live: "Archiving ship", done: "Archived ship", detail: "io" };
15789
+ return mothershipAction === "list" ? { ...step, category: "tool", icon: "network", live: "Listing ships", done: "Listed ships", detail: "io" } : { ...step, category: "tool", icon: "network", live: "Reading ship response", done: "Read ship response", detail: "io" };
15790
+ }
15791
+ const replicasStep = replicasTool ? REPLICAS_API_STEPS[replicasTool] : void 0;
15792
+ if (replicasStep) {
15793
+ const replica = parseToolCallInput(message2.output).inputObject?.replica;
15794
+ const replicaFields = isRecord(replica) ? replica : null;
15795
+ const command = replicasTool === REPLICAS_MCP_TOOLS.runCommand ? inputString(input, "command") : void 0;
15796
+ const name = inputString(input, "name") ?? inputString(replicaFields, "name");
15797
+ const workspaceId = inputString(input, "id") ?? inputString(replicaFields, "id");
15798
+ const label = command ? commandLabel(command) : inputString(input, "title") ?? (replicasTool === REPLICAS_MCP_TOOLS.createAutomation ? name : void 0);
15799
+ return {
15800
+ ...base,
15801
+ key,
15802
+ category: "tool",
15803
+ ...replicasStep,
15804
+ target: label ? { text: label, plain: !command } : void 0,
15805
+ workspace: workspaceId && UUID_RE.test(workspaceId) ? { id: workspaceId, name } : void 0,
15806
+ detail: message2.input || message2.output ? "io" : void 0
15807
+ };
15808
+ }
15809
+ const shellCommand = /^(bash|shell|run_shell_command)$/i.test(tool) ? inputString(input, "command", "cmd") : void 0;
15810
+ if (shellCommand) {
15811
+ return { ...base, key, category: "command", icon: "terminal", live: "Running", done: "Ran", target: { text: commandLabel(shellCommand) }, detail: "io" };
15812
+ }
15813
+ if (/^(read|read_file|view)$/i.test(tool) && filePath) {
15814
+ return { ...base, key, category: "read", icon: "book", live: "Reading", done: "Read", target: { text: filePath, path: filePath }, detail: "io" };
15815
+ }
15816
+ if (/^(grep|glob|search|find|codebase_search|file_search)$/i.test(tool)) {
15817
+ const scope = inputString(input, "path", "glob", "include", "target_directories");
15818
+ return {
15819
+ ...base,
15820
+ key,
15821
+ category: "search",
15822
+ icon: "search",
15823
+ live: "Searching for",
15824
+ done: "Searched for",
15825
+ target: { text: inputString(input, "pattern", "query", "glob_pattern", "globPattern") ?? tool },
15826
+ scope,
15827
+ detail: message2.output ? "results" : void 0
15828
+ };
15829
+ }
15830
+ if (/^(ls|list_dir|list_directory)$/i.test(tool)) {
15831
+ const path = inputString(input, "path", "relative_workspace_path") ?? ".";
15832
+ return { ...base, key, category: "read", icon: "folder", live: "Listing", done: "Listed", target: { text: path, path }, detail: "io" };
15833
+ }
15834
+ if (/^(webfetch|web_fetch|fetch)$/i.test(tool)) {
15835
+ return { ...base, key, category: "web", icon: "globe", live: "Fetching", done: "Fetched", target: { text: inputString(input, "url") ?? tool }, detail: "io" };
15836
+ }
15837
+ if (/^(websearch|web_search)$/i.test(tool)) {
15838
+ return { ...base, key, category: "web", icon: "globe", live: "Searching the web for", done: "Searched the web for", target: { text: inputString(input, "query") ?? tool } };
15839
+ }
15840
+ if (/^(edit|write|multiedit|notebookedit|apply_patch|str_replace)/i.test(tool) && filePath) {
15841
+ return { ...base, key, category: "edit", icon: "file-pen", live: "Editing", done: "Edited", target: { text: filePath, path: filePath }, detail: "io" };
15842
+ }
15843
+ return {
15844
+ ...base,
15845
+ key,
15846
+ category: "tool",
15847
+ icon: "wrench",
15848
+ live: "Calling",
15849
+ done: "Called",
15850
+ target: { text: mcp?.tool ?? tool },
15851
+ scope: mcp?.server ?? (message2.server && message2.server !== "claude" ? message2.server : void 0),
15852
+ detail: message2.input || message2.output ? "io" : void 0
15853
+ };
15854
+ }
15855
+ var stepCache = /* @__PURE__ */ new WeakMap();
15856
+ function describeSteps(message2, { durations, backgroundTasks }) {
15857
+ const durationMs = durations.get(message2.id);
15858
+ const backgroundId = message2.type === "command" ? /^Command running in background with ID: (\w+)/.exec(message2.output ?? "")?.[1] : message2.type === "subagent" ? message2.toolUseId : void 0;
15859
+ const background = backgroundId ? backgroundTasks?.get(backgroundId) : void 0;
15860
+ const cached = stepCache.get(message2);
15861
+ if (cached && cached.durationMs === durationMs && cached.background === background) return cached.steps;
15862
+ const steps = describeMessageSteps(message2, durationMs, background).map((step) => ({
15863
+ ...step,
15864
+ stats: step.operation && !step.failed ? operationDiffStats(step.operation) : void 0
15865
+ }));
15866
+ stepCache.set(message2, { durationMs, background, steps });
15867
+ return steps;
15868
+ }
15869
+ var NO_DURATIONS = /* @__PURE__ */ new Map();
15870
+ function currentStepLabel(messages) {
15871
+ const step = messages.flatMap((message2) => describeSteps(message2, { durations: NO_DURATIONS })).filter((candidate) => candidate.running).at(-1);
15872
+ if (!step) return void 0;
15873
+ const target = step.target?.path ? step.target.path.split("/").pop() : step.target?.text;
15874
+ return [step.live, target].filter(Boolean).join(" ");
15875
+ }
15343
15876
 
15344
15877
  // ../shared/src/user-message-attachments.ts
15345
15878
  var ATTACHMENT_PLACEHOLDER_REGEX = /^\[\d+ (?:(?:images?|files?)(?: and \d+ files?)? attached|(?:image )?attachments?)\]$/;
@@ -16386,9 +16919,6 @@ function parseOpencodeEvents(events) {
16386
16919
  }
16387
16920
 
16388
16921
  // ../shared/src/display-message/parsers/muse-parser.ts
16389
- function isToolInputQuestion(value) {
16390
- return isRecord(value) && typeof value.id === "string" && typeof value.prompt === "string" && typeof value.multiSelect === "boolean" && Array.isArray(value.options) && value.options.every((option) => isRecord(option) && typeof option.id === "string" && typeof option.label === "string");
16391
- }
16392
16922
  function parseMuseEvents(events) {
16393
16923
  const messages = [];
16394
16924
  const deltas = /* @__PURE__ */ new Map();
@@ -18762,7 +19292,7 @@ var CLAUDE_AUTH_ENV_KEYS_BY_METHOD = {
18762
19292
  };
18763
19293
 
18764
19294
  // ../shared/src/routes/command-protection.ts
18765
- import { z as z22 } from "zod";
19295
+ import { z as z23 } from "zod";
18766
19296
 
18767
19297
  // ../shared/src/git-invocations.ts
18768
19298
  var COMMIT_VALUE_OPTIONS = /* @__PURE__ */ new Set(["message", "file", "trailer", "reuse-message", "reedit-message", "fixup", "squash", "template", "author", "date", "cleanup", "pathspec-from-file"]);
@@ -18853,27 +19383,27 @@ function findCheckoutTarget(args) {
18853
19383
  }
18854
19384
 
18855
19385
  // ../shared/src/routes/command-protection.ts
18856
- var commandProtectionRepoStateSchema = z22.object({
18857
- branch: z22.string().nullable(),
18858
- defaultBranch: z22.string().nullable(),
18859
- pushBranch: z22.string().nullable(),
18860
- pushConfig: z22.string().nullable(),
18861
- headMessage: z22.string().nullable(),
18862
- mergeInProgress: z22.boolean().optional()
19386
+ var commandProtectionRepoStateSchema = z23.object({
19387
+ branch: z23.string().nullable(),
19388
+ defaultBranch: z23.string().nullable(),
19389
+ pushBranch: z23.string().nullable(),
19390
+ pushConfig: z23.string().nullable(),
19391
+ headMessage: z23.string().nullable(),
19392
+ mergeInProgress: z23.boolean().optional()
18863
19393
  });
18864
- var commandProtectionEvaluateRequestSchema = z22.object({
18865
- provider: z22.enum(["claude", "codex", "cursor", "opencode", "pi"]),
18866
- source: z22.enum(["claude_pre_tool_use", "codex_approval_request", "cursor_pre_tool_use", "opencode_pre_tool_use", "pi_tool_call"]),
18867
- toolName: z22.string(),
18868
- toolInput: z22.unknown(),
18869
- command: z22.string().nullish(),
18870
- cwd: z22.string().nullish(),
18871
- toolUseId: z22.string().nullish(),
19394
+ var commandProtectionEvaluateRequestSchema = z23.object({
19395
+ provider: z23.enum(["claude", "codex", "cursor", "opencode", "pi"]),
19396
+ source: z23.enum(["claude_pre_tool_use", "codex_approval_request", "cursor_pre_tool_use", "opencode_pre_tool_use", "pi_tool_call"]),
19397
+ toolName: z23.string(),
19398
+ toolInput: z23.unknown(),
19399
+ command: z23.string().nullish(),
19400
+ cwd: z23.string().nullish(),
19401
+ toolUseId: z23.string().nullish(),
18872
19402
  // Read by the engine before the command runs, keyed by absolute path, so the
18873
19403
  // policy can see branches and commit messages the command text only references.
18874
- gitContext: z22.object({
18875
- repos: z22.record(z22.string(), commandProtectionRepoStateSchema),
18876
- messageFiles: z22.record(z22.string(), z22.string())
19404
+ gitContext: z23.object({
19405
+ repos: z23.record(z23.string(), commandProtectionRepoStateSchema),
19406
+ messageFiles: z23.record(z23.string(), z23.string())
18877
19407
  }).optional()
18878
19408
  });
18879
19409
  var COMMAND_PROTECTION_COMMAND_KEYS = ["command", "cmd", "script", "query", "endpoint", "path", "url", "mutation"];
@@ -19093,118 +19623,118 @@ function shouldRefreshPullRequests(toolName, toolInput) {
19093
19623
  }
19094
19624
 
19095
19625
  // ../shared/src/routes/linear.ts
19096
- import { z as z23 } from "zod";
19097
- var linearSessionMetadataSchema = z23.object({
19098
- via_mothership: z23.boolean().optional(),
19099
- attached: z23.boolean().optional(),
19100
- issue_id: z23.string(),
19101
- issue_identifier: z23.string(),
19102
- issue_title: z23.string(),
19103
- issue_description: z23.string(),
19104
- issue_url: z23.string(),
19105
- comment_id: z23.string(),
19106
- comment_body: z23.string(),
19107
- triggered_by_id: z23.string().optional(),
19108
- triggered_by_name: z23.string().optional(),
19109
- triggered_by_email: z23.string().optional(),
19110
- linear_workspace_id: z23.string().optional(),
19111
- creator_id: z23.string().optional(),
19112
- creator_name: z23.string().optional(),
19113
- creator_email: z23.string().optional(),
19114
- assignee_id: z23.string().optional(),
19115
- assignee_name: z23.string().optional(),
19116
- assignee_email: z23.string().optional(),
19117
- issue_state: z23.string().optional(),
19118
- parent_issue: z23.object({
19119
- id: z23.string(),
19120
- identifier: z23.string(),
19121
- title: z23.string(),
19122
- description: z23.string().nullable()
19626
+ import { z as z24 } from "zod";
19627
+ var linearSessionMetadataSchema = z24.object({
19628
+ via_mothership: z24.boolean().optional(),
19629
+ attached: z24.boolean().optional(),
19630
+ issue_id: z24.string(),
19631
+ issue_identifier: z24.string(),
19632
+ issue_title: z24.string(),
19633
+ issue_description: z24.string(),
19634
+ issue_url: z24.string(),
19635
+ comment_id: z24.string(),
19636
+ comment_body: z24.string(),
19637
+ triggered_by_id: z24.string().optional(),
19638
+ triggered_by_name: z24.string().optional(),
19639
+ triggered_by_email: z24.string().optional(),
19640
+ linear_workspace_id: z24.string().optional(),
19641
+ creator_id: z24.string().optional(),
19642
+ creator_name: z24.string().optional(),
19643
+ creator_email: z24.string().optional(),
19644
+ assignee_id: z24.string().optional(),
19645
+ assignee_name: z24.string().optional(),
19646
+ assignee_email: z24.string().optional(),
19647
+ issue_state: z24.string().optional(),
19648
+ parent_issue: z24.object({
19649
+ id: z24.string(),
19650
+ identifier: z24.string(),
19651
+ title: z24.string(),
19652
+ description: z24.string().nullable()
19123
19653
  }).optional(),
19124
- workspace: z23.object({
19125
- id: z23.string(),
19126
- coding_agent: z23.custom((value) => typeof value === "string" && isValidAgentProvider(value)),
19127
- task_description: z23.string(),
19128
- created_at: z23.string()
19654
+ workspace: z24.object({
19655
+ id: z24.string(),
19656
+ coding_agent: z24.custom((value) => typeof value === "string" && isValidAgentProvider(value)),
19657
+ task_description: z24.string(),
19658
+ created_at: z24.string()
19129
19659
  }).optional()
19130
19660
  });
19131
19661
 
19132
19662
  // ../shared/src/routes/scout.ts
19133
- import { z as z24 } from "zod";
19663
+ import { z as z25 } from "zod";
19134
19664
  var SCOUT_LINEAR_ACTIONS = ["ask", "start"];
19135
- var scoutLinearSessionIntentRequestSchema = z24.object({
19136
- comment_id: z24.string().trim().min(1).describe("Id of the Linear comment the session will be created on."),
19137
- action: z24.enum(SCOUT_LINEAR_ACTIONS).describe("`ask` when the comment is a clarifying question, `start` when it hands off the task.")
19665
+ var scoutLinearSessionIntentRequestSchema = z25.object({
19666
+ comment_id: z25.string().trim().min(1).describe("Id of the Linear comment the session will be created on."),
19667
+ action: z25.enum(SCOUT_LINEAR_ACTIONS).describe("`ask` when the comment is a clarifying question, `start` when it hands off the task.")
19138
19668
  });
19139
- var scoutLinearStartRequestSchema = z24.object({
19140
- issue_id: z24.string().describe("Linear issue id from the envelope's `issue_id`."),
19141
- agent_session_id: z24.string().describe("Existing Linear agent session id from the envelope's `agent_session_id`."),
19142
- prompt: z24.string().trim().min(1).describe("The latest request, in its author's words. The workspace already receives the issue and its comments.")
19669
+ var scoutLinearStartRequestSchema = z25.object({
19670
+ issue_id: z25.string().describe("Linear issue id from the envelope's `issue_id`."),
19671
+ agent_session_id: z25.string().describe("Existing Linear agent session id from the envelope's `agent_session_id`."),
19672
+ prompt: z25.string().trim().min(1).describe("The latest request, in its author's words. The workspace already receives the issue and its comments.")
19143
19673
  });
19144
- var slackChannelIdSchema = z24.string().describe("Slack channel id from the envelope's `channel_id`.");
19145
- var slackThreadTsSchema = z24.string().describe("Slack thread timestamp from the envelope's `thread_ts`.");
19146
- var scoutSlackSpawnRequestSchema = z24.object({
19674
+ var slackChannelIdSchema = z25.string().describe("Slack channel id from the envelope's `channel_id`.");
19675
+ var slackThreadTsSchema = z25.string().describe("Slack thread timestamp from the envelope's `thread_ts`.");
19676
+ var scoutSlackSpawnRequestSchema = z25.object({
19147
19677
  channel_id: slackChannelIdSchema,
19148
19678
  thread_ts: slackThreadTsSchema,
19149
- message_ts: z24.string().describe("Timestamp of the Slack message that asked for the work (the envelope's `message_ts`). The server verifies this message and its author."),
19150
- user_id: z24.string().describe("Slack user id of that message's author (the envelope's `user_id`). The workspace is attributed to them."),
19151
- prompt: z24.string().describe("The person's request in their own words, quoting earlier messages only when it points to them. The workspace already receives the Slack thread, so add no research, plan, or guesses."),
19152
- acknowledgement_ts: z24.string().optional().describe("`ts` of the one-line reply you posted in this thread before spawning. The server appends the workspace link to it and tells the workspace not to acknowledge again."),
19153
- environment_id: z24.string().optional().describe(`Environment id from \`${REPLICAS_MCP_TOOLS.listEnvironments}\`. Pass it only when clearly confident it fits; omit it to let routing choose. If routing cannot choose, the call fails and nothing is posted, so pick one or ask the person.`)
19679
+ message_ts: z25.string().describe("Timestamp of the Slack message that asked for the work (the envelope's `message_ts`). The server verifies this message and its author."),
19680
+ user_id: z25.string().describe("Slack user id of that message's author (the envelope's `user_id`). The workspace is attributed to them."),
19681
+ prompt: z25.string().describe("The person's request in their own words, quoting earlier messages only when it points to them. The workspace already receives the Slack thread, so add no research, plan, or guesses."),
19682
+ acknowledgement_ts: z25.string().optional().describe("`ts` of the one-line reply you posted in this thread before spawning. The server appends the workspace link to it and tells the workspace not to acknowledge again."),
19683
+ environment_id: z25.string().optional().describe(`Environment id from \`${REPLICAS_MCP_TOOLS.listEnvironments}\`. Pass it only when clearly confident it fits; omit it to let routing choose. If routing cannot choose, the call fails and nothing is posted, so pick one or ask the person.`)
19154
19684
  });
19155
19685
  var scoutSlackSpawnInNewThreadRequestSchema = scoutSlackSpawnRequestSchema.extend({
19156
- title: z24.string().trim().min(1).max(500).describe("One or two sentences stating the task, posted as the new top-level message."),
19157
- prompt: z24.string().describe("The person's request in their own words. The full source thread is attached as background, so add no summary, research, plan, or guesses."),
19158
- acknowledgement_ts: z24.string().optional().describe("`ts` of the one-line reply you posted in this thread before spawning. The server appends the new thread's link to it.")
19686
+ title: z25.string().trim().min(1).max(500).describe("One or two sentences stating the task, posted as the new top-level message."),
19687
+ prompt: z25.string().describe("The person's request in their own words. The full source thread is attached as background, so add no summary, research, plan, or guesses."),
19688
+ acknowledgement_ts: z25.string().optional().describe("`ts` of the one-line reply you posted in this thread before spawning. The server appends the new thread's link to it.")
19159
19689
  });
19160
- var scoutSlackRelayRequestSchema = z24.object({
19690
+ var scoutSlackRelayRequestSchema = z25.object({
19161
19691
  channel_id: slackChannelIdSchema,
19162
19692
  thread_ts: slackThreadTsSchema,
19163
- message: z24.string().describe("The follow-up to deliver: every fresh message that belongs to this update, in its author's words, with no research, plan, or guesses added."),
19164
- user_id: z24.string().optional().describe("Slack user id of the follow-up's author (the envelope's `user_id`), so it is attributed to them. Defaults to the thread's original requester. Required with `workspace_id`."),
19165
- queue: z24.boolean().optional().describe("Set true only when the person explicitly asked for this to happen after the current task finishes. Delivers behind the active turn instead of interrupting it."),
19166
- workspace_id: z24.string().optional().describe(`Existing workspace id, from \`${REPLICAS_MCP_TOOLS.listWorkspaces}\` or a workspace link in the thread, to bind a thread without a workspace to before relaying. The author must be able to see it. A Mothership gets the person's own Slack message and the thread instead of \`message\`. Omit to relay into the thread's own workspace.`),
19167
- message_ts: z24.string().optional().describe("Timestamp of the Slack message that led to this relay (the envelope's `message_ts`). Required with `workspace_id`; the server verifies this message and its author.")
19693
+ message: z25.string().describe("The follow-up to deliver: every fresh message that belongs to this update, in its author's words, with no research, plan, or guesses added."),
19694
+ user_id: z25.string().optional().describe("Slack user id of the follow-up's author (the envelope's `user_id`), so it is attributed to them. Defaults to the thread's original requester. Required with `workspace_id`."),
19695
+ queue: z25.boolean().optional().describe("Set true only when the person explicitly asked for this to happen after the current task finishes. Delivers behind the active turn instead of interrupting it."),
19696
+ workspace_id: z25.string().optional().describe(`Existing workspace id, from \`${REPLICAS_MCP_TOOLS.listWorkspaces}\` or a workspace link in the thread, to bind a thread without a workspace to before relaying. The author must be able to see it. A Mothership gets the person's own Slack message and the thread instead of \`message\`. Omit to relay into the thread's own workspace.`),
19697
+ message_ts: z25.string().optional().describe("Timestamp of the Slack message that led to this relay (the envelope's `message_ts`). Required with `workspace_id`; the server verifies this message and its author.")
19168
19698
  });
19169
- var scoutSlackSetThreadMutedRequestSchema = z24.object({
19699
+ var scoutSlackSetThreadMutedRequestSchema = z25.object({
19170
19700
  channel_id: slackChannelIdSchema,
19171
19701
  thread_ts: slackThreadTsSchema,
19172
- muted: z24.boolean().describe("true to mute Replicas in this thread, false to unmute it.")
19702
+ muted: z25.boolean().describe("true to mute Replicas in this thread, false to unmute it.")
19173
19703
  });
19174
- var scoutListWorkspacesRequestSchema = z24.object({
19704
+ var scoutListWorkspacesRequestSchema = z25.object({
19175
19705
  channel_id: slackChannelIdSchema,
19176
19706
  thread_ts: slackThreadTsSchema,
19177
- message_ts: z24.string().describe("The envelope's `message_ts`. The server verifies this message and its author."),
19178
- user_id: z24.string().describe("Slack user id of that message's author (the envelope's `user_id`). Only workspaces they can see are listed."),
19179
- query: z24.string().trim().min(1).optional().describe("Case-insensitive text to match against workspace and Mothership names and pull request URLs.")
19707
+ message_ts: z25.string().describe("The envelope's `message_ts`. The server verifies this message and its author."),
19708
+ user_id: z25.string().describe("Slack user id of that message's author (the envelope's `user_id`). Only workspaces they can see are listed."),
19709
+ query: z25.string().trim().min(1).optional().describe("Case-insensitive text to match against workspace and Mothership names and pull request URLs.")
19180
19710
  });
19181
- var scoutSlackConfirmationSchema = z24.object({
19182
- confirmation_channel_id: z24.string().describe("`channel_id` from the envelope of the Slack message that asked for or accepted this."),
19183
- confirmation_thread_ts: z24.string().describe("`thread_ts` from that message's envelope."),
19184
- confirmation_message_ts: z24.string().describe("`message_ts` from that message's envelope."),
19185
- confirmation_user_id: z24.string().describe("`user_id` from that message's envelope.")
19711
+ var scoutSlackConfirmationSchema = z25.object({
19712
+ confirmation_channel_id: z25.string().describe("`channel_id` from the envelope of the Slack message that asked for or accepted this."),
19713
+ confirmation_thread_ts: z25.string().describe("`thread_ts` from that message's envelope."),
19714
+ confirmation_message_ts: z25.string().describe("`message_ts` from that message's envelope."),
19715
+ confirmation_user_id: z25.string().describe("`user_id` from that message's envelope.")
19186
19716
  });
19187
19717
  var scoutAutomationToolInputSchema = automationToolInputSchema.extend(scoutSlackConfirmationSchema.shape);
19188
19718
  var scoutSaveChannelPresetToolInputSchema = scoutSlackConfirmationSchema.extend({
19189
- preset_id: z24.string().optional().describe(`Id of the preset to update, from \`${REPLICAS_MCP_TOOLS.listChannelSettings}\`. Omit to create a new preset.`),
19190
- name: z24.string().trim().min(1).max(SCOUT_PRESET_NAME_MAX_LENGTH).optional().describe("Preset name. Required when creating."),
19191
- description: z24.string().optional().describe("One-line summary shown in settings."),
19192
- icon: z24.enum(SCOUT_PRESET_ICONS).optional(),
19193
- instructions: z24.string().optional().describe("Complete preset instructions; replaces the existing text. Required when creating.")
19719
+ preset_id: z25.string().optional().describe(`Id of the preset to update, from \`${REPLICAS_MCP_TOOLS.listChannelSettings}\`. Omit to create a new preset.`),
19720
+ name: z25.string().trim().min(1).max(SCOUT_PRESET_NAME_MAX_LENGTH).optional().describe("Preset name. Required when creating."),
19721
+ description: z25.string().optional().describe("One-line summary shown in settings."),
19722
+ icon: z25.enum(SCOUT_PRESET_ICONS).optional(),
19723
+ instructions: z25.string().optional().describe("Complete preset instructions; replaces the existing text. Required when creating.")
19194
19724
  });
19195
19725
  var scoutUpdateChannelSettingsToolInputSchema = scoutSlackConfirmationSchema.extend({
19196
- source: z24.enum(SCOUT_SOURCE_TYPES).optional().describe("Defaults to `slack`."),
19197
- external_id: z24.string().describe("Slack channel id or Linear team id."),
19198
- monitored: z24.boolean().optional().describe("Linear: `true` starts monitoring the team (organization admins only), `false` stops. Slack: kept for older callers; prefer `proactivity`. `false` means `tagged`, and `true` lifts a `tagged` channel back to the organization's level. Omit to keep it."),
19199
- preset_id: z24.string().nullable().optional().describe("Preset to assign; `null` removes the preset. Omit to keep it."),
19200
- instructions: z24.string().nullable().optional().describe("Complete channel-specific instructions, applied after the preset; replaces the existing text. `null` clears them. Omit to keep them."),
19201
- proactivity: z24.enum([...SCOUT_PROACTIVITY_LEVELS, "organization"]).optional().describe("Slack only: this channel's or group DM's own level, overriding the organization's here alone. `organization` makes it follow the organization's level again. Omit to keep it. 1:1 DMs are always addressed to Replicas, so they take no level.")
19726
+ source: z25.enum(SCOUT_SOURCE_TYPES).optional().describe("Defaults to `slack`."),
19727
+ external_id: z25.string().describe("Slack channel id or Linear team id."),
19728
+ monitored: z25.boolean().optional().describe("Linear: `true` starts monitoring the team (organization admins only), `false` stops. Slack: kept for older callers; prefer `proactivity`. `false` means `tagged`, and `true` lifts a `tagged` channel back to the organization's level. Omit to keep it."),
19729
+ preset_id: z25.string().nullable().optional().describe("Preset to assign; `null` removes the preset. Omit to keep it."),
19730
+ instructions: z25.string().nullable().optional().describe("Complete channel-specific instructions, applied after the preset; replaces the existing text. `null` clears them. Omit to keep them."),
19731
+ proactivity: z25.enum([...SCOUT_PROACTIVITY_LEVELS, "organization"]).optional().describe("Slack only: this channel's or group DM's own level, overriding the organization's here alone. `organization` makes it follow the organization's level again. Omit to keep it. 1:1 DMs are always addressed to Replicas, so they take no level.")
19202
19732
  });
19203
19733
  var scoutSetOrganizationProactivityToolInputSchema = scoutSlackConfirmationSchema.extend({
19204
- proactivity: z24.enum(SCOUT_PROACTIVITY_LEVELS).describe("The level every Slack channel and group DM follows unless it has its own. Slack Connect channels without their own level stay `tagged`.")
19734
+ proactivity: z25.enum(SCOUT_PROACTIVITY_LEVELS).describe("The level every Slack channel and group DM follows unless it has its own. Slack Connect channels without their own level stay `tagged`.")
19205
19735
  });
19206
19736
  var scoutDeleteChannelPresetToolInputSchema = scoutSlackConfirmationSchema.extend({
19207
- preset_id: z24.string().describe(`Id of the preset to delete, from \`${REPLICAS_MCP_TOOLS.listChannelSettings}\`.`)
19737
+ preset_id: z25.string().describe(`Id of the preset to delete, from \`${REPLICAS_MCP_TOOLS.listChannelSettings}\`.`)
19208
19738
  });
19209
19739
 
19210
19740
  // ../shared/src/routes/plugin-catalog.ts
@@ -19585,85 +20115,81 @@ var promptHistoryClientStateKey = orgUserClientStateKey(PROMPT_HISTORY_CLIENT_ST
19585
20115
  var workspaceSearchOpensClientStateKey = orgUserClientStateKey(WORKSPACE_SEARCH_OPENS_CLIENT_STATE_KEY_PREFIX);
19586
20116
 
19587
20117
  // ../shared/src/routes/workspace-events.ts
19588
- import { z as z25 } from "zod";
19589
-
19590
- // ../shared/src/workspace-attention.ts
19591
- var WORKSPACE_ATTENTION_REASONS = ["question", "blocked"];
19592
-
19593
- // ../shared/src/routes/workspace-events.ts
19594
- var workspaceTurnCompletionSchema = z25.object({
19595
- workspaceName: z25.string(),
19596
- completedAt: z25.string(),
19597
- processing: z25.boolean().optional(),
19598
- pullRequestFeedback: z25.boolean().optional(),
19599
- attention: z25.object({ reason: z25.enum(WORKSPACE_ATTENTION_REASONS), userId: z25.string() }).optional()
20118
+ import { z as z26 } from "zod";
20119
+ var workspaceTurnCompletionSchema = z26.object({
20120
+ workspaceName: z26.string(),
20121
+ completedAt: z26.string(),
20122
+ processing: z26.boolean().optional(),
20123
+ pullRequestFeedback: z26.boolean().optional(),
20124
+ attention: z26.object({ reason: z26.enum(CHAT_ATTENTION_REASONS), userId: z26.string() }).optional()
19600
20125
  });
19601
- var workspaceChangedEventSchema = z25.discriminatedUnion("type", [
19602
- z25.object({
19603
- type: z25.literal("workspace.changed"),
19604
- workspaceId: z25.string(),
19605
- workspace: z25.object({ status: z25.enum(WORKSPACE_STATUSES), last_activity_at: z25.string().nullable() }).optional(),
20126
+ var workspaceChangedEventSchema = z26.discriminatedUnion("type", [
20127
+ z26.object({
20128
+ type: z26.literal("workspace.changed"),
20129
+ workspaceId: z26.string(),
20130
+ workspace: z26.object({ status: z26.enum(WORKSPACE_STATUSES), last_activity_at: z26.string().nullable() }).optional(),
19606
20131
  completion: workspaceTurnCompletionSchema.optional(),
19607
- ts: z25.string()
20132
+ ts: z26.string()
19608
20133
  }),
19609
- z25.object({
19610
- type: z25.literal("workspace.chat.changed"),
19611
- workspaceId: z25.string(),
19612
- chatId: z25.string(),
19613
- ts: z25.string()
20134
+ z26.object({
20135
+ type: z26.literal("workspace.chat.changed"),
20136
+ workspaceId: z26.string(),
20137
+ chatId: z26.string(),
20138
+ ts: z26.string()
19614
20139
  }),
19615
- z25.object({
19616
- type: z25.literal("workspace.chat.advanced"),
19617
- workspaceId: z25.string(),
19618
- chatId: z25.string(),
19619
- afterCursor: z25.string().optional(),
19620
- processing: z25.boolean(),
19621
- ts: z25.string()
20140
+ z26.object({
20141
+ type: z26.literal("workspace.chat.advanced"),
20142
+ workspaceId: z26.string(),
20143
+ chatId: z26.string(),
20144
+ afterCursor: z26.string().optional(),
20145
+ processing: z26.boolean(),
20146
+ ts: z26.string()
19622
20147
  }),
19623
- z25.object({ type: z25.literal("presence.changed"), ts: z25.string() }),
19624
- z25.object({
19625
- type: z25.literal("mobile-testing.changed"),
19626
- workspaceId: z25.string(),
19627
- ts: z25.string()
20148
+ z26.object({ type: z26.literal("presence.changed"), ts: z26.string() }),
20149
+ z26.object({
20150
+ type: z26.literal("mobile-testing.changed"),
20151
+ workspaceId: z26.string(),
20152
+ ts: z26.string()
19628
20153
  }),
19629
- z25.object({
19630
- type: z25.literal("variable-request.changed"),
19631
- workspaceId: z25.string(),
19632
- ts: z25.string()
20154
+ z26.object({
20155
+ type: z26.literal("variable-request.changed"),
20156
+ workspaceId: z26.string(),
20157
+ ts: z26.string()
19633
20158
  }),
19634
- z25.object({
19635
- type: z25.literal("pull-request.changed"),
19636
- prUrl: z25.string(),
19637
- ts: z25.string()
20159
+ z26.object({
20160
+ type: z26.literal("pull-request.changed"),
20161
+ prUrl: z26.string(),
20162
+ ts: z26.string()
19638
20163
  }),
19639
- z25.object({
19640
- type: z25.literal("mothership.subagent.changed"),
19641
- workspaceId: z25.string(),
19642
- subagent: z25.object({ id: z25.string(), name: z25.string(), prUrl: z25.string().nullable() }),
19643
- ts: z25.string()
19644
- })
20164
+ z26.object({
20165
+ type: z26.literal("mothership.subagent.changed"),
20166
+ workspaceId: z26.string(),
20167
+ subagent: z26.object({ id: z26.string(), name: z26.string(), prUrl: z26.string().nullable() }),
20168
+ ts: z26.string()
20169
+ }),
20170
+ z26.object({ type: z26.literal("needs-you.changed"), workspaceId: z26.string().nullable(), ts: z26.string() })
19645
20171
  ]);
19646
20172
 
19647
20173
  // ../shared/src/routes/presence.ts
19648
- import { z as z26 } from "zod";
19649
- var presenceStatusSchema = z26.enum(["online", "typing"]);
19650
- var presenceLocationSchema = z26.object({
19651
- workspaceId: z26.string().optional()
20174
+ import { z as z27 } from "zod";
20175
+ var presenceStatusSchema = z27.enum(["online", "typing"]);
20176
+ var presenceLocationSchema = z27.object({
20177
+ workspaceId: z27.string().optional()
19652
20178
  });
19653
- var presenceEntrySchema = z26.object({
19654
- userId: z26.string(),
20179
+ var presenceEntrySchema = z27.object({
20180
+ userId: z27.string(),
19655
20181
  status: presenceStatusSchema,
19656
20182
  location: presenceLocationSchema,
19657
- ts: z26.string()
20183
+ ts: z27.string()
19658
20184
  });
19659
- var updatePresenceRequestSchema = z26.object({
20185
+ var updatePresenceRequestSchema = z27.object({
19660
20186
  status: presenceStatusSchema,
19661
20187
  location: presenceLocationSchema.optional()
19662
20188
  });
19663
20189
 
19664
20190
  // ../shared/src/routes/review-messages.ts
19665
- import { z as z27 } from "zod";
19666
- var sendPullRequestReviewMessageRequestSchema = z27.object({
20191
+ import { z as z28 } from "zod";
20192
+ var sendPullRequestReviewMessageRequestSchema = z28.object({
19667
20193
  ...sendChatMessageRequestSchema.pick({
19668
20194
  message: true,
19669
20195
  messageId: true,
@@ -19676,8 +20202,8 @@ var sendPullRequestReviewMessageRequestSchema = z27.object({
19676
20202
  ultrafastMode: true
19677
20203
  }).shape,
19678
20204
  /** Starts a new chat instead of continuing the PR's review chat. The provider only applies to a new chat. */
19679
- newChat: z27.boolean().optional(),
19680
- provider: z27.enum(VALID_AGENT_PROVIDERS).optional()
20205
+ newChat: z28.boolean().optional(),
20206
+ provider: z28.enum(VALID_AGENT_PROVIDERS).optional()
19681
20207
  });
19682
20208
 
19683
20209
  // ../shared/src/audit-log.ts
@@ -19898,30 +20424,30 @@ function isSkillRegistryManifest(value) {
19898
20424
  }
19899
20425
 
19900
20426
  // ../shared/src/routes/variable-requests.ts
19901
- import { z as z28 } from "zod";
20427
+ import { z as z29 } from "zod";
19902
20428
  var VARIABLE_REQUEST_WAIT = { defaultMs: 10 * 6e4, maxMs: 30 * 6e4, pollMs: 3e3, waiterStaleMs: 15e3 };
19903
20429
  var VARIABLE_REQUEST_DESTINATIONS = ["environment", "workspace"];
19904
- var requestedVariableSchema = z28.object({
19905
- key: z28.string().regex(VARIABLE_KEY_RE, "must be a valid environment variable name").max(ENVIRONMENT_SETUP_LIMITS.variableKeyChars),
19906
- required: z28.boolean(),
19907
- replace: z28.boolean().optional()
20430
+ var requestedVariableSchema = z29.object({
20431
+ key: z29.string().regex(VARIABLE_KEY_RE, "must be a valid environment variable name").max(ENVIRONMENT_SETUP_LIMITS.variableKeyChars),
20432
+ required: z29.boolean(),
20433
+ replace: z29.boolean().optional()
19908
20434
  });
19909
- var requestedVariablesSchema = z28.array(requestedVariableSchema).min(1, "must not be empty").max(ENVIRONMENT_SETUP_LIMITS.variables).refine((variables) => new Set(variables.map((variable) => variable.key)).size === variables.length, "must have unique keys");
19910
- var createVariableRequestSchema = z28.object({
20435
+ var requestedVariablesSchema = z29.array(requestedVariableSchema).min(1, "must not be empty").max(ENVIRONMENT_SETUP_LIMITS.variables).refine((variables) => new Set(variables.map((variable) => variable.key)).size === variables.length, "must have unique keys");
20436
+ var createVariableRequestSchema = z29.object({
19911
20437
  variables: requestedVariablesSchema,
19912
- reason: z28.string().trim().max(500).nullish().transform((value) => value || null),
19913
- wait: z28.boolean().default(true)
20438
+ reason: z29.string().trim().max(500).nullish().transform((value) => value || null),
20439
+ wait: z29.boolean().default(true)
19914
20440
  });
19915
- var respondVariableRequestSchema = z28.discriminatedUnion("action", [
19916
- z28.object({
19917
- action: z28.literal("provide"),
19918
- destination: z28.enum(VARIABLE_REQUEST_DESTINATIONS),
20441
+ var respondVariableRequestSchema = z29.discriminatedUnion("action", [
20442
+ z29.object({
20443
+ action: z29.literal("provide"),
20444
+ destination: z29.enum(VARIABLE_REQUEST_DESTINATIONS),
19919
20445
  /** Defaults to the workspace's environment, so older clients keep saving there. */
19920
- environment_ids: z28.array(z28.string().uuid()).optional(),
19921
- overwrite: z28.boolean().optional(),
19922
- values: z28.record(z28.string().regex(VARIABLE_KEY_RE), z28.string())
20446
+ environment_ids: z29.array(z29.string().uuid()).optional(),
20447
+ overwrite: z29.boolean().optional(),
20448
+ values: z29.record(z29.string().regex(VARIABLE_KEY_RE), z29.string())
19923
20449
  }),
19924
- z28.object({ action: z28.literal("skip") })
20450
+ z29.object({ action: z29.literal("skip") })
19925
20451
  ]);
19926
20452
 
19927
20453
  export {
@@ -20072,6 +20598,7 @@ export {
20072
20598
  codexTurnFromEvent,
20073
20599
  codexTranscriptToEvents,
20074
20600
  steerQueuedInOrder,
20601
+ respondToolInputRequestSchema,
20075
20602
  isLatestChatHistoryPage,
20076
20603
  getChatHistoryPageSenders,
20077
20604
  parseChatHistoryCursor,
@@ -20127,6 +20654,7 @@ export {
20127
20654
  formatChatForkHandoffMessage,
20128
20655
  formatChatForkUpdateMessage,
20129
20656
  threadHandoffText,
20657
+ isToolInputQuestion,
20130
20658
  fileContentDiff,
20131
20659
  skillNamesFromCommand,
20132
20660
  parseMcpToolName,
@@ -20136,6 +20664,7 @@ export {
20136
20664
  learnedSkillsManifestSchema,
20137
20665
  learnedSkillFormatInstruction,
20138
20666
  areUserMessagesWithinMatchWindow,
20667
+ currentStepLabel,
20139
20668
  codexPromptTurnId,
20140
20669
  extractErrorText,
20141
20670
  isTransientErrorText,