replicas-cli 0.2.388 → 0.2.390

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 +58 -26
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -22986,7 +22986,7 @@ GitHub does NOT have a public API for uploading images to PRs/issues. When you n
22986
22986
  - Do NOT commit screenshots as files to the repository
22987
22987
  - Run \`replicas media upload <image> --share\` and put the printed \`Forge embed\` Markdown in the PR body or comment
22988
22988
  - For video, embed a shared poster image linked to the recording's **View in Replicas** URL; GitHub does not reliably render externally hosted video inline
22989
- - Treat the public URL as an opt-in bearer capability and revoke it with \`replicas media revoke <media-id>\` when appropriate
22989
+ - Treat the public URL as an opt-in bearer capability; revoke it with \`replicas media revoke <media-id>\` only when the user asks or the media should stop rendering \u2014 revoking breaks embeds already posted on the PR
22990
22990
  - If you were triggered from Slack, also upload the image to the Slack thread so the user can see it directly
22991
22991
  `;
22992
22992
  var GITHUB_ABILITY = {
@@ -23765,7 +23765,7 @@ GitHub does not reliably render arbitrary external videos as inline players. For
23765
23765
  [![Demo recording](<public-poster-url>)](<recording-dashboard-url>)
23766
23766
  \`\`\`
23767
23767
 
23768
- Public forge shares are bearer capabilities. For private repositories, create one only when the user asked for inline PR media, and revoke it with \`replicas media revoke <media-id>\` when it should stop resolving.
23768
+ Public forge shares are bearer capabilities. For private repositories, create one only when the user asked for inline PR media. Revoke with \`replicas media revoke <media-id>\` **only** when the user asks or the media should intentionally stop rendering \u2014 never as routine post-task cleanup, since revoking breaks every embed already posted on the PR.
23769
23769
 
23770
23770
  Do **not** commit screenshots to the repo, use placeholder URLs, expose the authenticated \`/v1/media/<id>\` URL, or automate GitHub's undocumented browser upload flow.
23771
23771
 
@@ -24378,7 +24378,7 @@ var HOOK_EXEC_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
24378
24378
  var REPLICAS_CONFIG_FILENAMES = ["replicas.json", "replicas.yaml", "replicas.yml"];
24379
24379
 
24380
24380
  // ../shared/src/cli-version.ts
24381
- var CLI_VERSION = "0.2.388";
24381
+ var CLI_VERSION = "0.2.390";
24382
24382
 
24383
24383
  // ../shared/src/version.ts
24384
24384
  function compareVersions(v1, v2) {
@@ -24405,6 +24405,14 @@ var DESKTOP_VIEWER_HEIGHT = 1080;
24405
24405
 
24406
24406
  // ../shared/src/engine/v1.ts
24407
24407
  var MERGED_MESSAGE_SEPARATOR = "\n\n<!-- replicas:merged -->\n\n";
24408
+ var createChatRequestSchema = external_exports.object({
24409
+ id: external_exports.string().uuid().optional(),
24410
+ createdAt: external_exports.string().datetime().optional(),
24411
+ provider: external_exports.enum(VALID_AGENT_PROVIDERS),
24412
+ title: external_exports.string().min(1).optional(),
24413
+ parentChatId: external_exports.string().uuid().optional(),
24414
+ clientRequestId: external_exports.string().min(1).max(128).optional()
24415
+ });
24408
24416
  function normalizeCodexAspTranscriptStatus(status, failed = false) {
24409
24417
  if (failed || status === "failed" || status === "declined") return "failed";
24410
24418
  if (status === "completed") return "completed";
@@ -24647,6 +24655,22 @@ function safeJsonParse(str, fallback) {
24647
24655
  }
24648
24656
  }
24649
24657
 
24658
+ // ../shared/src/display-message/parsers/utils.ts
24659
+ function userMessageImages(value) {
24660
+ if (!Array.isArray(value)) return void 0;
24661
+ const images = value.filter((item) => isRecord(item) && item.type === "image" && typeof item.mediaType === "string" && typeof item.data === "string");
24662
+ return images.length > 0 ? images : void 0;
24663
+ }
24664
+ function stringifyDisplayValue(value) {
24665
+ if (value === void 0 || value === null) return void 0;
24666
+ if (typeof value === "string") return value;
24667
+ try {
24668
+ return JSON.stringify(value, null, 2);
24669
+ } catch {
24670
+ return String(value);
24671
+ }
24672
+ }
24673
+
24650
24674
  // ../shared/src/display-message/parsers/codex-parser.ts
24651
24675
  function getStatusFromExitCode(exitCode) {
24652
24676
  return exitCode === 0 ? "completed" : "failed";
@@ -24659,14 +24683,6 @@ function displayId(event, eventIndex, prefix) {
24659
24683
  const stableId = getPayloadString(event, USER_MESSAGE_ID_PAYLOAD_KEY) ?? getPayloadString(event, CODEX_ASP_ITEM_ID_PAYLOAD_KEY);
24660
24684
  return stableId ? `${prefix}-${stableId}` : `${prefix}-${event.timestamp}-${eventIndex}`;
24661
24685
  }
24662
- function userMessageImages(value) {
24663
- if (!Array.isArray(value)) return void 0;
24664
- const images = value.filter((item) => {
24665
- if (!isRecord(item)) return false;
24666
- return item.type === "image" && typeof item.mediaType === "string" && typeof item.data === "string";
24667
- });
24668
- return images.length > 0 ? images : void 0;
24669
- }
24670
24686
  function parseShellOutput(raw) {
24671
24687
  const exitCodeMatch = raw.match(/^Exit code: (\d+)/m) || raw.match(/Process exited with code (\d+)/);
24672
24688
  const exitCode = exitCodeMatch ? parseInt(exitCodeMatch[1], 10) : 0;
@@ -24890,17 +24906,6 @@ function parseCodexEvents(events) {
24890
24906
  return messages;
24891
24907
  }
24892
24908
 
24893
- // ../shared/src/display-message/parsers/utils.ts
24894
- function stringifyDisplayValue(value) {
24895
- if (value === void 0 || value === null) return void 0;
24896
- if (typeof value === "string") return value;
24897
- try {
24898
- return JSON.stringify(value, null, 2);
24899
- } catch {
24900
- return String(value);
24901
- }
24902
- }
24903
-
24904
24909
  // ../shared/src/display-message/parsers/cursor-parser.ts
24905
24910
  function getTextContent(value) {
24906
24911
  if (!Array.isArray(value)) return "";
@@ -25463,6 +25468,7 @@ function parseClaudeEvents(events, parentToolUseId) {
25463
25468
  let liveStreamId = null;
25464
25469
  const assistantThinking = /* @__PURE__ */ new Map();
25465
25470
  const assistantTextCounts = /* @__PURE__ */ new Map();
25471
+ const acceptedUserMessageIndexes = /* @__PURE__ */ new Set();
25466
25472
  const taskAccumulator = new TaskAccumulator();
25467
25473
  const taskSnapshot = () => taskAccumulator.getTasks().map((task) => ({
25468
25474
  text: task.subject,
@@ -25470,6 +25476,21 @@ function parseClaudeEvents(events, parentToolUseId) {
25470
25476
  itemStatus: task.status
25471
25477
  }));
25472
25478
  filteredEvents.forEach((event) => {
25479
+ if (event.type === "event_msg" && event.payload.type === "user_message") {
25480
+ const content = typeof event.payload.message === "string" ? event.payload.message : "";
25481
+ const images = userMessageImages(event.payload.images);
25482
+ if (content || images) {
25483
+ const messageId = event.payload[USER_MESSAGE_ID_PAYLOAD_KEY];
25484
+ acceptedUserMessageIndexes.add(messages.push({
25485
+ id: typeof messageId === "string" ? messageId : `user-${event.timestamp}`,
25486
+ type: "user",
25487
+ content,
25488
+ images,
25489
+ timestamp: event.timestamp
25490
+ }) - 1);
25491
+ }
25492
+ return;
25493
+ }
25473
25494
  if (event.type === CLAUDE_PARTIAL_MESSAGE_EVENT_TYPE) {
25474
25495
  const payload = coerceClaudePartialMessagePayload(event.payload);
25475
25496
  if (!payload) return;
@@ -25527,13 +25548,24 @@ function parseClaudeEvents(events, parentToolUseId) {
25527
25548
  };
25528
25549
  }).filter((img) => img.data);
25529
25550
  if (textContent || images.length > 0) {
25530
- messages.push({
25531
- id: `user-${event.timestamp}`,
25551
+ const acceptedIndex = [...acceptedUserMessageIndexes].find((index) => {
25552
+ const accepted2 = messages[index];
25553
+ return accepted2?.type === "user" && accepted2.content === textContent;
25554
+ });
25555
+ const accepted = acceptedIndex === void 0 ? void 0 : messages[acceptedIndex];
25556
+ const message = {
25557
+ id: accepted?.id ?? `user-${event.timestamp}`,
25532
25558
  type: "user",
25533
25559
  content: textContent || (images.length > 0 ? `[${images.length} image${images.length > 1 ? "s" : ""} attached]` : ""),
25534
- images: images.length > 0 ? images : void 0,
25560
+ images: images.length > 0 ? images : accepted?.type === "user" ? accepted.images : void 0,
25535
25561
  timestamp: event.timestamp
25536
- });
25562
+ };
25563
+ if (acceptedIndex === void 0) {
25564
+ messages.push(message);
25565
+ } else {
25566
+ messages[acceptedIndex] = message;
25567
+ acceptedUserMessageIndexes.delete(acceptedIndex);
25568
+ }
25537
25569
  }
25538
25570
  }
25539
25571
  if (event.type === "claude-assistant") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.2.388",
3
+ "version": "0.2.390",
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": {