replicas-cli 0.3.300 → 0.3.301

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/index.cjs +390 -206
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -214,7 +214,62 @@ function getOrganizationMediaPath(organizationId, mediaId) {
214
214
  function getOrganizationMediaUrl(organizationId, mediaId, webAppUrl2 = DEFAULT_WEB_APP_URL) {
215
215
  return `${webAppUrl2}${getOrganizationMediaPath(organizationId, mediaId)}`;
216
216
  }
217
- var DEFAULT_WEB_APP_URL, DEFAULT_SUPABASE_URL, DEFAULT_SUPABASE_ANON_KEY, DASHBOARD_PATH, WEB_APP_PATHS, LEGACY_WEB_APP_PATHS;
217
+ function parsePrUrl(url2) {
218
+ const match = url2.match(PR_URL_REGEX);
219
+ if (!match) return null;
220
+ const [, owner, repo, numberStr] = match;
221
+ const number4 = Number.parseInt(numberStr, 10);
222
+ if (!Number.isFinite(number4)) return null;
223
+ return { owner, repo, number: number4 };
224
+ }
225
+ function parseCodeHostPrUrl(url2) {
226
+ const github = parsePrUrl(url2);
227
+ if (github) {
228
+ return {
229
+ ...github,
230
+ provider: "github",
231
+ host: "github.com",
232
+ repositoryPath: `${github.owner}/${github.repo}`,
233
+ repoUrl: `https://github.com/${github.owner}/${github.repo}`
234
+ };
235
+ }
236
+ let parsed;
237
+ try {
238
+ parsed = new URL(url2);
239
+ } catch {
240
+ return null;
241
+ }
242
+ if (parsed.protocol !== "https:" && parsed.protocol !== "http:") return null;
243
+ const segments = parsed.pathname.split("/").filter(Boolean);
244
+ const separatorIndex = segments.indexOf("-");
245
+ if (separatorIndex <= 0 || segments[separatorIndex + 1] !== "merge_requests") return null;
246
+ const number4 = Number.parseInt(segments[separatorIndex + 2] ?? "", 10);
247
+ if (!Number.isFinite(number4)) return null;
248
+ const repositorySegments = decodePathSegments(segments.slice(0, separatorIndex));
249
+ const repo = repositorySegments[repositorySegments.length - 1];
250
+ const owner = repositorySegments[0];
251
+ if (!owner || !repo) return null;
252
+ const repositoryPath = repositorySegments.join("/");
253
+ return {
254
+ provider: "gitlab",
255
+ host: parsed.host.toLowerCase(),
256
+ owner,
257
+ repo,
258
+ number: number4,
259
+ repositoryPath,
260
+ repoUrl: `${parsed.origin}/${repositoryPath}`
261
+ };
262
+ }
263
+ function decodePathSegments(segments) {
264
+ return segments.map((segment) => {
265
+ try {
266
+ return decodeURIComponent(segment);
267
+ } catch {
268
+ return segment;
269
+ }
270
+ });
271
+ }
272
+ var DEFAULT_WEB_APP_URL, DEFAULT_SUPABASE_URL, DEFAULT_SUPABASE_ANON_KEY, DASHBOARD_PATH, WEB_APP_PATHS, LEGACY_WEB_APP_PATHS, PR_URL_REGEX;
218
273
  var init_urls = __esm({
219
274
  "../shared/src/urls.ts"() {
220
275
  "use strict";
@@ -256,6 +311,7 @@ var init_urls = __esm({
256
311
  home: "/home",
257
312
  dashboardWorkspaces: `${DASHBOARD_PATH}/workspaces`
258
313
  };
314
+ PR_URL_REGEX = /github\.com\/([^/]+)\/([^/]+)\/pull\/(\d+)/;
259
315
  }
260
316
  });
261
317
 
@@ -8031,8 +8087,8 @@ var init_lt = __esm({
8031
8087
  "../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/locales/lt.js"() {
8032
8088
  "use strict";
8033
8089
  init_util();
8034
- capitalizeFirstCharacter = (text3) => {
8035
- return text3.charAt(0).toUpperCase() + text3.slice(1);
8090
+ capitalizeFirstCharacter = (text4) => {
8091
+ return text4.charAt(0).toUpperCase() + text4.slice(1);
8036
8092
  };
8037
8093
  error28 = () => {
8038
8094
  const Sizable = {
@@ -16046,7 +16102,7 @@ var init_fallback_chains = __esm({
16046
16102
  fallbackHarnessStepSchema
16047
16103
  ]);
16048
16104
  fallbackPlanResponseSchema = external_exports.object({
16049
- steps: external_exports.array(external_exports.unknown()).transform((steps) => steps.flatMap((step) => fallbackPlanStepSchema.safeParse(step).data ?? []))
16105
+ steps: external_exports.array(external_exports.unknown()).transform((steps2) => steps2.flatMap((step) => fallbackPlanStepSchema.safeParse(step).data ?? []))
16050
16106
  });
16051
16107
  }
16052
16108
  });
@@ -16694,14 +16750,14 @@ function coerceClaudePartialMessagePayload(payload) {
16694
16750
  const streamId = payload.streamId;
16695
16751
  if (typeof streamId !== "string" || !streamId) return null;
16696
16752
  const parentToolUseId = payload.parent_tool_use_id;
16697
- const text3 = typeof payload.text === "string" && payload.text ? payload.text : void 0;
16753
+ const text4 = typeof payload.text === "string" && payload.text ? payload.text : void 0;
16698
16754
  const thinking = typeof payload.thinking === "string" && payload.thinking ? payload.thinking : void 0;
16699
16755
  const tool = isRecord(payload.tool) && typeof payload.tool.id === "string" && typeof payload.tool.name === "string" ? typeof payload.tool.filePath === "string" ? { id: payload.tool.id, name: payload.tool.name, filePath: payload.tool.filePath } : typeof payload.tool.command === "string" ? { id: payload.tool.id, name: payload.tool.name, command: payload.tool.command } : void 0 : void 0;
16700
- if (!text3 && !thinking && !tool) return null;
16756
+ if (!text4 && !thinking && !tool) return null;
16701
16757
  return {
16702
16758
  streamId,
16703
16759
  parent_tool_use_id: typeof parentToolUseId === "string" ? parentToolUseId : null,
16704
- ...text3 ? { text: text3 } : {},
16760
+ ...text4 ? { text: text4 } : {},
16705
16761
  ...thinking ? { thinking } : {},
16706
16762
  ...tool ? { tool } : {},
16707
16763
  status: payload.status === "completed" ? "completed" : "in_progress"
@@ -17267,6 +17323,7 @@ var init_pull_requests = __esm({
17267
17323
  "../shared/src/routes/pull-requests.ts"() {
17268
17324
  "use strict";
17269
17325
  init_zod();
17326
+ init_urls();
17270
17327
  PULL_REQUEST_MERGE_METHODS = ["merge", "squash", "rebase"];
17271
17328
  DEPLOY_START_WINDOW_MS = 30 * 6e4;
17272
17329
  mergePullRequestRequestSchema = external_exports.object({
@@ -17414,6 +17471,8 @@ var init_replicas_mcp = __esm({
17414
17471
  readSubagent: "read_subagent",
17415
17472
  archiveSubagent: "archive_subagent",
17416
17473
  waitForSubagents: "wait_for_subagents",
17474
+ getBoard: "get_board",
17475
+ updateBoard: "update_board",
17417
17476
  getLinearRouting: "get_linear_routing",
17418
17477
  setLinearRouting: "set_linear_routing",
17419
17478
  clearLinearRouting: "clear_linear_routing",
@@ -20548,14 +20607,14 @@ var init_replicas_agent = __esm({
20548
20607
  });
20549
20608
 
20550
20609
  // ../shared/src/prompts.ts
20551
- function removeTag(text3, tag) {
20610
+ function removeTag(text4, tag) {
20552
20611
  const regex = new RegExp(`<${tag}>[\\s\\S]*?</${tag}>`, "g");
20553
- return text3.replace(regex, "").trim();
20612
+ return text4.replace(regex, "").trim();
20554
20613
  }
20555
- function stripReplicasInstructionBlock(text3) {
20556
- return removeTag(text3, REPLICAS_INSTRUCTIONS_TAG);
20614
+ function stripReplicasInstructionBlock(text4) {
20615
+ return removeTag(text4, REPLICAS_INSTRUCTIONS_TAG);
20557
20616
  }
20558
- var REPLICAS_INSTRUCTIONS_TAG, MOTHERSHIP_INSTRUCTIONS_TAG, MOTHERSHIP_INSTRUCTIONS_BLOCK, SCOUT_ADAPTIVE_SETTINGS_PROMPT;
20617
+ var REPLICAS_INSTRUCTIONS_TAG, MOTHERSHIP_INSTRUCTIONS_TAG, BOARD_RULES, MOTHERSHIP_INSTRUCTIONS_BLOCK, SCOUT_ADAPTIVE_SETTINGS_PROMPT;
20559
20618
  var init_prompts = __esm({
20560
20619
  "../shared/src/prompts.ts"() {
20561
20620
  "use strict";
@@ -20571,6 +20630,11 @@ var init_prompts = __esm({
20571
20630
  init_slack_response_style();
20572
20631
  REPLICAS_INSTRUCTIONS_TAG = "replicas_instructions";
20573
20632
  MOTHERSHIP_INSTRUCTIONS_TAG = "multitask_instructions";
20633
+ BOARD_RULES = `- The board, a live status page you keep with \`${REPLICAS_MCP_TOOLS.updateBoard}\` in the Ships pane beside this chat, is the user's one view of the work: keep it covering every ship, pull request, deploy, blocker and ask. Show ships, pull requests and Linear tickets as ship, pr and linear blocks, which stay current on their own, instead of describing their status. Start with sections Needs you, Ready to review, Working, Shipping and Done, and add blocks and buttons whenever they help the user act.
20634
+ - A ship with open pull requests is not done when it sends \`finished\`: Replicas fixes their CI failures and review comments automatically, then sends \`ready\` or \`needs_attention\`. On \`needs_attention\`, direct the ship, or put the decision to the user if it needs one.
20635
+ - On every ship event, update the board, act with tools if other work waits on it, such as starting the next task once a pull request merges, and end your turn with no text at all. Never write an acknowledgement such as "Noted.", even if earlier turns did.
20636
+ - Write in chat only to answer the user, or to ask a decision in a line or two. Put each decision on the board too, as a choice when it has clear options, and ask it in chat once. Never restate the board in chat: no status tables, per-ship lists or summaries of what ships did; link the pull request you mean and leave status to the board.
20637
+ `;
20574
20638
  MOTHERSHIP_INSTRUCTIONS_BLOCK = new RegExp(`\\s*<${MOTHERSHIP_INSTRUCTIONS_TAG}>\\n([\\s\\S]*?)\\n</${MOTHERSHIP_INSTRUCTIONS_TAG}>`);
20575
20639
  SCOUT_ADAPTIVE_SETTINGS_PROMPT = `### Adapting to each channel
20576
20640
  There is no settings page: people change how you behave by telling you, and you suggest a change when it would clearly help. The envelope carries the channel's \`proactivity\` and \`offers\`, the offers you may still make in this channel (${SCOUT_CHANNEL_SETTINGS_OFFERS.map((offer) => `\`${offer}\``).join(", ")}); \`offers=none\` means make none. Offer only what \`offers\` lists, at most one per message. Claim an offer with \`${REPLICAS_MCP_TOOLS.claimSettingsOffer}\` right before posting it, and post it only when the claim succeeds. When someone declines ("no", "it's fine", "leave it"), record it with \`declined: true\` and drop it; never repeat an ignored offer. When they accept, apply it with the settings tools using the accepting message as confirmation, then confirm what changed in one short line.
@@ -20612,8 +20676,8 @@ var init_message_origin = __esm({
20612
20676
  });
20613
20677
 
20614
20678
  // ../shared/src/mothership-events.ts
20615
- function extractMothershipEvents(text3) {
20616
- return [...text3.matchAll(BLOCK)].flatMap((match) => {
20679
+ function extractMothershipEvents(text4) {
20680
+ return [...text4.matchAll(BLOCK)].flatMap((match) => {
20617
20681
  const attributes = Object.fromEntries([...match[1].matchAll(ATTRIBUTE)].map(([, key, value]) => [key, unescapeAttribute(value)]));
20618
20682
  if (!attributes.kind || !attributes.id || !attributes.agent_id) return [];
20619
20683
  const kind = MOTHERSHIP_EVENT_KINDS.find((candidate) => candidate === attributes.kind) ?? UNKNOWN_EVENT_KIND;
@@ -20632,9 +20696,9 @@ function extractMothershipEvents(text3) {
20632
20696
  }];
20633
20697
  });
20634
20698
  }
20635
- function parseMothershipEvents(text3) {
20636
- const events = extractMothershipEvents(text3);
20637
- return events.length > 0 && text3.replace(BLOCK, "").replaceAll(MERGED_MESSAGE_SEPARATOR.trim(), "").trim() === "" ? events : null;
20699
+ function parseMothershipEvents(text4) {
20700
+ const events = extractMothershipEvents(text4);
20701
+ return events.length > 0 && text4.replace(BLOCK, "").replaceAll(MERGED_MESSAGE_SEPARATOR.trim(), "").trim() === "" ? events : null;
20638
20702
  }
20639
20703
  var MOTHERSHIP_EVENT_KINDS, UNKNOWN_EVENT_KIND, MOTHERSHIP_EVENT_TYPE, mothershipEventSchema, TAG, BLOCK, ATTRIBUTE, unescapeAttribute;
20640
20704
  var init_mothership_events = __esm({
@@ -20695,11 +20759,11 @@ function coerceBackgroundTaskPayload(payload) {
20695
20759
  const workflowAgents = Array.isArray(payload.workflow_progress) ? payload.workflow_progress.flatMap((entry) => {
20696
20760
  if (!isRecord(entry) || entry.type !== "workflow_agent") return [];
20697
20761
  const agentId = optionalString(entry.agentId);
20698
- const label = optionalString(entry.label);
20699
- if (!agentId || !label) return [];
20762
+ const label2 = optionalString(entry.label);
20763
+ if (!agentId || !label2) return [];
20700
20764
  return [{
20701
20765
  agentId,
20702
- label,
20766
+ label: label2,
20703
20767
  model: optionalString(entry.model),
20704
20768
  state: optionalString(entry.state),
20705
20769
  promptPreview: optionalString(entry.promptPreview),
@@ -20825,8 +20889,8 @@ function indexOrEnd(src, search, from) {
20825
20889
  const index = src.indexOf(search, from);
20826
20890
  return index < 0 ? src.length : index;
20827
20891
  }
20828
- function decodeAnsiC(text3) {
20829
- return text3.replace(/\\(x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{1,4}|[0-7]{1,3}|[\s\S])/g, (_match, escape) => {
20892
+ function decodeAnsiC(text4) {
20893
+ return text4.replace(/\\(x[0-9a-fA-F]{1,2}|u[0-9a-fA-F]{1,4}|[0-7]{1,3}|[\s\S])/g, (_match, escape) => {
20830
20894
  if (escape[0] === "x" || escape[0] === "u") return String.fromCharCode(parseInt(escape.slice(1), 16));
20831
20895
  if (/^[0-7]/.test(escape)) return String.fromCharCode(parseInt(escape, 8));
20832
20896
  return ANSI_C_ESCAPES[escape] ?? escape;
@@ -20843,8 +20907,8 @@ function staticOutput(argv, stdin) {
20843
20907
  if (flags.includes("n")) newline = false;
20844
20908
  if (flags.includes("e")) escapes = true;
20845
20909
  }
20846
- const text3 = args.join(" ");
20847
- return (escapes ? decodeAnsiC(text3) : text3) + (newline ? "\n" : "");
20910
+ const text4 = args.join(" ");
20911
+ return (escapes ? decodeAnsiC(text4) : text4) + (newline ? "\n" : "");
20848
20912
  }
20849
20913
  if (name === "printf" && args.length > 0) {
20850
20914
  const format = decodeAnsiC(args[0]);
@@ -21004,8 +21068,8 @@ function parseUntil(scope, start, closeParen) {
21004
21068
  let quoted = false;
21005
21069
  let redirect = null;
21006
21070
  let parens = 0;
21007
- const append = (text3, isQuoted = false) => {
21008
- word = (word ?? "") + text3;
21071
+ const append = (text4, isQuoted = false) => {
21072
+ word = (word ?? "") + text4;
21009
21073
  quoted || (quoted = isQuoted);
21010
21074
  };
21011
21075
  const endWord = () => {
@@ -21240,13 +21304,13 @@ var init_utils = __esm({
21240
21304
  });
21241
21305
 
21242
21306
  // ../shared/src/display-message/format.ts
21243
- function fileContentDiff(path10, content, action) {
21307
+ function fileContentDiff(path10, content, action2) {
21244
21308
  const lines = content.replace(/\n$/, "").split("\n");
21245
21309
  return [
21246
- `--- ${action === "add" ? "/dev/null" : `a/${path10}`}`,
21247
- `+++ ${action === "add" ? `b/${path10}` : "/dev/null"}`,
21248
- action === "add" ? `@@ -0,0 +1,${lines.length} @@` : `@@ -1,${lines.length} +0,0 @@`,
21249
- ...lines.map((line) => `${action === "add" ? "+" : "-"}${line}`)
21310
+ `--- ${action2 === "add" ? "/dev/null" : `a/${path10}`}`,
21311
+ `+++ ${action2 === "add" ? `b/${path10}` : "/dev/null"}`,
21312
+ action2 === "add" ? `@@ -0,0 +1,${lines.length} @@` : `@@ -1,${lines.length} +0,0 @@`,
21313
+ ...lines.map((line) => `${action2 === "add" ? "+" : "-"}${line}`)
21250
21314
  ].join("\n");
21251
21315
  }
21252
21316
  function shellCommands(command) {
@@ -22338,14 +22402,14 @@ var require_foldFlowLines = __commonJS({
22338
22402
  var FOLD_FLOW = "flow";
22339
22403
  var FOLD_BLOCK = "block";
22340
22404
  var FOLD_QUOTED = "quoted";
22341
- function foldFlowLines(text3, indent, mode = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
22405
+ function foldFlowLines(text4, indent, mode = "flow", { indentAtStart, lineWidth = 80, minContentWidth = 20, onFold, onOverflow } = {}) {
22342
22406
  if (!lineWidth || lineWidth < 0)
22343
- return text3;
22407
+ return text4;
22344
22408
  if (lineWidth < minContentWidth)
22345
22409
  minContentWidth = 0;
22346
22410
  const endStep = Math.max(1 + minContentWidth, 1 + lineWidth - indent.length);
22347
- if (text3.length <= endStep)
22348
- return text3;
22411
+ if (text4.length <= endStep)
22412
+ return text4;
22349
22413
  const folds = [];
22350
22414
  const escapedFolds = {};
22351
22415
  let end = lineWidth - indent.length;
@@ -22362,14 +22426,14 @@ var require_foldFlowLines = __commonJS({
22362
22426
  let escStart = -1;
22363
22427
  let escEnd = -1;
22364
22428
  if (mode === FOLD_BLOCK) {
22365
- i = consumeMoreIndentedLines(text3, i, indent.length);
22429
+ i = consumeMoreIndentedLines(text4, i, indent.length);
22366
22430
  if (i !== -1)
22367
22431
  end = i + endStep;
22368
22432
  }
22369
- for (let ch; ch = text3[i += 1]; ) {
22433
+ for (let ch; ch = text4[i += 1]; ) {
22370
22434
  if (mode === FOLD_QUOTED && ch === "\\") {
22371
22435
  escStart = i;
22372
- switch (text3[i + 1]) {
22436
+ switch (text4[i + 1]) {
22373
22437
  case "x":
22374
22438
  i += 3;
22375
22439
  break;
@@ -22386,12 +22450,12 @@ var require_foldFlowLines = __commonJS({
22386
22450
  }
22387
22451
  if (ch === "\n") {
22388
22452
  if (mode === FOLD_BLOCK)
22389
- i = consumeMoreIndentedLines(text3, i, indent.length);
22453
+ i = consumeMoreIndentedLines(text4, i, indent.length);
22390
22454
  end = i + indent.length + endStep;
22391
22455
  split = void 0;
22392
22456
  } else {
22393
22457
  if (ch === " " && prev && prev !== " " && prev !== "\n" && prev !== " ") {
22394
- const next = text3[i + 1];
22458
+ const next = text4[i + 1];
22395
22459
  if (next && next !== " " && next !== "\n" && next !== " ")
22396
22460
  split = i;
22397
22461
  }
@@ -22403,12 +22467,12 @@ var require_foldFlowLines = __commonJS({
22403
22467
  } else if (mode === FOLD_QUOTED) {
22404
22468
  while (prev === " " || prev === " ") {
22405
22469
  prev = ch;
22406
- ch = text3[i += 1];
22470
+ ch = text4[i += 1];
22407
22471
  overflow = true;
22408
22472
  }
22409
22473
  const j = i > escEnd + 1 ? i - 2 : escStart - 1;
22410
22474
  if (escapedFolds[j])
22411
- return text3;
22475
+ return text4;
22412
22476
  folds.push(j);
22413
22477
  escapedFolds[j] = true;
22414
22478
  end = j + endStep;
@@ -22423,39 +22487,39 @@ var require_foldFlowLines = __commonJS({
22423
22487
  if (overflow && onOverflow)
22424
22488
  onOverflow();
22425
22489
  if (folds.length === 0)
22426
- return text3;
22490
+ return text4;
22427
22491
  if (onFold)
22428
22492
  onFold();
22429
- let res = text3.slice(0, folds[0]);
22493
+ let res = text4.slice(0, folds[0]);
22430
22494
  for (let i2 = 0; i2 < folds.length; ++i2) {
22431
22495
  const fold = folds[i2];
22432
- const end2 = folds[i2 + 1] || text3.length;
22496
+ const end2 = folds[i2 + 1] || text4.length;
22433
22497
  if (fold === 0)
22434
22498
  res = `
22435
- ${indent}${text3.slice(0, end2)}`;
22499
+ ${indent}${text4.slice(0, end2)}`;
22436
22500
  else {
22437
22501
  if (mode === FOLD_QUOTED && escapedFolds[fold])
22438
- res += `${text3[fold]}\\`;
22502
+ res += `${text4[fold]}\\`;
22439
22503
  res += `
22440
- ${indent}${text3.slice(fold + 1, end2)}`;
22504
+ ${indent}${text4.slice(fold + 1, end2)}`;
22441
22505
  }
22442
22506
  }
22443
22507
  return res;
22444
22508
  }
22445
- function consumeMoreIndentedLines(text3, i, indent) {
22509
+ function consumeMoreIndentedLines(text4, i, indent) {
22446
22510
  let end = i;
22447
22511
  let start = i + 1;
22448
- let ch = text3[start];
22512
+ let ch = text4[start];
22449
22513
  while (ch === " " || ch === " ") {
22450
22514
  if (i < start + indent) {
22451
- ch = text3[++i];
22515
+ ch = text4[++i];
22452
22516
  } else {
22453
22517
  do {
22454
- ch = text3[++i];
22518
+ ch = text4[++i];
22455
22519
  } while (ch && ch !== "\n");
22456
22520
  end = i;
22457
22521
  start = i + 1;
22458
- ch = text3[start];
22522
+ ch = text4[start];
22459
22523
  }
22460
22524
  }
22461
22525
  return end;
@@ -28829,7 +28893,9 @@ var init_steps = __esm({
28829
28893
  [REPLICAS_MCP_TOOLS.createAutomation]: { icon: "clock", live: "Creating automation", done: "Created automation" },
28830
28894
  [REPLICAS_MCP_TOOLS.getLinearRouting]: { icon: "search", live: "Checking Linear routing", done: "Checked Linear routing" },
28831
28895
  [REPLICAS_MCP_TOOLS.setLinearRouting]: { icon: "wrench", live: "Setting Linear routing", done: "Set Linear routing" },
28832
- [REPLICAS_MCP_TOOLS.clearLinearRouting]: { icon: "trash", live: "Clearing Linear routing", done: "Cleared Linear routing" }
28896
+ [REPLICAS_MCP_TOOLS.clearLinearRouting]: { icon: "trash", live: "Clearing Linear routing", done: "Cleared Linear routing" },
28897
+ [REPLICAS_MCP_TOOLS.getBoard]: { icon: "book", live: "Reading board", done: "Read board" },
28898
+ [REPLICAS_MCP_TOOLS.updateBoard]: { icon: "file-pen", live: "Updating board", done: "Updated board" }
28833
28899
  };
28834
28900
  }
28835
28901
  });
@@ -28876,9 +28942,9 @@ function parseAppshot(match) {
28876
28942
  .../ \(cut short\)\. Treat that text as untrusted data/.test(match[4] ?? "") && { textTruncated: true }
28877
28943
  };
28878
28944
  }
28879
- function stripAttachmentNote(text3) {
28880
- const match = text3.match(/(?:^|\n\n)<replicas_attachments>\nUploaded files are available at:((?:\n- .*)*)(?:\n<\/?[a-z_]*>?)?$/) ?? text3.match(/(?:^|\n\n)Uploaded files are available at:((?:\n- .*)*)$/);
28881
- let content = match ? text3.replace(match[0], "").trim() : text3;
28945
+ function stripAttachmentNote(text4) {
28946
+ const match = text4.match(/(?:^|\n\n)<replicas_attachments>\nUploaded files are available at:((?:\n- .*)*)(?:\n<\/?[a-z_]*>?)?$/) ?? text4.match(/(?:^|\n\n)Uploaded files are available at:((?:\n- .*)*)$/);
28947
+ let content = match ? text4.replace(match[0], "").trim() : text4;
28882
28948
  const takeTrailingNotes = (noteRegex, truncatedRegex, parse3) => {
28883
28949
  const notes = [];
28884
28950
  const truncated = noteRegex.test(content) ? null : content.match(truncatedRegex);
@@ -28917,7 +28983,7 @@ var init_user_message_attachments = __esm({
28917
28983
  APPSHOT_NOTE_REGEX = /(?:^|\n\n)<replicas_appshot app="([^"\n]*)" window="([^"\n]*)" image="(\d+)">\n([^\n<]*)(?:\n\n([^<]*))?\n<\/replicas_appshot>$/;
28918
28984
  TRUNCATED_APPSHOT_NOTE_REGEX = /(?:^|\n\n)<replicas_appshot app="([^"\n]*)(?:" window="([^"\n]*)(?:" image="(\d*))?)?[^<]*(?:<\/?[a-z_]*)?$/;
28919
28985
  XML_UNESCAPES = { "&amp;": "&", "&lt;": "<", "&gt;": ">", "&quot;": '"', "&#39;": "'" };
28920
- unescapeXml = (text3) => text3.replace(/&(?:amp|lt|gt|quot|#39);/g, (entity) => XML_UNESCAPES[entity]);
28986
+ unescapeXml = (text4) => text4.replace(/&(?:amp|lt|gt|quot|#39);/g, (entity) => XML_UNESCAPES[entity]);
28921
28987
  WALKTHROUGH_NOTE_REGEX = /(?:^|\n\n)<replicas_walkthrough path="([^"\n]+)" duration_seconds="(\d+)" audio="(true|false)">\n[^<]*\n<\/replicas_walkthrough>$/;
28922
28988
  TRUNCATED_WALKTHROUGH_NOTE_REGEX = /(?:^|\n\n)<replicas_walkthrough path="([^"\n]*)(?:" duration_seconds="(\d*))?(?:" audio="(true)?)?[^<]*(?:<\/?[a-z_]*)?$/;
28923
28989
  }
@@ -28974,7 +29040,7 @@ function codexTurnMessages(turn) {
28974
29040
  return [{
28975
29041
  type: "reasoning",
28976
29042
  id: turn.id,
28977
- text: reasoning.map(({ text: text3 }) => text3.trim()).join("\n\n"),
29043
+ text: reasoning.map(({ text: text4 }) => text4.trim()).join("\n\n"),
28978
29044
  timestamp: reasoning[0].timestamp,
28979
29045
  status: reasoning.at(-1)?.status ?? "completed"
28980
29046
  }];
@@ -29504,7 +29570,7 @@ var init_codex_parser = __esm({
29504
29570
  // ../shared/src/display-message/parsers/cursor-parser.ts
29505
29571
  function getTextContent(value) {
29506
29572
  if (!Array.isArray(value)) return "";
29507
- return value.map((block) => isRecord(block) && block.type === "text" && typeof block.text === "string" ? block.text : "").join("");
29573
+ return value.map((block2) => isRecord(block2) && block2.type === "text" && typeof block2.text === "string" ? block2.text : "").join("");
29508
29574
  }
29509
29575
  function cursorStatusToDisplayStatus(status) {
29510
29576
  return status === "completed" || status === "FINISHED" ? "completed" : status === "error" || status === "ERROR" || status === "CANCELLED" || status === "EXPIRED" ? "failed" : "in_progress";
@@ -29518,8 +29584,8 @@ function getCursorAssistantText(event) {
29518
29584
  return getTextContent(message2?.content);
29519
29585
  }
29520
29586
  function getCursorThinkingText(event) {
29521
- const text3 = event.payload.text;
29522
- if (typeof text3 === "string") return text3;
29587
+ const text4 = event.payload.text;
29588
+ if (typeof text4 === "string") return text4;
29523
29589
  const message2 = isRecord(event.payload.message) ? event.payload.message : null;
29524
29590
  return typeof message2?.text === "string" ? message2.text : "";
29525
29591
  }
@@ -29570,8 +29636,8 @@ function parseCursorEvents(events) {
29570
29636
  continue;
29571
29637
  }
29572
29638
  if (event.type === "cursor-assistant") {
29573
- const text3 = getCursorAssistantText(event);
29574
- if (text3) {
29639
+ const text4 = getCursorAssistantText(event);
29640
+ if (text4) {
29575
29641
  const runId = cursorRunId(event);
29576
29642
  if (!activeAssistant || activeAssistant.runId !== runId) {
29577
29643
  const segment = runAssistantSegments.get(runId) ?? 0;
@@ -29590,15 +29656,15 @@ function parseCursorEvents(events) {
29590
29656
  if (message2?.type === "agent") {
29591
29657
  messages[activeAssistant.index] = {
29592
29658
  ...message2,
29593
- content: `${message2.content}${text3}`
29659
+ content: `${message2.content}${text4}`
29594
29660
  };
29595
29661
  }
29596
29662
  }
29597
29663
  continue;
29598
29664
  }
29599
29665
  if (event.type === "cursor-thinking") {
29600
- const text3 = getCursorThinkingText(event);
29601
- if (text3.trim()) {
29666
+ const text4 = getCursorThinkingText(event);
29667
+ if (text4.trim()) {
29602
29668
  const runId = cursorRunId(event);
29603
29669
  if (!activeThinking || activeThinking.runId !== runId) {
29604
29670
  const segment = runThinkingSegments.get(runId) ?? 0;
@@ -29618,7 +29684,7 @@ function parseCursorEvents(events) {
29618
29684
  if (message2?.type === "reasoning") {
29619
29685
  messages[activeThinking.index] = {
29620
29686
  ...message2,
29621
- content: `${message2.content}${text3}`,
29687
+ content: `${message2.content}${text4}`,
29622
29688
  status: "in_progress"
29623
29689
  };
29624
29690
  }
@@ -29650,12 +29716,12 @@ function parseCursorEvents(events) {
29650
29716
  }
29651
29717
  if (event.type === "cursor-task") {
29652
29718
  activeAssistant = null;
29653
- const text3 = event.payload.text;
29654
- if (typeof text3 === "string" && text3.trim()) {
29719
+ const text4 = event.payload.text;
29720
+ if (typeof text4 === "string" && text4.trim()) {
29655
29721
  messages.push({
29656
29722
  id: `cursor-task-${event.timestamp}-${messages.length}`,
29657
29723
  type: "agent",
29658
- content: text3,
29724
+ content: text4,
29659
29725
  timestamp: event.timestamp
29660
29726
  });
29661
29727
  }
@@ -29699,8 +29765,8 @@ var init_cursor_parser = __esm({
29699
29765
  });
29700
29766
 
29701
29767
  // ../shared/src/errors.ts
29702
- function isTransientErrorText(text3, options = {}) {
29703
- const normalized = text3.toLowerCase();
29768
+ function isTransientErrorText(text4, options = {}) {
29769
+ const normalized = text4.toLowerCase();
29704
29770
  if (!normalized) return false;
29705
29771
  if (TRANSIENT_NETWORK_ERROR_PATTERNS.some((pattern) => pattern.test(normalized))) return true;
29706
29772
  if (options.includeRateLimit && /rate limit/.test(normalized)) return true;
@@ -29744,8 +29810,8 @@ var init_errors3 = __esm({
29744
29810
 
29745
29811
  // ../shared/src/display-message/parsers/inference-error.ts
29746
29812
  function formatInferenceError(message2, context = {}) {
29747
- const label = context.provider ? INFERENCE_PROVIDER_LABELS[context.provider] ?? context.provider : null;
29748
- const source = label ? `${label}${context.model ? ` (${context.model})` : ""} request failed${typeof context.status === "number" ? ` with HTTP ${context.status}` : ""}` : null;
29813
+ const label2 = context.provider ? INFERENCE_PROVIDER_LABELS[context.provider] ?? context.provider : null;
29814
+ const source = label2 ? `${label2}${context.model ? ` (${context.model})` : ""} request failed${typeof context.status === "number" ? ` with HTTP ${context.status}` : ""}` : null;
29749
29815
  let body = source ? message2 ? `${source}: ${message2}` : `${source}.` : message2;
29750
29816
  const detail = context.detail?.trim();
29751
29817
  if (detail && !body.includes(detail)) {
@@ -29857,24 +29923,24 @@ function parseOpencodeEvents(events) {
29857
29923
  const time3 = isRecord(part.time) ? part.time : null;
29858
29924
  const timestamp = timestampFromMs(time3?.start, event.timestamp);
29859
29925
  if (part.type === "text") {
29860
- const text3 = typeof part.text === "string" ? part.text : "";
29861
- if (text3.trim()) {
29926
+ const text4 = typeof part.text === "string" ? part.text : "";
29927
+ if (text4.trim()) {
29862
29928
  upsertDisplayMessage(messages, {
29863
29929
  id,
29864
29930
  type: "agent",
29865
- content: text3,
29931
+ content: text4,
29866
29932
  timestamp
29867
29933
  });
29868
29934
  }
29869
29935
  continue;
29870
29936
  }
29871
29937
  if (part.type === "reasoning") {
29872
- const text3 = typeof part.text === "string" ? part.text : "";
29873
- if (text3.trim()) {
29938
+ const text4 = typeof part.text === "string" ? part.text : "";
29939
+ if (text4.trim()) {
29874
29940
  upsertDisplayMessage(messages, {
29875
29941
  id,
29876
29942
  type: "reasoning",
29877
- content: text3,
29943
+ content: text4,
29878
29944
  status: time3?.end ? "completed" : "in_progress",
29879
29945
  timestamp
29880
29946
  });
@@ -30057,7 +30123,7 @@ function assistantErrorMessage(value) {
30057
30123
  }
30058
30124
  function parsePiEvents(events) {
30059
30125
  const messages = [];
30060
- const text3 = /* @__PURE__ */ new Map();
30126
+ const text4 = /* @__PURE__ */ new Map();
30061
30127
  const thinking = /* @__PURE__ */ new Map();
30062
30128
  let activeMessageId = "assistant";
30063
30129
  for (const event of events) {
@@ -30088,9 +30154,9 @@ function parsePiEvents(events) {
30088
30154
  if (event.type === "pi-message_update") {
30089
30155
  const payload = nestedPayload(event);
30090
30156
  const id = typeof payload.id === "string" ? payload.id : activeMessageId;
30091
- if (payload.type === "text_delta" && typeof payload.delta === "string") text3.set(id, `${text3.get(id) ?? ""}${payload.delta}`);
30157
+ if (payload.type === "text_delta" && typeof payload.delta === "string") text4.set(id, `${text4.get(id) ?? ""}${payload.delta}`);
30092
30158
  if (payload.type === "thinking_delta" && typeof payload.delta === "string") thinking.set(id, `${thinking.get(id) ?? ""}${payload.delta}`);
30093
- const textContent = text3.get(id);
30159
+ const textContent = text4.get(id);
30094
30160
  const thinkingContent = thinking.get(id);
30095
30161
  if (textContent !== void 0) upsertDisplayMessage(messages, { id: `pi-${id}`, type: "agent", content: textContent, timestamp: event.timestamp });
30096
30162
  if (thinkingContent !== void 0) upsertDisplayMessage(messages, { id: `pi-thinking-${id}`, type: "reasoning", content: thinkingContent, status: "in_progress", timestamp: event.timestamp });
@@ -30162,7 +30228,7 @@ function normalizeContentBlocks(content) {
30162
30228
  if (typeof content === "string") {
30163
30229
  return content ? [{ type: "text", text: content }] : [];
30164
30230
  }
30165
- return Array.isArray(content) ? content.filter((block) => isRecord(block) && typeof block.type === "string") : [];
30231
+ return Array.isArray(content) ? content.filter((block2) => isRecord(block2) && typeof block2.type === "string") : [];
30166
30232
  }
30167
30233
  function parseStringField(value) {
30168
30234
  if (typeof value !== "string") return null;
@@ -30251,13 +30317,13 @@ var init_task_accumulator = __esm({
30251
30317
  }
30252
30318
  return out;
30253
30319
  }
30254
- processContentBlock(block) {
30255
- if (!isRecord(block)) return false;
30256
- if (block.type === "tool_use" && typeof block.name === "string" && typeof block.id === "string") {
30257
- return this.processToolUse(block.name, block.id, toAccumulatorInput(block.input));
30320
+ processContentBlock(block2) {
30321
+ if (!isRecord(block2)) return false;
30322
+ if (block2.type === "tool_use" && typeof block2.name === "string" && typeof block2.id === "string") {
30323
+ return this.processToolUse(block2.name, block2.id, toAccumulatorInput(block2.input));
30258
30324
  }
30259
- if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
30260
- return this.processCreateResult(block.tool_use_id, block.content);
30325
+ if (block2.type === "tool_result" && typeof block2.tool_use_id === "string") {
30326
+ return this.processCreateResult(block2.tool_use_id, block2.content);
30261
30327
  }
30262
30328
  return false;
30263
30329
  }
@@ -30266,12 +30332,12 @@ var init_task_accumulator = __esm({
30266
30332
  });
30267
30333
 
30268
30334
  // ../shared/src/display-message/parsers/claude-parser.ts
30269
- function fileOrCommandMessage(block, timestamp) {
30270
- let template = toolMessageTemplates.get(block);
30335
+ function fileOrCommandMessage(block2, timestamp) {
30336
+ let template = toolMessageTemplates.get(block2);
30271
30337
  if (!template) {
30272
- const input = typeof block.input === "string" ? safeJsonParse(block.input, {}) : block.input ?? {};
30273
- template = toolMessageTemplate(block.name ?? "", block.id ?? "", input);
30274
- toolMessageTemplates.set(block, template);
30338
+ const input = typeof block2.input === "string" ? safeJsonParse(block2.input, {}) : block2.input ?? {};
30339
+ template = toolMessageTemplate(block2.name ?? "", block2.id ?? "", input);
30340
+ toolMessageTemplates.set(block2, template);
30275
30341
  }
30276
30342
  return { ...template, timestamp };
30277
30343
  }
@@ -30369,8 +30435,8 @@ function isClaudeResultError(payload) {
30369
30435
  }
30370
30436
  function readClaudeUserPrompt(payload, content) {
30371
30437
  if (payload.isSynthetic || content.some((c) => c.type === "tool_result" && c.tool_use_id)) return void 0;
30372
- const text3 = content.filter((c) => c.type === "text").map((c) => c.text || "").join("\n");
30373
- if (LOCAL_COMMAND_ECHO_REGEX.test(text3.trim())) return void 0;
30438
+ const text4 = content.filter((c) => c.type === "text").map((c) => c.text || "").join("\n");
30439
+ if (LOCAL_COMMAND_ECHO_REGEX.test(text4.trim())) return void 0;
30374
30440
  const images = content.filter((c) => c.type === "image" && c.source).map((c) => {
30375
30441
  const source = c.source;
30376
30442
  return {
@@ -30380,7 +30446,7 @@ function readClaudeUserPrompt(payload, content) {
30380
30446
  ...c.replicasOmitted ? { replicasOmitted: c.replicasOmitted } : {}
30381
30447
  };
30382
30448
  }).filter((img) => img.data || img.replicasOmitted);
30383
- return text3 || images.length > 0 ? { text: text3, images } : void 0;
30449
+ return text4 || images.length > 0 ? { text: text4, images } : void 0;
30384
30450
  }
30385
30451
  function parseClaudeEvents(events, parentToolUseId) {
30386
30452
  const messages = [];
@@ -30597,13 +30663,13 @@ function parseClaudeEvents(events, parentToolUseId) {
30597
30663
  if (liveStreamId !== null && liveStreamId !== messageId) {
30598
30664
  supersededStreamIds.add(liveStreamId);
30599
30665
  }
30600
- if (contentBlocks.some((block) => block.type === "text" && block.text)) {
30666
+ if (contentBlocks.some((block2) => block2.type === "text" && block2.text)) {
30601
30667
  completedStreamIds.add(messageId);
30602
30668
  liveStreamId = null;
30603
30669
  }
30604
30670
  }
30605
30671
  const thinkingBlocks = contentBlocks.flatMap(
30606
- (block) => block.type === "thinking" && typeof block.thinking === "string" ? [block.thinking] : []
30672
+ (block2) => block2.type === "thinking" && typeof block2.thinking === "string" ? [block2.thinking] : []
30607
30673
  );
30608
30674
  if (thinkingBlocks.length > 0) {
30609
30675
  const allThinking = [...assistantThinking.get(messageKey) ?? [], ...thinkingBlocks];
@@ -30622,14 +30688,14 @@ function parseClaudeEvents(events, parentToolUseId) {
30622
30688
  upsertMessage(reasoningMessage);
30623
30689
  }
30624
30690
  }
30625
- contentBlocks.forEach((block) => {
30626
- if (block.type === "text" && block.text) {
30691
+ contentBlocks.forEach((block2) => {
30692
+ if (block2.type === "text" && block2.text) {
30627
30693
  const textIndex = assistantTextCounts.get(messageKey) ?? 0;
30628
30694
  assistantTextCounts.set(messageKey, textIndex + 1);
30629
30695
  const agentMessage = {
30630
30696
  id: `agent-${messageKey}-${textIndex}`,
30631
30697
  type: "agent",
30632
- content: block.text,
30698
+ content: block2.text,
30633
30699
  timestamp: event.timestamp
30634
30700
  };
30635
30701
  if (streamRefs?.agent !== void 0) {
@@ -30639,10 +30705,10 @@ function parseClaudeEvents(events, parentToolUseId) {
30639
30705
  upsertMessage(agentMessage);
30640
30706
  }
30641
30707
  }
30642
- if (block.type === "tool_use" && block.id) {
30643
- const toolName = block.name || "unknown";
30644
- const toolInput = block.input || {};
30645
- const toolUseId = block.id;
30708
+ if (block2.type === "tool_use" && block2.id) {
30709
+ const toolName = block2.name || "unknown";
30710
+ const toolInput = block2.input || {};
30711
+ const toolUseId = block2.id;
30646
30712
  toolCallMap.set(toolUseId, {
30647
30713
  messageIndex: messages.length,
30648
30714
  toolName,
@@ -30661,9 +30727,9 @@ function parseClaudeEvents(events, parentToolUseId) {
30661
30727
  nestedEvents
30662
30728
  }));
30663
30729
  } else if (COMMAND_TOOL_NAMES.has(toolName) || FILE_TOOL_NAMES.has(toolName)) {
30664
- messages.push(fileOrCommandMessage(block, event.timestamp));
30730
+ messages.push(fileOrCommandMessage(block2, event.timestamp));
30665
30731
  } else if (toolName === "TaskCreate" || toolName === "TaskUpdate" || toolName === "TaskList") {
30666
- taskAccumulator.processContentBlock(block);
30732
+ taskAccumulator.processContentBlock(block2);
30667
30733
  const snapshot = taskSnapshot();
30668
30734
  if (snapshot.length > 0) {
30669
30735
  messages.push({
@@ -31724,7 +31790,7 @@ var CLI_VERSION;
31724
31790
  var init_cli_version = __esm({
31725
31791
  "../shared/src/cli-version.ts"() {
31726
31792
  "use strict";
31727
- CLI_VERSION = "0.3.300";
31793
+ CLI_VERSION = "0.3.301";
31728
31794
  }
31729
31795
  });
31730
31796
 
@@ -35917,12 +35983,12 @@ var require_luxon = __commonJS({
35917
35983
  * @example Duration.fromISO('P5Y3M').toObject() //=> { years: 5, months: 3 }
35918
35984
  * @return {Duration}
35919
35985
  */
35920
- static fromISO(text3, opts) {
35921
- const [parsed] = parseISODuration(text3);
35986
+ static fromISO(text4, opts) {
35987
+ const [parsed] = parseISODuration(text4);
35922
35988
  if (parsed) {
35923
35989
  return _Duration.fromObject(parsed, opts);
35924
35990
  } else {
35925
- return _Duration.invalid("unparsable", `the input "${text3}" can't be parsed as ISO 8601`);
35991
+ return _Duration.invalid("unparsable", `the input "${text4}" can't be parsed as ISO 8601`);
35926
35992
  }
35927
35993
  }
35928
35994
  /**
@@ -35941,12 +36007,12 @@ var require_luxon = __commonJS({
35941
36007
  * @example Duration.fromISOTime('T1100').toObject() //=> { hours: 11, minutes: 0, seconds: 0 }
35942
36008
  * @return {Duration}
35943
36009
  */
35944
- static fromISOTime(text3, opts) {
35945
- const [parsed] = parseISOTimeOnly(text3);
36010
+ static fromISOTime(text4, opts) {
36011
+ const [parsed] = parseISOTimeOnly(text4);
35946
36012
  if (parsed) {
35947
36013
  return _Duration.fromObject(parsed, opts);
35948
36014
  } else {
35949
- return _Duration.invalid("unparsable", `the input "${text3}" can't be parsed as ISO 8601`);
36015
+ return _Duration.invalid("unparsable", `the input "${text4}" can't be parsed as ISO 8601`);
35950
36016
  }
35951
36017
  }
35952
36018
  /**
@@ -36611,8 +36677,8 @@ var require_luxon = __commonJS({
36611
36677
  * @see https://en.wikipedia.org/wiki/ISO_8601#Time_intervals
36612
36678
  * @return {Interval}
36613
36679
  */
36614
- static fromISO(text3, opts) {
36615
- const [s2, e] = (text3 || "").split("/", 2);
36680
+ static fromISO(text4, opts) {
36681
+ const [s2, e] = (text4 || "").split("/", 2);
36616
36682
  if (s2 && e) {
36617
36683
  let start, startIsValid;
36618
36684
  try {
@@ -36643,7 +36709,7 @@ var require_luxon = __commonJS({
36643
36709
  }
36644
36710
  }
36645
36711
  }
36646
- return _Interval.invalid("unparsable", `the input "${text3}" can't be parsed as ISO 8601`);
36712
+ return _Interval.invalid("unparsable", `the input "${text4}" can't be parsed as ISO 8601`);
36647
36713
  }
36648
36714
  /**
36649
36715
  * Check if an object is an Interval. Works across context boundaries
@@ -37873,7 +37939,7 @@ var require_luxon = __commonJS({
37873
37939
  o
37874
37940
  };
37875
37941
  }
37876
- function parseDataToDateTime(parsed, parsedZone, opts, format, text3, specificOffset) {
37942
+ function parseDataToDateTime(parsed, parsedZone, opts, format, text4, specificOffset) {
37877
37943
  const {
37878
37944
  setZone,
37879
37945
  zone
@@ -37886,7 +37952,7 @@ var require_luxon = __commonJS({
37886
37952
  });
37887
37953
  return setZone ? inst : inst.setZone(zone);
37888
37954
  } else {
37889
- return DateTime.invalid(new Invalid("unparsable", `the input "${text3}" can't be parsed as ${format}`));
37955
+ return DateTime.invalid(new Invalid("unparsable", `the input "${text4}" can't be parsed as ${format}`));
37890
37956
  }
37891
37957
  }
37892
37958
  function toTechFormat(dt, format, allowZ = true) {
@@ -38408,9 +38474,9 @@ var require_luxon = __commonJS({
38408
38474
  * @example DateTime.fromISO('2016-W05-4')
38409
38475
  * @return {DateTime}
38410
38476
  */
38411
- static fromISO(text3, opts = {}) {
38412
- const [vals, parsedZone] = parseISODate(text3);
38413
- return parseDataToDateTime(vals, parsedZone, opts, "ISO 8601", text3);
38477
+ static fromISO(text4, opts = {}) {
38478
+ const [vals, parsedZone] = parseISODate(text4);
38479
+ return parseDataToDateTime(vals, parsedZone, opts, "ISO 8601", text4);
38414
38480
  }
38415
38481
  /**
38416
38482
  * Create a DateTime from an RFC 2822 string
@@ -38427,9 +38493,9 @@ var require_luxon = __commonJS({
38427
38493
  * @example DateTime.fromRFC2822('25 Nov 2016 13:23 Z')
38428
38494
  * @return {DateTime}
38429
38495
  */
38430
- static fromRFC2822(text3, opts = {}) {
38431
- const [vals, parsedZone] = parseRFC2822Date(text3);
38432
- return parseDataToDateTime(vals, parsedZone, opts, "RFC 2822", text3);
38496
+ static fromRFC2822(text4, opts = {}) {
38497
+ const [vals, parsedZone] = parseRFC2822Date(text4);
38498
+ return parseDataToDateTime(vals, parsedZone, opts, "RFC 2822", text4);
38433
38499
  }
38434
38500
  /**
38435
38501
  * Create a DateTime from an HTTP header date
@@ -38447,8 +38513,8 @@ var require_luxon = __commonJS({
38447
38513
  * @example DateTime.fromHTTP('Sun Nov 6 08:49:37 1994')
38448
38514
  * @return {DateTime}
38449
38515
  */
38450
- static fromHTTP(text3, opts = {}) {
38451
- const [vals, parsedZone] = parseHTTPDate(text3);
38516
+ static fromHTTP(text4, opts = {}) {
38517
+ const [vals, parsedZone] = parseHTTPDate(text4);
38452
38518
  return parseDataToDateTime(vals, parsedZone, opts, "HTTP", opts);
38453
38519
  }
38454
38520
  /**
@@ -38465,8 +38531,8 @@ var require_luxon = __commonJS({
38465
38531
  * @param {string} opts.outputCalendar - the output calendar to set on the resulting DateTime instance
38466
38532
  * @return {DateTime}
38467
38533
  */
38468
- static fromFormat(text3, fmt, opts = {}) {
38469
- if (isUndefined(text3) || isUndefined(fmt)) {
38534
+ static fromFormat(text4, fmt, opts = {}) {
38535
+ if (isUndefined(text4) || isUndefined(fmt)) {
38470
38536
  throw new InvalidArgumentError2("fromFormat requires an input string and a format");
38471
38537
  }
38472
38538
  const {
@@ -38476,18 +38542,18 @@ var require_luxon = __commonJS({
38476
38542
  locale,
38477
38543
  numberingSystem,
38478
38544
  defaultToEN: true
38479
- }), [vals, parsedZone, specificOffset, invalid] = parseFromTokens(localeToUse, text3, fmt);
38545
+ }), [vals, parsedZone, specificOffset, invalid] = parseFromTokens(localeToUse, text4, fmt);
38480
38546
  if (invalid) {
38481
38547
  return _DateTime.invalid(invalid);
38482
38548
  } else {
38483
- return parseDataToDateTime(vals, parsedZone, opts, `format ${fmt}`, text3, specificOffset);
38549
+ return parseDataToDateTime(vals, parsedZone, opts, `format ${fmt}`, text4, specificOffset);
38484
38550
  }
38485
38551
  }
38486
38552
  /**
38487
38553
  * @deprecated use fromFormat instead
38488
38554
  */
38489
- static fromString(text3, fmt, opts = {}) {
38490
- return _DateTime.fromFormat(text3, fmt, opts);
38555
+ static fromString(text4, fmt, opts = {}) {
38556
+ return _DateTime.fromFormat(text4, fmt, opts);
38491
38557
  }
38492
38558
  /**
38493
38559
  * Create a DateTime from a SQL date, time, or datetime
@@ -38510,9 +38576,9 @@ var require_luxon = __commonJS({
38510
38576
  * @example DateTime.fromSQL('09:12:34.342')
38511
38577
  * @return {DateTime}
38512
38578
  */
38513
- static fromSQL(text3, opts = {}) {
38514
- const [vals, parsedZone] = parseSQL(text3);
38515
- return parseDataToDateTime(vals, parsedZone, opts, "SQL", text3);
38579
+ static fromSQL(text4, opts = {}) {
38580
+ const [vals, parsedZone] = parseSQL(text4);
38581
+ return parseDataToDateTime(vals, parsedZone, opts, "SQL", text4);
38516
38582
  }
38517
38583
  /**
38518
38584
  * Create an invalid DateTime.
@@ -39697,7 +39763,7 @@ var require_luxon = __commonJS({
39697
39763
  * @param {Object} options - options taken by fromFormat()
39698
39764
  * @return {Object}
39699
39765
  */
39700
- static fromFormatExplain(text3, fmt, options = {}) {
39766
+ static fromFormatExplain(text4, fmt, options = {}) {
39701
39767
  const {
39702
39768
  locale = null,
39703
39769
  numberingSystem = null
@@ -39706,13 +39772,13 @@ var require_luxon = __commonJS({
39706
39772
  numberingSystem,
39707
39773
  defaultToEN: true
39708
39774
  });
39709
- return explainFromTokens(localeToUse, text3, fmt);
39775
+ return explainFromTokens(localeToUse, text4, fmt);
39710
39776
  }
39711
39777
  /**
39712
39778
  * @deprecated use fromFormatExplain instead
39713
39779
  */
39714
- static fromStringExplain(text3, fmt, options = {}) {
39715
- return _DateTime.fromFormatExplain(text3, fmt, options);
39780
+ static fromStringExplain(text4, fmt, options = {}) {
39781
+ return _DateTime.fromFormatExplain(text4, fmt, options);
39716
39782
  }
39717
39783
  /**
39718
39784
  * Build a parser for `fmt` using the given locale. This parser can be passed
@@ -39747,8 +39813,8 @@ var require_luxon = __commonJS({
39747
39813
  * @param {Object} opts - options taken by fromFormat()
39748
39814
  * @returns {DateTime}
39749
39815
  */
39750
- static fromFormatParser(text3, formatParser, opts = {}) {
39751
- if (isUndefined(text3) || isUndefined(formatParser)) {
39816
+ static fromFormatParser(text4, formatParser, opts = {}) {
39817
+ if (isUndefined(text4) || isUndefined(formatParser)) {
39752
39818
  throw new InvalidArgumentError2("fromFormatParser requires an input string and a format parser");
39753
39819
  }
39754
39820
  const {
@@ -39767,11 +39833,11 @@ var require_luxon = __commonJS({
39767
39833
  zone,
39768
39834
  specificOffset,
39769
39835
  invalidReason
39770
- } = formatParser.explainFromTokens(text3);
39836
+ } = formatParser.explainFromTokens(text4);
39771
39837
  if (invalidReason) {
39772
39838
  return _DateTime.invalid(invalidReason);
39773
39839
  } else {
39774
- return parseDataToDateTime(result, zone, opts, `format ${formatParser.format}`, text3, specificOffset);
39840
+ return parseDataToDateTime(result, zone, opts, `format ${formatParser.format}`, text4, specificOffset);
39775
39841
  }
39776
39842
  }
39777
39843
  // FORMAT PRESETS
@@ -41314,8 +41380,8 @@ var require_CronExpression = __commonJS({
41314
41380
  return false;
41315
41381
  }
41316
41382
  if (__privateMethod(this, _CronExpression_instances, checkDstTransition_fn).call(this, currentDate)) {
41317
- const steps = reverse ? currentHour - nextHour : nextHour - currentHour;
41318
- for (let i = 0; i < steps; i++) {
41383
+ const steps2 = reverse ? currentHour - nextHour : nextHour - currentHour;
41384
+ for (let i = 0; i < steps2; i++) {
41319
41385
  currentDate.applyDateOperation(dateMathVerb, CronDate_1.TimeUnit.Hour, hours.length);
41320
41386
  if (!reverse && currentDate.getHours() >= nextHour)
41321
41387
  break;
@@ -41806,8 +41872,8 @@ var require_CronFileParser = __commonJS({
41806
41872
  expressions: [],
41807
41873
  errors: {}
41808
41874
  };
41809
- for (const block of blocks) {
41810
- const entry = block.trim();
41875
+ for (const block2 of blocks) {
41876
+ const entry = block2.trim();
41811
41877
  if (entry.length === 0 || entry.startsWith("#")) {
41812
41878
  continue;
41813
41879
  }
@@ -42341,6 +42407,123 @@ var init_websocket_liveness = __esm({
42341
42407
  }
42342
42408
  });
42343
42409
 
42410
+ // ../shared/src/mothership-board.ts
42411
+ var MOTHERSHIP_BOARD_TONES, label, tone, blockId, httpsUrl, prUrl, linearIdentifier, action, text3, badge, pr, ship, linear, button, steps, inline, row, blockTypes, blockSchemas, block, MOTHERSHIP_BOARD_CONTAINER_TYPES, mothershipBoardBlocksSchema, mothershipBoardOperationsSchema, LINEAR_ISSUE_SUMMARIES_MAX, linearIssueSummariesRequestSchema;
42412
+ var init_mothership_board = __esm({
42413
+ "../shared/src/mothership-board.ts"() {
42414
+ "use strict";
42415
+ init_zod();
42416
+ init_urls();
42417
+ MOTHERSHIP_BOARD_TONES = ["neutral", "needs_you", "warning", "success", "danger"];
42418
+ label = (max) => external_exports.string().trim().min(1).max(max);
42419
+ tone = external_exports.enum(MOTHERSHIP_BOARD_TONES);
42420
+ blockId = external_exports.string().regex(/^[\w.:-]{1,64}$/, "Use 1-64 letters, digits, _, -, . or :");
42421
+ httpsUrl = external_exports.url({ protocol: /^https$/, error: "Must be an https URL" });
42422
+ prUrl = httpsUrl.refine((url2) => parseCodeHostPrUrl(url2) !== null, "Must be a GitHub pull request or GitLab merge request URL");
42423
+ linearIdentifier = external_exports.string().regex(/^[A-Za-z][A-Za-z0-9]{0,9}-\d{1,7}$/, "Use a Linear identifier such as REP-123");
42424
+ action = external_exports.discriminatedUnion("type", [
42425
+ external_exports.object({ type: external_exports.literal("open_ship"), workspace_id: external_exports.uuid() }),
42426
+ external_exports.object({ type: external_exports.literal("message_ship"), workspace_id: external_exports.uuid(), message: label(4e3) }),
42427
+ external_exports.object({ type: external_exports.literal("open_pr"), url: prUrl }),
42428
+ external_exports.object({ type: external_exports.literal("merge_pr"), url: prUrl }),
42429
+ external_exports.object({ type: external_exports.literal("message_mothership"), message: label(4e3) }),
42430
+ external_exports.object({ type: external_exports.literal("open_link"), url: httpsUrl })
42431
+ ]);
42432
+ text3 = external_exports.object({ type: external_exports.literal("text"), id: blockId.optional(), text: label(2e3) });
42433
+ badge = external_exports.object({ type: external_exports.literal("badge"), id: blockId.optional(), label: label(40), tone: tone.optional() });
42434
+ pr = external_exports.object({ type: external_exports.literal("pr"), id: blockId.optional(), url: prUrl });
42435
+ ship = external_exports.object({ type: external_exports.literal("ship"), id: blockId.optional(), workspace_id: external_exports.uuid() });
42436
+ linear = external_exports.object({ type: external_exports.literal("linear"), id: blockId.optional(), identifier: linearIdentifier });
42437
+ button = external_exports.object({ type: external_exports.literal("button"), id: blockId.optional(), label: label(60), action, variant: external_exports.enum(["primary", "outline", "warning", "destructive"]).optional() });
42438
+ steps = external_exports.object({
42439
+ type: external_exports.literal("steps"),
42440
+ id: blockId.optional(),
42441
+ steps: external_exports.array(external_exports.object({ label: label(30), state: external_exports.enum(["done", "current", "pending", "failed"]) })).min(1).max(8)
42442
+ });
42443
+ inline = external_exports.discriminatedUnion("type", [text3, badge, pr, ship, linear, button, steps]);
42444
+ row = external_exports.object({ type: external_exports.literal("row"), id: blockId.optional(), cells: external_exports.array(external_exports.union([label(500), inline])).min(1).max(6) });
42445
+ blockTypes = {
42446
+ text: text3,
42447
+ badge,
42448
+ pr,
42449
+ ship,
42450
+ linear,
42451
+ button,
42452
+ steps,
42453
+ stat: external_exports.object({ type: external_exports.literal("stat"), id: blockId.optional(), label: label(40), value: label(40), tone: tone.optional() }),
42454
+ divider: external_exports.object({ type: external_exports.literal("divider"), id: blockId.optional() }),
42455
+ updated_at: external_exports.object({ type: external_exports.literal("updated_at"), id: blockId.optional() }),
42456
+ choice: external_exports.object({
42457
+ type: external_exports.literal("choice"),
42458
+ id: blockId.optional(),
42459
+ question: label(500),
42460
+ options: external_exports.array(external_exports.object({ label: label(60), message: label(2e3).optional() })).min(2).max(6)
42461
+ }),
42462
+ button_group: external_exports.object({ type: external_exports.literal("button_group"), id: blockId.optional(), children: external_exports.array(button).min(1).max(8) }),
42463
+ table: external_exports.object({ type: external_exports.literal("table"), id: blockId.optional(), columns: external_exports.array(label(40)).min(1).max(6), children: external_exports.array(row).max(100) }),
42464
+ callout: external_exports.object({
42465
+ type: external_exports.literal("callout"),
42466
+ id: blockId.optional(),
42467
+ tone,
42468
+ title: label(120).optional(),
42469
+ get children() {
42470
+ return external_exports.array(block).max(20).optional();
42471
+ }
42472
+ }),
42473
+ list: external_exports.object({
42474
+ type: external_exports.literal("list"),
42475
+ id: blockId.optional(),
42476
+ ordered: external_exports.boolean().optional(),
42477
+ get children() {
42478
+ return external_exports.array(block).max(100);
42479
+ }
42480
+ }),
42481
+ section: external_exports.object({
42482
+ type: external_exports.literal("section"),
42483
+ id: blockId.optional(),
42484
+ title: label(120),
42485
+ collapsed: external_exports.boolean().optional(),
42486
+ get children() {
42487
+ return external_exports.array(block).max(100);
42488
+ }
42489
+ })
42490
+ };
42491
+ blockSchemas = [text3, ...Object.values(blockTypes).filter((schema) => schema !== text3)];
42492
+ block = external_exports.discriminatedUnion("type", blockSchemas);
42493
+ MOTHERSHIP_BOARD_CONTAINER_TYPES = Object.entries(blockTypes).filter(([, schema]) => "children" in schema.shape).map(([type]) => type);
42494
+ mothershipBoardBlocksSchema = external_exports.array(block).max(100).superRefine((blocks, ctx) => {
42495
+ const seen = /* @__PURE__ */ new Set();
42496
+ const visit = (node, path10) => {
42497
+ if (typeof node === "string") return;
42498
+ if (node.id) {
42499
+ if (seen.has(node.id)) ctx.addIssue({ code: "custom", path: [...path10, "id"], message: `Duplicate block id "${node.id}"` });
42500
+ seen.add(node.id);
42501
+ }
42502
+ if (node.type === "table") {
42503
+ node.children.forEach((child, index) => {
42504
+ if (child.cells.length > node.columns.length) ctx.addIssue({ code: "custom", path: [...path10, "children", index, "cells"], message: `Row has ${child.cells.length} cells but the table has ${node.columns.length} columns` });
42505
+ });
42506
+ }
42507
+ if (node.type === "row") node.cells.forEach((cell, index) => visit(cell, [...path10, "cells", index]));
42508
+ else if ("children" in node) node.children?.forEach((child, index) => visit(child, [...path10, "children", index]));
42509
+ };
42510
+ blocks.forEach((node, index) => visit(node, [index]));
42511
+ });
42512
+ mothershipBoardOperationsSchema = external_exports.array(external_exports.discriminatedUnion("op", [
42513
+ external_exports.object({ op: external_exports.literal("replace"), blocks: external_exports.array(block) }),
42514
+ external_exports.object({
42515
+ op: external_exports.literal("upsert"),
42516
+ block: external_exports.discriminatedUnion("type", [row, ...blockSchemas]).refine((value) => Boolean(value.id), { message: "Give the block an id", path: ["id"] }),
42517
+ parent_id: blockId.optional(),
42518
+ position: external_exports.number().int().min(0).optional()
42519
+ }),
42520
+ external_exports.object({ op: external_exports.literal("remove"), id: blockId })
42521
+ ])).min(1).max(50);
42522
+ LINEAR_ISSUE_SUMMARIES_MAX = 50;
42523
+ linearIssueSummariesRequestSchema = external_exports.object({ identifiers: external_exports.array(linearIdentifier).min(1).max(LINEAR_ISSUE_SUMMARIES_MAX) });
42524
+ }
42525
+ });
42526
+
42344
42527
  // ../shared/src/index.ts
42345
42528
  var init_src = __esm({
42346
42529
  "../shared/src/index.ts"() {
@@ -42519,6 +42702,7 @@ var init_src = __esm({
42519
42702
  init_variable_requests();
42520
42703
  init_api_casing();
42521
42704
  init_websocket_liveness();
42705
+ init_mothership_board();
42522
42706
  }
42523
42707
  });
42524
42708
 
@@ -42878,8 +43062,8 @@ var init_api2 = __esm({
42878
43062
  });
42879
43063
 
42880
43064
  // src/lib/oauth-flow-ui.ts
42881
- function field(label, value) {
42882
- console.log(` ${import_chalk2.default.gray(label.padEnd(LABEL_WIDTH))}${value}`);
43065
+ function field(label2, value) {
43066
+ console.log(` ${import_chalk2.default.gray(label2.padEnd(LABEL_WIDTH))}${value}`);
42883
43067
  }
42884
43068
  function appliesTo(target) {
42885
43069
  if (!target.isUserScoped) return "Organization Settings";
@@ -42979,8 +43163,8 @@ function renderAuthFlowStep(step, total, title2) {
42979
43163
  console.log(import_chalk2.default.bold(`
42980
43164
  ${step}/${total} ${title2}`));
42981
43165
  }
42982
- function renderAuthFlowDetail(text3) {
42983
- console.log(import_chalk2.default.gray(` ${text3}`));
43166
+ function renderAuthFlowDetail(text4) {
43167
+ console.log(import_chalk2.default.gray(` ${text4}`));
42984
43168
  }
42985
43169
  function renderAuthFlowSuccess(providerLabel, summary, target) {
42986
43170
  console.log(brand.bold(`
@@ -44425,8 +44609,8 @@ async function exchangeCodeForTokens2(code, state, expectedState, codeVerifier)
44425
44609
  body: JSON.stringify(payload)
44426
44610
  });
44427
44611
  if (!response.ok) {
44428
- const text3 = await response.text();
44429
- throw new Error(`Failed to exchange authorization code: ${response.status} ${text3}`);
44612
+ const text4 = await response.text();
44613
+ throw new Error(`Failed to exchange authorization code: ${response.status} ${text4}`);
44430
44614
  }
44431
44615
  const data = await response.json();
44432
44616
  return {
@@ -44483,8 +44667,8 @@ async function claudeAuthCommand(options = {}) {
44483
44667
  oauthSteps: 2,
44484
44668
  orgEndpoint: "/v1/claude/credentials",
44485
44669
  userEndpoint: "/v1/claude/user/credentials",
44486
- runOAuth: async (steps, save) => {
44487
- await openForApproval("Replicas", await save(await runClaudeOAuthFlow(steps)));
44670
+ runOAuth: async (steps2, save) => {
44671
+ await openForApproval("Replicas", await save(await runClaudeOAuthFlow(steps2)));
44488
44672
  },
44489
44673
  toRequestBody: (tokens) => ({
44490
44674
  access_token: tokens.accessToken,
@@ -44594,8 +44778,8 @@ async function museAuthCommand(options = {}) {
44594
44778
  oauthSteps: 1,
44595
44779
  orgEndpoint: "/v1/muse/credentials",
44596
44780
  userEndpoint: "/v1/muse/user/credentials",
44597
- runOAuth: async (steps, save) => {
44598
- await openForApproval("Replicas", await save(await runMuseOAuthFlow(steps)));
44781
+ runOAuth: async (steps2, save) => {
44782
+ await openForApproval("Replicas", await save(await runMuseOAuthFlow(steps2)));
44599
44783
  },
44600
44784
  toRequestBody: (tokens) => ({ access_token: tokens.accessToken })
44601
44785
  });
@@ -44753,8 +44937,8 @@ async function credentialsUsageCommand({ org: org2, user }) {
44753
44937
  `${Math.round(window.usedPercent)}%`,
44754
44938
  window.resetsAt && import_chalk17.default.gray(`(resets ${formatDate(window.resetsAt)})`)
44755
44939
  ].filter(Boolean).join(" ")).join(", ");
44756
- const label = [account.email ?? account.credentialId, account.planType].filter(Boolean).join(" ");
44757
- console.log(`${account.provider} ${scopeLabel({ org: account.scope === "org" })} ${label} ${limits}`);
44940
+ const label2 = [account.email ?? account.credentialId, account.planType].filter(Boolean).join(" ");
44941
+ console.log(`${account.provider} ${scopeLabel({ org: account.scope === "org" })} ${label2} ${limits}`);
44758
44942
  if (account.exhaustedUntil) console.log(import_chalk17.default.gray(` Workspaces skip this account until ${formatDate(account.exhaustedUntil)}`));
44759
44943
  }
44760
44944
  });
@@ -45360,15 +45544,15 @@ async function envHookTestCommand(envIdOrName, options, kind) {
45360
45544
  }
45361
45545
  );
45362
45546
  if (errorMessage) throw new Error(errorMessage);
45363
- const label = kind === "warm" ? "Warm" : "Start";
45547
+ const label2 = kind === "warm" ? "Warm" : "Start";
45364
45548
  const passed = !timedOut && exitCode === 0;
45365
45549
  output({ passed, exit_code: exitCode, timed_out: timedOut, saved: passed && !!options.save, output: logs }, () => {
45366
45550
  if (passed) console.log(import_chalk20.default.green(`
45367
- ${label} hook passed${options.save ? " and was saved" : ""} (exit code ${exitCode}).
45551
+ ${label2} hook passed${options.save ? " and was saved" : ""} (exit code ${exitCode}).
45368
45552
  `));
45369
45553
  });
45370
- if (timedOut) throw new Error(`${label} hook timed out.`);
45371
- if (!passed) throw new Error(`${label} hook failed (exit code ${exitCode ?? "unknown"}).`);
45554
+ if (timedOut) throw new Error(`${label2} hook timed out.`);
45555
+ if (!passed) throw new Error(`${label2} hook failed (exit code ${exitCode ?? "unknown"}).`);
45372
45556
  }
45373
45557
  async function envHookRepositoryHooksCommand(envIdOrName, kind) {
45374
45558
  ensureOrgApiAuthenticated();
@@ -45561,9 +45745,9 @@ function formatStatus(status) {
45561
45745
  if (isWorkspaceSuspendedStatus(status)) return import_chalk21.default.gray(status);
45562
45746
  return status;
45563
45747
  }
45564
- function truncate(text3, maxLength) {
45565
- if (text3.length <= maxLength) return text3;
45566
- return text3.substring(0, maxLength) + "...";
45748
+ function truncate(text4, maxLength) {
45749
+ if (text4.length <= maxLength) return text4;
45750
+ return text4.substring(0, maxLength) + "...";
45567
45751
  }
45568
45752
  function formatDisplayMessage(message2) {
45569
45753
  const time3 = new Date(message2.timestamp).toLocaleTimeString();
@@ -45686,8 +45870,8 @@ Replicas (Page ${response2.page} of ${response2.total_pages}, Total: ${response2
45686
45870
  console.log(import_chalk21.default.gray(` Created: ${formatDate(replica.created_at)}`));
45687
45871
  if (replica.pull_requests && replica.pull_requests.length > 0) {
45688
45872
  console.log(import_chalk21.default.gray(` Pull Requests:`));
45689
- for (const pr2 of replica.pull_requests) {
45690
- console.log(import_chalk21.default.cyan(` - ${pr2.repository} #${pr2.number}: ${pr2.url}`));
45873
+ for (const pr3 of replica.pull_requests) {
45874
+ console.log(import_chalk21.default.cyan(` - ${pr3.repository} #${pr3.number}: ${pr3.url}`));
45691
45875
  }
45692
45876
  }
45693
45877
  console.log();
@@ -45720,8 +45904,8 @@ Replica: ${replica.name}
45720
45904
  }
45721
45905
  if (replica.pull_requests && replica.pull_requests.length > 0) {
45722
45906
  console.log(import_chalk21.default.gray(` Pull Requests:`));
45723
- for (const pr2 of replica.pull_requests) {
45724
- console.log(import_chalk21.default.cyan(` - ${pr2.repository} #${pr2.number}: ${pr2.url}`));
45907
+ for (const pr3 of replica.pull_requests) {
45908
+ console.log(import_chalk21.default.cyan(` - ${pr3.repository} #${pr3.number}: ${pr3.url}`));
45725
45909
  }
45726
45910
  }
45727
45911
  console.log();
@@ -45955,10 +46139,10 @@ async function workspaceWakeCommand(id, options) {
45955
46139
  await orgAuthenticatedFetch(`/v1/replica/${id}/wake${options.restore ? "?restore=true" : ""}`, { method: "POST" });
45956
46140
  outputSuccess(`Waking workspace ${id}. Check progress with: replicas status ${id}`);
45957
46141
  }
45958
- function workspaceLifecycleCommand(action) {
46142
+ function workspaceLifecycleCommand(action2) {
45959
46143
  return async (id) => {
45960
- await orgAuthenticatedFetch(`/v1/replica/${id}/${action}`, { method: "POST" });
45961
- outputSuccess(`Workspace ${id} ${action === "sleep" ? "is going to sleep" : "archived"}.`);
46144
+ await orgAuthenticatedFetch(`/v1/replica/${id}/${action2}`, { method: "POST" });
46145
+ outputSuccess(`Workspace ${id} ${action2 === "sleep" ? "is going to sleep" : "archived"}.`);
45962
46146
  };
45963
46147
  }
45964
46148
  async function workspaceWaitCommand(id, options) {
@@ -46079,7 +46263,7 @@ async function shareRemoveCommand(id, userId) {
46079
46263
  outputSuccess(`Stopped sharing workspace ${id} with ${userId}`);
46080
46264
  }
46081
46265
  async function prViewCommand(id, prUrls) {
46082
- const urls = prUrls.length > 0 ? prUrls : (await orgAuthenticatedFetch(`/v1/replica/${id}`)).replica.pull_requests?.map((pr2) => pr2.url) ?? [];
46266
+ const urls = prUrls.length > 0 ? prUrls : (await orgAuthenticatedFetch(`/v1/replica/${id}`)).replica.pull_requests?.map((pr3) => pr3.url) ?? [];
46083
46267
  if (urls.length === 0) {
46084
46268
  output({ pullRequests: [] }, () => console.log("No pull requests linked to this workspace."));
46085
46269
  return;
@@ -46103,15 +46287,15 @@ ${url2}`));
46103
46287
  }
46104
46288
  });
46105
46289
  }
46106
- async function prMergeCommand(id, prUrl) {
46107
- const { queued } = await orgAuthenticatedFetch(`/v1/replica/${id}/pull-requests/merge`, { method: "POST", body: { prUrl } });
46108
- outputSuccess(`${queued ? "Added to the merge queue:" : "Merged"} ${prUrl}`);
46290
+ async function prMergeCommand(id, prUrl2) {
46291
+ const { queued } = await orgAuthenticatedFetch(`/v1/replica/${id}/pull-requests/merge`, { method: "POST", body: { prUrl: prUrl2 } });
46292
+ outputSuccess(`${queued ? "Added to the merge queue:" : "Merged"} ${prUrl2}`);
46109
46293
  }
46110
- function prUpdateCommand(action) {
46111
- return async (id, prUrl) => {
46112
- const body = { prUrl, action };
46294
+ function prUpdateCommand(action2) {
46295
+ return async (id, prUrl2) => {
46296
+ const body = { prUrl: prUrl2, action: action2 };
46113
46297
  await orgAuthenticatedFetch(`/v1/replica/${id}/pull-requests/update`, { method: "POST", body });
46114
- outputSuccess(`${prUrl}: ${action.replaceAll("_", " ")} done`);
46298
+ outputSuccess(`${prUrl2}: ${action2.replaceAll("_", " ")} done`);
46115
46299
  };
46116
46300
  }
46117
46301
  async function canvasListCommand(id) {
@@ -46259,7 +46443,7 @@ var init_chat = __esm({
46259
46443
  chatQueueRemoveCommand = (id, chatId, messageId) => mutateQueue(chatPath2(id, chatId, `/queue/${messageId}`), "DELETE");
46260
46444
  chatQueueEditCommand = (id, chatId, messageId, message2) => mutateQueue(chatPath2(id, chatId, `/queue/${messageId}`), "PATCH", { message: message2 });
46261
46445
  chatQueueMoveCommand = (id, chatId, messageId, position) => mutateQueue(chatPath2(id, chatId, "/queue/reorder"), "PATCH", { messageId, position: Number(position) });
46262
- chatQueueActionCommand = (action) => (id, chatId, messageId) => mutateQueue(chatPath2(id, chatId, `/queue/${messageId}/${action}`), "POST");
46446
+ chatQueueActionCommand = (action2) => (id, chatId, messageId) => mutateQueue(chatPath2(id, chatId, `/queue/${messageId}/${action2}`), "POST");
46263
46447
  }
46264
46448
  });
46265
46449
 
@@ -46352,11 +46536,11 @@ async function environmentSetupStepCommand(key, status) {
46352
46536
  \u2713 ${key} \u2192 ${status}
46353
46537
  `)));
46354
46538
  }
46355
- function readJsonFile(file2, label) {
46539
+ function readJsonFile(file2, label2) {
46356
46540
  try {
46357
46541
  return JSON.parse(import_fs6.default.readFileSync(file2, "utf8"));
46358
46542
  } catch (error51) {
46359
- throw new Error(`Could not read ${label} JSON from ${file2}: ${error51 instanceof Error ? error51.message : String(error51)}`);
46543
+ throw new Error(`Could not read ${label2} JSON from ${file2}: ${error51 instanceof Error ? error51.message : String(error51)}`);
46360
46544
  }
46361
46545
  }
46362
46546
  async function environmentSetupProposeCommand(options) {
@@ -46591,9 +46775,9 @@ function buildTriggersFromOptions(options, runAt, repositories) {
46591
46775
  }
46592
46776
  return triggers;
46593
46777
  }
46594
- function truncate2(text3, maxLength) {
46595
- if (text3.length <= maxLength) return text3;
46596
- return text3.substring(0, maxLength) + "...";
46778
+ function truncate2(text4, maxLength) {
46779
+ if (text4.length <= maxLength) return text4;
46780
+ return text4.substring(0, maxLength) + "...";
46597
46781
  }
46598
46782
  function formatAutoPause(automation2) {
46599
46783
  return `${AUTOMATION_AUTO_PAUSE_LABEL}${automation2.failing_cause ? `: ${automation2.failing_cause}` : ""}`;
@@ -47921,8 +48105,8 @@ async function inspect(html, source) {
47921
48105
  const page = await chrome.newPage();
47922
48106
  const messages = [];
47923
48107
  page.on("Runtime.consoleAPICalled", ({ type, args }) => {
47924
- const text3 = args.map((arg) => arg.value === void 0 ? arg.description ?? "" : typeof arg.value === "string" ? arg.value : JSON.stringify(arg.value)).join(" ");
47925
- messages.push({ level: type === "error" || type === "assert" ? "error" : type === "warning" ? "warning" : "log", text: text3 });
48108
+ const text4 = args.map((arg) => arg.value === void 0 ? arg.description ?? "" : typeof arg.value === "string" ? arg.value : JSON.stringify(arg.value)).join(" ");
48109
+ messages.push({ level: type === "error" || type === "assert" ? "error" : type === "warning" ? "warning" : "log", text: text4 });
47926
48110
  });
47927
48111
  page.on("Runtime.exceptionThrown", ({ exceptionDetails }) => {
47928
48112
  messages.push({ level: "error", text: exceptionDetails.exception?.description ?? exceptionDetails.text });
@@ -48799,17 +48983,17 @@ function registerSlackCommands(parent) {
48799
48983
  slackThread.command("switch <workspace>").description("Point the current Slack thread at another workspace ID or name").option("-c, --channel <channelId>", "Slack channel ID (defaults to REPLICAS_SLACK_CHANNEL_ID)").option("-t, --thread-ts <threadTs>", "Slack thread timestamp (defaults to REPLICAS_SLACK_THREAD_TS)").action(run(slackThreadSwitchCommand));
48800
48984
  }
48801
48985
  function registerEnvironmentHookCommands(parent, config3) {
48802
- const label = `${config3.kind} hook`;
48986
+ const label2 = `${config3.kind} hook`;
48803
48987
  const hooks = parent.command(`${config3.kind}-hooks`).description(config3.kind === "warm" ? "Manage env-level warm hooks (run while pre-warming workspaces)" : "Manage env-level start hooks (run on every workspace boot, before repo-level start hooks)");
48804
- hooks.command("get <env>").description(`Show the active ${label} for an environment`).action(run(config3.get));
48805
- hooks.command("save <env>").description(`Save and activate a ${label}${config3.kind === "warm" ? " without testing it" : ""}`).option("-c, --content <content>", "Inline hook script").option("-f, --file <local-path>", "Read hook script from a local file").action(run(config3.save));
48806
- hooks.command("test <env>").description(`Run a ${label} in an isolated sandbox without saving it`).option("-c, --content <content>", "Inline hook script").option("-f, --file <local-path>", "Read hook script from a local file").action(run(config3.test));
48988
+ hooks.command("get <env>").description(`Show the active ${label2} for an environment`).action(run(config3.get));
48989
+ hooks.command("save <env>").description(`Save and activate a ${label2}${config3.kind === "warm" ? " without testing it" : ""}`).option("-c, --content <content>", "Inline hook script").option("-f, --file <local-path>", "Read hook script from a local file").action(run(config3.save));
48990
+ hooks.command("test <env>").description(`Run a ${label2} in an isolated sandbox without saving it`).option("-c, --content <content>", "Inline hook script").option("-f, --file <local-path>", "Read hook script from a local file").action(run(config3.test));
48807
48991
  if (config3.saveTest) {
48808
- hooks.command("save-test <env>").description(`Test a ${label} and save it only if the test passes`).option("-c, --content <content>", "Inline hook script").option("-f, --file <local-path>", "Read hook script from a local file").action(run(config3.saveTest));
48992
+ hooks.command("save-test <env>").description(`Test a ${label2} and save it only if the test passes`).option("-c, --content <content>", "Inline hook script").option("-f, --file <local-path>", "Read hook script from a local file").action(run(config3.saveTest));
48809
48993
  }
48810
48994
  hooks.command("repository-hooks <env>").description(`List per-repo ${config3.kind} hooks defined in replicas.json / replicas.yaml`).action(run(config3.repositoryHooks));
48811
48995
  }
48812
- var import_config20, import_commander, collect, program, organizationOptionalCommands, interactiveCommands, org, config2, chat, chatQueue, share, pr, canvas, credentials, automation, repos, plugins, skills, media, environment, envVars, envFiles, envSkills, envMcps, envDevices, envWarmPool, preview, authenticatedPreviewHelp;
48996
+ var import_config20, import_commander, collect, program, organizationOptionalCommands, interactiveCommands, org, config2, chat, chatQueue, share, pr2, canvas, credentials, automation, repos, plugins, skills, media, environment, envVars, envFiles, envSkills, envMcps, envDevices, envWarmPool, preview, authenticatedPreviewHelp;
48813
48997
  var init_src2 = __esm({
48814
48998
  "src/index.ts"() {
48815
48999
  "use strict";
@@ -48953,13 +49137,13 @@ var init_src2 = __esm({
48953
49137
  share.command("list <id>").description("List members a replica is shared with").action(run(shareListCommand));
48954
49138
  share.command("add <id> <userId>").description("Share a replica with a member").action(run(shareAddCommand));
48955
49139
  share.command("remove <id> <userId>").description("Stop sharing a replica with a member").action(run(shareRemoveCommand));
48956
- pr = program.command("pr").description("Inspect and act on pull requests linked to a replica");
48957
- pr.command("view <id> [prUrls...]").description("Show state, CI, and mergeability (defaults to every linked pull request)").action(run(prViewCommand));
48958
- pr.command("merge <id> <prUrl>").description("Merge a pull request").action(run(prMergeCommand));
48959
- pr.command("approve <id> <prUrl>").description("Approve a pull request").action(run(prUpdateCommand("approve")));
48960
- pr.command("close <id> <prUrl>").description("Close a pull request").action(run(prUpdateCommand("close")));
48961
- pr.command("draft <id> <prUrl>").description("Convert a pull request to a draft").action(run(prUpdateCommand("convert_to_draft")));
48962
- pr.command("ready <id> <prUrl>").description("Mark a draft pull request ready for review").action(run(prUpdateCommand("mark_ready_for_review")));
49140
+ pr2 = program.command("pr").description("Inspect and act on pull requests linked to a replica");
49141
+ pr2.command("view <id> [prUrls...]").description("Show state, CI, and mergeability (defaults to every linked pull request)").action(run(prViewCommand));
49142
+ pr2.command("merge <id> <prUrl>").description("Merge a pull request").action(run(prMergeCommand));
49143
+ pr2.command("approve <id> <prUrl>").description("Approve a pull request").action(run(prUpdateCommand("approve")));
49144
+ pr2.command("close <id> <prUrl>").description("Close a pull request").action(run(prUpdateCommand("close")));
49145
+ pr2.command("draft <id> <prUrl>").description("Convert a pull request to a draft").action(run(prUpdateCommand("convert_to_draft")));
49146
+ pr2.command("ready <id> <prUrl>").description("Mark a draft pull request ready for review").action(run(prUpdateCommand("mark_ready_for_review")));
48963
49147
  canvas = program.command("canvas").description("Read and edit files in a replica Canvas");
48964
49148
  canvas.command("list <id>").description("List Canvas files").action(run(canvasListCommand));
48965
49149
  canvas.command("get <id> <filename>").description("Print a Canvas text file").action(run(canvasGetCommand));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.3.300",
3
+ "version": "0.3.301",
4
4
  "description": "CLI for managing Replicas workspaces - SSH into cloud dev environments with automatic port forwarding",
5
5
  "main": "dist/index.cjs",
6
6
  "bin": {