replicas-cli 0.3.218 → 0.3.219

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 +55 -21
  2. package/package.json +1 -1
package/dist/index.cjs CHANGED
@@ -29942,6 +29942,33 @@ function readClaudeUserPrompt(payload, content) {
29942
29942
  }
29943
29943
  function parseClaudeEvents(events, parentToolUseId) {
29944
29944
  const messages = [];
29945
+ const indexesById = /* @__PURE__ */ new Map();
29946
+ let indexedCount = 0;
29947
+ const indexesOf = (id) => {
29948
+ for (; indexedCount < messages.length; indexedCount++) {
29949
+ const indexes = indexesById.get(messages[indexedCount].id);
29950
+ if (indexes) indexes.push(indexedCount);
29951
+ else indexesById.set(messages[indexedCount].id, [indexedCount]);
29952
+ }
29953
+ return indexesById.get(id) ?? [];
29954
+ };
29955
+ const replaceMessage = (index, message2) => {
29956
+ const previousId = messages[index].id;
29957
+ messages[index] = message2;
29958
+ if (index >= indexedCount || previousId === message2.id) return;
29959
+ const previous = indexesById.get(previousId);
29960
+ if (!previous) throw new Error(`Chat message ${previousId} is missing from the id index`);
29961
+ previous.splice(previous.indexOf(index), 1);
29962
+ const next = indexesById.get(message2.id);
29963
+ if (!next) indexesById.set(message2.id, [index]);
29964
+ else next.splice(next.filter((other) => other < index).length, 0, index);
29965
+ };
29966
+ const upsertMessage = (message2) => {
29967
+ const [index] = indexesOf(message2.id);
29968
+ if (index === void 0) messages.push(message2);
29969
+ else replaceMessage(index, message2);
29970
+ return message2;
29971
+ };
29945
29972
  const filterValue = parentToolUseId !== void 0 ? parentToolUseId : null;
29946
29973
  const filteredEvents = events.filter((e) => {
29947
29974
  const eventParentToolUseId = e.payload.parent_tool_use_id ?? null;
@@ -29972,13 +29999,14 @@ function parseClaudeEvents(events, parentToolUseId) {
29972
29999
  const stampedUserMessages = /* @__PURE__ */ new Set();
29973
30000
  const findMatchingUserMessageIndex = (indexes, content, timestamp, messageId) => {
29974
30001
  if (typeof messageId === "string") {
29975
- const byId = messages.findIndex((message2, index) => message2.type === "user" && message2.id === messageId && !supersededUserMessageIndexes.has(index));
29976
- if (byId !== -1) return byId;
30002
+ const byId = indexesOf(messageId).find((index) => messages[index].type === "user" && !supersededUserMessageIndexes.has(index));
30003
+ if (byId !== void 0) return byId;
29977
30004
  }
29978
- return [...indexes].find((index) => {
30005
+ for (const index of indexes) {
29979
30006
  const message2 = messages[index];
29980
- return message2?.type === "user" && !(typeof messageId === "string" && stampedUserMessages.has(message2)) && areUserMessagesWithinMatchWindow(message2, { content, timestamp });
29981
- });
30007
+ if (message2?.type === "user" && !(typeof messageId === "string" && stampedUserMessages.has(message2)) && areUserMessagesWithinMatchWindow(message2, { content, timestamp })) return index;
30008
+ }
30009
+ return void 0;
29982
30010
  };
29983
30011
  const taskAccumulator = new TaskAccumulator();
29984
30012
  let nestedEventsByParent;
@@ -30007,7 +30035,7 @@ function parseClaudeEvents(events, parentToolUseId) {
30007
30035
  if (canonicalIndex === void 0) {
30008
30036
  acceptedUserMessageIndexes.add(messages.push(message2) - 1);
30009
30037
  } else {
30010
- messages[canonicalIndex] = message2;
30038
+ replaceMessage(canonicalIndex, message2);
30011
30039
  canonicalUserMessageIndexes.delete(canonicalIndex);
30012
30040
  }
30013
30041
  if (typeof messageId === "string" || canonical && stampedUserMessages.has(canonical)) stampedUserMessages.add(message2);
@@ -30031,7 +30059,7 @@ function parseClaudeEvents(events, parentToolUseId) {
30031
30059
  status: payload.status,
30032
30060
  timestamp: event.timestamp
30033
30061
  };
30034
- if (existing.reasoning !== void 0) messages[existing.reasoning] = reasoningMessage;
30062
+ if (existing.reasoning !== void 0) replaceMessage(existing.reasoning, reasoningMessage);
30035
30063
  else existing.reasoning = messages.push(reasoningMessage) - 1;
30036
30064
  }
30037
30065
  if (payload.text && !completedStreamIds.has(payload.streamId)) {
@@ -30041,7 +30069,7 @@ function parseClaudeEvents(events, parentToolUseId) {
30041
30069
  content: payload.text,
30042
30070
  timestamp: event.timestamp
30043
30071
  };
30044
- if (existing.agent !== void 0) messages[existing.agent] = agentMessage;
30072
+ if (existing.agent !== void 0) replaceMessage(existing.agent, agentMessage);
30045
30073
  else existing.agent = messages.push(agentMessage) - 1;
30046
30074
  }
30047
30075
  if (payload.tool) streamingTools.set(payload.streamId, { tool: payload.tool, timestamp: event.timestamp });
@@ -30098,7 +30126,7 @@ function parseClaudeEvents(events, parentToolUseId) {
30098
30126
  acceptedUserMessageIndexes.delete(acceptedIndex);
30099
30127
  canonicalUserMessageIndexes.add(messages.push(message2) - 1);
30100
30128
  } else {
30101
- messages[acceptedIndex] = message2;
30129
+ replaceMessage(acceptedIndex, message2);
30102
30130
  }
30103
30131
  if (typeof stampedId === "string" || accepted && stampedUserMessages.has(accepted)) stampedUserMessages.add(message2);
30104
30132
  }
@@ -30110,7 +30138,7 @@ function parseClaudeEvents(events, parentToolUseId) {
30110
30138
  const localCommand = event.payload.local_command_run;
30111
30139
  const goalArgs = isRecord(localCommand) && localCommand.command === GOAL_TOOL_NAME && typeof localCommand.args === "string" ? localCommand.args.trim() : "";
30112
30140
  if (goalArgs) {
30113
- upsertDisplayMessage(messages, {
30141
+ upsertMessage({
30114
30142
  id: `goal-${messageKey}`,
30115
30143
  type: "tool_call",
30116
30144
  server: "claude",
@@ -30146,10 +30174,10 @@ function parseClaudeEvents(events, parentToolUseId) {
30146
30174
  timestamp: event.timestamp
30147
30175
  };
30148
30176
  if (streamRefs?.reasoning !== void 0) {
30149
- messages[streamRefs.reasoning] = reasoningMessage;
30177
+ replaceMessage(streamRefs.reasoning, reasoningMessage);
30150
30178
  streamRefs.reasoning = void 0;
30151
30179
  } else {
30152
- upsertDisplayMessage(messages, reasoningMessage);
30180
+ upsertMessage(reasoningMessage);
30153
30181
  }
30154
30182
  }
30155
30183
  contentBlocks.forEach((block) => {
@@ -30163,10 +30191,10 @@ function parseClaudeEvents(events, parentToolUseId) {
30163
30191
  timestamp: event.timestamp
30164
30192
  };
30165
30193
  if (streamRefs?.agent !== void 0) {
30166
- messages[streamRefs.agent] = agentMessage;
30194
+ replaceMessage(streamRefs.agent, agentMessage);
30167
30195
  streamRefs.agent = void 0;
30168
30196
  } else {
30169
- upsertDisplayMessage(messages, agentMessage);
30197
+ upsertMessage(agentMessage);
30170
30198
  }
30171
30199
  }
30172
30200
  if (block.type === "tool_use" && block.id) {
@@ -30260,7 +30288,7 @@ function parseClaudeEvents(events, parentToolUseId) {
30260
30288
  if (event.type === "claude-result") {
30261
30289
  const payload = coerceClaudeResultPayload(event.payload);
30262
30290
  const last = messages.at(-1);
30263
- if (last?.type === "agent") messages[messages.length - 1] = { ...last, endsTurn: true };
30291
+ if (last?.type === "agent") replaceMessage(messages.length - 1, { ...last, endsTurn: true });
30264
30292
  if (isClaudeResultError(payload)) {
30265
30293
  const genuineErrors = stripAgentDiagnosticErrors(payload.errors ?? []);
30266
30294
  messages.push({
@@ -30303,7 +30331,7 @@ function parseClaudeEvents(events, parentToolUseId) {
30303
30331
  nestedEvents: existingWorkflowAgent?.nestedEvents ?? collectNestedEvents(workflowAgent.agentId)
30304
30332
  }
30305
30333
  );
30306
- workflowAgentMessageMap.set(workflowAgent.agentId, upsertDisplayMessage(messages, nextWorkflowAgent));
30334
+ workflowAgentMessageMap.set(workflowAgent.agentId, upsertMessage(nextWorkflowAgent));
30307
30335
  }
30308
30336
  const existing = taskMessageMap.get(payload.taskId);
30309
30337
  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";
@@ -30327,7 +30355,7 @@ function parseClaudeEvents(events, parentToolUseId) {
30327
30355
  notifiedAt: payload.subtype === "task_notification" ? event.timestamp : existing?.notifiedAt,
30328
30356
  timestamp: existing?.timestamp ?? event.timestamp
30329
30357
  };
30330
- taskMessageMap.set(payload.taskId, upsertDisplayMessage(messages, nextMessage));
30358
+ taskMessageMap.set(payload.taskId, upsertMessage(nextMessage));
30331
30359
  }
30332
30360
  }
30333
30361
  });
@@ -30396,7 +30424,7 @@ function parseClaudeEvents(events, parentToolUseId) {
30396
30424
  message2.outputOmitted = outputOmitted;
30397
30425
  message2.status = status;
30398
30426
  } else if (message2.type === "skill" && isError && message2.path) {
30399
- messages[toolInfo.messageIndex] = { id: message2.id, type: "tool_call", server: "claude", tool: toolInfo.toolName, input: toolInfo.input, output: resultContent, outputOmitted, status, timestamp: message2.timestamp };
30427
+ replaceMessage(toolInfo.messageIndex, { id: message2.id, type: "tool_call", server: "claude", tool: toolInfo.toolName, input: toolInfo.input, output: resultContent, outputOmitted, status, timestamp: message2.timestamp });
30400
30428
  } else if (message2.type === "skill") {
30401
30429
  message2.status = status;
30402
30430
  } else if (message2.type === "subagent") {
@@ -30470,9 +30498,15 @@ function parseDisplayMessages(events, agentType, options = {}) {
30470
30498
  return withoutReplacedMessages(excludeQueuedAcceptedEvents(events, []), (segment) => {
30471
30499
  const parsedEvents = parseProviderEvents(segment, agentType, options.parentToolUseId);
30472
30500
  const reconciledEvents = [];
30501
+ const firstIndexById = /* @__PURE__ */ new Map();
30473
30502
  for (const message2 of parsedEvents) {
30474
- if (message2.type === "user") upsertDisplayMessage(reconciledEvents, message2);
30475
- else reconciledEvents.push(message2);
30503
+ const index = message2.type === "user" ? firstIndexById.get(message2.id) : void 0;
30504
+ if (index !== void 0) {
30505
+ reconciledEvents[index] = message2;
30506
+ continue;
30507
+ }
30508
+ if (!firstIndexById.has(message2.id)) firstIndexById.set(message2.id, reconciledEvents.length);
30509
+ reconciledEvents.push(message2);
30476
30510
  }
30477
30511
  if (options.filter === false) return reconciledEvents;
30478
30512
  return applyEngineNotices(
@@ -31326,7 +31360,7 @@ var CLI_VERSION;
31326
31360
  var init_cli_version = __esm({
31327
31361
  "../shared/src/cli-version.ts"() {
31328
31362
  "use strict";
31329
- CLI_VERSION = "0.3.212";
31363
+ CLI_VERSION = "0.3.219";
31330
31364
  }
31331
31365
  });
31332
31366
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.3.218",
3
+ "version": "0.3.219",
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": {