@quantiya/codevibe-antigravity-plugin 2.0.30 → 2.0.31
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 +358 -38
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -1120,23 +1120,28 @@ var TmuxPaneObserver = class _TmuxPaneObserver extends import_events2.EventEmitt
|
|
|
1120
1120
|
async probeApprovalUIActive() {
|
|
1121
1121
|
try {
|
|
1122
1122
|
const snapshot = await this.captureSnapshot();
|
|
1123
|
-
const
|
|
1123
|
+
const hasPrompt = looksLikePromptSnapshot(snapshot);
|
|
1124
1124
|
let headerText = null;
|
|
1125
|
-
|
|
1126
|
-
|
|
1125
|
+
let kind = null;
|
|
1126
|
+
if (hasPrompt) {
|
|
1127
|
+
kind = detectActivePromptKind(snapshot);
|
|
1127
1128
|
if (kind === "question") {
|
|
1128
1129
|
const q = extractQuestionHeader(snapshot);
|
|
1129
1130
|
headerText = q ? q.body : null;
|
|
1130
1131
|
} else if (kind === "file_access") {
|
|
1131
1132
|
const fileAccess = extractFileAccessPrompt(snapshot);
|
|
1132
1133
|
headerText = fileAccess ? fileAccess.identity : null;
|
|
1134
|
+
} else if (kind === "system_error") {
|
|
1135
|
+
const err = extractSystemErrorPrompt(snapshot);
|
|
1136
|
+
headerText = err ? err.message : null;
|
|
1133
1137
|
} else if (kind === "approval") {
|
|
1134
1138
|
headerText = extractHeader(snapshot);
|
|
1135
1139
|
}
|
|
1136
1140
|
}
|
|
1137
|
-
|
|
1141
|
+
const isChooser = hasPrompt && kind !== "system_error";
|
|
1142
|
+
return { active: isChooser, headerText, probeSucceeded: true, kind };
|
|
1138
1143
|
} catch {
|
|
1139
|
-
return { active: false, headerText: null, probeSucceeded: false };
|
|
1144
|
+
return { active: false, headerText: null, probeSucceeded: false, kind: null };
|
|
1140
1145
|
}
|
|
1141
1146
|
}
|
|
1142
1147
|
// ─── tmux pipe-pane plumbing ─────────────────────────────────────────────
|
|
@@ -1397,25 +1402,119 @@ var TmuxPaneObserver = class _TmuxPaneObserver extends import_events2.EventEmitt
|
|
|
1397
1402
|
function looksLikePromptDelta(chunk) {
|
|
1398
1403
|
return (
|
|
1399
1404
|
// Approval UI signatures
|
|
1400
|
-
/Requesting permission for:/i.test(chunk) || /Do you want to proceed\?/i.test(chunk) || /\besc to cancel\b/i.test(chunk) || /^\s*[1-9]\. (?:Yes|No)\b/im.test(chunk) || /\[(?:y\/n|Y\/n|y\/N)\]/.test(chunk) || /Question \d+\/\d+:/i.test(chunk) || /\benter Select\b/i.test(chunk) || /^File access\s*$/im.test(chunk) || /Allow access to this file\?/i.test(chunk) || /No, deny access/i.test(chunk)
|
|
1405
|
+
/Requesting permission for:/i.test(chunk) || /Do you want to proceed\?/i.test(chunk) || /\besc to cancel\b/i.test(chunk) || /^\s*[1-9]\. (?:Yes|No)\b/im.test(chunk) || /\[(?:y\/n|Y\/n|y\/N)\]/.test(chunk) || /Question \d+\/\d+:/i.test(chunk) || /\benter Select\b/i.test(chunk) || /^File access\s*$/im.test(chunk) || /Allow access to this file\?/i.test(chunk) || /No, deny access/i.test(chunk) || /Our servers are experiencing/i.test(chunk) || /Error ID:\s*[0-9a-fA-F-]+/i.test(chunk) || /(?:⚠️|⚠\uFE0F?)\s+.*(?:high traffic|try again in a minute|try again later|stream was interrupted|stream interrupted|overloaded|unexpected error)/i.test(chunk)
|
|
1401
1406
|
);
|
|
1402
1407
|
}
|
|
1408
|
+
function isSystemErrorBannerLine(line) {
|
|
1409
|
+
const trimmed = line.trim();
|
|
1410
|
+
if (!trimmed) return false;
|
|
1411
|
+
if (!/^(?:⚠️|⚠\uFE0F?)\s+/.test(trimmed)) return false;
|
|
1412
|
+
if (/Our servers are experiencing/i.test(trimmed)) return true;
|
|
1413
|
+
if (/The stream was interrupted/i.test(trimmed)) return true;
|
|
1414
|
+
if (/The model is overloaded/i.test(trimmed)) return true;
|
|
1415
|
+
if (/(?:high traffic|try again in a minute|try again later|stream was interrupted|stream interrupted|overloaded|unexpected error|error id:)/i.test(trimmed)) return true;
|
|
1416
|
+
return false;
|
|
1417
|
+
}
|
|
1418
|
+
function isSystemErrorActiveFromIndex(lines, errorIdx) {
|
|
1419
|
+
let inHeaderBlock = true;
|
|
1420
|
+
let sawErrorIdLine = false;
|
|
1421
|
+
for (let j = errorIdx + 1; j < lines.length; j++) {
|
|
1422
|
+
const trimmed = lines[j].trim();
|
|
1423
|
+
if (!trimmed) {
|
|
1424
|
+
sawErrorIdLine = false;
|
|
1425
|
+
continue;
|
|
1426
|
+
}
|
|
1427
|
+
if (/^[│\s]*[❯>]\s+\S/.test(trimmed)) return false;
|
|
1428
|
+
if (/^[▶▸\s]*Thought for\s+\d+/i.test(trimmed)) return false;
|
|
1429
|
+
if (/^Thinking\b/i.test(trimmed)) return false;
|
|
1430
|
+
if (/^[●\s]*(?:[A-Za-z_-]+)\(/.test(trimmed)) return false;
|
|
1431
|
+
if (/Requesting permission for:/i.test(trimmed)) return false;
|
|
1432
|
+
if (/Question \d+\/\d+:/i.test(trimmed)) return false;
|
|
1433
|
+
if (/^\s*File access\s*$/i.test(trimmed)) return false;
|
|
1434
|
+
if (/^[>\s]*[1-9]\. \S/.test(trimmed)) return false;
|
|
1435
|
+
if (/Allow access to this file\?/i.test(trimmed)) return false;
|
|
1436
|
+
if (/Do you want to proceed\?/i.test(trimmed)) return false;
|
|
1437
|
+
if (/\benter Select\b/i.test(trimmed)) return false;
|
|
1438
|
+
if (/^Error ID:\s*[0-9a-fA-F-]*/i.test(trimmed)) {
|
|
1439
|
+
inHeaderBlock = false;
|
|
1440
|
+
sawErrorIdLine = true;
|
|
1441
|
+
continue;
|
|
1442
|
+
}
|
|
1443
|
+
if (sawErrorIdLine && /^[0-9a-fA-F-]+$/.test(trimmed) && /[0-9a-fA-F]/.test(trimmed)) {
|
|
1444
|
+
continue;
|
|
1445
|
+
}
|
|
1446
|
+
sawErrorIdLine = false;
|
|
1447
|
+
if (/^[─━│╭╰╮╯\s_-]*$/.test(trimmed)) {
|
|
1448
|
+
inHeaderBlock = false;
|
|
1449
|
+
continue;
|
|
1450
|
+
}
|
|
1451
|
+
if (/^[│\s]*[❯>]\s*$/.test(trimmed)) {
|
|
1452
|
+
inHeaderBlock = false;
|
|
1453
|
+
continue;
|
|
1454
|
+
}
|
|
1455
|
+
if (/^\s*(?:\?\s+for shortcuts|esc to cancel)\b/i.test(trimmed)) {
|
|
1456
|
+
inHeaderBlock = false;
|
|
1457
|
+
continue;
|
|
1458
|
+
}
|
|
1459
|
+
if (/^\s*(?:accept-edits\s+·\s+)?Gemini\s+[\d.]+\s+(?:Flash|Pro)\b/i.test(trimmed)) {
|
|
1460
|
+
inHeaderBlock = false;
|
|
1461
|
+
continue;
|
|
1462
|
+
}
|
|
1463
|
+
if (inHeaderBlock && j - errorIdx <= 4) {
|
|
1464
|
+
continue;
|
|
1465
|
+
}
|
|
1466
|
+
return false;
|
|
1467
|
+
}
|
|
1468
|
+
return true;
|
|
1469
|
+
}
|
|
1470
|
+
function isLegacyYNActiveInLines(lines) {
|
|
1471
|
+
let ynIdx = -1;
|
|
1472
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
1473
|
+
if (/\[(?:y\/n|Y\/n|y\/N)\]/.test(lines[i]) && /\b(?:apply|approve|allow|continue|proceed|run|execute|confirm)\b/i.test(lines[i])) {
|
|
1474
|
+
ynIdx = i;
|
|
1475
|
+
break;
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
if (ynIdx < 0) return { active: false, lineIdx: -1 };
|
|
1479
|
+
for (let j = ynIdx + 1; j < lines.length; j++) {
|
|
1480
|
+
const trimmed = lines[j].trim();
|
|
1481
|
+
if (!trimmed) continue;
|
|
1482
|
+
if (/^[─━│╭╰╮╯\s_-]*$/.test(trimmed)) continue;
|
|
1483
|
+
if (/^\s*(?:\?\s+for shortcuts|esc to cancel)\b/i.test(trimmed)) continue;
|
|
1484
|
+
return { active: false, lineIdx: -1 };
|
|
1485
|
+
}
|
|
1486
|
+
return { active: true, lineIdx: ynIdx };
|
|
1487
|
+
}
|
|
1403
1488
|
function looksLikePromptSnapshot(snapshot) {
|
|
1404
1489
|
const stripped = snapshot.replace(ANSI_ESCAPE_REGEX, "");
|
|
1405
|
-
const
|
|
1406
|
-
|
|
1407
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1490
|
+
const activeKind = detectActivePromptKind(snapshot);
|
|
1491
|
+
if (activeKind !== null) {
|
|
1492
|
+
if (activeKind === "system_error") return true;
|
|
1493
|
+
const recent = stripped.trimEnd().split("\n").slice(-30).join("\n");
|
|
1494
|
+
if (activeKind === "approval") {
|
|
1495
|
+
const hasApprovalHeader = /Requesting permission for:/i.test(recent) || /Do you want to proceed\?/i.test(recent);
|
|
1496
|
+
const hasApprovalOptions = /^[>\s]*[1-9]\. (?:Yes|No)\b/im.test(recent);
|
|
1497
|
+
const hasApprovalFooter = /\besc to cancel\b/i.test(recent);
|
|
1498
|
+
return hasApprovalHeader && hasApprovalOptions && hasApprovalFooter;
|
|
1499
|
+
}
|
|
1500
|
+
if (activeKind === "question") {
|
|
1501
|
+
const hasQuestionHeader = /Question \d+\/\d+:/i.test(recent);
|
|
1502
|
+
const hasQuestionOptions = /^[>\s]*[1-9]\. \S/im.test(recent);
|
|
1503
|
+
const hasQuestionFooter = /\benter Select\b/i.test(recent);
|
|
1504
|
+
return hasQuestionHeader && hasQuestionOptions && hasQuestionFooter;
|
|
1505
|
+
}
|
|
1506
|
+
if (activeKind === "file_access") {
|
|
1507
|
+
const hasFileAccessHeader = /^File access\s*$/im.test(recent);
|
|
1508
|
+
const hasFileAccessQuestion = /Allow access to this file\?/i.test(recent);
|
|
1509
|
+
const hasApprovalOptions = /^[>\s]*[1-9]\. (?:Yes|No)\b/im.test(recent);
|
|
1510
|
+
const hasApprovalFooter = /\besc to cancel\b/i.test(recent);
|
|
1511
|
+
return hasFileAccessHeader && hasFileAccessQuestion && hasApprovalOptions && hasApprovalFooter;
|
|
1512
|
+
}
|
|
1513
|
+
return true;
|
|
1514
|
+
}
|
|
1515
|
+
const lines = stripped.split("\n");
|
|
1516
|
+
const legacyYN = isLegacyYNActiveInLines(lines);
|
|
1517
|
+
return legacyYN.active;
|
|
1419
1518
|
}
|
|
1420
1519
|
function extractFileAccessPrompt(snapshot) {
|
|
1421
1520
|
const stripped = snapshot.replace(ANSI_ESCAPE_REGEX, "");
|
|
@@ -1451,31 +1550,221 @@ function extractFullHeaderLine(snapshot) {
|
|
|
1451
1550
|
}
|
|
1452
1551
|
function detectActivePromptKind(snapshot) {
|
|
1453
1552
|
const stripped = snapshot.replace(ANSI_ESCAPE_REGEX, "");
|
|
1454
|
-
const lines = stripped.split("\n");
|
|
1553
|
+
const lines = stripped.trimEnd().split("\n");
|
|
1554
|
+
const windowStart = Math.max(0, lines.length - 30);
|
|
1455
1555
|
const approvalRe = /Requesting permission for:/i;
|
|
1456
1556
|
const questionRe = /Question \d+\/\d+:/i;
|
|
1457
1557
|
const fileAccessRe = /^\s*File access\s*$/i;
|
|
1458
1558
|
let lastApprovalLineIdx = -1;
|
|
1459
1559
|
let lastQuestionLineIdx = -1;
|
|
1460
1560
|
let lastFileAccessLineIdx = -1;
|
|
1561
|
+
let lastSystemErrorLineIdx = -1;
|
|
1461
1562
|
for (let i = lines.length - 1; i >= 0; i--) {
|
|
1462
|
-
|
|
1463
|
-
|
|
1563
|
+
const line = lines[i];
|
|
1564
|
+
if (i >= windowStart) {
|
|
1565
|
+
if (lastApprovalLineIdx < 0 && approvalRe.test(line)) {
|
|
1566
|
+
lastApprovalLineIdx = i;
|
|
1567
|
+
}
|
|
1568
|
+
if (lastQuestionLineIdx < 0 && questionRe.test(line)) {
|
|
1569
|
+
lastQuestionLineIdx = i;
|
|
1570
|
+
}
|
|
1571
|
+
if (lastFileAccessLineIdx < 0 && fileAccessRe.test(line)) {
|
|
1572
|
+
lastFileAccessLineIdx = i;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
if (lastSystemErrorLineIdx < 0 && isSystemErrorBannerLine(line)) {
|
|
1576
|
+
lastSystemErrorLineIdx = i;
|
|
1464
1577
|
}
|
|
1465
|
-
if (lastQuestionLineIdx
|
|
1466
|
-
|
|
1578
|
+
if (lastApprovalLineIdx >= 0 && lastQuestionLineIdx >= 0 && lastFileAccessLineIdx >= 0 && lastSystemErrorLineIdx >= 0) break;
|
|
1579
|
+
}
|
|
1580
|
+
if (lastApprovalLineIdx < 0 && lastQuestionLineIdx < 0) {
|
|
1581
|
+
for (let i = lines.length - 1; i >= windowStart; i--) {
|
|
1582
|
+
if (/Do you want to proceed\?/i.test(lines[i])) {
|
|
1583
|
+
lastApprovalLineIdx = i;
|
|
1584
|
+
break;
|
|
1585
|
+
}
|
|
1586
|
+
}
|
|
1587
|
+
}
|
|
1588
|
+
const latestChooserIdx = Math.max(
|
|
1589
|
+
lastApprovalLineIdx,
|
|
1590
|
+
lastQuestionLineIdx,
|
|
1591
|
+
lastFileAccessLineIdx
|
|
1592
|
+
);
|
|
1593
|
+
if (lastSystemErrorLineIdx >= 0 && lastSystemErrorLineIdx > latestChooserIdx) {
|
|
1594
|
+
if (latestChooserIdx >= 0) {
|
|
1595
|
+
const remainingLines = lines.slice(lastSystemErrorLineIdx + 1).join("\n");
|
|
1596
|
+
if (latestChooserIdx === lastQuestionLineIdx) {
|
|
1597
|
+
const hasQuestionOptions = /^[>\s]*[1-9]\. \S/im.test(remainingLines);
|
|
1598
|
+
const hasQuestionFooter = /\benter Select\b/i.test(remainingLines);
|
|
1599
|
+
if (hasQuestionOptions && hasQuestionFooter) {
|
|
1600
|
+
return "question";
|
|
1601
|
+
}
|
|
1602
|
+
} else if (latestChooserIdx === lastFileAccessLineIdx) {
|
|
1603
|
+
const hasFileAccessQuestion = /Allow access to this file\?/i.test(remainingLines);
|
|
1604
|
+
const hasApprovalOptions = /^[>\s]*[1-9]\. (?:Yes|No)\b/im.test(remainingLines);
|
|
1605
|
+
const hasApprovalFooter = /\besc to cancel\b/i.test(remainingLines);
|
|
1606
|
+
if (hasFileAccessQuestion && hasApprovalOptions && hasApprovalFooter) {
|
|
1607
|
+
return "file_access";
|
|
1608
|
+
}
|
|
1609
|
+
} else if (latestChooserIdx === lastApprovalLineIdx) {
|
|
1610
|
+
const hasApprovalOptions = /^[>\s]*[1-9]\. (?:Yes|No)\b/im.test(remainingLines);
|
|
1611
|
+
const hasApprovalFooter = /\besc to cancel\b/i.test(remainingLines);
|
|
1612
|
+
if (hasApprovalOptions && hasApprovalFooter) {
|
|
1613
|
+
return "approval";
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1467
1616
|
}
|
|
1468
|
-
if (
|
|
1469
|
-
|
|
1617
|
+
if (isSystemErrorActiveFromIndex(lines, lastSystemErrorLineIdx)) {
|
|
1618
|
+
return "system_error";
|
|
1470
1619
|
}
|
|
1471
|
-
|
|
1620
|
+
return null;
|
|
1621
|
+
}
|
|
1622
|
+
if (latestChooserIdx < 0) return null;
|
|
1623
|
+
if (latestChooserIdx === lastFileAccessLineIdx) {
|
|
1624
|
+
return "file_access";
|
|
1625
|
+
}
|
|
1626
|
+
if (latestChooserIdx === lastQuestionLineIdx) {
|
|
1627
|
+
return "question";
|
|
1472
1628
|
}
|
|
1473
|
-
const latest = Math.max(lastApprovalLineIdx, lastQuestionLineIdx, lastFileAccessLineIdx);
|
|
1474
|
-
if (latest < 0) return null;
|
|
1475
|
-
if (latest === lastFileAccessLineIdx) return "file_access";
|
|
1476
|
-
if (latest === lastQuestionLineIdx) return "question";
|
|
1477
1629
|
return "approval";
|
|
1478
1630
|
}
|
|
1631
|
+
var SYSTEM_ERROR_COMPLETE_WORDS = /* @__PURE__ */ new Set([
|
|
1632
|
+
"our",
|
|
1633
|
+
"servers",
|
|
1634
|
+
"server",
|
|
1635
|
+
"are",
|
|
1636
|
+
"experiencing",
|
|
1637
|
+
"experience",
|
|
1638
|
+
"high",
|
|
1639
|
+
"traffic",
|
|
1640
|
+
"right",
|
|
1641
|
+
"now",
|
|
1642
|
+
"please",
|
|
1643
|
+
"try",
|
|
1644
|
+
"again",
|
|
1645
|
+
"in",
|
|
1646
|
+
"a",
|
|
1647
|
+
"minute",
|
|
1648
|
+
"minutes",
|
|
1649
|
+
"an",
|
|
1650
|
+
"unexpected",
|
|
1651
|
+
"error",
|
|
1652
|
+
"occurred",
|
|
1653
|
+
"the",
|
|
1654
|
+
"model",
|
|
1655
|
+
"is",
|
|
1656
|
+
"overloaded",
|
|
1657
|
+
"later",
|
|
1658
|
+
"stream",
|
|
1659
|
+
"was",
|
|
1660
|
+
"interrupted",
|
|
1661
|
+
"continue",
|
|
1662
|
+
"task",
|
|
1663
|
+
"you",
|
|
1664
|
+
"were",
|
|
1665
|
+
"working",
|
|
1666
|
+
"on",
|
|
1667
|
+
"while",
|
|
1668
|
+
"processing",
|
|
1669
|
+
"your",
|
|
1670
|
+
"connection",
|
|
1671
|
+
"timeout",
|
|
1672
|
+
"temporary",
|
|
1673
|
+
"unavailable",
|
|
1674
|
+
"service",
|
|
1675
|
+
"gateway",
|
|
1676
|
+
"capacity",
|
|
1677
|
+
"exceeded",
|
|
1678
|
+
"resource",
|
|
1679
|
+
"exhausted",
|
|
1680
|
+
"internal",
|
|
1681
|
+
"failure",
|
|
1682
|
+
"request",
|
|
1683
|
+
"response",
|
|
1684
|
+
"refused",
|
|
1685
|
+
"reset",
|
|
1686
|
+
"network",
|
|
1687
|
+
"operation",
|
|
1688
|
+
"aborted",
|
|
1689
|
+
"cancelled",
|
|
1690
|
+
"rate",
|
|
1691
|
+
"limit",
|
|
1692
|
+
"limited",
|
|
1693
|
+
"throttle",
|
|
1694
|
+
"throttled"
|
|
1695
|
+
]);
|
|
1696
|
+
function extractSystemErrorPrompt(snapshot) {
|
|
1697
|
+
const stripped = snapshot.replace(ANSI_ESCAPE_REGEX, "");
|
|
1698
|
+
const lines = stripped.split("\n");
|
|
1699
|
+
let bannerIdx = -1;
|
|
1700
|
+
let rawMessage = "";
|
|
1701
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
1702
|
+
if (isSystemErrorBannerLine(lines[i])) {
|
|
1703
|
+
bannerIdx = i;
|
|
1704
|
+
rawMessage = lines[i].trim();
|
|
1705
|
+
break;
|
|
1706
|
+
}
|
|
1707
|
+
}
|
|
1708
|
+
if (bannerIdx < 0) return null;
|
|
1709
|
+
let message = rawMessage.replace(/^(?:⚠️|⚠\uFE0F?)\s*/, "").trim();
|
|
1710
|
+
let wrapWidth = Array.from(lines[bannerIdx].trimEnd()).length;
|
|
1711
|
+
for (let j = bannerIdx + 1; j < Math.min(lines.length, bannerIdx + 6); j++) {
|
|
1712
|
+
const trimmed = lines[j].trim();
|
|
1713
|
+
if (!trimmed || /^Error ID:/i.test(trimmed) || /^[─━│╭╰╮╯\s_-]*$/.test(trimmed) || /^[│\s]*[❯>]/.test(trimmed)) break;
|
|
1714
|
+
const len = Array.from(lines[j].trimEnd()).length;
|
|
1715
|
+
if (len > wrapWidth) wrapWidth = len;
|
|
1716
|
+
}
|
|
1717
|
+
let errorId;
|
|
1718
|
+
for (let j = bannerIdx + 1; j < Math.min(lines.length, bannerIdx + 6); j++) {
|
|
1719
|
+
const trimmed = lines[j].trim();
|
|
1720
|
+
if (!trimmed) continue;
|
|
1721
|
+
if (/^[─━│╭╰╮╯\s_-]*$/.test(trimmed)) break;
|
|
1722
|
+
if (/^[│\s]*[❯>]/.test(trimmed)) break;
|
|
1723
|
+
const idMatch = trimmed.match(/^Error ID:\s*([0-9a-fA-F-]*)/i);
|
|
1724
|
+
if (idMatch) {
|
|
1725
|
+
if (idMatch[1]) {
|
|
1726
|
+
errorId = idMatch[1].trim();
|
|
1727
|
+
}
|
|
1728
|
+
let k = j + 1;
|
|
1729
|
+
while (k < lines.length) {
|
|
1730
|
+
const nextRaw = lines[k];
|
|
1731
|
+
if (!nextRaw.trim()) break;
|
|
1732
|
+
const nextPiece = nextRaw.trim().match(/^([0-9a-fA-F-]+)$/);
|
|
1733
|
+
if (nextPiece && /[0-9a-fA-F]/.test(nextPiece[1]) && !/^[─━│╭╰╮╯\s_-]*$/.test(nextPiece[1])) {
|
|
1734
|
+
errorId = `${errorId || ""}${nextPiece[1].trim()}`;
|
|
1735
|
+
k++;
|
|
1736
|
+
} else {
|
|
1737
|
+
break;
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1740
|
+
break;
|
|
1741
|
+
}
|
|
1742
|
+
const prevRaw = lines[j - 1];
|
|
1743
|
+
if (message.endsWith("-") || trimmed.startsWith("-")) {
|
|
1744
|
+
message = `${message}${trimmed}`;
|
|
1745
|
+
} else if (/^[.,!?:;]/.test(trimmed)) {
|
|
1746
|
+
message = `${message}${trimmed}`;
|
|
1747
|
+
} else {
|
|
1748
|
+
const prevEndedAlnum = /[a-zA-Z0-9]$/.test(message);
|
|
1749
|
+
const nextStartsAlnum = /^[a-zA-Z0-9]/.test(trimmed);
|
|
1750
|
+
const prevHadSpace = /\s$/.test(prevRaw);
|
|
1751
|
+
const nextHadSpace = /^\s/.test(lines[j]);
|
|
1752
|
+
const prevLen = Array.from(prevRaw.trimEnd()).length;
|
|
1753
|
+
const prevWord = ((message.match(/([a-zA-Z0-9]+)$/) || [])[1] || "").toLowerCase();
|
|
1754
|
+
const nextWord = ((trimmed.match(/^([a-zA-Z0-9]+)/) || [])[1] || "").toLowerCase();
|
|
1755
|
+
const isTwoCompleteWords = SYSTEM_ERROR_COMPLETE_WORDS.has(prevWord) && SYSTEM_ERROR_COMPLETE_WORDS.has(nextWord);
|
|
1756
|
+
const reachedMargin = prevLen >= wrapWidth - 1;
|
|
1757
|
+
const isPhysicalWrap = !prevHadSpace && !nextHadSpace && prevEndedAlnum && nextStartsAlnum && reachedMargin && !isTwoCompleteWords;
|
|
1758
|
+
if (isPhysicalWrap) {
|
|
1759
|
+
message = `${message}${trimmed}`;
|
|
1760
|
+
} else {
|
|
1761
|
+
message = `${message} ${trimmed}`.trim();
|
|
1762
|
+
}
|
|
1763
|
+
}
|
|
1764
|
+
}
|
|
1765
|
+
const fullLine = errorId ? `\u26A0\uFE0F Antigravity error: ${message} (Error ID: ${errorId})` : `\u26A0\uFE0F Antigravity error: ${message}`;
|
|
1766
|
+
return { message, errorId, fullLine };
|
|
1767
|
+
}
|
|
1479
1768
|
function extractQuestionHeader(snapshot) {
|
|
1480
1769
|
const stripped = snapshot.replace(ANSI_ESCAPE_REGEX, "");
|
|
1481
1770
|
const matches = Array.from(stripped.matchAll(/Question \d+\/\d+:\s*([^\n]+)/gi));
|
|
@@ -1524,6 +1813,12 @@ function parseApprovalSnapshot(snapshot) {
|
|
|
1524
1813
|
return parseQuestionSnapshot(stripped, snapshot, questionHeader);
|
|
1525
1814
|
}
|
|
1526
1815
|
}
|
|
1816
|
+
if (kind === "system_error") {
|
|
1817
|
+
const systemError = extractSystemErrorPrompt(stripped);
|
|
1818
|
+
if (systemError) {
|
|
1819
|
+
return parseSystemErrorSnapshot(stripped, snapshot, systemError);
|
|
1820
|
+
}
|
|
1821
|
+
}
|
|
1527
1822
|
return parseApprovalUISnapshot(stripped, snapshot);
|
|
1528
1823
|
}
|
|
1529
1824
|
function buildApprovalSemanticKey(candidate) {
|
|
@@ -1569,6 +1864,19 @@ function parseFileAccessSnapshot(stripped, originalSnapshot, prompt) {
|
|
|
1569
1864
|
paneHash: hashPromptSnapshot(originalSnapshot)
|
|
1570
1865
|
};
|
|
1571
1866
|
}
|
|
1867
|
+
function parseSystemErrorSnapshot(stripped, originalSnapshot, prompt) {
|
|
1868
|
+
return {
|
|
1869
|
+
kind: "system_error",
|
|
1870
|
+
headerText: prompt.message,
|
|
1871
|
+
fullHeaderLine: prompt.fullLine,
|
|
1872
|
+
command: void 0,
|
|
1873
|
+
filePath: void 0,
|
|
1874
|
+
options: [],
|
|
1875
|
+
submitMap: {},
|
|
1876
|
+
body: prompt.errorId ? `Error ID: ${prompt.errorId}` : "",
|
|
1877
|
+
paneHash: hashPromptSnapshot(originalSnapshot)
|
|
1878
|
+
};
|
|
1879
|
+
}
|
|
1572
1880
|
function parseApprovalUISnapshot(stripped, originalSnapshot) {
|
|
1573
1881
|
const headerText = extractHeader(stripped);
|
|
1574
1882
|
if (!headerText) return null;
|
|
@@ -4290,14 +4598,16 @@ var McpServer = class _McpServer {
|
|
|
4290
4598
|
* Content is E2E-encrypted; the raise identity rides plaintext top-level.
|
|
4291
4599
|
* Fail-closed on a missing session key — never cleartext.
|
|
4292
4600
|
*/
|
|
4293
|
-
async emitSuppressedPromptCarrier(session, record) {
|
|
4294
|
-
const bannerText = "\u26A0\uFE0F A prompt is waiting in your desktop terminal, but its options could not be shown here. Please answer it on your desktop.";
|
|
4601
|
+
async emitSuppressedPromptCarrier(session, record, customBannerText) {
|
|
4602
|
+
const bannerText = customBannerText || "\u26A0\uFE0F A prompt is waiting in your desktop terminal, but its options could not be shown here. Please answer it on your desktop.";
|
|
4295
4603
|
const input = {
|
|
4296
4604
|
sessionId: session.sessionId,
|
|
4297
4605
|
type: import_codevibe_core5.EventType.NOTIFICATION,
|
|
4298
4606
|
source: import_codevibe_core5.EventSource.DESKTOP,
|
|
4299
4607
|
content: bannerText,
|
|
4300
|
-
metadata: {
|
|
4608
|
+
metadata: {
|
|
4609
|
+
e1SuppressedPrompt: true
|
|
4610
|
+
},
|
|
4301
4611
|
...(0, import_codevibe_core5.raiseFieldsFromRecord)(record),
|
|
4302
4612
|
notificationText: bannerText,
|
|
4303
4613
|
timestamp: (0, import_codevibe_core5.prepareEventTimestamp)({ orderingKey: session.sessionId })
|
|
@@ -4318,7 +4628,7 @@ var McpServer = class _McpServer {
|
|
|
4318
4628
|
* NOTIFICATION carrier. A null content-key always mints (can't prove a
|
|
4319
4629
|
* re-observation) — never under-nag.
|
|
4320
4630
|
*/
|
|
4321
|
-
raiseSuppressedBadge(session, contentKey) {
|
|
4631
|
+
raiseSuppressedBadge(session, contentKey, customBannerText) {
|
|
4322
4632
|
if (contentKey) {
|
|
4323
4633
|
const idxKey = `${session.sessionId}::${contentKey}`;
|
|
4324
4634
|
const existingId = this.e1ContentKeyIndex.get(idxKey);
|
|
@@ -4327,7 +4637,13 @@ var McpServer = class _McpServer {
|
|
|
4327
4637
|
}
|
|
4328
4638
|
const record = this.newE1Raise(session.sessionId, false);
|
|
4329
4639
|
if (contentKey) this.e1ContentKeyIndex.set(`${session.sessionId}::${contentKey}`, record.promptId);
|
|
4330
|
-
|
|
4640
|
+
if (customBannerText) {
|
|
4641
|
+
const entry = this.e1PromptRaises.get(record.promptId);
|
|
4642
|
+
if (entry) {
|
|
4643
|
+
entry.contentPlain = customBannerText;
|
|
4644
|
+
}
|
|
4645
|
+
}
|
|
4646
|
+
this.emitSuppressedPromptCarrier(session, record, customBannerText).catch((e) => {
|
|
4331
4647
|
logger.error("E1: failed to emit suppressed-prompt badge carrier", {
|
|
4332
4648
|
sessionId: session.sessionId,
|
|
4333
4649
|
promptId: record.promptId,
|
|
@@ -4495,7 +4811,7 @@ var McpServer = class _McpServer {
|
|
|
4495
4811
|
if (!await this.createEncryptedEvent(session, input)) return false;
|
|
4496
4812
|
} else {
|
|
4497
4813
|
rec.mobileActionable = false;
|
|
4498
|
-
if (!await this.emitSuppressedPromptCarrier(session, rec)) return false;
|
|
4814
|
+
if (!await this.emitSuppressedPromptCarrier(session, rec, entry.contentPlain)) return false;
|
|
4499
4815
|
}
|
|
4500
4816
|
this.e1NeedsReRaise.delete(rec.promptId);
|
|
4501
4817
|
logger.info("E1: re-raised prompt onto replacement session", {
|
|
@@ -4708,6 +5024,10 @@ var McpServer = class _McpServer {
|
|
|
4708
5024
|
this.raiseSuppressedBadge(session, cand.snapshotHash);
|
|
4709
5025
|
return;
|
|
4710
5026
|
}
|
|
5027
|
+
if (parsed.kind === "system_error") {
|
|
5028
|
+
this.raiseSuppressedBadge(session, cand.snapshotHash, parsed.fullHeaderLine);
|
|
5029
|
+
return;
|
|
5030
|
+
}
|
|
4711
5031
|
const activeConvId = this.pickActiveConversationForPrompt();
|
|
4712
5032
|
if (!activeConvId) {
|
|
4713
5033
|
logger.warn("Prompt candidate fired but no active conversation known", {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quantiya/codevibe-antigravity-plugin",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.31",
|
|
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
|
"codevibe": {
|