@quantiya/codevibe-antigravity-plugin 1.0.1 → 1.0.3

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/server.js +187 -6
  2. package/package.json +1 -1
package/dist/server.js CHANGED
@@ -1457,6 +1457,7 @@ function parseApprovalUISnapshot(stripped, originalSnapshot) {
1457
1457
  if (options.length < 2) return null;
1458
1458
  const submitMap = buildApprovalSubmitMap(options);
1459
1459
  const { command, filePath } = extractIdentity(headerText);
1460
+ const body = extractBodyBetweenHeaderAndFirstOption(belowHeader);
1460
1461
  return {
1461
1462
  kind: "approval",
1462
1463
  headerText,
@@ -1465,6 +1466,7 @@ function parseApprovalUISnapshot(stripped, originalSnapshot) {
1465
1466
  filePath,
1466
1467
  options,
1467
1468
  submitMap,
1469
+ body,
1468
1470
  paneHash: hashPromptSnapshot(originalSnapshot)
1469
1471
  };
1470
1472
  }
@@ -1481,6 +1483,7 @@ function parseQuestionSnapshot(stripped, originalSnapshot, header) {
1481
1483
  const options = parseOptions(belowHeader);
1482
1484
  if (options.length < 2) return null;
1483
1485
  const submitMap = buildQuestionSubmitMap(options);
1486
+ const body = extractBodyBetweenHeaderAndFirstOption(belowHeader);
1484
1487
  return {
1485
1488
  kind: "question",
1486
1489
  headerText: header.body,
@@ -1489,9 +1492,30 @@ function parseQuestionSnapshot(stripped, originalSnapshot, header) {
1489
1492
  filePath: void 0,
1490
1493
  options,
1491
1494
  submitMap,
1495
+ body,
1492
1496
  paneHash: hashPromptSnapshot(originalSnapshot)
1493
1497
  };
1494
1498
  }
1499
+ function extractBodyBetweenHeaderAndFirstOption(belowHeader) {
1500
+ const lines = belowHeader.split("\n");
1501
+ const optionRegex = /^[>\s]*([1-9])\. (.+?)\s*$/;
1502
+ const fenceRegex = /^```/;
1503
+ let firstOptionIdx = -1;
1504
+ let inFence = false;
1505
+ for (let i = 0; i < lines.length; i++) {
1506
+ if (fenceRegex.test(lines[i])) {
1507
+ inFence = !inFence;
1508
+ continue;
1509
+ }
1510
+ if (inFence) continue;
1511
+ if (optionRegex.test(lines[i])) {
1512
+ firstOptionIdx = i;
1513
+ break;
1514
+ }
1515
+ }
1516
+ if (firstOptionIdx <= 0) return "";
1517
+ return lines.slice(0, firstOptionIdx).join("\n").trim();
1518
+ }
1495
1519
  function parseOptions(snapshot) {
1496
1520
  const recent = snapshot.split("\n").slice(-30);
1497
1521
  const optionRegex = /^[>\s]*([1-9])\. (.+?)\s*$/;
@@ -1720,6 +1744,7 @@ var ApprovalDetector = class extends import_events3.EventEmitter {
1720
1744
  submitMap: candidate.submitMap,
1721
1745
  matchedPaneHeader: candidate.headerText,
1722
1746
  paneDisplayHeader: candidate.fullHeaderLine,
1747
+ body: candidate.body,
1723
1748
  emittedAt: Date.now(),
1724
1749
  ttlMs: this.promptTtlMs,
1725
1750
  paneOptions: candidate.options
@@ -1904,6 +1929,7 @@ var ApprovalDetector = class extends import_events3.EventEmitter {
1904
1929
  submitMap: candidate.submitMap,
1905
1930
  matchedPaneHeader: candidate.headerText,
1906
1931
  paneDisplayHeader: candidate.fullHeaderLine,
1932
+ body: candidate.body,
1907
1933
  emittedAt: Date.now(),
1908
1934
  ttlMs: this.promptTtlMs
1909
1935
  };
@@ -3270,12 +3296,36 @@ var McpServer = class {
3270
3296
  return;
3271
3297
  }
3272
3298
  const optionsArr = state.paneOptions ? state.paneOptions.map((o) => ({ number: o.number, text: o.text })) : Object.keys(state.submitMap).map((n) => ({ number: n }));
3299
+ const diffParsed = parseFencedDiffFromBody(
3300
+ state.body,
3301
+ state.paneDisplayHeader
3302
+ );
3303
+ if (diffParsed) {
3304
+ logger.info("Parsed fenced diff for INTERACTIVE_PROMPT", {
3305
+ promptId: state.promptId,
3306
+ filePath: diffParsed.filePath,
3307
+ oldLines: diffParsed.oldString.split("\n").length,
3308
+ newLines: diffParsed.newString.split("\n").length,
3309
+ rawDiffLength: diffParsed.rawDiff.length
3310
+ });
3311
+ }
3312
+ const toolName = diffParsed ? "Edit" : state.pendingCall?.toolType;
3313
+ const filePath = diffParsed?.filePath ?? state.pendingCall?.filePath;
3314
+ const toolInput = diffParsed ? {
3315
+ file_path: diffParsed.filePath,
3316
+ old_string: diffParsed.oldString,
3317
+ new_string: diffParsed.newString,
3318
+ old_start_line: diffParsed.oldStartLine,
3319
+ new_start_line: diffParsed.newStartLine,
3320
+ diff: diffParsed.rawDiff
3321
+ } : void 0;
3273
3322
  const optionsForMobile = state.pendingCall ? {
3274
3323
  promptId: state.promptId,
3275
- tool_name: state.pendingCall.toolType,
3324
+ tool_name: toolName,
3276
3325
  command: state.pendingCall.command,
3277
- file_path: state.pendingCall.filePath,
3278
- options: optionsArr
3326
+ file_path: filePath,
3327
+ options: optionsArr,
3328
+ ...toolInput ? { tool_input: toolInput } : {}
3279
3329
  } : { promptId: state.promptId };
3280
3330
  const content = state.paneDisplayHeader || state.matchedPaneHeader || state.pendingCall?.command || state.pendingCall?.filePath || "approval requested";
3281
3331
  const input = {
@@ -3604,10 +3654,56 @@ function generateLaunchSessionId(wrapperPid) {
3604
3654
  const nonce = crypto3.randomBytes(8).toString("hex");
3605
3655
  return `agy-${wrapperPid}-${nonce}`;
3606
3656
  }
3657
+ var cliLogResolvedPathCache = /* @__PURE__ */ new Map();
3658
+ var CLI_LOG_RESOLVE_TTL_MS = 5e3;
3607
3659
  function getActiveConversationFromCliLog(cliLogPath) {
3608
3660
  try {
3609
- if (!fs5.existsSync(cliLogPath)) return null;
3610
- const content = fs5.readFileSync(cliLogPath, "utf8");
3661
+ let initialStat;
3662
+ try {
3663
+ initialStat = fs5.lstatSync(cliLogPath);
3664
+ } catch {
3665
+ return null;
3666
+ }
3667
+ let resolvedPath = null;
3668
+ try {
3669
+ if (initialStat.isSymbolicLink()) {
3670
+ const now = Date.now();
3671
+ const cached = cliLogResolvedPathCache.get(cliLogPath);
3672
+ if (cached && now - cached.lastScanMs < CLI_LOG_RESOLVE_TTL_MS) {
3673
+ resolvedPath = cached.resolvedPath;
3674
+ } else {
3675
+ const logDir = path5.join(path5.dirname(cliLogPath), "log");
3676
+ let dirOk = false;
3677
+ try {
3678
+ dirOk = fs5.statSync(logDir).isDirectory();
3679
+ } catch {
3680
+ }
3681
+ if (dirOk) {
3682
+ const entries = [];
3683
+ for (const name of fs5.readdirSync(logDir)) {
3684
+ if (!/^cli-.*\.log$/.test(name)) continue;
3685
+ const full = path5.join(logDir, name);
3686
+ try {
3687
+ const s = fs5.statSync(full);
3688
+ if (s.isFile()) entries.push({ full, mtimeMs: s.mtimeMs });
3689
+ } catch {
3690
+ }
3691
+ }
3692
+ if (entries.length > 0) {
3693
+ entries.sort((a, b) => b.mtimeMs - a.mtimeMs || b.full.localeCompare(a.full));
3694
+ resolvedPath = entries[0].full;
3695
+ }
3696
+ }
3697
+ cliLogResolvedPathCache.set(cliLogPath, { resolvedPath, lastScanMs: now });
3698
+ }
3699
+ } else {
3700
+ resolvedPath = cliLogPath;
3701
+ }
3702
+ } catch {
3703
+ resolvedPath = initialStat.isSymbolicLink() ? null : cliLogPath;
3704
+ }
3705
+ if (resolvedPath === null) return null;
3706
+ const content = fs5.readFileSync(resolvedPath, "utf8");
3611
3707
  const regex = /(?:Created conversation|Streaming conversation|Starting conversation update stream for)\s+([0-9a-fA-F-]{36})/g;
3612
3708
  const matches = Array.from(content.matchAll(regex));
3613
3709
  if (matches.length === 0) return null;
@@ -3657,11 +3753,96 @@ function parseArgs(argv) {
3657
3753
  if (require.main === module) {
3658
3754
  void main();
3659
3755
  }
3756
+ function parseFencedDiffFromBody(body, header) {
3757
+ if (!body) return null;
3758
+ const fenceMatch = body.match(/```[^\n]*\n([\s\S]*?)\n```/i);
3759
+ if (!fenceMatch) return null;
3760
+ const rawDiff = fenceMatch[1];
3761
+ const oldLines = [];
3762
+ const newLines = [];
3763
+ const hunkHeaderPattern = /^@@ -(\d+)(?:,\d+)? \+(\d+)(?:,\d+)? @@/;
3764
+ let currentOldLine = 0;
3765
+ let currentNewLine = 0;
3766
+ let oldStartLine;
3767
+ let newStartLine;
3768
+ let hunkCount = 0;
3769
+ let filePath;
3770
+ const stripPrefix = (raw) => {
3771
+ let p = raw.trim();
3772
+ if (p.startsWith("a/") || p.startsWith("b/")) p = p.slice(2);
3773
+ if (p === "/dev/null") return "";
3774
+ return p;
3775
+ };
3776
+ for (const line of rawDiff.split("\n")) {
3777
+ const hunkMatch = line.match(hunkHeaderPattern);
3778
+ if (hunkMatch) {
3779
+ hunkCount += 1;
3780
+ currentOldLine = Number.parseInt(hunkMatch[1], 10);
3781
+ currentNewLine = Number.parseInt(hunkMatch[2], 10);
3782
+ continue;
3783
+ }
3784
+ if (line.startsWith("+++ ")) {
3785
+ const pathVal = stripPrefix(line.slice(4));
3786
+ if (pathVal) filePath = pathVal;
3787
+ continue;
3788
+ }
3789
+ if (line.startsWith("--- ")) {
3790
+ if (!filePath) {
3791
+ const pathVal = stripPrefix(line.slice(4));
3792
+ if (pathVal) filePath = pathVal;
3793
+ }
3794
+ continue;
3795
+ }
3796
+ if (line.startsWith("+")) {
3797
+ if (newStartLine === void 0) newStartLine = currentNewLine;
3798
+ newLines.push(line.slice(1));
3799
+ currentNewLine += 1;
3800
+ } else if (line.startsWith("-")) {
3801
+ if (oldStartLine === void 0) oldStartLine = currentOldLine;
3802
+ oldLines.push(line.slice(1));
3803
+ currentOldLine += 1;
3804
+ } else if (line.startsWith(" ")) {
3805
+ const ctx = line.slice(1);
3806
+ oldLines.push(ctx);
3807
+ newLines.push(ctx);
3808
+ currentOldLine += 1;
3809
+ currentNewLine += 1;
3810
+ }
3811
+ }
3812
+ if (hunkCount > 1) {
3813
+ oldStartLine = void 0;
3814
+ newStartLine = void 0;
3815
+ }
3816
+ if (!filePath) {
3817
+ const searchTargets = [body, header ?? ""];
3818
+ for (const target of searchTargets) {
3819
+ if (!target) continue;
3820
+ const m = target.match(/\[.*?\]\(file:\/\/([^\s\)]+)\)/) || target.match(/file:\/\/([^\s\)]+)/);
3821
+ if (m) {
3822
+ try {
3823
+ filePath = decodeURIComponent(m[1]);
3824
+ } catch {
3825
+ filePath = m[1];
3826
+ }
3827
+ break;
3828
+ }
3829
+ }
3830
+ }
3831
+ return {
3832
+ filePath,
3833
+ oldString: oldLines.join("\n"),
3834
+ newString: newLines.join("\n"),
3835
+ oldStartLine,
3836
+ newStartLine,
3837
+ rawDiff
3838
+ };
3839
+ }
3660
3840
  var __testing = {
3661
3841
  generateLaunchSessionId,
3662
3842
  parseArgs,
3663
3843
  parseMaybeJson,
3664
- getActiveConversationFromCliLog
3844
+ getActiveConversationFromCliLog,
3845
+ parseFencedDiffFromBody
3665
3846
  };
3666
3847
  // Annotate the CommonJS export names for ESM import in node:
3667
3848
  0 && (module.exports = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quantiya/codevibe-antigravity-plugin",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "Control Antigravity CLI from your iPhone and Android — real-time sync, approve file edits, send prompts by voice. Part of CodeVibe.",
5
5
  "main": "dist/server.js",
6
6
  "bin": {