replicas-cli 0.2.276 → 0.2.278

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 +270 -35
  2. package/package.json +1 -1
package/dist/index.mjs CHANGED
@@ -1473,7 +1473,7 @@ var require_stringify = __commonJS({
1473
1473
  props.push(doc.directives.tagString(tag));
1474
1474
  return props.join(" ");
1475
1475
  }
1476
- function stringify(item, ctx, onComment, onChompKeep) {
1476
+ function stringify2(item, ctx, onComment, onChompKeep) {
1477
1477
  if (identity.isPair(item))
1478
1478
  return item.toString(ctx, onComment, onChompKeep);
1479
1479
  if (identity.isAlias(item)) {
@@ -1502,7 +1502,7 @@ var require_stringify = __commonJS({
1502
1502
  ${ctx.indent}${str}`;
1503
1503
  }
1504
1504
  exports.createStringifyContext = createStringifyContext;
1505
- exports.stringify = stringify;
1505
+ exports.stringify = stringify2;
1506
1506
  }
1507
1507
  });
1508
1508
 
@@ -1512,7 +1512,7 @@ var require_stringifyPair = __commonJS({
1512
1512
  "use strict";
1513
1513
  var identity = require_identity();
1514
1514
  var Scalar = require_Scalar();
1515
- var stringify = require_stringify();
1515
+ var stringify2 = require_stringify();
1516
1516
  var stringifyComment = require_stringifyComment();
1517
1517
  function stringifyPair({ key, value }, ctx, onComment, onChompKeep) {
1518
1518
  const { allNullValues, doc, indent, indentStep, options: { commentString, indentSeq, simpleKeys } } = ctx;
@@ -1534,7 +1534,7 @@ var require_stringifyPair = __commonJS({
1534
1534
  });
1535
1535
  let keyCommentDone = false;
1536
1536
  let chompKeep = false;
1537
- let str = stringify.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
1537
+ let str = stringify2.stringify(key, ctx, () => keyCommentDone = true, () => chompKeep = true);
1538
1538
  if (!explicitKey && !ctx.inFlow && str.length > 1024) {
1539
1539
  if (simpleKeys)
1540
1540
  throw new Error("With simple keys, single line scalar must not span more than 1024 characters");
@@ -1586,7 +1586,7 @@ ${indent}:`;
1586
1586
  ctx.indent = ctx.indent.substring(2);
1587
1587
  }
1588
1588
  let valueCommentDone = false;
1589
- const valueStr = stringify.stringify(value, ctx, () => valueCommentDone = true, () => chompKeep = true);
1589
+ const valueStr = stringify2.stringify(value, ctx, () => valueCommentDone = true, () => chompKeep = true);
1590
1590
  let ws = " ";
1591
1591
  if (keyComment || vsb || vcb) {
1592
1592
  ws = vsb ? "\n" : "";
@@ -1727,7 +1727,7 @@ var require_addPairToJSMap = __commonJS({
1727
1727
  "use strict";
1728
1728
  var log = require_log();
1729
1729
  var merge = require_merge();
1730
- var stringify = require_stringify();
1730
+ var stringify2 = require_stringify();
1731
1731
  var identity = require_identity();
1732
1732
  var toJS = require_toJS();
1733
1733
  function addPairToJSMap(ctx, map, { key, value }) {
@@ -1763,7 +1763,7 @@ var require_addPairToJSMap = __commonJS({
1763
1763
  if (typeof jsKey !== "object")
1764
1764
  return String(jsKey);
1765
1765
  if (identity.isNode(key) && ctx?.doc) {
1766
- const strCtx = stringify.createStringifyContext(ctx.doc, {});
1766
+ const strCtx = stringify2.createStringifyContext(ctx.doc, {});
1767
1767
  strCtx.anchors = /* @__PURE__ */ new Set();
1768
1768
  for (const node of ctx.anchors.keys())
1769
1769
  strCtx.anchors.add(node.anchor);
@@ -1830,12 +1830,12 @@ var require_stringifyCollection = __commonJS({
1830
1830
  "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyCollection.js"(exports) {
1831
1831
  "use strict";
1832
1832
  var identity = require_identity();
1833
- var stringify = require_stringify();
1833
+ var stringify2 = require_stringify();
1834
1834
  var stringifyComment = require_stringifyComment();
1835
1835
  function stringifyCollection(collection, ctx, options) {
1836
1836
  const flow = ctx.inFlow ?? collection.flow;
1837
- const stringify2 = flow ? stringifyFlowCollection : stringifyBlockCollection;
1838
- return stringify2(collection, ctx, options);
1837
+ const stringify3 = flow ? stringifyFlowCollection : stringifyBlockCollection;
1838
+ return stringify3(collection, ctx, options);
1839
1839
  }
1840
1840
  function stringifyBlockCollection({ comment, items }, ctx, { blockItemPrefix, flowChars, itemIndent, onChompKeep, onComment }) {
1841
1841
  const { indent, options: { commentString } } = ctx;
@@ -1860,7 +1860,7 @@ var require_stringifyCollection = __commonJS({
1860
1860
  }
1861
1861
  }
1862
1862
  chompKeep = false;
1863
- let str2 = stringify.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
1863
+ let str2 = stringify2.stringify(item, itemCtx, () => comment2 = null, () => chompKeep = true);
1864
1864
  if (comment2)
1865
1865
  str2 += stringifyComment.lineComment(str2, itemIndent, commentString(comment2));
1866
1866
  if (chompKeep && comment2)
@@ -1927,7 +1927,7 @@ ${indent}${line}` : "\n";
1927
1927
  }
1928
1928
  if (comment)
1929
1929
  reqNewline = true;
1930
- let str = stringify.stringify(item, itemCtx, () => comment = null);
1930
+ let str = stringify2.stringify(item, itemCtx, () => comment = null);
1931
1931
  reqNewline || (reqNewline = lines.length > linesAtValue || str.includes("\n"));
1932
1932
  if (i < items.length - 1) {
1933
1933
  str += ",";
@@ -3288,7 +3288,7 @@ var require_stringifyDocument = __commonJS({
3288
3288
  "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/stringify/stringifyDocument.js"(exports) {
3289
3289
  "use strict";
3290
3290
  var identity = require_identity();
3291
- var stringify = require_stringify();
3291
+ var stringify2 = require_stringify();
3292
3292
  var stringifyComment = require_stringifyComment();
3293
3293
  function stringifyDocument(doc, options) {
3294
3294
  const lines = [];
@@ -3303,7 +3303,7 @@ var require_stringifyDocument = __commonJS({
3303
3303
  }
3304
3304
  if (hasDirectives)
3305
3305
  lines.push("---");
3306
- const ctx = stringify.createStringifyContext(doc, options);
3306
+ const ctx = stringify2.createStringifyContext(doc, options);
3307
3307
  const { commentString } = ctx.options;
3308
3308
  if (doc.commentBefore) {
3309
3309
  if (lines.length !== 1)
@@ -3325,7 +3325,7 @@ var require_stringifyDocument = __commonJS({
3325
3325
  contentComment = doc.contents.comment;
3326
3326
  }
3327
3327
  const onChompKeep = contentComment ? void 0 : () => chompKeep = true;
3328
- let body = stringify.stringify(doc.contents, ctx, () => contentComment = null, onChompKeep);
3328
+ let body = stringify2.stringify(doc.contents, ctx, () => contentComment = null, onChompKeep);
3329
3329
  if (contentComment)
3330
3330
  body += stringifyComment.lineComment(body, "", commentString(contentComment));
3331
3331
  if ((body[0] === "|" || body[0] === ">") && lines[lines.length - 1] === "---") {
@@ -3333,7 +3333,7 @@ var require_stringifyDocument = __commonJS({
3333
3333
  } else
3334
3334
  lines.push(body);
3335
3335
  } else {
3336
- lines.push(stringify.stringify(doc.contents, ctx));
3336
+ lines.push(stringify2.stringify(doc.contents, ctx));
3337
3337
  }
3338
3338
  if (doc.directives?.docEnd) {
3339
3339
  if (doc.comment) {
@@ -5468,7 +5468,7 @@ var require_cst_scalar = __commonJS({
5468
5468
  var require_cst_stringify = __commonJS({
5469
5469
  "../node_modules/.bun/yaml@2.9.0/node_modules/yaml/dist/parse/cst-stringify.js"(exports) {
5470
5470
  "use strict";
5471
- var stringify = (cst) => "type" in cst ? stringifyToken(cst) : stringifyItem(cst);
5471
+ var stringify2 = (cst) => "type" in cst ? stringifyToken(cst) : stringifyItem(cst);
5472
5472
  function stringifyToken(token) {
5473
5473
  switch (token.type) {
5474
5474
  case "block-scalar": {
@@ -5521,7 +5521,7 @@ var require_cst_stringify = __commonJS({
5521
5521
  res += stringifyToken(value);
5522
5522
  return res;
5523
5523
  }
5524
- exports.stringify = stringify;
5524
+ exports.stringify = stringify2;
5525
5525
  }
5526
5526
  });
5527
5527
 
@@ -7251,7 +7251,7 @@ var require_public_api = __commonJS({
7251
7251
  }
7252
7252
  return doc.toJS(Object.assign({ reviver: _reviver }, options));
7253
7253
  }
7254
- function stringify(value, replacer, options) {
7254
+ function stringify2(value, replacer, options) {
7255
7255
  let _replacer = null;
7256
7256
  if (typeof replacer === "function" || Array.isArray(replacer)) {
7257
7257
  _replacer = replacer;
@@ -7276,7 +7276,7 @@ var require_public_api = __commonJS({
7276
7276
  exports.parse = parse;
7277
7277
  exports.parseAllDocuments = parseAllDocuments;
7278
7278
  exports.parseDocument = parseDocument;
7279
- exports.stringify = stringify;
7279
+ exports.stringify = stringify2;
7280
7280
  }
7281
7281
  });
7282
7282
 
@@ -7555,7 +7555,7 @@ function createErrorResult(error) {
7555
7555
  }
7556
7556
 
7557
7557
  // ../shared/src/agent.ts
7558
- var VALID_AGENT_PROVIDERS = ["claude", "codex", "relay"];
7558
+ var VALID_AGENT_PROVIDERS = ["claude", "codex", "cursor", "relay"];
7559
7559
  function isValidAgentProvider(value) {
7560
7560
  return VALID_AGENT_PROVIDERS.some((p) => p === value);
7561
7561
  }
@@ -7567,6 +7567,8 @@ function getProviderDisplayName(provider) {
7567
7567
  switch (provider) {
7568
7568
  case "codex":
7569
7569
  return "Codex";
7570
+ case "cursor":
7571
+ return "Cursor";
7570
7572
  case "relay":
7571
7573
  return "Relay";
7572
7574
  case "claude":
@@ -9236,7 +9238,7 @@ var HOOK_EXEC_MAX_BUFFER_BYTES = 10 * 1024 * 1024;
9236
9238
  var REPLICAS_CONFIG_FILENAMES = ["replicas.json", "replicas.yaml", "replicas.yml"];
9237
9239
 
9238
9240
  // ../shared/src/cli-version.ts
9239
- var CLI_VERSION = "0.2.276";
9241
+ var CLI_VERSION = "0.2.278";
9240
9242
 
9241
9243
  // ../shared/src/engine/environment.ts
9242
9244
  var DESKTOP_NOVNC_PORT = 6080;
@@ -9252,6 +9254,7 @@ var DESKTOP_VIEWER_HEIGHT = 1080;
9252
9254
  var DEFAULT_CHAT_TITLES = {
9253
9255
  claude: "Claude Code",
9254
9256
  codex: "Codex",
9257
+ cursor: "Cursor",
9255
9258
  relay: "Relay"
9256
9259
  };
9257
9260
  function getInitialChatId(chats, preferredProvider = "claude") {
@@ -9266,6 +9269,7 @@ function getInitialChatId(chats, preferredProvider = "claude") {
9266
9269
  var CLAUDE_OPUS_1M_MODEL = "opus[1m]";
9267
9270
  var LEGACY_CLAUDE_OPUS_1M_MODEL = "opus-1m";
9268
9271
  var DEFAULT_CODEX_MODEL = "gpt-5.5";
9272
+ var DEFAULT_CURSOR_MODEL = "composer-2";
9269
9273
  function normalizeClaudeModel(model) {
9270
9274
  if (model === LEGACY_CLAUDE_OPUS_1M_MODEL) {
9271
9275
  return CLAUDE_OPUS_1M_MODEL;
@@ -9275,6 +9279,7 @@ function normalizeClaudeModel(model) {
9275
9279
  var AGENT_MODELS = {
9276
9280
  claude: [CLAUDE_OPUS_1M_MODEL, "sonnet", "haiku"],
9277
9281
  codex: [DEFAULT_CODEX_MODEL, "gpt-5.4", "gpt-5.4-mini", "gpt-5.3-codex", "gpt-5.2"],
9282
+ cursor: [DEFAULT_CURSOR_MODEL, "composer-2.5"],
9278
9283
  relay: [CLAUDE_OPUS_1M_MODEL, "sonnet"]
9279
9284
  };
9280
9285
  var MODEL_LABELS = {
@@ -9284,6 +9289,8 @@ var MODEL_LABELS = {
9284
9289
  [LEGACY_CLAUDE_OPUS_1M_MODEL]: "Opus 4.8 (1M)",
9285
9290
  haiku: "Haiku 4.5",
9286
9291
  [DEFAULT_CODEX_MODEL]: "GPT-5.5",
9292
+ [DEFAULT_CURSOR_MODEL]: "Composer 2",
9293
+ "composer-2.5": "Composer 2.5",
9287
9294
  "gpt-5.4": "GPT-5.4",
9288
9295
  "gpt-5.4-mini": "GPT-5.4 Mini",
9289
9296
  "gpt-5.3-codex": "GPT-5.3 Codex",
@@ -9738,6 +9745,204 @@ function parseCodexEvents(events) {
9738
9745
  return messages;
9739
9746
  }
9740
9747
 
9748
+ // ../shared/src/display-message/parsers/cursor-parser.ts
9749
+ function getTextContent(value) {
9750
+ if (!Array.isArray(value)) return "";
9751
+ return value.map((block) => isRecord(block) && block.type === "text" && typeof block.text === "string" ? block.text : "").join("");
9752
+ }
9753
+ function stringify(value) {
9754
+ if (value === void 0 || value === null) return void 0;
9755
+ if (typeof value === "string") return value;
9756
+ try {
9757
+ return JSON.stringify(value, null, 2);
9758
+ } catch {
9759
+ return String(value);
9760
+ }
9761
+ }
9762
+ function cursorStatusToDisplayStatus(status) {
9763
+ return status === "completed" || status === "FINISHED" ? "completed" : status === "error" || status === "ERROR" || status === "CANCELLED" || status === "EXPIRED" ? "failed" : "in_progress";
9764
+ }
9765
+ function cursorRunId(event) {
9766
+ const runId = event.payload.run_id;
9767
+ return typeof runId === "string" ? runId : "unknown-run";
9768
+ }
9769
+ function getCursorAssistantText(event) {
9770
+ const message = isRecord(event.payload.message) ? event.payload.message : null;
9771
+ return getTextContent(message?.content);
9772
+ }
9773
+ function getCursorThinkingText(event) {
9774
+ const text = event.payload.text;
9775
+ if (typeof text === "string") return text;
9776
+ const message = isRecord(event.payload.message) ? event.payload.message : null;
9777
+ return typeof message?.text === "string" ? message.text : "";
9778
+ }
9779
+ function isTerminalStatus(status) {
9780
+ return status === "FINISHED" || status === "ERROR" || status === "CANCELLED" || status === "EXPIRED";
9781
+ }
9782
+ function finalizeOpenTools(messages, toolIndexes, status) {
9783
+ for (const index of toolIndexes.values()) {
9784
+ const message = messages[index];
9785
+ if (message?.type === "tool_call" && message.status === "in_progress") {
9786
+ messages[index] = {
9787
+ ...message,
9788
+ status
9789
+ };
9790
+ }
9791
+ }
9792
+ }
9793
+ function parseCursorEvents(events) {
9794
+ const messages = [];
9795
+ const toolIndexes = /* @__PURE__ */ new Map();
9796
+ const runAssistantSegments = /* @__PURE__ */ new Map();
9797
+ const runThinkingSegments = /* @__PURE__ */ new Map();
9798
+ let activeAssistant = null;
9799
+ let activeThinking = null;
9800
+ const finalizeActiveThinking = (status) => {
9801
+ if (!activeThinking) return;
9802
+ const message = messages[activeThinking.index];
9803
+ if (message?.type === "reasoning") {
9804
+ messages[activeThinking.index] = {
9805
+ ...message,
9806
+ status
9807
+ };
9808
+ }
9809
+ };
9810
+ for (const event of events) {
9811
+ if (event.type === "event_msg" && event.payload.type === "user_message") {
9812
+ activeAssistant = null;
9813
+ activeThinking = null;
9814
+ const message = event.payload.message;
9815
+ if (typeof message === "string" && message.trim()) {
9816
+ messages.push({
9817
+ id: `cursor-user-${event.timestamp}-${messages.length}`,
9818
+ type: "user",
9819
+ content: message,
9820
+ timestamp: event.timestamp
9821
+ });
9822
+ }
9823
+ continue;
9824
+ }
9825
+ if (event.type === "cursor-assistant") {
9826
+ const text = getCursorAssistantText(event);
9827
+ if (text) {
9828
+ const runId = cursorRunId(event);
9829
+ if (!activeAssistant || activeAssistant.runId !== runId) {
9830
+ const segment = runAssistantSegments.get(runId) ?? 0;
9831
+ runAssistantSegments.set(runId, segment + 1);
9832
+ activeAssistant = {
9833
+ runId,
9834
+ index: messages.push({
9835
+ id: `cursor-agent-${runId}-${segment}`,
9836
+ type: "agent",
9837
+ content: "",
9838
+ timestamp: event.timestamp
9839
+ }) - 1
9840
+ };
9841
+ }
9842
+ const message = messages[activeAssistant.index];
9843
+ if (message?.type === "agent") {
9844
+ messages[activeAssistant.index] = {
9845
+ ...message,
9846
+ content: `${message.content}${text}`
9847
+ };
9848
+ }
9849
+ }
9850
+ continue;
9851
+ }
9852
+ if (event.type === "cursor-thinking") {
9853
+ const text = getCursorThinkingText(event);
9854
+ if (text.trim()) {
9855
+ const runId = cursorRunId(event);
9856
+ if (!activeThinking || activeThinking.runId !== runId) {
9857
+ const segment = runThinkingSegments.get(runId) ?? 0;
9858
+ runThinkingSegments.set(runId, segment + 1);
9859
+ activeThinking = {
9860
+ runId,
9861
+ index: messages.push({
9862
+ id: `cursor-reasoning-${runId}-${segment}`,
9863
+ type: "reasoning",
9864
+ content: "",
9865
+ status: "in_progress",
9866
+ timestamp: event.timestamp
9867
+ }) - 1
9868
+ };
9869
+ }
9870
+ const message = messages[activeThinking.index];
9871
+ if (message?.type === "reasoning") {
9872
+ messages[activeThinking.index] = {
9873
+ ...message,
9874
+ content: `${message.content}${text}`,
9875
+ status: "in_progress"
9876
+ };
9877
+ }
9878
+ }
9879
+ continue;
9880
+ }
9881
+ if (event.type === "cursor-tool_call") {
9882
+ activeAssistant = null;
9883
+ const callId = typeof event.payload.call_id === "string" ? event.payload.call_id : `cursor-tool-${event.timestamp}-${messages.length}`;
9884
+ const tool = typeof event.payload.name === "string" ? event.payload.name : "tool";
9885
+ const status = cursorStatusToDisplayStatus(event.payload.status);
9886
+ const input = isRecord(event.payload.args) ? event.payload.args : typeof event.payload.args === "string" ? event.payload.args : void 0;
9887
+ const existing = toolIndexes.get(callId);
9888
+ const next = {
9889
+ id: callId,
9890
+ type: "tool_call",
9891
+ server: "cursor",
9892
+ tool,
9893
+ ...input !== void 0 ? { input } : {},
9894
+ output: stringify(event.payload.result),
9895
+ status,
9896
+ timestamp: event.timestamp
9897
+ };
9898
+ if (existing === void 0) {
9899
+ toolIndexes.set(callId, messages.push(next) - 1);
9900
+ } else {
9901
+ messages[existing] = { ...messages[existing], ...next };
9902
+ }
9903
+ continue;
9904
+ }
9905
+ if (event.type === "cursor-task") {
9906
+ activeAssistant = null;
9907
+ const text = event.payload.text;
9908
+ if (typeof text === "string" && text.trim()) {
9909
+ messages.push({
9910
+ id: `cursor-task-${event.timestamp}-${messages.length}`,
9911
+ type: "agent",
9912
+ content: text,
9913
+ timestamp: event.timestamp
9914
+ });
9915
+ }
9916
+ continue;
9917
+ }
9918
+ if (event.type === "cursor-status") {
9919
+ const status = event.payload.status;
9920
+ if (isTerminalStatus(status)) {
9921
+ const displayStatus = cursorStatusToDisplayStatus(status);
9922
+ finalizeActiveThinking(displayStatus);
9923
+ finalizeOpenTools(messages, toolIndexes, displayStatus);
9924
+ activeThinking = null;
9925
+ activeAssistant = null;
9926
+ }
9927
+ continue;
9928
+ }
9929
+ if (event.type === "cursor-error") {
9930
+ finalizeActiveThinking("failed");
9931
+ finalizeOpenTools(messages, toolIndexes, "failed");
9932
+ activeAssistant = null;
9933
+ activeThinking = null;
9934
+ const message = typeof event.payload.message === "string" ? event.payload.message : "Cursor run failed";
9935
+ messages.push({
9936
+ id: `cursor-error-${event.timestamp}-${messages.length}`,
9937
+ type: "error",
9938
+ message,
9939
+ timestamp: event.timestamp
9940
+ });
9941
+ }
9942
+ }
9943
+ return messages;
9944
+ }
9945
+
9741
9946
  // ../shared/src/display-message/task-accumulator.ts
9742
9947
  function mapTaskStatus(status) {
9743
9948
  if (status === "in_progress" || status === "completed") return status;
@@ -10444,6 +10649,9 @@ function parseAgentEvents(events, agentType) {
10444
10649
  if (agentType === "codex") {
10445
10650
  return parseCodexEvents(events);
10446
10651
  }
10652
+ if (agentType === "cursor") {
10653
+ return parseCursorEvents(events);
10654
+ }
10447
10655
  return parseClaudeEvents(events);
10448
10656
  }
10449
10657
  function parseDisplayMessages(events, agentType, codexAspTranscript, options = {}) {
@@ -10800,25 +11008,51 @@ function parseGitHubPRExistingReview(content) {
10800
11008
  };
10801
11009
  }
10802
11010
  function parseGitHubPRExistingGeneral(content) {
10803
- const headerMatch = content.match(
10804
- /^You received a comment on Pull Request #(\d+)\./m
10805
- );
10806
- if (!headerMatch) return null;
10807
- const prNumber = parseInt(headerMatch[1], 10);
10808
- const commentMatch = content.match(
10809
- /Comment from @(\S+):\n([\s\S]*?)(?=\n\*\*(?:PR|Issue|User|File) URL:\*\*|\nIMPORTANT INSTRUCTIONS:)/
11011
+ const fields = parseHostReviewThreadFields(
11012
+ content,
11013
+ /^You received a comment on Pull Request #(\d+)\./m,
11014
+ /Comment from @(\S+):\n([\s\S]*?)(?=\n\*\*(?:PR|Issue|User|File) URL:\*\*|\nIMPORTANT INSTRUCTIONS:)/,
11015
+ /\*\*PR URL:\*\*\s*(.+)/
10810
11016
  );
10811
- const prUrlMatch = content.match(/\*\*PR URL:\*\*\s*(.+)/);
11017
+ if (!fields) return null;
10812
11018
  const userUrlMatch = content.match(/\*\*User URL:\*\*\s*(.+)/);
10813
11019
  return {
10814
11020
  source: "github_pr_existing_general",
10815
- prNumber,
10816
- commentUser: commentMatch?.[1] ?? "",
10817
- commentBody: commentMatch?.[2]?.trim() ?? "",
10818
- prUrl: prUrlMatch?.[1]?.trim(),
11021
+ prNumber: fields.itemNumber,
11022
+ commentUser: fields.commentUser,
11023
+ commentBody: fields.commentBody,
11024
+ prUrl: fields.itemUrl,
10819
11025
  userUrl: userUrlMatch?.[1]?.trim()
10820
11026
  };
10821
11027
  }
11028
+ function parseGitLabMRExistingGeneral(content) {
11029
+ const fields = parseHostReviewThreadFields(
11030
+ content,
11031
+ /^You received a comment on GitLab Merge Request !(\d+)\./m,
11032
+ /Comment from @?([^:\n]+):\n([\s\S]*?)(?=\n\*\*(?:Merge Request|Comment)(?: URL)?:\*\*|\nIMPORTANT INSTRUCTIONS:)/,
11033
+ /\*\*Comment URL:\*\*\s*(.+)/
11034
+ );
11035
+ if (!fields) return null;
11036
+ return {
11037
+ source: "gitlab_mr_existing_general",
11038
+ mergeRequestIid: fields.itemNumber,
11039
+ commentUser: fields.commentUser,
11040
+ commentBody: fields.commentBody,
11041
+ commentUrl: fields.itemUrl
11042
+ };
11043
+ }
11044
+ function parseHostReviewThreadFields(content, headerPattern, commentPattern, itemUrlPattern) {
11045
+ const headerMatch = content.match(headerPattern);
11046
+ if (!headerMatch) return null;
11047
+ const commentMatch = content.match(commentPattern);
11048
+ const itemUrlMatch = content.match(itemUrlPattern);
11049
+ return {
11050
+ itemNumber: parseInt(headerMatch[1], 10),
11051
+ commentUser: commentMatch?.[1]?.trim() ?? "",
11052
+ commentBody: commentMatch?.[2]?.trim() ?? "",
11053
+ itemUrl: itemUrlMatch?.[1]?.trim()
11054
+ };
11055
+ }
10822
11056
  function parseSlackTask(content) {
10823
11057
  if (!content.startsWith("# Task from Slack")) return null;
10824
11058
  const targetMatch = content.match(/## Workspace Target\nWorking in: (.+?)(?=\n\*\*(?:Thread|Target) URL:\*\*|\n\n)/);
@@ -10911,7 +11145,7 @@ function parseAutomationTriggered(content) {
10911
11145
  };
10912
11146
  }
10913
11147
  function parseSingleMessage(content) {
10914
- return parseCIFailure(content) ?? parseGitHubIssueNew(content) ?? parseGitHubIssueExisting(content) ?? parseGitLabIssueNew(content) ?? parseGitLabIssueExisting(content) ?? parseGitHubPRNew(content) ?? parseGitHubPRExistingPRReview(content) ?? parseGitHubPRExistingReview(content) ?? parseGitHubPRExistingGeneral(content) ?? parseSlackTask(content) ?? parseLinearIssue(content) ?? parseAutomationTriggered(content) ?? parseInlineDiffComments(content) ?? parsePlanQuote(content) ?? { source: "raw", content };
11148
+ return parseCIFailure(content) ?? parseGitHubIssueNew(content) ?? parseGitHubIssueExisting(content) ?? parseGitLabIssueNew(content) ?? parseGitLabIssueExisting(content) ?? parseGitHubPRNew(content) ?? parseGitHubPRExistingPRReview(content) ?? parseGitHubPRExistingReview(content) ?? parseGitHubPRExistingGeneral(content) ?? parseGitLabMRExistingGeneral(content) ?? parseSlackTask(content) ?? parseLinearIssue(content) ?? parseAutomationTriggered(content) ?? parseInlineDiffComments(content) ?? parsePlanQuote(content) ?? { source: "raw", content };
10915
11149
  }
10916
11150
  function parseMerged(content) {
10917
11151
  if (!content.includes(MERGED_MESSAGE_SEPARATOR)) return null;
@@ -10939,6 +11173,7 @@ var SOURCE_CONFIG = {
10939
11173
  github_pr_existing_review: { label: "Code Review", color: "#8b949e" },
10940
11174
  github_pr_existing_pr_review: { label: "PR Review", color: "#8b949e" },
10941
11175
  github_pr_existing_general: { label: "GitHub PR", color: "#8b949e" },
11176
+ gitlab_mr_existing_general: { label: "GitLab MR", color: "#fc6d26" },
10942
11177
  slack_task: { label: "Slack", color: "#BF6CC2" },
10943
11178
  automation_triggered: { label: "Automation", color: "#f59e0b" },
10944
11179
  plan_quote: { label: "Plan", color: "#3eeba3" },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "replicas-cli",
3
- "version": "0.2.276",
3
+ "version": "0.2.278",
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": {