fix(observer): text-level markdown table wrapping for Discord — AG Native uses divs not HTML tables (v0.5.59) #task-634

This commit is contained in:
Variet Worker
2026-04-18 06:46:21 +09:00
parent c7f939ce85
commit 98b7585e3c
3 changed files with 60 additions and 4 deletions

View File

@@ -1,12 +1,12 @@
{ {
"name": "gravity-bridge", "name": "gravity-bridge",
"version": "0.5.58", "version": "0.5.59",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "gravity-bridge", "name": "gravity-bridge",
"version": "0.5.58", "version": "0.5.59",
"dependencies": { "dependencies": {
"cheerio": "^1.2.0", "cheerio": "^1.2.0",
"ws": "^8.19.0" "ws": "^8.19.0"

View File

@@ -2,7 +2,7 @@
"name": "gravity-bridge", "name": "gravity-bridge",
"displayName": "Gravity Bridge", "displayName": "Gravity Bridge",
"description": "Discord-based unified approval system for Antigravity AI interactions.", "description": "Discord-based unified approval system for Antigravity AI interactions.",
"version": "0.5.58", "version": "0.5.59",
"publisher": "variet", "publisher": "variet",
"engines": { "engines": {
"vscode": "^1.100.0" "vscode": "^1.100.0"

View File

@@ -648,7 +648,63 @@ export function generateApprovalObserverScript(_port: number): string {
} }
} }
return finalLines.join('\\n').substring(0, 3500); // v19: Post-process — wrap markdown table patterns in code blocks for Discord
// AG Native renders tables as divs, not <table> HTML, so DOM-level handler can't catch them.
// Detect consecutive lines with pipe separators (| col1 | col2 |) and wrap in code block fences
var bt = String.fromCharCode(96, 96, 96);
var result = [];
var tableBlock = [];
var inCodeBlock = false;
for (var fi = 0; fi < finalLines.length; fi++) {
var fl = finalLines[fi];
// Track existing code blocks to avoid double-wrapping
if (fl.trim().indexOf(bt) === 0) {
inCodeBlock = !inCodeBlock;
// Flush any pending table block before code block marker
if (tableBlock.length > 0) {
result.push(bt);
for (var ti = 0; ti < tableBlock.length; ti++) result.push(tableBlock[ti]);
result.push(bt);
tableBlock = [];
}
result.push(fl);
continue;
}
if (inCodeBlock) {
result.push(fl);
continue;
}
// Detect table row: has at least 2 pipe characters and content between them
var pipeCount = 0;
for (var pc = 0; pc < fl.length; pc++) { if (fl.charAt(pc) === '|') pipeCount++; }
var isTableRow = pipeCount >= 2 && fl.trim().charAt(0) === '|';
var isSeparator = isTableRow && /^[\\s|:-]+$/.test(fl.trim());
if (isTableRow) {
tableBlock.push(fl);
} else {
// Flush table block if it had enough rows (header + separator + data)
if (tableBlock.length >= 2) {
result.push(bt);
for (var ti2 = 0; ti2 < tableBlock.length; ti2++) result.push(tableBlock[ti2]);
result.push(bt);
} else {
// Not a real table, push lines back normally
for (var ti3 = 0; ti3 < tableBlock.length; ti3++) result.push(tableBlock[ti3]);
}
tableBlock = [];
result.push(fl);
}
}
// Flush trailing table block
if (tableBlock.length >= 2) {
result.push(bt);
for (var ti4 = 0; ti4 < tableBlock.length; ti4++) result.push(tableBlock[ti4]);
result.push(bt);
} else {
for (var ti5 = 0; ti5 < tableBlock.length; ti5++) result.push(tableBlock[ti5]);
}
return result.join('\\n').substring(0, 3500);
} }
function scanChatBodies() { function scanChatBodies() {