replicas-cli 0.2.189 → 0.2.191

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.mjs +40 -16
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -8001,6 +8001,8 @@ function getProviderDisplayName(provider) {
8001
8001
  }
8002
8002
 
8003
8003
  // ../shared/src/event.ts
8004
+ var USER_MESSAGE_ID_PAYLOAD_KEY = "replicasMessageId";
8005
+ var CODEX_ASP_ITEM_ID_PAYLOAD_KEY = "codexAspItemId";
8004
8006
  var CODEX_QUOTA_STATUS_EVENT_TYPE = "codex-quota-status";
8005
8007
 
8006
8008
  // ../shared/src/pricing.ts
@@ -8492,8 +8494,8 @@ gh pr review 123 --request-changes --body "Changes needed"
8492
8494
  GitHub does NOT have a public API for uploading images to PRs/issues. When you need to include images:
8493
8495
  - Do NOT use placeholder image URLs
8494
8496
  - Do NOT commit screenshots as files to the repository
8495
- - Upload images to Imgur (or another external host) and use the returned URLs in your PR markdown
8496
- - If you were triggered from Slack, also upload the images to the Slack thread so the user can see them directly
8497
+ - Use the \`replicas-agent\` skill to share the image
8498
+ - If you were triggered from Slack, also upload the image to the Slack thread so the user can see it directly
8497
8499
  `;
