@ccpocket/bridge 1.6.1 → 1.7.0
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/cli.js +14 -2
- package/dist/cli.js.map +1 -1
- package/dist/doctor.d.ts +49 -0
- package/dist/doctor.js +517 -0
- package/dist/doctor.js.map +1 -0
- package/dist/parser.d.ts +30 -0
- package/dist/parser.js +8 -0
- package/dist/parser.js.map +1 -1
- package/dist/websocket.d.ts +21 -0
- package/dist/websocket.js +198 -3
- package/dist/websocket.js.map +1 -1
- package/dist/worktree.d.ts +2 -0
- package/dist/worktree.js +13 -0
- package/dist/worktree.js.map +1 -1
- package/package.json +3 -2
package/dist/parser.d.ts
CHANGED
|
@@ -146,6 +146,11 @@ export type ClientMessage = {
|
|
|
146
146
|
} | {
|
|
147
147
|
type: "get_diff";
|
|
148
148
|
projectPath: string;
|
|
149
|
+
} | {
|
|
150
|
+
type: "get_diff_image";
|
|
151
|
+
projectPath: string;
|
|
152
|
+
filePath: string;
|
|
153
|
+
version: "old" | "new";
|
|
149
154
|
} | {
|
|
150
155
|
type: "interrupt";
|
|
151
156
|
sessionId?: string;
|
|
@@ -209,6 +214,22 @@ export type ClientMessage = {
|
|
|
209
214
|
provider: Provider;
|
|
210
215
|
projectPath: string;
|
|
211
216
|
};
|
|
217
|
+
/** Image change detected in a git diff (binary image file). */
|
|
218
|
+
export interface ImageChange {
|
|
219
|
+
filePath: string;
|
|
220
|
+
isNew: boolean;
|
|
221
|
+
isDeleted: boolean;
|
|
222
|
+
isSvg: boolean;
|
|
223
|
+
oldSize?: number;
|
|
224
|
+
newSize?: number;
|
|
225
|
+
/** Base64-encoded old image (included only when size ≤ 200KB). */
|
|
226
|
+
oldBase64?: string;
|
|
227
|
+
/** Base64-encoded new image (included only when size ≤ 200KB). */
|
|
228
|
+
newBase64?: string;
|
|
229
|
+
mimeType: string;
|
|
230
|
+
/** Whether the image can be loaded on demand (200KB–2MB range). */
|
|
231
|
+
loadable: boolean;
|
|
232
|
+
}
|
|
212
233
|
export interface DebugTraceEvent {
|
|
213
234
|
ts: string;
|
|
214
235
|
sessionId: string;
|
|
@@ -289,9 +310,18 @@ export type ServerMessage = {
|
|
|
289
310
|
type: "diff_result";
|
|
290
311
|
diff: string;
|
|
291
312
|
error?: string;
|
|
313
|
+
imageChanges?: ImageChange[];
|
|
314
|
+
} | {
|
|
315
|
+
type: "diff_image_result";
|
|
316
|
+
filePath: string;
|
|
317
|
+
version: "old" | "new";
|
|
318
|
+
base64?: string;
|
|
319
|
+
mimeType?: string;
|
|
320
|
+
error?: string;
|
|
292
321
|
} | {
|
|
293
322
|
type: "worktree_list";
|
|
294
323
|
worktrees: WorktreeInfo[];
|
|
324
|
+
mainBranch?: string;
|
|
295
325
|
} | {
|
|
296
326
|
type: "worktree_removed";
|
|
297
327
|
worktreePath: string;
|
package/dist/parser.js
CHANGED
|
@@ -151,6 +151,14 @@ export function parseClientMessage(data) {
|
|
|
151
151
|
if (typeof msg.projectPath !== "string")
|
|
152
152
|
return null;
|
|
153
153
|
break;
|
|
154
|
+
case "get_diff_image":
|
|
155
|
+
if (typeof msg.projectPath !== "string")
|
|
156
|
+
return null;
|
|
157
|
+
if (typeof msg.filePath !== "string")
|
|
158
|
+
return null;
|
|
159
|
+
if (msg.version !== "old" && msg.version !== "new")
|
|
160
|
+
return null;
|
|
161
|
+
break;
|
|
154
162
|
case "interrupt":
|
|
155
163
|
break;
|
|
156
164
|
case "list_project_history":
|
package/dist/parser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"parser.js","sourceRoot":"","sources":["../src/parser.ts"],"names":[],"mappings":"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"}
|
package/dist/websocket.d.ts
CHANGED
|
@@ -78,6 +78,27 @@ export declare class BridgeWebSocketServer {
|
|
|
78
78
|
/** Broadcast a gallery_new_image message to all connected clients. */
|
|
79
79
|
broadcastGalleryNewImage(image: import("./gallery-store.js").GalleryImageInfo): void;
|
|
80
80
|
private collectGitDiff;
|
|
81
|
+
private static readonly IMAGE_EXTENSIONS;
|
|
82
|
+
private static readonly AUTO_DISPLAY_THRESHOLD;
|
|
83
|
+
private static readonly MAX_IMAGE_SIZE;
|
|
84
|
+
private static mimeTypeForExt;
|
|
85
|
+
/**
|
|
86
|
+
* Scan diff text for image file changes and extract base64 data where appropriate.
|
|
87
|
+
*
|
|
88
|
+
* Detection strategy:
|
|
89
|
+
* 1. Binary markers: "Binary files a/<path> and b/<path> differ"
|
|
90
|
+
* 2. diff --git headers where the file extension is an image type
|
|
91
|
+
*
|
|
92
|
+
* For each detected image file:
|
|
93
|
+
* - Old version: `git show HEAD:<path>` (committed version)
|
|
94
|
+
* - New version: read from working tree
|
|
95
|
+
* - Apply size thresholds for auto-display / on-demand / text-only
|
|
96
|
+
*/
|
|
97
|
+
private collectImageChanges;
|
|
98
|
+
/**
|
|
99
|
+
* Load a single diff image on demand (for images between auto-display and max thresholds).
|
|
100
|
+
*/
|
|
101
|
+
private loadDiffImage;
|
|
81
102
|
private extractSessionIdFromClientMessage;
|
|
82
103
|
private extractSessionIdFromServerMessage;
|
|
83
104
|
private recordDebugEvent;
|
package/dist/websocket.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { execFile, execFileSync } from "node:child_process";
|
|
2
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
2
3
|
import { unlink } from "node:fs/promises";
|
|
4
|
+
import { resolve, extname } from "node:path";
|
|
3
5
|
import { WebSocketServer, WebSocket } from "ws";
|
|
4
6
|
import { SessionManager } from "./session.js";
|
|
5
7
|
import { SdkProcess } from "./sdk-process.js";
|
|
@@ -7,7 +9,7 @@ import { parseClientMessage } from "./parser.js";
|
|
|
7
9
|
import { getAllRecentSessions, getCodexSessionHistory, getSessionHistory, findSessionsByClaudeIds, extractMessageImages, getClaudeSessionName, loadCodexSessionNames, renameClaudeSession, renameCodexSession } from "./sessions-index.js";
|
|
8
10
|
import { ArchiveStore } from "./archive-store.js";
|
|
9
11
|
import { WorktreeStore } from "./worktree-store.js";
|
|
10
|
-
import { listWorktrees, removeWorktree, worktreeExists } from "./worktree.js";
|
|
12
|
+
import { listWorktrees, removeWorktree, worktreeExists, getMainBranch } from "./worktree.js";
|
|
11
13
|
import { listWindows, takeScreenshot } from "./screenshot.js";
|
|
12
14
|
import { DebugTraceStore } from "./debug-trace-store.js";
|
|
13
15
|
import { RecordingStore } from "./recording-store.js";
|
|
@@ -959,14 +961,27 @@ export class BridgeWebSocketServer {
|
|
|
959
961
|
this.send(ws, { type: "diff_result", diff: "", error: `Failed to get diff: ${error}` });
|
|
960
962
|
return;
|
|
961
963
|
}
|
|
962
|
-
this.
|
|
964
|
+
void this.collectImageChanges(msg.projectPath, diff).then((imageChanges) => {
|
|
965
|
+
if (imageChanges.length > 0) {
|
|
966
|
+
this.send(ws, { type: "diff_result", diff, imageChanges });
|
|
967
|
+
}
|
|
968
|
+
else {
|
|
969
|
+
this.send(ws, { type: "diff_result", diff });
|
|
970
|
+
}
|
|
971
|
+
});
|
|
963
972
|
});
|
|
964
973
|
break;
|
|
965
974
|
}
|
|
975
|
+
case "get_diff_image": {
|
|
976
|
+
const result = this.loadDiffImage(msg.projectPath, msg.filePath, msg.version);
|
|
977
|
+
this.send(ws, { type: "diff_image_result", filePath: msg.filePath, version: msg.version, ...result });
|
|
978
|
+
break;
|
|
979
|
+
}
|
|
966
980
|
case "list_worktrees": {
|
|
967
981
|
try {
|
|
968
982
|
const worktrees = listWorktrees(msg.projectPath);
|
|
969
|
-
|
|
983
|
+
const mainBranch = getMainBranch(msg.projectPath);
|
|
984
|
+
this.send(ws, { type: "worktree_list", worktrees, mainBranch });
|
|
970
985
|
}
|
|
971
986
|
catch (err) {
|
|
972
987
|
this.send(ws, { type: "error", message: `Failed to list worktrees: ${err}` });
|
|
@@ -1542,6 +1557,186 @@ export class BridgeWebSocketServer {
|
|
|
1542
1557
|
callback({ diff: stdout });
|
|
1543
1558
|
});
|
|
1544
1559
|
}
|
|
1560
|
+
// ---------------------------------------------------------------------------
|
|
1561
|
+
// Image diff helpers
|
|
1562
|
+
// ---------------------------------------------------------------------------
|
|
1563
|
+
static IMAGE_EXTENSIONS = new Set([
|
|
1564
|
+
".png", ".jpg", ".jpeg", ".gif", ".webp", ".ico", ".bmp", ".svg",
|
|
1565
|
+
]);
|
|
1566
|
+
// Image diff thresholds (configurable via environment variables)
|
|
1567
|
+
// - Auto-display: images ≤ threshold are sent inline as base64
|
|
1568
|
+
// - Max size: images ≤ max are available for on-demand loading
|
|
1569
|
+
// - Images > max size show text info only
|
|
1570
|
+
static AUTO_DISPLAY_THRESHOLD = (() => {
|
|
1571
|
+
const kb = parseInt(process.env.DIFF_IMAGE_AUTO_DISPLAY_KB ?? "", 10);
|
|
1572
|
+
return Number.isFinite(kb) && kb > 0 ? kb * 1024 : 1024 * 1024; // default 1 MB
|
|
1573
|
+
})();
|
|
1574
|
+
static MAX_IMAGE_SIZE = (() => {
|
|
1575
|
+
const mb = parseInt(process.env.DIFF_IMAGE_MAX_SIZE_MB ?? "", 10);
|
|
1576
|
+
return Number.isFinite(mb) && mb > 0 ? mb * 1024 * 1024 : 5 * 1024 * 1024; // default 5 MB
|
|
1577
|
+
})();
|
|
1578
|
+
static mimeTypeForExt(ext) {
|
|
1579
|
+
const map = {
|
|
1580
|
+
".png": "image/png",
|
|
1581
|
+
".jpg": "image/jpeg",
|
|
1582
|
+
".jpeg": "image/jpeg",
|
|
1583
|
+
".gif": "image/gif",
|
|
1584
|
+
".webp": "image/webp",
|
|
1585
|
+
".ico": "image/x-icon",
|
|
1586
|
+
".bmp": "image/bmp",
|
|
1587
|
+
".svg": "image/svg+xml",
|
|
1588
|
+
};
|
|
1589
|
+
return map[ext.toLowerCase()] ?? "application/octet-stream";
|
|
1590
|
+
}
|
|
1591
|
+
/**
|
|
1592
|
+
* Scan diff text for image file changes and extract base64 data where appropriate.
|
|
1593
|
+
*
|
|
1594
|
+
* Detection strategy:
|
|
1595
|
+
* 1. Binary markers: "Binary files a/<path> and b/<path> differ"
|
|
1596
|
+
* 2. diff --git headers where the file extension is an image type
|
|
1597
|
+
*
|
|
1598
|
+
* For each detected image file:
|
|
1599
|
+
* - Old version: `git show HEAD:<path>` (committed version)
|
|
1600
|
+
* - New version: read from working tree
|
|
1601
|
+
* - Apply size thresholds for auto-display / on-demand / text-only
|
|
1602
|
+
*/
|
|
1603
|
+
async collectImageChanges(cwd, diffText) {
|
|
1604
|
+
const entries = [];
|
|
1605
|
+
const processedPaths = new Set();
|
|
1606
|
+
const lines = diffText.split("\n");
|
|
1607
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1608
|
+
const line = lines[i];
|
|
1609
|
+
const gitMatch = line.match(/^diff --git a\/(.+?) b\/(.+)$/);
|
|
1610
|
+
if (!gitMatch)
|
|
1611
|
+
continue;
|
|
1612
|
+
const filePath = gitMatch[2];
|
|
1613
|
+
const ext = extname(filePath).toLowerCase();
|
|
1614
|
+
if (!BridgeWebSocketServer.IMAGE_EXTENSIONS.has(ext))
|
|
1615
|
+
continue;
|
|
1616
|
+
if (processedPaths.has(filePath))
|
|
1617
|
+
continue;
|
|
1618
|
+
processedPaths.add(filePath);
|
|
1619
|
+
let isNew = false;
|
|
1620
|
+
let isDeleted = false;
|
|
1621
|
+
for (let j = i + 1; j < Math.min(i + 6, lines.length); j++) {
|
|
1622
|
+
if (lines[j].startsWith("diff --git "))
|
|
1623
|
+
break;
|
|
1624
|
+
if (lines[j].startsWith("new file mode"))
|
|
1625
|
+
isNew = true;
|
|
1626
|
+
if (lines[j].startsWith("deleted file mode"))
|
|
1627
|
+
isDeleted = true;
|
|
1628
|
+
}
|
|
1629
|
+
entries.push({
|
|
1630
|
+
filePath,
|
|
1631
|
+
isNew,
|
|
1632
|
+
isDeleted,
|
|
1633
|
+
isSvg: ext === ".svg",
|
|
1634
|
+
mimeType: BridgeWebSocketServer.mimeTypeForExt(ext),
|
|
1635
|
+
ext,
|
|
1636
|
+
});
|
|
1637
|
+
}
|
|
1638
|
+
if (entries.length === 0)
|
|
1639
|
+
return [];
|
|
1640
|
+
// Phase 2: Read image data asynchronously
|
|
1641
|
+
const { readFile } = await import("node:fs/promises");
|
|
1642
|
+
const { promisify } = await import("node:util");
|
|
1643
|
+
const execFileAsync = promisify(execFile);
|
|
1644
|
+
const changes = [];
|
|
1645
|
+
for (const entry of entries) {
|
|
1646
|
+
let oldBuf;
|
|
1647
|
+
let newBuf;
|
|
1648
|
+
// Read old image (committed version)
|
|
1649
|
+
if (!entry.isNew) {
|
|
1650
|
+
try {
|
|
1651
|
+
const result = await execFileAsync("git", ["show", `HEAD:${entry.filePath}`], {
|
|
1652
|
+
cwd,
|
|
1653
|
+
maxBuffer: BridgeWebSocketServer.MAX_IMAGE_SIZE + 1024,
|
|
1654
|
+
encoding: "buffer",
|
|
1655
|
+
});
|
|
1656
|
+
oldBuf = result.stdout;
|
|
1657
|
+
}
|
|
1658
|
+
catch {
|
|
1659
|
+
// File may not exist in HEAD (e.g. untracked)
|
|
1660
|
+
}
|
|
1661
|
+
}
|
|
1662
|
+
// Read new image (working tree)
|
|
1663
|
+
if (!entry.isDeleted) {
|
|
1664
|
+
try {
|
|
1665
|
+
const absPath = resolve(cwd, entry.filePath);
|
|
1666
|
+
if (existsSync(absPath)) {
|
|
1667
|
+
newBuf = await readFile(absPath);
|
|
1668
|
+
}
|
|
1669
|
+
}
|
|
1670
|
+
catch {
|
|
1671
|
+
// Ignore read errors
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
const oldSize = oldBuf?.length;
|
|
1675
|
+
const newSize = newBuf?.length;
|
|
1676
|
+
const maxSize = Math.max(oldSize ?? 0, newSize ?? 0);
|
|
1677
|
+
const autoDisplay = maxSize <= BridgeWebSocketServer.AUTO_DISPLAY_THRESHOLD;
|
|
1678
|
+
const loadable = !autoDisplay && maxSize <= BridgeWebSocketServer.MAX_IMAGE_SIZE;
|
|
1679
|
+
const change = {
|
|
1680
|
+
filePath: entry.filePath,
|
|
1681
|
+
isNew: entry.isNew,
|
|
1682
|
+
isDeleted: entry.isDeleted,
|
|
1683
|
+
isSvg: entry.isSvg,
|
|
1684
|
+
mimeType: entry.mimeType,
|
|
1685
|
+
loadable,
|
|
1686
|
+
};
|
|
1687
|
+
if (oldSize !== undefined)
|
|
1688
|
+
change.oldSize = oldSize;
|
|
1689
|
+
if (newSize !== undefined)
|
|
1690
|
+
change.newSize = newSize;
|
|
1691
|
+
if (autoDisplay) {
|
|
1692
|
+
if (oldBuf)
|
|
1693
|
+
change.oldBase64 = oldBuf.toString("base64");
|
|
1694
|
+
if (newBuf)
|
|
1695
|
+
change.newBase64 = newBuf.toString("base64");
|
|
1696
|
+
}
|
|
1697
|
+
changes.push(change);
|
|
1698
|
+
}
|
|
1699
|
+
return changes;
|
|
1700
|
+
}
|
|
1701
|
+
/**
|
|
1702
|
+
* Load a single diff image on demand (for images between auto-display and max thresholds).
|
|
1703
|
+
*/
|
|
1704
|
+
loadDiffImage(cwd, filePath, version) {
|
|
1705
|
+
// Path traversal guard: reject paths containing '..' or absolute paths
|
|
1706
|
+
if (filePath.includes("..") || filePath.startsWith("/")) {
|
|
1707
|
+
return { error: "Invalid file path" };
|
|
1708
|
+
}
|
|
1709
|
+
const ext = extname(filePath).toLowerCase();
|
|
1710
|
+
if (!BridgeWebSocketServer.IMAGE_EXTENSIONS.has(ext)) {
|
|
1711
|
+
return { error: "Not an image file" };
|
|
1712
|
+
}
|
|
1713
|
+
const mimeType = BridgeWebSocketServer.mimeTypeForExt(ext);
|
|
1714
|
+
try {
|
|
1715
|
+
let buf;
|
|
1716
|
+
if (version === "old") {
|
|
1717
|
+
buf = execFileSync("git", ["show", `HEAD:${filePath}`], {
|
|
1718
|
+
cwd,
|
|
1719
|
+
maxBuffer: BridgeWebSocketServer.MAX_IMAGE_SIZE + 1024,
|
|
1720
|
+
encoding: "buffer",
|
|
1721
|
+
});
|
|
1722
|
+
}
|
|
1723
|
+
else {
|
|
1724
|
+
const absPath = resolve(cwd, filePath);
|
|
1725
|
+
// Verify resolved path stays within cwd
|
|
1726
|
+
if (!absPath.startsWith(resolve(cwd) + "/")) {
|
|
1727
|
+
return { error: "Invalid file path" };
|
|
1728
|
+
}
|
|
1729
|
+
buf = readFileSync(absPath);
|
|
1730
|
+
}
|
|
1731
|
+
if (buf.length > BridgeWebSocketServer.MAX_IMAGE_SIZE) {
|
|
1732
|
+
return { error: "Image too large" };
|
|
1733
|
+
}
|
|
1734
|
+
return { base64: buf.toString("base64"), mimeType };
|
|
1735
|
+
}
|
|
1736
|
+
catch (err) {
|
|
1737
|
+
return { error: err instanceof Error ? err.message : String(err) };
|
|
1738
|
+
}
|
|
1739
|
+
}
|
|
1545
1740
|
extractSessionIdFromClientMessage(msg) {
|
|
1546
1741
|
return "sessionId" in msg && typeof msg.sessionId === "string" ? msg.sessionId : undefined;
|
|
1547
1742
|
}
|