@jingyi0605/codingns 0.5.0 → 0.5.5
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/public/assets/AdaptiveButlerPage-CUyNL98E.js +3 -0
- package/dist/public/assets/App-BFP7LCSC.js +30 -0
- package/dist/public/assets/{BootstrapPage-Vu5oEJ8z.js → BootstrapPage-G74dX2Us.js} +1 -1
- package/dist/public/assets/ConversationPage-Bz0_tvvM.js +2 -0
- package/dist/public/assets/{DesktopDetachPreviewPage-BgeEqbc5.js → DesktopDetachPreviewPage-IV7oEdOX.js} +1 -1
- package/dist/public/assets/DesktopWindowPage-BBmHyRg5.js +2 -0
- package/dist/public/assets/FileContextPanel--FVTxDrq.js +1 -0
- package/dist/public/assets/GitSidebar-DAiSi9oc.js +6 -0
- package/dist/public/assets/{MobileCreateSessionSheet-DLq5qPkx.js → MobileCreateSessionSheet-DqVwz_Hp.js} +1 -1
- package/dist/public/assets/MobileSheet-D1lMrcvD.js +1 -0
- package/dist/public/assets/{MobileTopHeaderFrame-DArgZI7L.js → MobileTopHeaderFrame-COTc7cRr.js} +1 -1
- package/dist/public/assets/{MobileWorkspaceSwitcherHeader-0ywJKfBQ.js → MobileWorkspaceSwitcherHeader-DJPV9ym2.js} +1 -1
- package/dist/public/assets/RelayConnectEntryPage-dSwU8VzK.js +1 -0
- package/dist/public/assets/{ServerSettingsModal-izoYMx9U.js → ServerSettingsModal-B34ms3ze.js} +1 -1
- package/dist/public/assets/{SessionIndexPage-C5aG8FIv.js → SessionIndexPage-D3tG1gmM.js} +1 -1
- package/dist/public/assets/SettingsPage-B3-6-5GL.js +1 -0
- package/dist/public/assets/TerminalManagerPanel-DhuTEdzV.js +1 -0
- package/dist/public/assets/{TerminalPage-CtKXIU0h.js → TerminalPage-DpsvQQVR.js} +19 -19
- package/dist/public/assets/{TerminalRuntimeFallbackModal-CRhOQOsT.js → TerminalRuntimeFallbackModal-CNzOt5v5.js} +1 -1
- package/dist/public/assets/{ToolFilesPage-DcYPsS-e.js → ToolFilesPage-BX9QDi9Y.js} +1 -1
- package/dist/public/assets/{ToolGitPage-CsPl89ty.js → ToolGitPage-4VtFox3p.js} +1 -1
- package/dist/public/assets/{ToolProcessesPage-D0dvR8xK.js → ToolProcessesPage-DZJC6Qnt.js} +1 -1
- package/dist/public/assets/{ToolsHomePage-4fP-KRiv.js → ToolsHomePage-D7JbrAWv.js} +1 -1
- package/dist/public/assets/{WorkbenchLandingPage-kvlfyxRo.js → WorkbenchLandingPage-C0yqnzqh.js} +1 -1
- package/dist/public/assets/WorkbenchLayout-Brlj8K3i.js +3 -0
- package/dist/public/assets/{WorkbenchModal-Ctob14VR.js → WorkbenchModal-CbDxaCOR.js} +1 -1
- package/dist/public/assets/WorkbenchShellRoute-BMcnFadA.css +1 -0
- package/dist/public/assets/WorkbenchShellRoute-puGpdDFY.js +1 -0
- package/dist/public/assets/{WorkspaceDebugDetailPage-Com5kEXJ.js → WorkspaceDebugDetailPage-fTGweC9N.js} +1 -1
- package/dist/public/assets/WorkspaceDetailPage-BtaIzSDB.js +1 -0
- package/dist/public/assets/WorkspaceHomePage-CUmmYDrM.js +1 -0
- package/dist/public/assets/client-runtime-manager-RHFa_iWo.js +1 -0
- package/dist/public/assets/{default-session-permission-mode-CcGwR4Kk.js → default-session-permission-mode-Cu5SreTG.js} +1 -1
- package/dist/public/assets/file-tree-icon-BMKuc5pw.js +31 -0
- package/dist/public/assets/index-Cq3ue0za.css +1 -0
- package/dist/public/assets/index-DEbFT-Aq.js +42 -0
- package/dist/public/assets/{preferences-service-KIYeE2gk.js → preferences-service-gv_9vGKz.js} +1 -1
- package/dist/public/assets/session-runtime-machine-Bfnxkk9B.js +17 -0
- package/dist/public/assets/{terminal-runtime-meta-AWXJpN4r.js → terminal-runtime-meta-B9xJGY__.js} +1 -1
- package/dist/public/assets/{useRegisteredDebugTemplates-DBDRdptr.js → useRegisteredDebugTemplates-CDfl54Wt.js} +1 -1
- package/dist/public/index.html +2 -2
- package/dist/server/config/env.d.ts +1 -0
- package/dist/server/config/env.js +36 -0
- package/dist/server/config/env.js.map +1 -1
- package/dist/server/modules/client/client-controller.js +1 -1
- package/dist/server/modules/client/client-controller.js.map +1 -1
- package/dist/server/modules/client/client-service.d.ts +16 -2
- package/dist/server/modules/client/client-service.js +21 -3
- package/dist/server/modules/client/client-service.js.map +1 -1
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.d.ts +16 -1
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-packets.js.map +1 -1
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.d.ts +2 -1
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js +18 -0
- package/dist/server/modules/relay-tunnel/crypto/relay-tunnel-protocol.js.map +1 -1
- package/dist/server/modules/relay-tunnel/relay-tunnel-client-context.d.ts +13 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-client-context.js +2 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-client-context.js.map +1 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.d.ts +6 -0
- package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js +110 -10
- package/dist/server/modules/relay-tunnel/relay-tunnel-gateway-service.js.map +1 -1
- package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.d.ts +16 -4
- package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js +216 -101
- package/dist/server/modules/relay-tunnel/relay-tunnel-runtime-adapter.js.map +1 -1
- package/dist/server/modules/relay-tunnel/relay-tunnel-service.d.ts +6 -2
- package/dist/server/modules/relay-tunnel/relay-tunnel-service.js +457 -40
- package/dist/server/modules/relay-tunnel/relay-tunnel-service.js.map +1 -1
- package/dist/server/modules/sessions/session-activity-inspector.js +6 -8
- package/dist/server/modules/sessions/session-activity-inspector.js.map +1 -1
- package/dist/server/modules/sessions/session-history-service.d.ts +1 -0
- package/dist/server/modules/sessions/session-history-service.js +62 -7
- package/dist/server/modules/sessions/session-history-service.js.map +1 -1
- package/dist/server/modules/workbench/snapshot-revision.d.ts +4 -0
- package/dist/server/modules/workbench/snapshot-revision.js +13 -0
- package/dist/server/modules/workbench/snapshot-revision.js.map +1 -0
- package/dist/server/modules/workbench/workbench-service.d.ts +33 -2
- package/dist/server/modules/workbench/workbench-service.js +39 -4
- package/dist/server/modules/workbench/workbench-service.js.map +1 -1
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.d.ts +6 -1
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.js +10 -8
- package/dist/server/modules/workbench/workspace-panel-snapshot-service.js.map +1 -1
- package/dist/server/server/create-server.js +11 -6
- package/dist/server/server/create-server.js.map +1 -1
- package/dist/server/types/domain.d.ts +9 -0
- package/dist/server/ws/workbench-ws-hub.js +295 -43
- package/dist/server/ws/workbench-ws-hub.js.map +1 -1
- package/dist/server/ws/ws-server.js +141 -8
- package/dist/server/ws/ws-server.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js +33 -6
- package/node_modules/@codingns/session-sync-core/dist/providers/codex.js.map +1 -1
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js +78 -36
- package/node_modules/@codingns/session-sync-core/dist/runtime/codex-runtime.js.map +1 -1
- package/package.json +1 -1
- package/dist/public/assets/AdaptiveButlerPage-R-XZw7pd.js +0 -3
- package/dist/public/assets/App-DkvE5EyM.js +0 -30
- package/dist/public/assets/ConversationPage-Cjpg6g0J.js +0 -2
- package/dist/public/assets/DesktopWindowPage-1WelvxdH.js +0 -2
- package/dist/public/assets/FileContextPanel-D_ghXJuW.js +0 -1
- package/dist/public/assets/GitSidebar-D9f9Jxwr.js +0 -6
- package/dist/public/assets/MobileSheet-DLg-gX1t.js +0 -1
- package/dist/public/assets/SettingsPage-HJIC-P-4.js +0 -1
- package/dist/public/assets/TerminalManagerPanel-DpyUTo9k.js +0 -1
- package/dist/public/assets/WorkbenchLayout-ByFw4eeu.js +0 -3
- package/dist/public/assets/WorkbenchShellRoute-BUITtdAg.css +0 -1
- package/dist/public/assets/WorkbenchShellRoute-Kw7JEZI3.js +0 -1
- package/dist/public/assets/WorkspaceDetailPage-D0Lrx4Uz.js +0 -1
- package/dist/public/assets/WorkspaceHomePage-wR8d3aP9.js +0 -1
- package/dist/public/assets/file-tree-icon-UFVoVzhM.js +0 -31
- package/dist/public/assets/index-Byp9hJ0c.js +0 -42
- package/dist/public/assets/index-_52jxu4a.css +0 -1
- package/dist/public/assets/session-runtime-machine-0KNSSPp5.js +0 -17
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { AppError } from "../shared/errors/app-error.js";
|
|
2
|
+
import { logPerformance } from "../shared/utils/perf-log.js";
|
|
2
3
|
import { logTerminalDebug, terminalDebugNowMs } from "../shared/utils/terminal-debug-log.js";
|
|
3
4
|
const WORKBENCH_REFRESH_INTERVAL_MS = 60_000;
|
|
4
5
|
const GIT_SUBSCRIPTION_MIN_REFRESH_INTERVAL_MS = 15_000;
|
|
@@ -42,7 +43,7 @@ export class WorkbenchWsHub {
|
|
|
42
43
|
try {
|
|
43
44
|
switch (message.type) {
|
|
44
45
|
case "workbench.subscribe":
|
|
45
|
-
void this.sendWorkbenchSnapshotToClient(client, userId, channel);
|
|
46
|
+
void this.sendWorkbenchSnapshotToClient(client, userId, channel, message.knownRevision);
|
|
46
47
|
if (this.workbenchService.shouldRefreshSnapshot()) {
|
|
47
48
|
this.workbenchService.scheduleSnapshotRefresh(userId);
|
|
48
49
|
}
|
|
@@ -51,18 +52,18 @@ export class WorkbenchWsHub {
|
|
|
51
52
|
void this.refreshAndBroadcast(userId, true);
|
|
52
53
|
return true;
|
|
53
54
|
case "fileTree.subscribe":
|
|
54
|
-
this.replaceFileTreeSubscription(client, message.workspaceId, message.paths);
|
|
55
|
+
this.replaceFileTreeSubscription(client, message.workspaceId, message.paths, message.knownRevisions);
|
|
55
56
|
void this.refreshFileTreeSubscriptions(client);
|
|
56
57
|
return true;
|
|
57
58
|
case "fileTree.refresh":
|
|
58
59
|
for (const path of normalizePanelPaths(message.paths)) {
|
|
59
60
|
this.workspacePanelSnapshotService.invalidateFileTree(message.workspaceId.trim(), path);
|
|
60
61
|
}
|
|
61
|
-
this.ensureFileTreeSubscription(client, message.workspaceId, message.paths);
|
|
62
|
+
this.ensureFileTreeSubscription(client, message.workspaceId, message.paths, message.knownRevisions);
|
|
62
63
|
void this.refreshFileTreeSubscriptions(client, true);
|
|
63
64
|
return true;
|
|
64
65
|
case "git.subscribe":
|
|
65
|
-
this.ensureGitSubscription(client, message.workspaceId);
|
|
66
|
+
this.ensureGitSubscription(client, message.workspaceId, message.knownRevision);
|
|
66
67
|
void this.refreshGitSubscription(client, false, {
|
|
67
68
|
deliverIfUnchanged: true,
|
|
68
69
|
ignoreMinInterval: true
|
|
@@ -70,18 +71,18 @@ export class WorkbenchWsHub {
|
|
|
70
71
|
return true;
|
|
71
72
|
case "git.refresh":
|
|
72
73
|
this.workspacePanelSnapshotService.invalidateGit(message.workspaceId.trim());
|
|
73
|
-
this.ensureGitSubscription(client, message.workspaceId);
|
|
74
|
+
this.ensureGitSubscription(client, message.workspaceId, message.knownRevision);
|
|
74
75
|
this.scheduleGitRefresh(client, {
|
|
75
76
|
force: true
|
|
76
77
|
});
|
|
77
78
|
return true;
|
|
78
79
|
case "terminalManager.subscribe":
|
|
79
|
-
this.ensureTerminalManagerSubscription(client, message.workspaceId);
|
|
80
|
+
this.ensureTerminalManagerSubscription(client, message.workspaceId, message.knownRevision);
|
|
80
81
|
this.scheduleTerminalManagerRefresh(client);
|
|
81
82
|
return true;
|
|
82
83
|
case "terminalManager.refresh":
|
|
83
84
|
this.workspacePanelSnapshotService.invalidateTerminalManager(message.workspaceId.trim());
|
|
84
|
-
this.ensureTerminalManagerSubscription(client, message.workspaceId);
|
|
85
|
+
this.ensureTerminalManagerSubscription(client, message.workspaceId, message.knownRevision);
|
|
85
86
|
this.scheduleTerminalManagerRefresh(client, {
|
|
86
87
|
force: true
|
|
87
88
|
});
|
|
@@ -89,7 +90,8 @@ export class WorkbenchWsHub {
|
|
|
89
90
|
case "workspaceManagement.subscribe":
|
|
90
91
|
this.clientWorkspaceManagementSubscriptions.set(client, {
|
|
91
92
|
workspaceId: message.workspaceId.trim(),
|
|
92
|
-
lastPayload: null
|
|
93
|
+
lastPayload: null,
|
|
94
|
+
knownRevision: normalizeKnownRevision(message.knownRevision) ?? null
|
|
93
95
|
});
|
|
94
96
|
void this.refreshWorkspaceManagementSubscription(client);
|
|
95
97
|
return true;
|
|
@@ -97,7 +99,8 @@ export class WorkbenchWsHub {
|
|
|
97
99
|
this.workspacePanelSnapshotService.invalidateWorkspaceManagement(message.workspaceId.trim());
|
|
98
100
|
this.clientWorkspaceManagementSubscriptions.set(client, {
|
|
99
101
|
workspaceId: message.workspaceId.trim(),
|
|
100
|
-
lastPayload: null
|
|
102
|
+
lastPayload: null,
|
|
103
|
+
knownRevision: normalizeKnownRevision(message.knownRevision) ?? null
|
|
101
104
|
});
|
|
102
105
|
void this.refreshWorkspaceManagementSubscription(client, true);
|
|
103
106
|
return true;
|
|
@@ -185,19 +188,42 @@ export class WorkbenchWsHub {
|
|
|
185
188
|
}
|
|
186
189
|
channel.realtimeBroadcastQueued = false;
|
|
187
190
|
channel.realtimeBroadcastTask = (async () => {
|
|
191
|
+
const startedAt = Date.now();
|
|
188
192
|
const startedAtMs = terminalDebugNowMs();
|
|
189
193
|
try {
|
|
190
|
-
const
|
|
191
|
-
|
|
194
|
+
const snapshotStartedAt = Date.now();
|
|
195
|
+
const snapshot = this.workbenchService.getSnapshot(userId);
|
|
196
|
+
const snapshotMs = Date.now() - snapshotStartedAt;
|
|
197
|
+
const serializeStartedAt = Date.now();
|
|
198
|
+
const payload = buildWorkbenchBroadcastPayload(channel.lastWorkbenchSnapshot, snapshot);
|
|
199
|
+
const serializeMs = Date.now() - serializeStartedAt;
|
|
200
|
+
if (snapshot.revision === channel.lastWorkbenchRevision) {
|
|
192
201
|
return;
|
|
193
202
|
}
|
|
194
203
|
channel.lastWorkbenchPayload = payload;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
204
|
+
channel.lastWorkbenchRevision = snapshot.revision;
|
|
205
|
+
channel.lastWorkbenchSnapshot = snapshot;
|
|
206
|
+
const sessionCount = snapshot.items.reduce((total, item) => total + countWorkbenchSessions(item), 0);
|
|
207
|
+
const broadcastMetric = broadcastSerializedPayload(channel.clients, payload);
|
|
208
|
+
logPerformance("ws.workbench.realtime_broadcast", Date.now() - startedAt, {
|
|
209
|
+
userId,
|
|
210
|
+
clientCount: channel.clients.size,
|
|
211
|
+
workspaceCount: snapshot.items.length,
|
|
212
|
+
sessionCount,
|
|
213
|
+
snapshotMs,
|
|
214
|
+
serializeMs,
|
|
215
|
+
payloadBytes: broadcastMetric.payloadBytes,
|
|
216
|
+
sendMs: broadcastMetric.sendMs,
|
|
217
|
+
maxBufferedAmount: broadcastMetric.maxBufferedAmount
|
|
218
|
+
}, {
|
|
219
|
+
thresholdMs: 0,
|
|
220
|
+
force: true
|
|
221
|
+
});
|
|
198
222
|
logTerminalDebug("workbench.realtime_broadcast.completed", {
|
|
199
223
|
userId,
|
|
200
224
|
clientCount: channel.clients.size,
|
|
225
|
+
payloadBytes: broadcastMetric.payloadBytes,
|
|
226
|
+
maxBufferedAmount: broadcastMetric.maxBufferedAmount,
|
|
201
227
|
durationMs: terminalDebugNowMs() - startedAtMs
|
|
202
228
|
});
|
|
203
229
|
}
|
|
@@ -263,6 +289,8 @@ export class WorkbenchWsHub {
|
|
|
263
289
|
channel = {
|
|
264
290
|
clients: new Set(),
|
|
265
291
|
lastWorkbenchPayload: null,
|
|
292
|
+
lastWorkbenchRevision: null,
|
|
293
|
+
lastWorkbenchSnapshot: null,
|
|
266
294
|
workbenchTimer: null,
|
|
267
295
|
workspaceManagementTimer: null,
|
|
268
296
|
realtimeBroadcastTimer: null,
|
|
@@ -288,11 +316,42 @@ export class WorkbenchWsHub {
|
|
|
288
316
|
this.userChannels.set(userId, channel);
|
|
289
317
|
return channel;
|
|
290
318
|
}
|
|
291
|
-
async sendWorkbenchSnapshotToClient(client, userId, channel) {
|
|
319
|
+
async sendWorkbenchSnapshotToClient(client, userId, channel, knownRevision) {
|
|
320
|
+
const startedAt = Date.now();
|
|
292
321
|
try {
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
322
|
+
const snapshotStartedAt = Date.now();
|
|
323
|
+
const snapshot = this.workbenchService.getSnapshot(userId);
|
|
324
|
+
const snapshotMs = Date.now() - snapshotStartedAt;
|
|
325
|
+
const fullPayloadStartedAt = Date.now();
|
|
326
|
+
const fullPayload = buildWorkbenchPayload(snapshot);
|
|
327
|
+
const fullPayloadBuildMs = Date.now() - fullPayloadStartedAt;
|
|
328
|
+
const unchanged = Boolean(knownRevision && knownRevision === snapshot.revision);
|
|
329
|
+
let clientPayload = fullPayload;
|
|
330
|
+
let clientPayloadBuildMs = 0;
|
|
331
|
+
if (unchanged) {
|
|
332
|
+
const clientPayloadStartedAt = Date.now();
|
|
333
|
+
clientPayload = buildWorkbenchPayload(snapshot, knownRevision);
|
|
334
|
+
clientPayloadBuildMs = Date.now() - clientPayloadStartedAt;
|
|
335
|
+
}
|
|
336
|
+
channel.lastWorkbenchPayload = fullPayload;
|
|
337
|
+
channel.lastWorkbenchRevision = snapshot.revision;
|
|
338
|
+
channel.lastWorkbenchSnapshot = snapshot;
|
|
339
|
+
const sendMetric = sendSerializedPayload(client, clientPayload);
|
|
340
|
+
logPerformance("ws.workbench.subscribe", Date.now() - startedAt, {
|
|
341
|
+
userId,
|
|
342
|
+
snapshotMs,
|
|
343
|
+
fullPayloadBuildMs,
|
|
344
|
+
clientPayloadBuildMs,
|
|
345
|
+
payloadBytes: sendMetric.payloadBytes,
|
|
346
|
+
sendMs: sendMetric.sendMs,
|
|
347
|
+
bufferedAmount: sendMetric.bufferedAmount,
|
|
348
|
+
workspaceCount: snapshot.items.length,
|
|
349
|
+
sessionCount: snapshot.items.reduce((total, item) => total + countWorkbenchSessions(item), 0),
|
|
350
|
+
unchanged
|
|
351
|
+
}, {
|
|
352
|
+
thresholdMs: 0,
|
|
353
|
+
force: true
|
|
354
|
+
});
|
|
296
355
|
}
|
|
297
356
|
catch (error) {
|
|
298
357
|
this.reportAsyncError("sendWorkbenchSnapshotToClient", error, { userId });
|
|
@@ -307,22 +366,45 @@ export class WorkbenchWsHub {
|
|
|
307
366
|
await channel.refreshTask;
|
|
308
367
|
}
|
|
309
368
|
channel.refreshTask = (async () => {
|
|
369
|
+
const startedAt = Date.now();
|
|
310
370
|
const startedAtMs = terminalDebugNowMs();
|
|
311
371
|
try {
|
|
372
|
+
const snapshotStartedAt = Date.now();
|
|
312
373
|
const snapshot = await this.workbenchService.refreshSnapshot(userId);
|
|
313
|
-
const
|
|
314
|
-
|
|
374
|
+
const snapshotMs = Date.now() - snapshotStartedAt;
|
|
375
|
+
const serializeStartedAt = Date.now();
|
|
376
|
+
const payload = buildWorkbenchBroadcastPayload(channel.lastWorkbenchSnapshot, snapshot);
|
|
377
|
+
const serializeMs = Date.now() - serializeStartedAt;
|
|
378
|
+
if (snapshot.revision === channel.lastWorkbenchRevision) {
|
|
315
379
|
return;
|
|
316
380
|
}
|
|
317
381
|
channel.lastWorkbenchPayload = payload;
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
382
|
+
channel.lastWorkbenchRevision = snapshot.revision;
|
|
383
|
+
channel.lastWorkbenchSnapshot = snapshot;
|
|
384
|
+
const sessionCount = snapshot.items.reduce((total, item) => total + countWorkbenchSessions(item), 0);
|
|
385
|
+
const broadcastMetric = broadcastSerializedPayload(channel.clients, payload);
|
|
386
|
+
logPerformance("ws.workbench.refresh", Date.now() - startedAt, {
|
|
387
|
+
userId,
|
|
388
|
+
force,
|
|
389
|
+
clientCount: channel.clients.size,
|
|
390
|
+
snapshotMs,
|
|
391
|
+
serializeMs,
|
|
392
|
+
payloadBytes: broadcastMetric.payloadBytes,
|
|
393
|
+
sendMs: broadcastMetric.sendMs,
|
|
394
|
+
maxBufferedAmount: broadcastMetric.maxBufferedAmount,
|
|
395
|
+
workspaceCount: snapshot.items.length,
|
|
396
|
+
sessionCount
|
|
397
|
+
}, {
|
|
398
|
+
thresholdMs: 0,
|
|
399
|
+
force: true
|
|
400
|
+
});
|
|
321
401
|
logTerminalDebug("workbench.refresh.completed", {
|
|
322
402
|
userId,
|
|
323
403
|
force,
|
|
324
404
|
clientCount: channel.clients.size,
|
|
325
405
|
workspaceCount: snapshot.items.length,
|
|
406
|
+
payloadBytes: broadcastMetric.payloadBytes,
|
|
407
|
+
maxBufferedAmount: broadcastMetric.maxBufferedAmount,
|
|
326
408
|
durationMs: terminalDebugNowMs() - startedAtMs
|
|
327
409
|
});
|
|
328
410
|
}
|
|
@@ -334,20 +416,23 @@ export class WorkbenchWsHub {
|
|
|
334
416
|
});
|
|
335
417
|
return channel.refreshTask;
|
|
336
418
|
}
|
|
337
|
-
ensureFileTreeSubscription(client, workspaceId, paths) {
|
|
419
|
+
ensureFileTreeSubscription(client, workspaceId, paths, knownRevisions) {
|
|
338
420
|
const current = this.clientFileTreeSubscriptions.get(client);
|
|
339
421
|
const normalizedWorkspaceId = workspaceId.trim();
|
|
340
422
|
const normalizedPaths = normalizePanelPaths(paths);
|
|
341
423
|
const nextPaths = normalizedPaths.length > 0 ? normalizedPaths : [""];
|
|
424
|
+
const nextKnownRevisionByPath = buildKnownRevisionByPathMap(nextPaths, knownRevisions);
|
|
342
425
|
if (current &&
|
|
343
426
|
current.workspaceId === normalizedWorkspaceId &&
|
|
344
427
|
areStringArraysEqual(current.paths, nextPaths)) {
|
|
428
|
+
current.knownRevisionByPath = nextKnownRevisionByPath;
|
|
345
429
|
return current;
|
|
346
430
|
}
|
|
347
431
|
const next = {
|
|
348
432
|
workspaceId: normalizedWorkspaceId,
|
|
349
433
|
paths: nextPaths,
|
|
350
|
-
lastPayloadByPath: new Map()
|
|
434
|
+
lastPayloadByPath: new Map(),
|
|
435
|
+
knownRevisionByPath: nextKnownRevisionByPath
|
|
351
436
|
};
|
|
352
437
|
this.fileWatcher.subscribeFileTree(normalizedWorkspaceId, nextPaths);
|
|
353
438
|
this.clientFileTreeSubscriptions.set(client, next);
|
|
@@ -356,8 +441,8 @@ export class WorkbenchWsHub {
|
|
|
356
441
|
}
|
|
357
442
|
return next;
|
|
358
443
|
}
|
|
359
|
-
replaceFileTreeSubscription(client, workspaceId, paths) {
|
|
360
|
-
return this.ensureFileTreeSubscription(client, workspaceId, paths);
|
|
444
|
+
replaceFileTreeSubscription(client, workspaceId, paths, knownRevisions) {
|
|
445
|
+
return this.ensureFileTreeSubscription(client, workspaceId, paths, knownRevisions);
|
|
361
446
|
}
|
|
362
447
|
async refreshFileTreeSubscriptions(client, force = false) {
|
|
363
448
|
const subscription = this.clientFileTreeSubscriptions.get(client);
|
|
@@ -368,11 +453,12 @@ export class WorkbenchWsHub {
|
|
|
368
453
|
const uniquePaths = normalizePanelPaths(subscription.paths);
|
|
369
454
|
for (const path of uniquePaths) {
|
|
370
455
|
const snapshot = await this.workspacePanelSnapshotService.getFileTreeSnapshot(subscription.workspaceId, path, { force });
|
|
371
|
-
const payload = buildFileTreePayload(snapshot);
|
|
456
|
+
const payload = buildFileTreePayload(snapshot, subscription.knownRevisionByPath.get(path) ?? null);
|
|
372
457
|
const lastPayload = subscription.lastPayloadByPath.get(path) ?? null;
|
|
373
458
|
if (payload === lastPayload) {
|
|
374
459
|
continue;
|
|
375
460
|
}
|
|
461
|
+
subscription.knownRevisionByPath.set(path, snapshot.revision);
|
|
376
462
|
subscription.lastPayloadByPath.set(path, payload);
|
|
377
463
|
client.send(payload);
|
|
378
464
|
}
|
|
@@ -422,10 +508,13 @@ export class WorkbenchWsHub {
|
|
|
422
508
|
if (controller.signal.aborted) {
|
|
423
509
|
return;
|
|
424
510
|
}
|
|
425
|
-
const payload = buildGitPayload(snapshot
|
|
426
|
-
|
|
511
|
+
const payload = buildGitPayload(snapshot, subscription.knownRevision, {
|
|
512
|
+
includeSnapshotWhenUnchanged: force || options?.deliverIfUnchanged === true
|
|
513
|
+
});
|
|
514
|
+
if (payload === subscription.lastPayload && !options?.deliverIfUnchanged && !force) {
|
|
427
515
|
return;
|
|
428
516
|
}
|
|
517
|
+
subscription.knownRevision = snapshot.revision;
|
|
429
518
|
subscription.lastPayload = payload;
|
|
430
519
|
client.send(payload);
|
|
431
520
|
logTerminalDebug("workbench.git_refresh.completed", {
|
|
@@ -455,15 +544,18 @@ export class WorkbenchWsHub {
|
|
|
455
544
|
});
|
|
456
545
|
return subscription.refreshTask;
|
|
457
546
|
}
|
|
458
|
-
ensureGitSubscription(client, workspaceId) {
|
|
547
|
+
ensureGitSubscription(client, workspaceId, knownRevision) {
|
|
459
548
|
const normalizedWorkspaceId = workspaceId.trim();
|
|
460
549
|
const current = this.clientGitSubscriptions.get(client);
|
|
550
|
+
const normalizedKnownRevision = normalizeKnownRevision(knownRevision) ?? null;
|
|
461
551
|
if (current && current.workspaceId === normalizedWorkspaceId) {
|
|
552
|
+
current.knownRevision = normalizedKnownRevision;
|
|
462
553
|
return current;
|
|
463
554
|
}
|
|
464
555
|
const next = {
|
|
465
556
|
workspaceId: normalizedWorkspaceId,
|
|
466
557
|
lastPayload: null,
|
|
558
|
+
knownRevision: normalizedKnownRevision,
|
|
467
559
|
lastRequestedAt: 0,
|
|
468
560
|
refreshTask: null,
|
|
469
561
|
refreshController: null,
|
|
@@ -523,10 +615,12 @@ export class WorkbenchWsHub {
|
|
|
523
615
|
this.flushQueuedGitRefresh(client);
|
|
524
616
|
}, Math.max(0, delayMs));
|
|
525
617
|
}
|
|
526
|
-
ensureTerminalManagerSubscription(client, workspaceId) {
|
|
618
|
+
ensureTerminalManagerSubscription(client, workspaceId, knownRevision) {
|
|
527
619
|
const normalizedWorkspaceId = workspaceId.trim();
|
|
528
620
|
const current = this.clientTerminalManagerSubscriptions.get(client);
|
|
621
|
+
const normalizedKnownRevision = normalizeKnownRevision(knownRevision) ?? null;
|
|
529
622
|
if (current && current.workspaceId === normalizedWorkspaceId) {
|
|
623
|
+
current.knownRevision = normalizedKnownRevision;
|
|
530
624
|
return current;
|
|
531
625
|
}
|
|
532
626
|
if (current?.refreshTimer) {
|
|
@@ -535,6 +629,7 @@ export class WorkbenchWsHub {
|
|
|
535
629
|
const next = {
|
|
536
630
|
workspaceId: normalizedWorkspaceId,
|
|
537
631
|
lastPayload: null,
|
|
632
|
+
knownRevision: normalizedKnownRevision,
|
|
538
633
|
refreshTask: null,
|
|
539
634
|
refreshTimer: null,
|
|
540
635
|
queuedRefresh: false,
|
|
@@ -602,11 +697,12 @@ export class WorkbenchWsHub {
|
|
|
602
697
|
const startedAtMs = terminalDebugNowMs();
|
|
603
698
|
const snapshot = await this.workspacePanelSnapshotService.getTerminalManagerSnapshot(subscription.workspaceId, { force });
|
|
604
699
|
const payloadStartedAtMs = terminalDebugNowMs();
|
|
605
|
-
const payload = buildTerminalManagerPayload(snapshot);
|
|
700
|
+
const payload = buildTerminalManagerPayload(snapshot, subscription.knownRevision);
|
|
606
701
|
const payloadBuildMs = terminalDebugNowMs() - payloadStartedAtMs;
|
|
607
702
|
if (payload === subscription.lastPayload) {
|
|
608
703
|
return;
|
|
609
704
|
}
|
|
705
|
+
subscription.knownRevision = snapshot.revision;
|
|
610
706
|
subscription.lastPayload = payload;
|
|
611
707
|
const sendStartedAtMs = terminalDebugNowMs();
|
|
612
708
|
client.send(payload);
|
|
@@ -641,10 +737,11 @@ export class WorkbenchWsHub {
|
|
|
641
737
|
}
|
|
642
738
|
try {
|
|
643
739
|
const snapshot = await this.workspacePanelSnapshotService.getWorkspaceManagementSnapshot(subscription.workspaceId, { force });
|
|
644
|
-
const payload = buildWorkspaceManagementPayload(snapshot);
|
|
740
|
+
const payload = buildWorkspaceManagementPayload(snapshot, subscription.knownRevision);
|
|
645
741
|
if (payload === subscription.lastPayload) {
|
|
646
742
|
return;
|
|
647
743
|
}
|
|
744
|
+
subscription.knownRevision = snapshot.revision;
|
|
648
745
|
subscription.lastPayload = payload;
|
|
649
746
|
client.send(payload);
|
|
650
747
|
}
|
|
@@ -700,7 +797,8 @@ function parseWorkbenchMessage(payload) {
|
|
|
700
797
|
case "workbench.subscribe":
|
|
701
798
|
case "workbench.refresh":
|
|
702
799
|
return {
|
|
703
|
-
type: candidate.type
|
|
800
|
+
type: candidate.type,
|
|
801
|
+
knownRevision: normalizeKnownRevision(candidate.knownRevision)
|
|
704
802
|
};
|
|
705
803
|
case "fileTree.subscribe":
|
|
706
804
|
case "fileTree.refresh":
|
|
@@ -710,7 +808,8 @@ function parseWorkbenchMessage(payload) {
|
|
|
710
808
|
workspaceId: candidate.workspaceId,
|
|
711
809
|
paths: Array.isArray(candidate.paths)
|
|
712
810
|
? candidate.paths.filter((value) => typeof value === "string")
|
|
713
|
-
: undefined
|
|
811
|
+
: undefined,
|
|
812
|
+
knownRevisions: normalizeKnownRevisionRecord(candidate.knownRevisions)
|
|
714
813
|
}
|
|
715
814
|
: null;
|
|
716
815
|
case "git.subscribe":
|
|
@@ -718,7 +817,8 @@ function parseWorkbenchMessage(payload) {
|
|
|
718
817
|
return typeof candidate.workspaceId === "string"
|
|
719
818
|
? {
|
|
720
819
|
type: candidate.type,
|
|
721
|
-
workspaceId: candidate.workspaceId
|
|
820
|
+
workspaceId: candidate.workspaceId,
|
|
821
|
+
knownRevision: normalizeKnownRevision(candidate.knownRevision)
|
|
722
822
|
}
|
|
723
823
|
: null;
|
|
724
824
|
case "terminalManager.subscribe":
|
|
@@ -728,7 +828,8 @@ function parseWorkbenchMessage(payload) {
|
|
|
728
828
|
return typeof candidate.workspaceId === "string"
|
|
729
829
|
? {
|
|
730
830
|
type: candidate.type,
|
|
731
|
-
workspaceId: candidate.workspaceId
|
|
831
|
+
workspaceId: candidate.workspaceId,
|
|
832
|
+
knownRevision: normalizeKnownRevision(candidate.knownRevision)
|
|
732
833
|
}
|
|
733
834
|
: null;
|
|
734
835
|
default:
|
|
@@ -764,34 +865,185 @@ function areStringArraysEqual(left, right) {
|
|
|
764
865
|
}
|
|
765
866
|
return left.every((value, index) => value === right[index]);
|
|
766
867
|
}
|
|
767
|
-
function
|
|
868
|
+
function sendSerializedPayload(client, payload) {
|
|
869
|
+
const sendStartedAt = Date.now();
|
|
870
|
+
client.send(payload);
|
|
871
|
+
return {
|
|
872
|
+
payloadBytes: Buffer.byteLength(payload),
|
|
873
|
+
sendMs: Date.now() - sendStartedAt,
|
|
874
|
+
bufferedAmount: client.bufferedAmount
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
function broadcastSerializedPayload(clients, payload) {
|
|
878
|
+
const sendStartedAt = Date.now();
|
|
879
|
+
let maxBufferedAmount = 0;
|
|
880
|
+
for (const client of clients) {
|
|
881
|
+
client.send(payload);
|
|
882
|
+
maxBufferedAmount = Math.max(maxBufferedAmount, client.bufferedAmount);
|
|
883
|
+
}
|
|
884
|
+
return {
|
|
885
|
+
payloadBytes: Buffer.byteLength(payload),
|
|
886
|
+
sendMs: Date.now() - sendStartedAt,
|
|
887
|
+
maxBufferedAmount
|
|
888
|
+
};
|
|
889
|
+
}
|
|
890
|
+
function buildWorkbenchPayload(snapshot, knownRevision) {
|
|
891
|
+
if (knownRevision && knownRevision === snapshot.revision) {
|
|
892
|
+
return JSON.stringify({
|
|
893
|
+
type: "workbench.snapshot",
|
|
894
|
+
revision: snapshot.revision,
|
|
895
|
+
unchanged: true,
|
|
896
|
+
snapshot: null
|
|
897
|
+
});
|
|
898
|
+
}
|
|
768
899
|
return JSON.stringify({
|
|
769
900
|
type: "workbench.snapshot",
|
|
901
|
+
revision: snapshot.revision,
|
|
902
|
+
unchanged: false,
|
|
770
903
|
snapshot
|
|
771
904
|
});
|
|
772
905
|
}
|
|
773
|
-
function
|
|
906
|
+
function buildWorkbenchBroadcastPayload(previousSnapshot, nextSnapshot) {
|
|
907
|
+
if (!previousSnapshot || previousSnapshot.revision === nextSnapshot.revision) {
|
|
908
|
+
return buildWorkbenchPayload(nextSnapshot);
|
|
909
|
+
}
|
|
910
|
+
const fullPayload = buildWorkbenchPayload(nextSnapshot);
|
|
911
|
+
const deltaPayload = JSON.stringify(buildWorkbenchDeltaPayload(previousSnapshot, nextSnapshot));
|
|
912
|
+
return Buffer.byteLength(deltaPayload, "utf8") < Buffer.byteLength(fullPayload, "utf8")
|
|
913
|
+
? deltaPayload
|
|
914
|
+
: fullPayload;
|
|
915
|
+
}
|
|
916
|
+
function buildWorkbenchDeltaPayload(previousSnapshot, nextSnapshot) {
|
|
917
|
+
const previousByWorkspaceId = new Map(previousSnapshot.items.map((item) => [item.workspace.id, item]));
|
|
918
|
+
const nextByWorkspaceId = new Map(nextSnapshot.items.map((item) => [item.workspace.id, item]));
|
|
919
|
+
const changedItems = [];
|
|
920
|
+
for (const item of nextSnapshot.items) {
|
|
921
|
+
const previous = previousByWorkspaceId.get(item.workspace.id);
|
|
922
|
+
if (!previous || JSON.stringify(previous) !== JSON.stringify(item)) {
|
|
923
|
+
changedItems.push(item);
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
return {
|
|
927
|
+
type: "workbench.delta",
|
|
928
|
+
baseRevision: previousSnapshot.revision,
|
|
929
|
+
revision: nextSnapshot.revision,
|
|
930
|
+
orderedWorkspaceIds: nextSnapshot.items.map((item) => item.workspace.id),
|
|
931
|
+
removedWorkspaceIds: previousSnapshot.items
|
|
932
|
+
.map((item) => item.workspace.id)
|
|
933
|
+
.filter((workspaceId) => !nextByWorkspaceId.has(workspaceId)),
|
|
934
|
+
changedItems
|
|
935
|
+
};
|
|
936
|
+
}
|
|
937
|
+
function buildFileTreePayload(snapshot, knownRevision) {
|
|
938
|
+
if (knownRevision && knownRevision === snapshot.revision) {
|
|
939
|
+
return JSON.stringify({
|
|
940
|
+
type: "fileTree.snapshot",
|
|
941
|
+
revision: snapshot.revision,
|
|
942
|
+
unchanged: true,
|
|
943
|
+
snapshot: null
|
|
944
|
+
});
|
|
945
|
+
}
|
|
774
946
|
return JSON.stringify({
|
|
775
947
|
type: "fileTree.snapshot",
|
|
948
|
+
revision: snapshot.revision,
|
|
949
|
+
unchanged: false,
|
|
776
950
|
snapshot
|
|
777
951
|
});
|
|
778
952
|
}
|
|
779
|
-
function buildGitPayload(snapshot) {
|
|
953
|
+
function buildGitPayload(snapshot, knownRevision, options) {
|
|
954
|
+
if (knownRevision
|
|
955
|
+
&& knownRevision === snapshot.revision
|
|
956
|
+
&& options?.includeSnapshotWhenUnchanged !== true) {
|
|
957
|
+
return JSON.stringify({
|
|
958
|
+
type: "git.snapshot",
|
|
959
|
+
revision: snapshot.revision,
|
|
960
|
+
unchanged: true,
|
|
961
|
+
snapshot: null
|
|
962
|
+
});
|
|
963
|
+
}
|
|
780
964
|
return JSON.stringify({
|
|
781
965
|
type: "git.snapshot",
|
|
966
|
+
revision: snapshot.revision,
|
|
967
|
+
unchanged: false,
|
|
782
968
|
snapshot
|
|
783
969
|
});
|
|
784
970
|
}
|
|
785
|
-
function buildTerminalManagerPayload(snapshot) {
|
|
971
|
+
function buildTerminalManagerPayload(snapshot, knownRevision) {
|
|
972
|
+
if (knownRevision && knownRevision === snapshot.revision) {
|
|
973
|
+
return JSON.stringify({
|
|
974
|
+
type: "terminalManager.snapshot",
|
|
975
|
+
revision: snapshot.revision,
|
|
976
|
+
unchanged: true,
|
|
977
|
+
snapshot: null
|
|
978
|
+
});
|
|
979
|
+
}
|
|
786
980
|
return JSON.stringify({
|
|
787
981
|
type: "terminalManager.snapshot",
|
|
982
|
+
revision: snapshot.revision,
|
|
983
|
+
unchanged: false,
|
|
788
984
|
snapshot
|
|
789
985
|
});
|
|
790
986
|
}
|
|
791
|
-
function buildWorkspaceManagementPayload(snapshot) {
|
|
987
|
+
function buildWorkspaceManagementPayload(snapshot, knownRevision) {
|
|
988
|
+
if (knownRevision && knownRevision === snapshot.revision) {
|
|
989
|
+
return JSON.stringify({
|
|
990
|
+
type: "workspaceManagement.snapshot",
|
|
991
|
+
revision: snapshot.revision,
|
|
992
|
+
unchanged: true,
|
|
993
|
+
snapshot: null
|
|
994
|
+
});
|
|
995
|
+
}
|
|
792
996
|
return JSON.stringify({
|
|
793
997
|
type: "workspaceManagement.snapshot",
|
|
998
|
+
revision: snapshot.revision,
|
|
999
|
+
unchanged: false,
|
|
794
1000
|
snapshot
|
|
795
1001
|
});
|
|
796
1002
|
}
|
|
1003
|
+
function normalizeKnownRevision(value) {
|
|
1004
|
+
return typeof value === "string" && value.trim().length > 0 ? value.trim() : undefined;
|
|
1005
|
+
}
|
|
1006
|
+
function normalizeKnownRevisionRecord(value) {
|
|
1007
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
1008
|
+
return undefined;
|
|
1009
|
+
}
|
|
1010
|
+
const normalizedEntries = Object.entries(value)
|
|
1011
|
+
.map(([key, candidate]) => [key.trim(), normalizeKnownRevision(candidate)])
|
|
1012
|
+
.filter((entry) => Boolean(entry[1]));
|
|
1013
|
+
if (normalizedEntries.length === 0) {
|
|
1014
|
+
return undefined;
|
|
1015
|
+
}
|
|
1016
|
+
return Object.fromEntries(normalizedEntries);
|
|
1017
|
+
}
|
|
1018
|
+
function buildKnownRevisionByPathMap(paths, knownRevisions) {
|
|
1019
|
+
const map = new Map();
|
|
1020
|
+
if (!knownRevisions) {
|
|
1021
|
+
return map;
|
|
1022
|
+
}
|
|
1023
|
+
for (const path of paths) {
|
|
1024
|
+
const knownRevision = knownRevisions[path];
|
|
1025
|
+
if (knownRevision) {
|
|
1026
|
+
map.set(path, knownRevision);
|
|
1027
|
+
}
|
|
1028
|
+
}
|
|
1029
|
+
return map;
|
|
1030
|
+
}
|
|
1031
|
+
function countWorkbenchSessions(item) {
|
|
1032
|
+
const childNodes = Array.isArray(item.childWorktrees)
|
|
1033
|
+
? item.childWorktrees
|
|
1034
|
+
: Array.isArray(item.children)
|
|
1035
|
+
? item.children
|
|
1036
|
+
: [];
|
|
1037
|
+
return item.sessions.length + childNodes.reduce((total, child) => {
|
|
1038
|
+
if (typeof child !== "object" || child === null) {
|
|
1039
|
+
return total;
|
|
1040
|
+
}
|
|
1041
|
+
const candidate = child;
|
|
1042
|
+
return total + countWorkbenchSessions({
|
|
1043
|
+
sessions: Array.isArray(candidate.sessions) ? candidate.sessions : [],
|
|
1044
|
+
childWorktrees: candidate.childWorktrees,
|
|
1045
|
+
children: candidate.children
|
|
1046
|
+
});
|
|
1047
|
+
}, 0);
|
|
1048
|
+
}
|
|
797
1049
|
//# sourceMappingURL=workbench-ws-hub.js.map
|