@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.
- package/dist/server.js +187 -6
- 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:
|
|
3324
|
+
tool_name: toolName,
|
|
3276
3325
|
command: state.pendingCall.command,
|
|
3277
|
-
file_path:
|
|
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
|
-
|
|
3610
|
-
|
|
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.
|
|
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": {
|