replicas-cli 0.3.156 → 0.3.158

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 +69 -46
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -26907,7 +26907,18 @@ function collectCodexTurns(events) {
26907
26907
  }
26908
26908
  return turns;
26909
26909
  }
26910
+ var turnMessages = /* @__PURE__ */ new WeakMap();
26910
26911
  function messagesForCodexTurn(turn) {
26912
+ const [first] = turn.items;
26913
+ const cached2 = first ? turnMessages.get(first) : void 0;
26914
+ if (cached2 && cached2.turn.id === turn.id && cached2.turn.status === turn.status && cached2.turn.completedAt === turn.completedAt && cached2.turn.error === turn.error && cached2.turn.items.length === turn.items.length && cached2.turn.items.every((item, index) => item === turn.items[index])) {
26915
+ return cached2.messages;
26916
+ }
26917
+ const messages = codexTurnMessages(turn);
26918
+ if (first) turnMessages.set(first, { turn, messages });
26919
+ return messages;
26920
+ }
26921
+ function codexTurnMessages(turn) {
26911
26922
  const items = turn.items.map((item, index) => ({ item, index })).sort((a, b) => parseTimestampMs(a.item.timestamp) - parseTimestampMs(b.item.timestamp) || a.index - b.index).map(({ item }) => item);
26912
26923
  const reasoning = items.filter(
26913
26924
  (item) => item.type === "reasoning" && item.text.trim().length > 0
@@ -27170,16 +27181,14 @@ function takeRecordedPrompt(prompts3, echo, turnIndex) {
27170
27181
  function parseCodexEvents(events) {
27171
27182
  const messages = [];
27172
27183
  const turns = collectCodexTurns(events);
27173
- const turnInsertions = [];
27184
+ const turnInsertions = /* @__PURE__ */ new Map();
27174
27185
  const pendingCommands = /* @__PURE__ */ new Map();
27175
27186
  const pendingToolCalls = /* @__PURE__ */ new Map();
27176
27187
  const pendingPatches = /* @__PURE__ */ new Map();
27177
27188
  events.forEach((event, eventIndex) => {
27178
27189
  const turnId = codexItemFromEvent(event)?.turnId ?? codexTurnFromEvent(event)?.turnId;
27179
27190
  if (turnId !== void 0) {
27180
- if (!turnInsertions.some((insertion) => insertion.turnId === turnId)) {
27181
- turnInsertions.push({ index: messages.length, turnId });
27182
- }
27191
+ if (!turnInsertions.has(turnId)) turnInsertions.set(turnId, messages.length);
27183
27192
  return;
27184
27193
  }
27185
27194
  if (event.type === "codex-asp-error") {
@@ -27359,7 +27368,7 @@ function parseCodexEvents(events) {
27359
27368
  recordedPrompts.set(content, prompts3);
27360
27369
  });
27361
27370
  const claimedPrompts = /* @__PURE__ */ new Set();
27362
- for (const { index, turnId } of turnInsertions.reverse()) {
27371
+ for (const [turnId, index] of [...turnInsertions].reverse()) {
27363
27372
  const turn = turns.get(turnId);
27364
27373
  if (!turn) continue;
27365
27374
  const kept = [];
@@ -28004,12 +28013,9 @@ function parseStringField(value) {
28004
28013
  return trimmed ? trimmed : null;
28005
28014
  }
28006
28015
  function parseCreateResultTaskId(resultText) {
28007
- try {
28008
- const parsed = JSON.parse(resultText);
28009
- if (isRecord(parsed) && isRecord(parsed.task)) {
28010
- return parseStringField(parsed.task.id);
28011
- }
28012
- } catch {
28016
+ const parsed = resultText.trimStart().startsWith("{") ? safeJsonParse(resultText, null) : null;
28017
+ if (isRecord(parsed) && isRecord(parsed.task)) {
28018
+ return parseStringField(parsed.task.id);
28013
28019
  }
28014
28020
  return resultText.match(/\bTask\s+#?([A-Za-z0-9_-]+)\s+created\b/i)?.[1] ?? null;
28015
28021
  }
@@ -28063,10 +28069,10 @@ var TaskAccumulator = class {
28063
28069
  }
28064
28070
  return false;
28065
28071
  }
28066
- processCreateResult(toolUseId, resultText) {
28072
+ processCreateResult(toolUseId, content) {
28067
28073
  const pending = this.tasksByCreateToolUseId.get(toolUseId);
28068
28074
  if (!pending) return false;
28069
- const taskId = parseCreateResultTaskId(resultText);
28075
+ const taskId = parseCreateResultTaskId(extractToolResultText(content, ""));
28070
28076
  if (!taskId) return false;
28071
28077
  this.tasksByTaskId.set(taskId, pending);
28072
28078
  this.tasksByCreateToolUseId.delete(toolUseId);
@@ -28088,7 +28094,7 @@ var TaskAccumulator = class {
28088
28094
  return this.processToolUse(block.name, block.id, toAccumulatorInput(block.input));
28089
28095
  }
28090
28096
  if (block.type === "tool_result" && typeof block.tool_use_id === "string") {
28091
- return this.processCreateResult(block.tool_use_id, extractToolResultText(block.content, ""));
28097
+ return this.processCreateResult(block.tool_use_id, block.content);
28092
28098
  }
28093
28099
  return false;
28094
28100
  }
@@ -28098,7 +28104,18 @@ var TaskAccumulator = class {
28098
28104
  var ABORTED_TERMINAL_REASONS = /* @__PURE__ */ new Set(["aborted_streaming", "aborted_tools"]);
28099
28105
  var COMMAND_TOOL_NAMES = /* @__PURE__ */ new Set(["Bash", "bash", "shell"]);
28100
28106
  var FILE_TOOL_NAMES = /* @__PURE__ */ new Set(["Write", "Edit"]);
28101
- function fileOrCommandMessage(toolName, toolUseId, input, timestamp) {
28107
+ var toolMessageTemplates = /* @__PURE__ */ new WeakMap();
28108
+ var toolResults = /* @__PURE__ */ new WeakMap();
28109
+ function fileOrCommandMessage(block, timestamp) {
28110
+ let template = toolMessageTemplates.get(block);
28111
+ if (!template) {
28112
+ const input = typeof block.input === "string" ? safeJsonParse(block.input, {}) : block.input ?? {};
28113
+ template = toolMessageTemplate(block.name ?? "", block.id ?? "", input);
28114
+ toolMessageTemplates.set(block, template);
28115
+ }
28116
+ return { ...template, timestamp };
28117
+ }
28118
+ function toolMessageTemplate(toolName, toolUseId, input) {
28102
28119
  if (COMMAND_TOOL_NAMES.has(toolName)) {
28103
28120
  const command = typeof input.command === "string" ? input.command : "";
28104
28121
  const skillNames = skillNamesFromCommand(command);
@@ -28108,8 +28125,7 @@ function fileOrCommandMessage(toolName, toolUseId, input, timestamp) {
28108
28125
  command,
28109
28126
  ...skillNames.length > 0 ? { skillNames } : {},
28110
28127
  output: "",
28111
- status: "in_progress",
28112
- timestamp
28128
+ status: "in_progress"
28113
28129
  };
28114
28130
  }
28115
28131
  const filePath = typeof input.file_path === "string" ? input.file_path : "";
@@ -28137,28 +28153,41 @@ function fileOrCommandMessage(toolName, toolUseId, input, timestamp) {
28137
28153
  id: `patch-${toolUseId}`,
28138
28154
  type: "patch",
28139
28155
  operations: [{ action: toolName === "Write" ? "add" : "update", path: filePath, diff }],
28140
- status: "in_progress",
28141
- timestamp
28156
+ status: "in_progress"
28142
28157
  };
28143
28158
  }
28144
- function createSubagentMessage(messageIndex, timestamp, fields) {
28145
- const { id = `subagent-${timestamp}-${messageIndex}`, ...message2 } = fields;
28146
- return { id, type: "subagent", ...message2, timestamp };
28159
+ function createSubagentMessage(timestamp, fields) {
28160
+ return { id: `subagent-${fields.toolUseId}`, type: "subagent", ...fields, timestamp };
28147
28161
  }
28148
- function collectNestedEvents(events, toolUseId) {
28149
- return events.filter((e) => e.payload.parent_tool_use_id === toolUseId).map(({ timestamp, type, payload }) => ({ timestamp, type, payload }));
28162
+ function groupNestedEvents(events) {
28163
+ const nested = /* @__PURE__ */ new Map();
28164
+ for (const { timestamp, type, payload } of events) {
28165
+ const parent = payload.parent_tool_use_id;
28166
+ if (typeof parent !== "string") continue;
28167
+ const siblings = nested.get(parent);
28168
+ if (siblings) siblings.push({ timestamp, type, payload });
28169
+ else nested.set(parent, [{ timestamp, type, payload }]);
28170
+ }
28171
+ return nested;
28150
28172
  }
28151
- function readToolResult(event) {
28152
- if (event.type !== "claude-user") return void 0;
28173
+ function extractToolResult(event) {
28153
28174
  const toolResult = normalizeContentBlocks(event.payload.message?.content).find((c) => c.type === "tool_result");
28154
28175
  if (!toolResult?.tool_use_id) return void 0;
28176
+ const output2 = extractToolResultText(toolResult.content);
28177
+ const exitCode = output2.match(/exit code:?\s*(\d+)/i)?.[1];
28155
28178
  return {
28156
28179
  toolResult,
28157
28180
  toolUseId: toolResult.tool_use_id,
28158
- output: extractToolResultText(toolResult.content),
28181
+ output: output2,
28182
+ exitCode: exitCode === void 0 ? void 0 : parseInt(exitCode, 10),
28159
28183
  status: toolResult.is_error ? "failed" : "completed"
28160
28184
  };
28161
28185
  }
28186
+ function readToolResult(event) {
28187
+ if (event.type !== "claude-user") return void 0;
28188
+ if (!toolResults.has(event)) toolResults.set(event, extractToolResult(event));
28189
+ return toolResults.get(event);
28190
+ }
28162
28191
  function coerceClaudeResultPayload(payload) {
28163
28192
  return {
28164
28193
  is_error: typeof payload.is_error === "boolean" ? payload.is_error : void 0,
@@ -28215,6 +28244,8 @@ function parseClaudeEvents(events, parentToolUseId) {
28215
28244
  });
28216
28245
  };
28217
28246
  const taskAccumulator = new TaskAccumulator();
28247
+ let nestedEventsByParent;
28248
+ const collectNestedEvents = (toolUseId) => (nestedEventsByParent ?? (nestedEventsByParent = groupNestedEvents(events))).get(toolUseId) ?? [];
28218
28249
  const todoItems = /* @__PURE__ */ new WeakMap();
28219
28250
  const taskSnapshot = () => taskAccumulator.getTasks().map((task) => {
28220
28251
  const item = todoItems.get(task) ?? { text: task.subject, completed: task.status === "completed", itemStatus: task.status };
@@ -28409,8 +28440,8 @@ function parseClaudeEvents(events, parentToolUseId) {
28409
28440
  });
28410
28441
  if (toolName === "Task" || toolName === "Agent") {
28411
28442
  const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
28412
- const nestedEvents = collectNestedEvents(events, toolUseId);
28413
- messages.push(createSubagentMessage(messages.length, event.timestamp, {
28443
+ const nestedEvents = collectNestedEvents(toolUseId);
28444
+ messages.push(createSubagentMessage(event.timestamp, {
28414
28445
  toolUseId,
28415
28446
  description: inputObj.description || "Subagent Task",
28416
28447
  prompt: inputObj.prompt || "",
@@ -28420,14 +28451,13 @@ function parseClaudeEvents(events, parentToolUseId) {
28420
28451
  nestedEvents
28421
28452
  }));
28422
28453
  } else if (COMMAND_TOOL_NAMES.has(toolName) || FILE_TOOL_NAMES.has(toolName)) {
28423
- const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
28424
- messages.push(fileOrCommandMessage(toolName, toolUseId, inputObj, event.timestamp));
28454
+ messages.push(fileOrCommandMessage(block, event.timestamp));
28425
28455
  } else if (toolName === "TaskCreate" || toolName === "TaskUpdate" || toolName === "TaskList") {
28426
28456
  taskAccumulator.processContentBlock(block);
28427
28457
  const snapshot = taskSnapshot();
28428
28458
  if (snapshot.length > 0) {
28429
28459
  messages.push({
28430
- id: `todo-${event.timestamp}-${messages.length}`,
28460
+ id: `todo-${toolUseId}`,
28431
28461
  type: "todo_list",
28432
28462
  items: snapshot,
28433
28463
  status: "completed",
@@ -28438,7 +28468,7 @@ function parseClaudeEvents(events, parentToolUseId) {
28438
28468
  const inputObj = typeof toolInput === "string" ? safeJsonParse(toolInput, {}) : toolInput;
28439
28469
  const query = inputObj.query || "";
28440
28470
  messages.push({
28441
- id: `search-${event.timestamp}-${messages.length}`,
28471
+ id: `search-${toolUseId}`,
28442
28472
  type: "web_search",
28443
28473
  query,
28444
28474
  status: "in_progress",
@@ -28456,7 +28486,7 @@ function parseClaudeEvents(events, parentToolUseId) {
28456
28486
  });
28457
28487
  } else {
28458
28488
  messages.push(createCallDisplayMessage({
28459
- id: `toolcall-${event.timestamp}-${messages.length}`,
28489
+ id: `toolcall-${toolUseId}`,
28460
28490
  server: "claude",
28461
28491
  tool: toolName,
28462
28492
  input: toolInput,
@@ -28507,10 +28537,8 @@ function parseClaudeEvents(events, parentToolUseId) {
28507
28537
  for (const workflowAgent of payload.workflowAgents ?? []) {
28508
28538
  const existingWorkflowAgent = workflowAgentMessageMap.get(workflowAgent.agentId);
28509
28539
  const nextWorkflowAgent = createSubagentMessage(
28510
- messages.length,
28511
28540
  existingWorkflowAgent?.timestamp ?? event.timestamp,
28512
28541
  {
28513
- id: existingWorkflowAgent?.id,
28514
28542
  toolUseId: workflowAgent.agentId,
28515
28543
  description: workflowAgent.label,
28516
28544
  prompt: workflowAgent.promptPreview ?? existingWorkflowAgent?.prompt ?? "",
@@ -28518,7 +28546,7 @@ function parseClaudeEvents(events, parentToolUseId) {
28518
28546
  model: workflowAgent.model ?? existingWorkflowAgent?.model,
28519
28547
  status: workflowAgent.state === "done" ? "completed" : workflowAgent.state === "error" ? "failed" : "in_progress",
28520
28548
  output: workflowAgent.resultPreview ?? workflowAgent.lastToolSummary ?? existingWorkflowAgent?.output,
28521
- nestedEvents: existingWorkflowAgent?.nestedEvents ?? collectNestedEvents(events, workflowAgent.agentId)
28549
+ nestedEvents: existingWorkflowAgent?.nestedEvents ?? collectNestedEvents(workflowAgent.agentId)
28522
28550
  }
28523
28551
  );
28524
28552
  workflowAgentMessageMap.set(workflowAgent.agentId, upsertDisplayMessage(messages, nextWorkflowAgent));
@@ -28526,7 +28554,7 @@ function parseClaudeEvents(events, parentToolUseId) {
28526
28554
  const existing = taskMessageMap.get(payload.taskId);
28527
28555
  const nextStatus = payload.subtype === "task_notification" ? normalizeBackgroundTaskStatus(payload.status) : payload.subtype === "task_updated" && payload.patch?.status !== void 0 ? normalizeBackgroundTaskStatus(payload.patch?.status) : existing?.status ?? "in_progress";
28528
28556
  const nextMessage = {
28529
- id: existing?.id ?? `task-${event.timestamp}-${messages.length}`,
28557
+ id: `task-${payload.taskId}`,
28530
28558
  type: "background_task",
28531
28559
  taskId: payload.taskId,
28532
28560
  toolUseId: payload.toolUseId ?? existing?.toolUseId,
@@ -28583,7 +28611,7 @@ function parseClaudeEvents(events, parentToolUseId) {
28583
28611
  for (const [streamId, { tool, timestamp }] of streamingTools) {
28584
28612
  if (toolCallMap.has(tool.id) || supersededStreamIds.has(streamId)) continue;
28585
28613
  if (!COMMAND_TOOL_NAMES.has(tool.name) && !FILE_TOOL_NAMES.has(tool.name)) continue;
28586
- messages.push(fileOrCommandMessage(tool.name, tool.id, "filePath" in tool ? { file_path: tool.filePath } : { command: tool.command }, timestamp));
28614
+ messages.push(fileOrCommandMessage({ type: "tool_use", id: tool.id, name: tool.name, input: "filePath" in tool ? { file_path: tool.filePath } : { command: tool.command } }, timestamp));
28587
28615
  }
28588
28616
  filteredEvents.forEach((event) => {
28589
28617
  const result = readToolResult(event);
@@ -28600,12 +28628,7 @@ function parseClaudeEvents(events, parentToolUseId) {
28600
28628
  if (message2.type === "command") {
28601
28629
  message2.output = resultContent;
28602
28630
  message2.status = status;
28603
- const exitCodeMatch = resultContent.match(/exit code:?\s*(\d+)/i);
28604
- if (exitCodeMatch) {
28605
- message2.exitCode = parseInt(exitCodeMatch[1], 10);
28606
- } else {
28607
- message2.exitCode = isError ? 1 : 0;
28608
- }
28631
+ message2.exitCode = result.exitCode ?? (isError ? 1 : 0);
28609
28632
  } else if (message2.type === "patch") {
28610
28633
  message2.status = status;
28611
28634
  } else if (message2.type === "web_search") {
@@ -29050,7 +29073,7 @@ var headlessAgentRequestSchema = external_exports.object({
29050
29073
  });
29051
29074
 
29052
29075
  // ../shared/src/cli-version.ts
29053
- var CLI_VERSION = "0.3.156";
29076
+ var CLI_VERSION = "0.3.158";
29054
29077
 
29055
29078
  // ../shared/src/version.ts
29056
29079
  function compareVersions(v1, v2) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.3.156",
3
+ "version": "0.3.158",
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": {