8498
8500
  var GITHUB_ABILITY = {
8499
8501
  label: "GitHub",
@@ -8941,10 +8943,9 @@ After (or alongside) the embeds, include a \`[View in Replicas](<deep-link>)\` h
8941
8943
 
8942
8944
  ### On external platforms (Slack, Linear, GitHub, etc.)
8943
8945
 
8944
- Do **both** of these \u2014 neither alone is sufficient:
8946
+ Always include a \`[View in Replicas](<deep-link>)\` hyperlink \u2014 use the per-file deep link the CLI printed for that file (\`...?mode=media&media=<media-id>\`), so the recipient lands directly on that specific item.
8945
8947
 
8946
- 1. Upload the raw bytes via that platform's own upload API (Slack \`files.upload\`, Linear attachments, Imgur for GitHub PR/issue images, etc.) so the recipient actually sees the media.
8947
- 2. Include a \`[View in Replicas](<deep-link>)\` hyperlink \u2014 use the per-file deep link the CLI printed for that file (\`...?mode=media&media=<media-id>\`), so the recipient lands directly on that specific item.
8948
+ For platforms that support native uploads (Slack \`files.upload\`, Linear attachments, etc.), upload the raw bytes there too so the recipient sees the media inline in addition to the Replicas link. GitHub PRs/issues do not have a public upload API, so the \`View in Replicas\` link is the canonical way to share media there \u2014 do not commit screenshots to the repo and do not use placeholder URLs.
8948
8949
 
8949
8950
  Do **not** include the \`![filename](https://api.tryreplicas.com/...)\` markdown embed in external messages. It will render as a broken image / 401 for the recipient.
8950
8951
 
@@ -8990,7 +8991,7 @@ replicas media upload chart-a.svg chart-b.svg --kind image
8990
8991
  var MEDIA_ABILITY = {
8991
8992
  label: "Media",
8992
8993
  description: "Share screenshots, recordings, generated images, and audio clips.",
8993
- bullet: "- Sharing media (screenshots, screen recordings, generated diagrams, audio clips) \u2014 including in your Replicas chat reply and to external platforms",
8994
+ bullet: "- Producing or showing the user any media \u2014 screenshots, screen recordings, generated images or diagrams, audio clips \u2014 including in your Replicas chat reply, PR descriptions/comments, and other external platforms",
8994
8995
  section: SECTION6,
8995
8996
  referenceFile: { name: "MEDIA.md", content: REFERENCE6 }
8996
8997
  };
@@ -9603,6 +9604,14 @@ function safeJsonParse(str, fallback) {
9603
9604
  function getStatusFromExitCode(exitCode) {
9604
9605
  return exitCode === 0 ? "completed" : "failed";
9605
9606
  }
9607
+ function getPayloadString(event, key) {
9608
+ const value = event.payload?.[key];
9609
+ return typeof value === "string" ? value : null;
9610
+ }
9611
+ function displayId(event, eventIndex, prefix) {
9612
+ const stableId = getPayloadString(event, USER_MESSAGE_ID_PAYLOAD_KEY) ?? getPayloadString(event, CODEX_ASP_ITEM_ID_PAYLOAD_KEY);
9613
+ return stableId ? `${prefix}-${stableId}` : `${prefix}-${event.timestamp}-${eventIndex}`;
9614
+ }
9606
9615
  function parseShellOutput(raw) {
9607
9616
  const exitCodeMatch = raw.match(/^Exit code: (\d+)/m) || raw.match(/Process exited with code (\d+)/);
9608
9617
  const exitCode = exitCodeMatch ? parseInt(exitCodeMatch[1], 10) : 0;
@@ -9666,6 +9675,7 @@ function parsePatch(input) {
9666
9675
  function parseCodexEvents(events) {
9667
9676
  const messages = [];
9668
9677
  const pendingCommands = /* @__PURE__ */ new Map();
9678
+ const pendingToolCalls = /* @__PURE__ */ new Map();
9669
9679
  const pendingPatches = /* @__PURE__ */ new Map();
9670
9680
  events.forEach((event, eventIndex) => {
9671
9681
  if (event.type === CODEX_QUOTA_STATUS_EVENT_TYPE) {
@@ -9686,7 +9696,7 @@ function parseCodexEvents(events) {
9686
9696
  }
9687
9697
  if (event.type === "event_msg" && event.payload?.type === "user_message") {
9688
9698
  messages.push({
9689
- id: `user-${event.timestamp}-${eventIndex}`,
9699
+ id: displayId(event, eventIndex, "user"),
9690
9700
  type: "user",
9691
9701
  content: event.payload.message || "",
9692
9702
  timestamp: event.timestamp
@@ -9694,7 +9704,7 @@ function parseCodexEvents(events) {
9694
9704
  }
9695
9705
  if (event.type === "event_msg" && event.payload?.type === "agent_reasoning") {
9696
9706
  messages.push({
9697
- id: `reasoning-${event.timestamp}-${eventIndex}-${messages.length}`,
9707
+ id: displayId(event, eventIndex, "reasoning"),
9698
9708
  type: "reasoning",
9699
9709
  content: event.payload.text || "",
9700
9710
  status: "completed",
@@ -9708,7 +9718,7 @@ function parseCodexEvents(events) {
9708
9718
  const textContent = content.filter((c) => c.type === "output_text").map((c) => c.text || "").join("\n");
9709
9719
  if (textContent) {
9710
9720
  messages.push({
9711
- id: `agent-${event.timestamp}-${eventIndex}`,
9721
+ id: displayId(event, eventIndex, "agent"),
9712
9722
  type: "agent",
9713
9723
  content: textContent,
9714
9724
  timestamp: event.timestamp
@@ -9748,19 +9758,25 @@ function parseCodexEvents(events) {
9748
9758
  const callId = event.payload.call_id;
9749
9759
  const name = event.payload.name;
9750
9760
  const input = event.payload.input || "";
9761
+ const server = typeof event.payload.server === "string" ? event.payload.server : "custom";
9751
9762
  const status = event.payload.status || "in_progress";
9752
9763
  if (name === "apply_patch") {
9753
9764
  const operations = parsePatch(input);
9754
9765
  pendingPatches.set(callId, { input, status, timestamp: event.timestamp, operations });
9755
9766
  } else {
9756
- messages.push({
9757
- id: `toolcall-${event.timestamp}-${eventIndex}`,
9767
+ const msg = {
9768
+ id: `toolcall-${callId || getPayloadString(event, CODEX_ASP_ITEM_ID_PAYLOAD_KEY) || `${event.timestamp}-${eventIndex}`}`,
9758
9769
  type: "tool_call",
9759
- server: "custom",
9770
+ server,
9760
9771
  tool: name,
9772
+ input,
9761
9773
  status,
9762
9774
  timestamp: event.timestamp
9763
- });
9775
+ };
9776
+ messages.push(msg);
9777
+ if (callId) {
9778
+ pendingToolCalls.set(callId, msg);
9779
+ }
9764
9780
  }
9765
9781
  }
9766
9782
  if (payloadType === "custom_tool_call_output") {
@@ -9782,9 +9798,14 @@ function parseCodexEvents(events) {
9782
9798
  });
9783
9799
  pendingPatches.delete(callId);
9784
9800
  } else {
9785
- const toolCallMsg = messages.findLast((m) => m.type === "tool_call");
9801
+ const fallbackToolCallMsg = messages.findLast((m) => m.type === "tool_call");
9802
+ const toolCallMsg = pendingToolCalls.get(callId) ?? fallbackToolCallMsg;
9786
9803
  if (toolCallMsg) {
9787
9804
  toolCallMsg.status = getStatusFromExitCode(output.metadata?.exit_code);
9805
+ toolCallMsg.output = output.output ?? (typeof event.payload.output === "string" ? event.payload.output : "");
9806
+ if (callId) {
9807
+ pendingToolCalls.delete(callId);
9808
+ }
9788
9809
  }
9789
9810
  }
9790
9811
  }
@@ -10135,6 +10156,9 @@ function parseAgentEvents(events, agentType) {
10135
10156
  }
10136
10157
  return parseClaudeEvents(events);
10137
10158
  }
10159
+ function isCodexInitializationPrompt(message) {
10160
+ return message.type === "user" && removeReplicasInstructions(message.content).trim() === "Hello";
10161
+ }
10138
10162
  function createUserMessage(content) {
10139
10163
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
10140
10164
  return {
@@ -10156,7 +10180,7 @@ function filterDisplayMessages(messages, provider) {
10156
10180
  let result = messages;
10157
10181
  if (provider === "codex") {
10158
10182
  const userMessages = result.map((msg, index) => ({ msg, index })).filter(({ msg }) => msg.type === "user");
10159
- if (userMessages.length >= 2) {
10183
+ if (userMessages.length >= 2 && isCodexInitializationPrompt(userMessages[0].msg)) {
10160
10184
  result = result.slice(userMessages[1].index);
10161
10185
  }
10162
10186
  }
@@ -16577,7 +16601,7 @@ Deleted file ${pathOrId}.
16577
16601
  }
16578
16602
 
16579
16603
  // src/index.ts
16580
- var CLI_VERSION = "0.2.189";
16604
+ var CLI_VERSION = "0.2.191";
16581
16605
  function parseBooleanOption(value) {
16582
16606
  if (value === "true") return true;
16583
16607
  if (value === "false") return false;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.2.189",
3
+ "version": "0.2.191",
4
4
  "description": "CLI for managing Replicas workspaces - SSH into cloud dev environments with automatic port forwarding",
5
5
  "main": "dist/index.mjs",
6
6
  "bin": {