@blue-soda/dsh-remote 0.5.6 → 0.5.7
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/README.md +2 -2
- package/cordis.patch.yml +30 -30
- package/dist/client.github.js +1 -1
- package/dist/client.js +1 -1
- package/dist/index.js +321 -57
- package/dist/index.js.map +3 -3
- package/dsh-plugin.json +41 -41
- package/package.json +165 -165
- package/dist/acp.d.ts +0 -75
- package/dist/acp.d.ts.map +0 -1
- package/dist/acp.js +0 -61
- package/dist/acp.js.map +0 -1
- package/dist/api-proxy-switch.d.ts +0 -33
- package/dist/api-proxy-switch.d.ts.map +0 -1
- package/dist/api-proxy-switch.js +0 -109
- package/dist/api-proxy-switch.js.map +0 -1
- package/dist/atomic-file.d.ts +0 -16
- package/dist/atomic-file.d.ts.map +0 -1
- package/dist/atomic-file.js +0 -81
- package/dist/atomic-file.js.map +0 -1
- package/dist/bin/doctor.d.ts +0 -3
- package/dist/bin/doctor.d.ts.map +0 -1
- package/dist/bin/doctor.js +0 -13
- package/dist/bin/doctor.js.map +0 -1
- package/dist/cli.d.ts +0 -32
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js +0 -289
- package/dist/cli.js.map +0 -1
- package/dist/client-runtime.d.ts +0 -375
- package/dist/client-runtime.d.ts.map +0 -1
- package/dist/client-runtime.js +0 -1768
- package/dist/client-runtime.js.map +0 -1
- package/dist/client-secure-transport.d.ts +0 -23
- package/dist/client-secure-transport.d.ts.map +0 -1
- package/dist/client-secure-transport.js +0 -144
- package/dist/client-secure-transport.js.map +0 -1
- package/dist/client-target-store.d.ts +0 -40
- package/dist/client-target-store.d.ts.map +0 -1
- package/dist/client-target-store.js +0 -79
- package/dist/client-target-store.js.map +0 -1
- package/dist/client.d.ts +0 -13
- package/dist/client.d.ts.map +0 -1
- package/dist/codex/app-server.d.ts +0 -71
- package/dist/codex/app-server.d.ts.map +0 -1
- package/dist/codex/app-server.js +0 -268
- package/dist/codex/app-server.js.map +0 -1
- package/dist/codex/codex-image-codec.d.ts +0 -7
- package/dist/codex/codex-image-codec.d.ts.map +0 -1
- package/dist/codex/codex-image-codec.js +0 -288
- package/dist/codex/codex-image-codec.js.map +0 -1
- package/dist/codex/domain.d.ts +0 -102
- package/dist/codex/domain.d.ts.map +0 -1
- package/dist/codex/domain.js +0 -1323
- package/dist/codex/domain.js.map +0 -1
- package/dist/codex/method-policy.d.ts +0 -338
- package/dist/codex/method-policy.d.ts.map +0 -1
- package/dist/codex/method-policy.js +0 -141
- package/dist/codex/method-policy.js.map +0 -1
- package/dist/codex/peer-bridge.d.ts +0 -57
- package/dist/codex/peer-bridge.d.ts.map +0 -1
- package/dist/codex/peer-bridge.js +0 -299
- package/dist/codex/peer-bridge.js.map +0 -1
- package/dist/codex/permissions.d.ts +0 -4
- package/dist/codex/permissions.d.ts.map +0 -1
- package/dist/codex/permissions.js +0 -21
- package/dist/codex/permissions.js.map +0 -1
- package/dist/codex/session-id.d.ts +0 -10
- package/dist/codex/session-id.d.ts.map +0 -1
- package/dist/codex/session-id.js +0 -15
- package/dist/codex/session-id.js.map +0 -1
- package/dist/codex/virtual-harness.d.ts +0 -209
- package/dist/codex/virtual-harness.d.ts.map +0 -1
- package/dist/codex/virtual-harness.js +0 -2650
- package/dist/codex/virtual-harness.js.map +0 -1
- package/dist/codex-workspace-bridge.d.ts +0 -108
- package/dist/codex-workspace-bridge.d.ts.map +0 -1
- package/dist/codex-workspace-bridge.js +0 -502
- package/dist/codex-workspace-bridge.js.map +0 -1
- package/dist/config.d.ts +0 -99
- package/dist/config.d.ts.map +0 -1
- package/dist/config.js +0 -127
- package/dist/config.js.map +0 -1
- package/dist/connection-controller.d.ts +0 -44
- package/dist/connection-controller.d.ts.map +0 -1
- package/dist/connection-controller.js +0 -185
- package/dist/connection-controller.js.map +0 -1
- package/dist/control-route.d.ts +0 -34
- package/dist/control-route.d.ts.map +0 -1
- package/dist/control-route.js +0 -136
- package/dist/control-route.js.map +0 -1
- package/dist/control-runtime.d.ts +0 -138
- package/dist/control-runtime.d.ts.map +0 -1
- package/dist/control-runtime.js +0 -543
- package/dist/control-runtime.js.map +0 -1
- package/dist/control-stream.d.ts +0 -67
- package/dist/control-stream.d.ts.map +0 -1
- package/dist/control-stream.js +0 -179
- package/dist/control-stream.js.map +0 -1
- package/dist/defaults.d.ts +0 -9
- package/dist/defaults.d.ts.map +0 -1
- package/dist/defaults.js +0 -9
- package/dist/defaults.js.map +0 -1
- package/dist/file-viewer-bridge.d.ts +0 -30
- package/dist/file-viewer-bridge.d.ts.map +0 -1
- package/dist/file-viewer-bridge.js +0 -128
- package/dist/file-viewer-bridge.js.map +0 -1
- package/dist/file-viewer-contract.d.ts +0 -5
- package/dist/file-viewer-contract.d.ts.map +0 -1
- package/dist/file-viewer-contract.js +0 -4
- package/dist/file-viewer-contract.js.map +0 -1
- package/dist/harness-api-bridge.d.ts +0 -81
- package/dist/harness-api-bridge.d.ts.map +0 -1
- package/dist/harness-api-bridge.js +0 -862
- package/dist/harness-api-bridge.js.map +0 -1
- package/dist/harness-api-history.d.ts +0 -3
- package/dist/harness-api-history.d.ts.map +0 -1
- package/dist/harness-api-history.js +0 -59
- package/dist/harness-api-history.js.map +0 -1
- package/dist/harness-remote-bridge.d.ts +0 -60
- package/dist/harness-remote-bridge.d.ts.map +0 -1
- package/dist/harness-remote-bridge.js +0 -540
- package/dist/harness-remote-bridge.js.map +0 -1
- package/dist/harness-version.d.ts +0 -23
- package/dist/harness-version.d.ts.map +0 -1
- package/dist/harness-version.js +0 -95
- package/dist/harness-version.js.map +0 -1
- package/dist/identity-store.d.ts +0 -45
- package/dist/identity-store.d.ts.map +0 -1
- package/dist/identity-store.js +0 -186
- package/dist/identity-store.js.map +0 -1
- package/dist/ids.d.ts +0 -2
- package/dist/ids.d.ts.map +0 -1
- package/dist/ids.js +0 -17
- package/dist/ids.js.map +0 -1
- package/dist/index.d.ts +0 -78
- package/dist/index.d.ts.map +0 -1
- package/dist/logging.d.ts +0 -18
- package/dist/logging.d.ts.map +0 -1
- package/dist/logging.js +0 -30
- package/dist/logging.js.map +0 -1
- package/dist/loopback-host.d.ts +0 -20
- package/dist/loopback-host.d.ts.map +0 -1
- package/dist/loopback-host.js +0 -245
- package/dist/loopback-host.js.map +0 -1
- package/dist/loopback-preview.d.ts +0 -19
- package/dist/loopback-preview.d.ts.map +0 -1
- package/dist/loopback-preview.js +0 -232
- package/dist/loopback-preview.js.map +0 -1
- package/dist/native-rtc-helper.d.ts +0 -14
- package/dist/native-rtc-helper.d.ts.map +0 -1
- package/dist/native-rtc-helper.js +0 -575
- package/dist/native-rtc-helper.js.map +0 -1
- package/dist/remote-api-proxy.d.ts +0 -17
- package/dist/remote-api-proxy.d.ts.map +0 -1
- package/dist/remote-api-proxy.js +0 -451
- package/dist/remote-api-proxy.js.map +0 -1
- package/dist/remote-directory-browser.d.ts +0 -16
- package/dist/remote-directory-browser.d.ts.map +0 -1
- package/dist/remote-directory-browser.js +0 -48
- package/dist/remote-directory-browser.js.map +0 -1
- package/dist/remote-file-content-provider.d.ts +0 -48
- package/dist/remote-file-content-provider.d.ts.map +0 -1
- package/dist/remote-file-content-provider.js +0 -93
- package/dist/remote-file-content-provider.js.map +0 -1
- package/dist/remote-typert-gateway.d.ts +0 -20
- package/dist/remote-typert-gateway.d.ts.map +0 -1
- package/dist/remote-typert-gateway.js +0 -334
- package/dist/remote-typert-gateway.js.map +0 -1
- package/dist/rpc-binary-attachments.d.ts +0 -33
- package/dist/rpc-binary-attachments.d.ts.map +0 -1
- package/dist/rpc-binary-attachments.js +0 -142
- package/dist/rpc-binary-attachments.js.map +0 -1
- package/dist/rpc-router.d.ts +0 -31
- package/dist/rpc-router.d.ts.map +0 -1
- package/dist/rpc-router.js +0 -201
- package/dist/rpc-router.js.map +0 -1
- package/dist/safe-error.d.ts +0 -8
- package/dist/safe-error.d.ts.map +0 -1
- package/dist/safe-error.js +0 -20
- package/dist/safe-error.js.map +0 -1
- package/dist/server-api.d.ts +0 -109
- package/dist/server-api.d.ts.map +0 -1
- package/dist/server-api.js +0 -520
- package/dist/server-api.js.map +0 -1
- package/dist/server-connection.d.ts +0 -79
- package/dist/server-connection.d.ts.map +0 -1
- package/dist/server-connection.js +0 -1023
- package/dist/server-connection.js.map +0 -1
- package/dist/server-credentials.d.ts +0 -55
- package/dist/server-credentials.d.ts.map +0 -1
- package/dist/server-credentials.js +0 -108
- package/dist/server-credentials.js.map +0 -1
- package/dist/service.d.ts +0 -151
- package/dist/service.d.ts.map +0 -1
- package/dist/service.js +0 -448
- package/dist/service.js.map +0 -1
- package/dist/session-format-compat.d.ts +0 -3
- package/dist/session-format-compat.d.ts.map +0 -1
- package/dist/session-format-compat.js +0 -183
- package/dist/session-format-compat.js.map +0 -1
- package/dist/status-stream.d.ts +0 -48
- package/dist/status-stream.d.ts.map +0 -1
- package/dist/status-stream.js +0 -133
- package/dist/status-stream.js.map +0 -1
- package/dist/terminal-policy.d.ts +0 -21
- package/dist/terminal-policy.d.ts.map +0 -1
- package/dist/terminal-policy.js +0 -68
- package/dist/terminal-policy.js.map +0 -1
- package/dist/tui-command.d.ts +0 -13
- package/dist/tui-command.d.ts.map +0 -1
- package/dist/tui-command.js +0 -392
- package/dist/tui-command.js.map +0 -1
- package/dist/typert-gateway-contract.d.ts +0 -59
- package/dist/typert-gateway-contract.d.ts.map +0 -1
- package/dist/typert-gateway-contract.js +0 -2
- package/dist/typert-gateway-contract.js.map +0 -1
- package/dist/typert-gateway-switch.d.ts +0 -85
- package/dist/typert-gateway-switch.d.ts.map +0 -1
- package/dist/typert-gateway-switch.js +0 -448
- package/dist/typert-gateway-switch.js.map +0 -1
- package/dist/types.d.ts +0 -20
- package/dist/types.d.ts.map +0 -1
- package/dist/types.js +0 -2
- package/dist/types.js.map +0 -1
- package/dist/version.d.ts +0 -12
- package/dist/version.d.ts.map +0 -1
- package/dist/version.js +0 -12
- package/dist/version.js.map +0 -1
- package/dist/werift-rtc.d.ts +0 -121
- package/dist/werift-rtc.d.ts.map +0 -1
- package/dist/werift-rtc.js +0 -490
- package/dist/werift-rtc.js.map +0 -1
package/dist/index.js
CHANGED
|
@@ -13521,7 +13521,7 @@ function normalizeServerUrl(value) {
|
|
|
13521
13521
|
}
|
|
13522
13522
|
|
|
13523
13523
|
// src/version.ts
|
|
13524
|
-
var PLUGIN_VERSION = "0.5.
|
|
13524
|
+
var PLUGIN_VERSION = "0.5.7";
|
|
13525
13525
|
|
|
13526
13526
|
// src/server-api.ts
|
|
13527
13527
|
var ENABLED_QR_PROVIDERS = ["github"];
|
|
@@ -13998,6 +13998,7 @@ function requireRecord(value, name2) {
|
|
|
13998
13998
|
|
|
13999
13999
|
// src/server-connection.ts
|
|
14000
14000
|
var DEFAULT_WEBRTC_NEGOTIATE_TIMEOUT_MS = 12e3;
|
|
14001
|
+
var CLOSE_DRAIN_TIMEOUT_MS = 5e3;
|
|
14001
14002
|
var HostServerConnection = class {
|
|
14002
14003
|
constructor(config, identity, identities, api, connections, logger, createWebSocket = (url) => new WebSocket(url), rtcFactoryProvider, hostCapabilities = () => ["harness.api.v1"], harnessVersion) {
|
|
14003
14004
|
this.config = config;
|
|
@@ -14041,7 +14042,7 @@ var HostServerConnection = class {
|
|
|
14041
14042
|
}
|
|
14042
14043
|
if (this.resumeQueued) return;
|
|
14043
14044
|
this.resumeQueued = true;
|
|
14044
|
-
void this.running.finally(() => {
|
|
14045
|
+
void this.running.catch(() => void 0).finally(() => {
|
|
14045
14046
|
this.resumeQueued = false;
|
|
14046
14047
|
if (!this.stopped) this.start();
|
|
14047
14048
|
});
|
|
@@ -14077,7 +14078,7 @@ var HostServerConnection = class {
|
|
|
14077
14078
|
this.reconnectRequested = true;
|
|
14078
14079
|
this.retryWake?.();
|
|
14079
14080
|
this.socket?.close(4e3, "manual reconnect");
|
|
14080
|
-
void this.running.finally(() => {
|
|
14081
|
+
void this.running.catch(() => void 0).finally(() => {
|
|
14081
14082
|
if (!this.reconnectRequested || this.stopped) return;
|
|
14082
14083
|
this.reconnectRequested = false;
|
|
14083
14084
|
this.start();
|
|
@@ -14107,7 +14108,7 @@ var HostServerConnection = class {
|
|
|
14107
14108
|
...connectionFailureDetail(error)
|
|
14108
14109
|
});
|
|
14109
14110
|
if (TERMINAL_AUTH_ERRORS.has(code)) {
|
|
14110
|
-
this.logger.warn(code === "CONNECTION_REPLACED" ? "Another instance is using this Host identity. Standing by: retrying in five minutes, and taking over as soon as it leaves." : code === "SERVER_CREDENTIALS_BUSY" ? "Credential refresh is locked. Stop other instances; after a crash, stop all instances before removing server-credentials.json.refresh-lock and authorizing again." : "Host authorization failed. Run /remote login or authorize this Host again in Remote settings.");
|
|
14111
|
+
this.logger.warn(code === "CONNECTION_REPLACED" ? "Another instance is using this Host identity. Standing by: retrying in five minutes, and taking over as soon as it leaves." : code === "SERVER_CREDENTIALS_BUSY" ? "Credential refresh is locked. Stop other instances; after a crash, stop all instances before removing server-credentials.json.refresh-lock and authorizing again." : code === "CONTROL_DISABLED" ? 'This device is not accepting control. Turn on "Allow control of this device" to reconnect.' : "Host authorization failed. Run /remote login or authorize this Host again in Remote settings.");
|
|
14111
14112
|
}
|
|
14112
14113
|
if (code === "DEVICE_REVOKED" || code === "AUTH_INVALID") {
|
|
14113
14114
|
try {
|
|
@@ -14166,9 +14167,25 @@ var HostServerConnection = class {
|
|
|
14166
14167
|
});
|
|
14167
14168
|
};
|
|
14168
14169
|
socket.onmessage = (event) => {
|
|
14170
|
+
let frame;
|
|
14171
|
+
try {
|
|
14172
|
+
frame = decodeControl(event.data, this.controlFrameLimits);
|
|
14173
|
+
} catch (error) {
|
|
14174
|
+
this.controlFrameFailed(socket, error);
|
|
14175
|
+
return;
|
|
14176
|
+
}
|
|
14177
|
+
this.lastActiveAt = Date.now();
|
|
14178
|
+
if (acknowledged && (frame.type === "ping" || frame.type === "pong")) {
|
|
14179
|
+
if (frame.type === "pong") return;
|
|
14180
|
+
const nonce = objectValue(frame.payload, "nonce");
|
|
14181
|
+
if (typeof nonce !== "string") {
|
|
14182
|
+
this.controlFrameFailed(socket, new ControlConnectionError("INVALID_MESSAGE", "Control ping has no nonce."));
|
|
14183
|
+
return;
|
|
14184
|
+
}
|
|
14185
|
+
this.sendControl("pong", { nonce });
|
|
14186
|
+
return;
|
|
14187
|
+
}
|
|
14169
14188
|
messageQueue = messageQueue.then(async () => {
|
|
14170
|
-
const frame = decodeControl(event.data, this.controlFrameLimits);
|
|
14171
|
-
this.lastActiveAt = Date.now();
|
|
14172
14189
|
if (frame.type === "hello.ack") {
|
|
14173
14190
|
const payload = requireHelloAck(frame.payload);
|
|
14174
14191
|
this.authRecoveryAttempted = false;
|
|
@@ -14193,13 +14210,7 @@ var HostServerConnection = class {
|
|
|
14193
14210
|
if (!acknowledged) throw new ControlConnectionError("INVALID_MESSAGE", "Server sent a frame before hello.ack.");
|
|
14194
14211
|
await this.handleFrame(frame);
|
|
14195
14212
|
}).catch((error) => {
|
|
14196
|
-
|
|
14197
|
-
this.terminalError = code;
|
|
14198
|
-
this.logger.error("server control frame failed", {
|
|
14199
|
-
code,
|
|
14200
|
-
reason: diagnosticReason(error)
|
|
14201
|
-
});
|
|
14202
|
-
socket.close(4008, "invalid control frame");
|
|
14213
|
+
this.controlFrameFailed(socket, error);
|
|
14203
14214
|
});
|
|
14204
14215
|
};
|
|
14205
14216
|
socket.onerror = (event) => {
|
|
@@ -14209,7 +14220,7 @@ var HostServerConnection = class {
|
|
|
14209
14220
|
};
|
|
14210
14221
|
socket.onclose = (event) => {
|
|
14211
14222
|
const close = async () => {
|
|
14212
|
-
await messageQueue
|
|
14223
|
+
await drainWithin(messageQueue, CLOSE_DRAIN_TIMEOUT_MS);
|
|
14213
14224
|
if (this.stopped) {
|
|
14214
14225
|
finish();
|
|
14215
14226
|
return;
|
|
@@ -14237,13 +14248,23 @@ var HostServerConnection = class {
|
|
|
14237
14248
|
finish(new ControlConnectionError("DEVICE_REVOKED", "The Server revoked this Host device."));
|
|
14238
14249
|
return;
|
|
14239
14250
|
}
|
|
14240
|
-
if (acknowledged) this.terminalError = closeCode(event.code);
|
|
14241
|
-
finish(acknowledged ? void 0 : new ControlConnectionError(closeCode(event.code), event.reason || "Server control connection closed."));
|
|
14251
|
+
if (acknowledged) this.terminalError = closeCode(event.code, event.reason);
|
|
14252
|
+
finish(acknowledged ? void 0 : new ControlConnectionError(closeCode(event.code, event.reason), event.reason || "Server control connection closed."));
|
|
14242
14253
|
};
|
|
14243
14254
|
void close();
|
|
14244
14255
|
};
|
|
14245
14256
|
});
|
|
14246
14257
|
}
|
|
14258
|
+
/** Record a frame failure and close the socket, so the run retries from a clean state. */
|
|
14259
|
+
controlFrameFailed(socket, error) {
|
|
14260
|
+
const code = errorCode2(error);
|
|
14261
|
+
this.terminalError = code;
|
|
14262
|
+
this.logger.error("server control frame failed", {
|
|
14263
|
+
code,
|
|
14264
|
+
reason: diagnosticReason(error)
|
|
14265
|
+
});
|
|
14266
|
+
socket.close(4008, "invalid control frame");
|
|
14267
|
+
}
|
|
14247
14268
|
async handleFrame(frame) {
|
|
14248
14269
|
if (frame.type === "ping") {
|
|
14249
14270
|
const nonce = objectValue(frame.payload, "nonce");
|
|
@@ -14705,10 +14726,25 @@ var HostServerConnection = class {
|
|
|
14705
14726
|
}
|
|
14706
14727
|
};
|
|
14707
14728
|
var REPLACED_FIRST_RETRY_MS = 65e3;
|
|
14729
|
+
async function drainWithin(promise, ms) {
|
|
14730
|
+
let timer;
|
|
14731
|
+
try {
|
|
14732
|
+
await Promise.race([
|
|
14733
|
+
promise.catch(() => void 0),
|
|
14734
|
+
new Promise((resolve4) => {
|
|
14735
|
+
timer = setTimeout(resolve4, ms);
|
|
14736
|
+
timer.unref?.();
|
|
14737
|
+
})
|
|
14738
|
+
]);
|
|
14739
|
+
} finally {
|
|
14740
|
+
if (timer !== void 0) clearTimeout(timer);
|
|
14741
|
+
}
|
|
14742
|
+
}
|
|
14708
14743
|
var TERMINAL_AUTH_ERRORS = /* @__PURE__ */ new Set([
|
|
14709
14744
|
"SERVER_CREDENTIALS_BUSY",
|
|
14710
14745
|
"ACCOUNT_AUTH_REQUIRED",
|
|
14711
14746
|
"AUTH_INVALID",
|
|
14747
|
+
"CONTROL_DISABLED",
|
|
14712
14748
|
"DEVICE_OWNERSHIP_REQUIRED",
|
|
14713
14749
|
"DEVICE_REVOKED",
|
|
14714
14750
|
"TOKEN_EXPIRED"
|
|
@@ -14926,14 +14962,25 @@ function errorCode2(error) {
|
|
|
14926
14962
|
function isRetryable(error) {
|
|
14927
14963
|
return !TERMINAL_AUTH_ERRORS.has(errorCode2(error)) && (!(error instanceof ServerApiError) || error.retryable);
|
|
14928
14964
|
}
|
|
14929
|
-
function closeCode(code) {
|
|
14965
|
+
function closeCode(code, reason) {
|
|
14930
14966
|
if (code === 4002) return "AUTH_INVALID";
|
|
14931
14967
|
if (code === 4003) return "CONNECTION_REPLACED";
|
|
14932
14968
|
if (code === 4004) return "DEVICE_REVOKED";
|
|
14933
14969
|
if (code === 4007) return "RATE_LIMITED";
|
|
14934
14970
|
if (code === 4011) return "UNSUPPORTED_VERSION";
|
|
14971
|
+
if (code === 4001 && reason !== void 0 && REJECTED_HELLO_CODES.has(reason)) return reason;
|
|
14935
14972
|
return "CONNECTION_FAILED";
|
|
14936
14973
|
}
|
|
14974
|
+
var REJECTED_HELLO_CODES = /* @__PURE__ */ new Set([
|
|
14975
|
+
"AUTH_REQUIRED",
|
|
14976
|
+
"AUTH_INVALID",
|
|
14977
|
+
"TOKEN_EXPIRED",
|
|
14978
|
+
"DEVICE_REVOKED",
|
|
14979
|
+
"CONTROL_DISABLED",
|
|
14980
|
+
"MEMBERSHIP_REQUIRED",
|
|
14981
|
+
"UNSUPPORTED_VERSION",
|
|
14982
|
+
"RATE_LIMITED"
|
|
14983
|
+
]);
|
|
14937
14984
|
|
|
14938
14985
|
// src/loopback-preview.ts
|
|
14939
14986
|
import { randomBytes as randomBytes7, randomUUID } from "node:crypto";
|
|
@@ -16893,7 +16940,7 @@ var RemoteHarnessApiProxy = class {
|
|
|
16893
16940
|
if (committed.transferId !== transferId || committed.totalBytes <= 0 || committed.totalBytes > MAX_HARNESS_API_TRANSFER_BYTES || committed.totalChunks !== Math.ceil(committed.totalBytes / HARNESS_API_TRANSFER_CHUNK_BYTES)) {
|
|
16894
16941
|
throw new Error("The remote Host returned an invalid Harness API transfer descriptor.");
|
|
16895
16942
|
}
|
|
16896
|
-
const
|
|
16943
|
+
const responseBytes2 = new Uint8Array(committed.totalBytes);
|
|
16897
16944
|
let offset = 0;
|
|
16898
16945
|
for (let index = 0; index < committed.totalChunks; index += 1) {
|
|
16899
16946
|
const result = await this.client.rpc(
|
|
@@ -16909,10 +16956,10 @@ var RemoteHarnessApiProxy = class {
|
|
|
16909
16956
|
if (chunk.byteLength !== expectedBytes) {
|
|
16910
16957
|
throw new Error("The remote Host returned an invalid Harness API transfer chunk.");
|
|
16911
16958
|
}
|
|
16912
|
-
|
|
16959
|
+
responseBytes2.set(chunk, offset);
|
|
16913
16960
|
offset += chunk.byteLength;
|
|
16914
16961
|
}
|
|
16915
|
-
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(
|
|
16962
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(responseBytes2));
|
|
16916
16963
|
} finally {
|
|
16917
16964
|
if (opened) {
|
|
16918
16965
|
await this.client.rpc("harness.api.transfer.close", { transferId }).catch(() => void 0);
|
|
@@ -17387,7 +17434,7 @@ var RemoteTypertGateway2 = class {
|
|
|
17387
17434
|
if (committed.transferId !== transferId || committed.totalBytes <= 0 || committed.totalBytes > MAX_HARNESS_API_TRANSFER_BYTES || committed.totalChunks !== Math.ceil(committed.totalBytes / HARNESS_API_TRANSFER_CHUNK_BYTES)) {
|
|
17388
17435
|
throw new Error("The remote Host returned an invalid Harness Remote transfer descriptor.");
|
|
17389
17436
|
}
|
|
17390
|
-
const
|
|
17437
|
+
const responseBytes2 = new Uint8Array(committed.totalBytes);
|
|
17391
17438
|
let offset = 0;
|
|
17392
17439
|
for (let index = 0; index < committed.totalChunks; index += 1) {
|
|
17393
17440
|
const result = await this.client.rpc(
|
|
@@ -17403,10 +17450,10 @@ var RemoteTypertGateway2 = class {
|
|
|
17403
17450
|
if (chunk.byteLength !== expectedBytes) {
|
|
17404
17451
|
throw new Error("The remote Host returned an invalid Harness Remote transfer chunk.");
|
|
17405
17452
|
}
|
|
17406
|
-
|
|
17453
|
+
responseBytes2.set(chunk, offset);
|
|
17407
17454
|
offset += chunk.byteLength;
|
|
17408
17455
|
}
|
|
17409
|
-
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(
|
|
17456
|
+
return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(responseBytes2));
|
|
17410
17457
|
} finally {
|
|
17411
17458
|
if (opened) await this.client.rpc("harness.remote.transfer.close", { transferId }).catch(() => void 0);
|
|
17412
17459
|
}
|
|
@@ -24797,22 +24844,22 @@ var CodexPeerBridge = class {
|
|
|
24797
24844
|
});
|
|
24798
24845
|
throw error;
|
|
24799
24846
|
}
|
|
24800
|
-
const
|
|
24801
|
-
if (
|
|
24802
|
-
if (
|
|
24847
|
+
const responseBytes2 = new TextEncoder().encode(JSON.stringify(response));
|
|
24848
|
+
if (responseBytes2.byteLength <= INLINE_TRANSFER_RESPONSE_BYTES) return { kind: "inline", response };
|
|
24849
|
+
if (responseBytes2.byteLength > MAX_CODEX_APP_TRANSFER_BYTES) {
|
|
24803
24850
|
throw new RpcError("RESPONSE_TOO_LARGE", "The Codex response exceeds the bounded transfer limit.");
|
|
24804
24851
|
}
|
|
24805
24852
|
if (this.outgoingTransfers.size >= MAX_ACTIVE_TRANSFERS) {
|
|
24806
24853
|
throw new RpcError("RATE_LIMITED", "Too many Codex response transfers are active.", void 0, true);
|
|
24807
24854
|
}
|
|
24808
|
-
const totalChunks = Math.ceil(
|
|
24855
|
+
const totalChunks = Math.ceil(responseBytes2.byteLength / CODEX_APP_TRANSFER_CHUNK_BYTES);
|
|
24809
24856
|
this.outgoingTransfers.set(params.transferId, {
|
|
24810
|
-
bytes:
|
|
24857
|
+
bytes: responseBytes2,
|
|
24811
24858
|
totalChunks,
|
|
24812
24859
|
nextIndex: 0,
|
|
24813
24860
|
touchedAt: Date.now()
|
|
24814
24861
|
});
|
|
24815
|
-
return { kind: "chunked", transferId: params.transferId, totalBytes:
|
|
24862
|
+
return { kind: "chunked", transferId: params.transferId, totalBytes: responseBytes2.byteLength, totalChunks };
|
|
24816
24863
|
}
|
|
24817
24864
|
readTransfer(input2) {
|
|
24818
24865
|
this.requireOpen();
|
|
@@ -26579,12 +26626,14 @@ var PluginControlRuntime = class {
|
|
|
26579
26626
|
/** Consecutive reconciliations without a DSH session: DSH refreshes its grant, so one empty read is not a sign-out. */
|
|
26580
26627
|
/** Guards against re-entry through configure(), which reads the settings view back. */
|
|
26581
26628
|
reconcilingWithDeepSeek = false;
|
|
26629
|
+
/** The authorization exchange in flight; a settings poll must not start a second one. */
|
|
26630
|
+
deepseekAuthorization;
|
|
26582
26631
|
/**
|
|
26583
26632
|
* Keep this device's Server credentials in step with DSH's DeepSeek session - that session is the credential, and
|
|
26584
26633
|
* the Server verifies it before issuing this device its own tokens.
|
|
26585
26634
|
*
|
|
26586
26635
|
* Three cases: DSH signed in and this device not authorized -> authorize; DSH signed out and this device authorized
|
|
26587
|
-
* -> sign out; otherwise nothing. At most
|
|
26636
|
+
* -> sign out; otherwise nothing. At most one exchange at a time, from the settings poll the panel already makes.
|
|
26588
26637
|
*/
|
|
26589
26638
|
async reconcileWithDeepSeek() {
|
|
26590
26639
|
if (this.deepseekSession === void 0 || this.reconcilingWithDeepSeek) return;
|
|
@@ -26593,19 +26642,20 @@ var PluginControlRuntime = class {
|
|
|
26593
26642
|
const session = await this.deepseekSession.read();
|
|
26594
26643
|
if (this.client !== void 0) this.client.hasDeepSeekSession = session !== void 0;
|
|
26595
26644
|
const authorized = this.client === void 0 ? false : await this.client.hasServerAuthorization();
|
|
26596
|
-
console.error(`[dsh-remote] reconcile ${JSON.stringify({ hasSession: session !== void 0, authorized })}`);
|
|
26597
26645
|
if (session === void 0 && authorized) {
|
|
26598
26646
|
await this.logout({ releaseDeepSeek: false });
|
|
26599
26647
|
return;
|
|
26600
26648
|
}
|
|
26601
26649
|
if (session === void 0 || authorized) return;
|
|
26650
|
+
if (this.deepseekAuthorization !== void 0) return;
|
|
26602
26651
|
if (this.client !== void 0) this.client.authorizingWithDeepSeek = true;
|
|
26603
|
-
|
|
26652
|
+
this.deepseekAuthorization = (async () => {
|
|
26604
26653
|
try {
|
|
26605
26654
|
await this.configure({ provider: "deepseek", serverUrl: this.config.serverUrl });
|
|
26606
26655
|
} catch (error) {
|
|
26607
26656
|
console.error(`[dsh-remote] reconcile failed ${JSON.stringify({ code: String(error?.code ?? "") })}`);
|
|
26608
26657
|
} finally {
|
|
26658
|
+
this.deepseekAuthorization = void 0;
|
|
26609
26659
|
if (this.client !== void 0) this.client.authorizingWithDeepSeek = false;
|
|
26610
26660
|
}
|
|
26611
26661
|
})();
|
|
@@ -27418,8 +27468,8 @@ async function callHistoryWithRetry(callWithTimeout, payload, rpcId2, pageSizes)
|
|
|
27418
27468
|
}
|
|
27419
27469
|
throw new RpcError("INTERNAL_ERROR", "Failed to load session history with a fallback page size.");
|
|
27420
27470
|
}
|
|
27421
|
-
function sessionHistoryFallbackPageSizes(
|
|
27422
|
-
const requested = normalizeSessionHistoryPageSize(
|
|
27471
|
+
function sessionHistoryFallbackPageSizes(requestedMaxMessages2) {
|
|
27472
|
+
const requested = normalizeSessionHistoryPageSize(requestedMaxMessages2);
|
|
27423
27473
|
const sizes = [];
|
|
27424
27474
|
if (requested === void 0) {
|
|
27425
27475
|
sizes.push(...SESSION_HISTORY_PAGE_SIZES);
|
|
@@ -27782,25 +27832,25 @@ var HarnessApiBridge = class {
|
|
|
27782
27832
|
}
|
|
27783
27833
|
const nativeRequest = callSchema2.parse(request);
|
|
27784
27834
|
const response = await this.call(nativeRequest);
|
|
27785
|
-
const
|
|
27786
|
-
if (
|
|
27835
|
+
const responseBytes2 = new TextEncoder().encode(JSON.stringify(response));
|
|
27836
|
+
if (responseBytes2.byteLength <= INLINE_TRANSFER_RESPONSE_BYTES2) {
|
|
27787
27837
|
return { kind: "inline", response };
|
|
27788
27838
|
}
|
|
27789
|
-
if (
|
|
27839
|
+
if (responseBytes2.byteLength > MAX_HARNESS_API_TRANSFER_BYTES) {
|
|
27790
27840
|
throw new RpcError("RESPONSE_TOO_LARGE", "The Harness API response exceeds the bounded transfer limit.");
|
|
27791
27841
|
}
|
|
27792
27842
|
this.pruneTransfers();
|
|
27793
27843
|
if (this.outgoingTransfers.size >= MAX_ACTIVE_API_TRANSFERS) {
|
|
27794
27844
|
throw new RpcError("RATE_LIMITED", "Too many Harness API response transfers are active.", void 0, true);
|
|
27795
27845
|
}
|
|
27796
|
-
const totalChunks = Math.ceil(
|
|
27846
|
+
const totalChunks = Math.ceil(responseBytes2.byteLength / HARNESS_API_TRANSFER_CHUNK_BYTES);
|
|
27797
27847
|
this.outgoingTransfers.set(params.transferId, {
|
|
27798
|
-
bytes:
|
|
27848
|
+
bytes: responseBytes2,
|
|
27799
27849
|
totalChunks,
|
|
27800
27850
|
nextIndex: 0,
|
|
27801
27851
|
touchedAt: Date.now()
|
|
27802
27852
|
});
|
|
27803
|
-
return { kind: "chunked", transferId: params.transferId, totalBytes:
|
|
27853
|
+
return { kind: "chunked", transferId: params.transferId, totalBytes: responseBytes2.byteLength, totalChunks };
|
|
27804
27854
|
}
|
|
27805
27855
|
readTransfer(input2) {
|
|
27806
27856
|
this.pruneTransfers();
|
|
@@ -28221,6 +28271,7 @@ function concatChunks2(chunks, totalBytes) {
|
|
|
28221
28271
|
}
|
|
28222
28272
|
|
|
28223
28273
|
// src/harness-remote-bridge.ts
|
|
28274
|
+
import { Buffer as Buffer4 } from "node:buffer";
|
|
28224
28275
|
var endpointSchema = external_exports.string().min(1).max(128).regex(/^(?:\$events(?:\/result)?|[A-Za-z0-9_$.-]+\/[A-Za-z0-9_$.-]+)$/);
|
|
28225
28276
|
var callSchema3 = external_exports.object({ endpoint: endpointSchema, payload: external_exports.unknown() }).strict();
|
|
28226
28277
|
var streamOpenSchema3 = external_exports.object({
|
|
@@ -28268,6 +28319,13 @@ var directoryListSchema2 = external_exports.object({
|
|
|
28268
28319
|
var MAX_ACTIVE_STREAMS2 = MAX_ALPHA_STREAMS_PER_CONNECTION;
|
|
28269
28320
|
var MAX_ACTIVE_TRANSFERS2 = MAX_ACTIVE_TRANSFERS_PER_DIRECTION;
|
|
28270
28321
|
var INLINE_TRANSFER_RESPONSE_BYTES3 = 2 * 1024 * 1024;
|
|
28322
|
+
var STREAM_FRAME_ENVELOPE_BYTES = 4 * 1024;
|
|
28323
|
+
var RESPONSE_ENVELOPE_BYTES = 8 * 1024;
|
|
28324
|
+
var HISTORY_PAGE_SIZES = [120, 80, 50, 30, 20, 12, 6, 3, 1];
|
|
28325
|
+
var MAX_HISTORY_PAGE_MESSAGES = 500;
|
|
28326
|
+
var REMOTE_HISTORY_CALL_ENDPOINTS = /* @__PURE__ */ new Set(["session/page", "session/history"]);
|
|
28327
|
+
var REMOTE_HISTORY_STREAM_ENDPOINTS = /* @__PURE__ */ new Set(["session/follow"]);
|
|
28328
|
+
var MAX_CACHED_HISTORY_PAGES = 64;
|
|
28271
28329
|
var HARNESS_REMOTE_ALLOWLIST = [
|
|
28272
28330
|
"$events",
|
|
28273
28331
|
"$events/result",
|
|
@@ -28356,6 +28414,8 @@ var HarnessRemoteBridge = class {
|
|
|
28356
28414
|
streams = /* @__PURE__ */ new Map();
|
|
28357
28415
|
incomingTransfers = /* @__PURE__ */ new Map();
|
|
28358
28416
|
outgoingTransfers = /* @__PURE__ */ new Map();
|
|
28417
|
+
/** Last page size that fit one secure message, per session, so probing is paid once. */
|
|
28418
|
+
historyPageSizes = /* @__PURE__ */ new Map();
|
|
28359
28419
|
/**
|
|
28360
28420
|
* Answer one remote Gateway call.
|
|
28361
28421
|
*
|
|
@@ -28396,7 +28456,7 @@ var HarnessRemoteBridge = class {
|
|
|
28396
28456
|
const signal = AbortSignal.timeout(6e4);
|
|
28397
28457
|
try {
|
|
28398
28458
|
const nativePayload = normalizeWorkspaceRequestPayload(params.endpoint, params.payload, this.harnessVersion);
|
|
28399
|
-
const nativeResult = params.endpoint === "commands/execute" ? await dispatchCommandForHost(this.gateway, params.payload, signal, this.harnessVersion) : await this.gateway.dispatch(params.endpoint, nativePayload, signal);
|
|
28459
|
+
const nativeResult = REMOTE_HISTORY_CALL_ENDPOINTS.has(params.endpoint) ? await this.dispatchHistoryPage(params.endpoint, nativePayload, signal) : params.endpoint === "commands/execute" ? await dispatchCommandForHost(this.gateway, params.payload, signal, this.harnessVersion) : await this.gateway.dispatch(params.endpoint, nativePayload, signal);
|
|
28400
28460
|
const result = params.endpoint === "directoryPicker/list" && needsDirectoryFallback(nativeResult) ? await this.directoryList(params.payload, signal) : nativeResult;
|
|
28401
28461
|
this.logger?.debug("harness remote call ok", {
|
|
28402
28462
|
endpoint: params.endpoint,
|
|
@@ -28417,7 +28477,10 @@ var HarnessRemoteBridge = class {
|
|
|
28417
28477
|
this.logger?.warn("harness remote call failed", {
|
|
28418
28478
|
endpoint: params.endpoint,
|
|
28419
28479
|
durationMs: Math.round(performance.now() - startedAt),
|
|
28420
|
-
code: this.gateway.failure(error).code
|
|
28480
|
+
code: this.gateway.failure(error).code,
|
|
28481
|
+
// The code alone is what the client sees; the message is the only thing that says WHY the
|
|
28482
|
+
// Host threw (a strict-schema rejection, an oversized page, a session the gateway lost).
|
|
28483
|
+
message: error instanceof Error ? error.message : String(error)
|
|
28421
28484
|
});
|
|
28422
28485
|
throw error;
|
|
28423
28486
|
}
|
|
@@ -28487,22 +28550,22 @@ var HarnessRemoteBridge = class {
|
|
|
28487
28550
|
throw new RpcError("INVALID_MESSAGE", "The Harness Remote transfer does not contain a valid request.");
|
|
28488
28551
|
}
|
|
28489
28552
|
const response = await this.call(callSchema3.parse(request));
|
|
28490
|
-
const
|
|
28491
|
-
if (
|
|
28492
|
-
if (
|
|
28553
|
+
const responseBytes2 = new TextEncoder().encode(JSON.stringify(response));
|
|
28554
|
+
if (responseBytes2.byteLength <= INLINE_TRANSFER_RESPONSE_BYTES3) return { kind: "inline", response };
|
|
28555
|
+
if (responseBytes2.byteLength > MAX_HARNESS_API_TRANSFER_BYTES) {
|
|
28493
28556
|
throw new RpcError("RESPONSE_TOO_LARGE", "The Harness Remote response exceeds the bounded transfer limit.");
|
|
28494
28557
|
}
|
|
28495
28558
|
if (this.outgoingTransfers.size >= MAX_ACTIVE_TRANSFERS2) {
|
|
28496
28559
|
throw new RpcError("RATE_LIMITED", "Too many Harness Remote response transfers are active.", void 0, true);
|
|
28497
28560
|
}
|
|
28498
|
-
const totalChunks = Math.ceil(
|
|
28561
|
+
const totalChunks = Math.ceil(responseBytes2.byteLength / HARNESS_API_TRANSFER_CHUNK_BYTES);
|
|
28499
28562
|
this.outgoingTransfers.set(params.transferId, {
|
|
28500
|
-
bytes:
|
|
28563
|
+
bytes: responseBytes2,
|
|
28501
28564
|
totalChunks,
|
|
28502
28565
|
nextIndex: 0,
|
|
28503
28566
|
touchedAt: Date.now()
|
|
28504
28567
|
});
|
|
28505
|
-
return { kind: "chunked", transferId: params.transferId, totalBytes:
|
|
28568
|
+
return { kind: "chunked", transferId: params.transferId, totalBytes: responseBytes2.byteLength, totalChunks };
|
|
28506
28569
|
}
|
|
28507
28570
|
readTransfer(input2) {
|
|
28508
28571
|
this.pruneTransfers();
|
|
@@ -28520,7 +28583,7 @@ var HarnessRemoteBridge = class {
|
|
|
28520
28583
|
return {
|
|
28521
28584
|
transferId: params.transferId,
|
|
28522
28585
|
index: params.index,
|
|
28523
|
-
data:
|
|
28586
|
+
data: Buffer4.from(transfer.bytes.subarray(start, end)).toString("base64")
|
|
28524
28587
|
};
|
|
28525
28588
|
}
|
|
28526
28589
|
closeTransfer(input2) {
|
|
@@ -28540,17 +28603,135 @@ var HarnessRemoteBridge = class {
|
|
|
28540
28603
|
}
|
|
28541
28604
|
const controller = new AbortController();
|
|
28542
28605
|
this.streams.set(params.streamId, { controller });
|
|
28543
|
-
let source;
|
|
28544
28606
|
try {
|
|
28545
|
-
|
|
28607
|
+
const nativePayload = normalizeWorkspaceChangesPayload(params.endpoint, params.payload, this.harnessVersion);
|
|
28608
|
+
if (REMOTE_HISTORY_STREAM_ENDPOINTS.has(params.endpoint)) {
|
|
28609
|
+
const opened = await this.openHistoryStream(params, nativePayload, controller.signal);
|
|
28610
|
+
void this.pump(params.streamId, opened.source, controller.signal, opened.frame);
|
|
28611
|
+
return { opened: true, streamId: params.streamId };
|
|
28612
|
+
}
|
|
28613
|
+
const source = (this.codexWorkspace === void 0 ? void 0 : await this.codexWorkspace.open(params.endpoint, params.payload, controller.signal)) ?? await this.gateway.open(params.endpoint, nativePayload, controller.signal);
|
|
28546
28614
|
controller.signal.throwIfAborted();
|
|
28615
|
+
void this.pump(params.streamId, source, controller.signal);
|
|
28616
|
+
return { opened: true, streamId: params.streamId };
|
|
28547
28617
|
} catch (error) {
|
|
28548
28618
|
this.streams.delete(params.streamId);
|
|
28549
28619
|
controller.abort();
|
|
28620
|
+
this.logger?.warn("harness remote stream open failed", {
|
|
28621
|
+
endpoint: params.endpoint,
|
|
28622
|
+
message: error instanceof Error ? error.message : String(error)
|
|
28623
|
+
});
|
|
28550
28624
|
throw error;
|
|
28551
28625
|
}
|
|
28552
|
-
|
|
28553
|
-
|
|
28626
|
+
}
|
|
28627
|
+
/**
|
|
28628
|
+
* Open a history stream with its opening page chosen by byte budget.
|
|
28629
|
+
*
|
|
28630
|
+
* `session/follow` yields one snapshot page and then live events. The snapshot cannot be
|
|
28631
|
+
* retried after the stream is handed to the client, so each attempt is pulled here, measured,
|
|
28632
|
+
* and closed again when it would not fit one secure message. The accepted iterator continues
|
|
28633
|
+
* after that first frame, which the pump publishes before the live tail.
|
|
28634
|
+
* @param params - the validated stream-open request.
|
|
28635
|
+
* @param payload - the request payload after endpoint normalization.
|
|
28636
|
+
* @param signal - the stream's cancellation signal.
|
|
28637
|
+
* @returns the remaining source and the measured first frame.
|
|
28638
|
+
*/
|
|
28639
|
+
async openHistoryStream(params, payload, signal) {
|
|
28640
|
+
const { key, sizes } = this.historyPageSizesFor(payload);
|
|
28641
|
+
for (const size of sizes) {
|
|
28642
|
+
const source = await this.gateway.open(params.endpoint, withHistoryWindow(payload, size), signal);
|
|
28643
|
+
const iterator = source[Symbol.asyncIterator]();
|
|
28644
|
+
let first;
|
|
28645
|
+
try {
|
|
28646
|
+
first = await iterator.next();
|
|
28647
|
+
} catch (error) {
|
|
28648
|
+
await iterator.return?.();
|
|
28649
|
+
throw error;
|
|
28650
|
+
}
|
|
28651
|
+
if (first.done === true) {
|
|
28652
|
+
await iterator.return?.();
|
|
28653
|
+
return { source: EMPTY_ASYNC_ITERABLE };
|
|
28654
|
+
}
|
|
28655
|
+
const frame = {
|
|
28656
|
+
streamId: params.streamId,
|
|
28657
|
+
hasValue: true,
|
|
28658
|
+
...first.value === void 0 ? {} : { value: collectRpcAttachments(first.value) }
|
|
28659
|
+
};
|
|
28660
|
+
const bytes = streamFrameBytes(frame);
|
|
28661
|
+
this.logger?.debug("history stream attempt", { endpoint: params.endpoint, size, bytes });
|
|
28662
|
+
if (bytes <= MAX_SECURE_MESSAGE_BYTES - STREAM_FRAME_ENVELOPE_BYTES) {
|
|
28663
|
+
this.rememberHistoryPageSize(key, size);
|
|
28664
|
+
return { source: remainingIterable(iterator), frame };
|
|
28665
|
+
}
|
|
28666
|
+
await iterator.return?.();
|
|
28667
|
+
}
|
|
28668
|
+
throw new RpcError(
|
|
28669
|
+
"RESPONSE_TOO_LARGE",
|
|
28670
|
+
"The Harness history page is too large for the secure Remote channel. Request a smaller page.",
|
|
28671
|
+
{ maxBytes: MAX_SECURE_MESSAGE_BYTES },
|
|
28672
|
+
true
|
|
28673
|
+
);
|
|
28674
|
+
}
|
|
28675
|
+
/**
|
|
28676
|
+
* Answer one unary history page with the largest window that still fits.
|
|
28677
|
+
*
|
|
28678
|
+
* DSH's client asks for 500 messages; a session whose only Turn is long answers that with
|
|
28679
|
+
* its whole log, which the 4 MiB secure-message limit cannot carry. Each page is measured
|
|
28680
|
+
* after attachment tagging (the form the wire carries) and the request steps down through
|
|
28681
|
+
* {@link HISTORY_PAGE_SIZES} until it fits. Only a size overflow retries: a business failure
|
|
28682
|
+
* is returned immediately.
|
|
28683
|
+
* @param endpoint - the history endpoint being called.
|
|
28684
|
+
* @param payload - the request payload after endpoint normalization.
|
|
28685
|
+
* @param signal - the call's timeout signal.
|
|
28686
|
+
* @returns the page, or `RESPONSE_TOO_LARGE` when even one message cannot cross.
|
|
28687
|
+
*/
|
|
28688
|
+
async dispatchHistoryPage(endpoint, payload, signal) {
|
|
28689
|
+
const { key, sizes } = this.historyPageSizesFor(payload);
|
|
28690
|
+
for (const size of sizes) {
|
|
28691
|
+
const startedAt = performance.now();
|
|
28692
|
+
const result = await this.gateway.dispatch(endpoint, withHistoryWindow(payload, size), signal);
|
|
28693
|
+
if (!result.ok) return result;
|
|
28694
|
+
const value = result.value;
|
|
28695
|
+
const wire = collectRpcAttachments(result);
|
|
28696
|
+
const bytes = responseBytes(wire);
|
|
28697
|
+
this.logger?.debug("history page attempt", {
|
|
28698
|
+
endpoint,
|
|
28699
|
+
size,
|
|
28700
|
+
durationMs: Math.round(performance.now() - startedAt),
|
|
28701
|
+
ok: result.ok,
|
|
28702
|
+
records: Array.isArray(value?.records) ? value.records.length : void 0,
|
|
28703
|
+
hasMore: value?.hasMore,
|
|
28704
|
+
bytes
|
|
28705
|
+
});
|
|
28706
|
+
if (bytes <= MAX_SECURE_MESSAGE_BYTES - RESPONSE_ENVELOPE_BYTES) {
|
|
28707
|
+
this.rememberHistoryPageSize(key, size);
|
|
28708
|
+
return wire;
|
|
28709
|
+
}
|
|
28710
|
+
}
|
|
28711
|
+
return {
|
|
28712
|
+
ok: false,
|
|
28713
|
+
error: {
|
|
28714
|
+
code: "RESPONSE_TOO_LARGE",
|
|
28715
|
+
message: "The Harness history page is too large for the secure Remote channel. Request a smaller page.",
|
|
28716
|
+
details: { maxBytes: MAX_SECURE_MESSAGE_BYTES }
|
|
28717
|
+
}
|
|
28718
|
+
};
|
|
28719
|
+
}
|
|
28720
|
+
/** The ladder for one history request, starting from what last fit for this session. */
|
|
28721
|
+
historyPageSizesFor(payload) {
|
|
28722
|
+
const key = historyPageKey(payload);
|
|
28723
|
+
const requested = requestedMaxMessages(payload) ?? HISTORY_PAGE_SIZES[0];
|
|
28724
|
+
const remembered = this.historyPageSizes.get(key);
|
|
28725
|
+
const start = Math.max(1, Math.min(requested, MAX_HISTORY_PAGE_MESSAGES, remembered ?? requested));
|
|
28726
|
+
this.logger?.debug("history window", { key: key.slice(0, 120), requested, remembered, start });
|
|
28727
|
+
return { key, sizes: historyPageSizes(start) };
|
|
28728
|
+
}
|
|
28729
|
+
rememberHistoryPageSize(key, size) {
|
|
28730
|
+
if (this.historyPageSizes.size >= MAX_CACHED_HISTORY_PAGES && !this.historyPageSizes.has(key)) {
|
|
28731
|
+
const oldest = this.historyPageSizes.keys().next().value;
|
|
28732
|
+
if (oldest !== void 0) this.historyPageSizes.delete(oldest);
|
|
28733
|
+
}
|
|
28734
|
+
this.historyPageSizes.set(key, size);
|
|
28554
28735
|
}
|
|
28555
28736
|
closeStream(input2) {
|
|
28556
28737
|
const params = streamCloseSchema3.parse(input2);
|
|
@@ -28566,6 +28747,7 @@ var HarnessRemoteBridge = class {
|
|
|
28566
28747
|
this.streams.clear();
|
|
28567
28748
|
this.incomingTransfers.clear();
|
|
28568
28749
|
this.outgoingTransfers.clear();
|
|
28750
|
+
this.historyPageSizes.clear();
|
|
28569
28751
|
for (const [, stream] of streams) stream.controller.abort(reason);
|
|
28570
28752
|
await this.codexWorkspace?.closeAll();
|
|
28571
28753
|
}
|
|
@@ -28577,17 +28759,28 @@ var HarnessRemoteBridge = class {
|
|
|
28577
28759
|
throw new RpcError("FEATURE_NOT_SUPPORTED", "This Harness version does not support Remote event transport.");
|
|
28578
28760
|
}
|
|
28579
28761
|
}
|
|
28580
|
-
async pump(streamId, source, signal) {
|
|
28762
|
+
async pump(streamId, source, signal, initialFrame) {
|
|
28581
28763
|
let reason = "completed";
|
|
28582
28764
|
let failure2;
|
|
28583
28765
|
try {
|
|
28766
|
+
if (initialFrame !== void 0 && !signal.aborted) await this.publish("harness.remote.frame", initialFrame);
|
|
28584
28767
|
for await (const value of source) {
|
|
28585
28768
|
if (signal.aborted) break;
|
|
28586
|
-
|
|
28769
|
+
const frame = {
|
|
28587
28770
|
streamId,
|
|
28588
28771
|
hasValue: true,
|
|
28589
28772
|
...value === void 0 ? {} : { value: collectRpcAttachments(value) }
|
|
28590
|
-
}
|
|
28773
|
+
};
|
|
28774
|
+
if (streamFrameBytes(frame) > MAX_SECURE_MESSAGE_BYTES - STREAM_FRAME_ENVELOPE_BYTES) {
|
|
28775
|
+
failure2 = {
|
|
28776
|
+
code: "RESPONSE_TOO_LARGE",
|
|
28777
|
+
message: "The Harness stream frame is too large for the secure Remote channel.",
|
|
28778
|
+
details: { maxBytes: MAX_SECURE_MESSAGE_BYTES }
|
|
28779
|
+
};
|
|
28780
|
+
reason = "failed";
|
|
28781
|
+
break;
|
|
28782
|
+
}
|
|
28783
|
+
await this.publish("harness.remote.frame", frame);
|
|
28591
28784
|
}
|
|
28592
28785
|
if (signal.aborted) reason = "cancelled";
|
|
28593
28786
|
} catch (error) {
|
|
@@ -28608,6 +28801,77 @@ var HarnessRemoteBridge = class {
|
|
|
28608
28801
|
for (const [id4, transfer] of this.outgoingTransfers) if (transfer.touchedAt < cutoff) this.outgoingTransfers.delete(id4);
|
|
28609
28802
|
}
|
|
28610
28803
|
};
|
|
28804
|
+
function withHistoryWindow(payload, maxMessages) {
|
|
28805
|
+
if (!isRecord14(payload)) return payload;
|
|
28806
|
+
if (Array.isArray(payload.args)) {
|
|
28807
|
+
const [first, ...rest] = payload.args;
|
|
28808
|
+
return isRecord14(first) ? { ...payload, args: [windowedParams(first, maxMessages), ...rest] } : payload;
|
|
28809
|
+
}
|
|
28810
|
+
if (isRecord14(payload.args)) return { ...payload, args: windowedParams(payload.args, maxMessages) };
|
|
28811
|
+
return windowedParams(payload, maxMessages);
|
|
28812
|
+
}
|
|
28813
|
+
function windowedParams(params, maxMessages) {
|
|
28814
|
+
return isRecord14(params.request) ? { ...params, request: windowedRequest(params.request, maxMessages) } : windowedRequest(params, maxMessages);
|
|
28815
|
+
}
|
|
28816
|
+
function windowedRequest(request, maxMessages) {
|
|
28817
|
+
const turnWindow = isRecord14(request.turnWindow) ? request.turnWindow : void 0;
|
|
28818
|
+
const next = { ...request, maxMessages };
|
|
28819
|
+
if (turnWindow !== void 0) {
|
|
28820
|
+
next.turnWindow = typeof turnWindow.minMessages === "number" && Number.isFinite(turnWindow.minMessages) ? { ...turnWindow, minMessages: Math.min(turnWindow.minMessages, maxMessages) } : turnWindow;
|
|
28821
|
+
}
|
|
28822
|
+
return next;
|
|
28823
|
+
}
|
|
28824
|
+
function historyPageSizes(start) {
|
|
28825
|
+
const sizes = [start];
|
|
28826
|
+
for (const size of HISTORY_PAGE_SIZES) if (size < start) sizes.push(size);
|
|
28827
|
+
return sizes;
|
|
28828
|
+
}
|
|
28829
|
+
function historyRequestOf(payload) {
|
|
28830
|
+
let node = payload;
|
|
28831
|
+
for (let depth = 0; depth < 4; depth += 1) {
|
|
28832
|
+
if (!isRecord14(node)) return void 0;
|
|
28833
|
+
if (Array.isArray(node.args)) {
|
|
28834
|
+
node = node.args[0];
|
|
28835
|
+
continue;
|
|
28836
|
+
}
|
|
28837
|
+
if (isRecord14(node.args)) {
|
|
28838
|
+
node = node.args;
|
|
28839
|
+
continue;
|
|
28840
|
+
}
|
|
28841
|
+
if (isRecord14(node.request)) {
|
|
28842
|
+
node = node.request;
|
|
28843
|
+
continue;
|
|
28844
|
+
}
|
|
28845
|
+
return node;
|
|
28846
|
+
}
|
|
28847
|
+
return void 0;
|
|
28848
|
+
}
|
|
28849
|
+
function requestedMaxMessages(payload) {
|
|
28850
|
+
const value = historyRequestOf(payload)?.maxMessages;
|
|
28851
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 ? Math.floor(value) : void 0;
|
|
28852
|
+
}
|
|
28853
|
+
function historyPageKey(payload) {
|
|
28854
|
+
const request = historyRequestOf(payload);
|
|
28855
|
+
if (request === void 0) return "default";
|
|
28856
|
+
const address = request.address ?? request.request ?? request.threadId ?? request.sessionId;
|
|
28857
|
+
if (address === void 0) return "default";
|
|
28858
|
+
try {
|
|
28859
|
+
return JSON.stringify(address);
|
|
28860
|
+
} catch {
|
|
28861
|
+
return "default";
|
|
28862
|
+
}
|
|
28863
|
+
}
|
|
28864
|
+
function responseBytes(result) {
|
|
28865
|
+
return Buffer4.byteLength(JSON.stringify(result), "utf8");
|
|
28866
|
+
}
|
|
28867
|
+
function streamFrameBytes(frame) {
|
|
28868
|
+
return Buffer4.byteLength(JSON.stringify(frame), "utf8");
|
|
28869
|
+
}
|
|
28870
|
+
function remainingIterable(iterator) {
|
|
28871
|
+
return { [Symbol.asyncIterator]: () => iterator };
|
|
28872
|
+
}
|
|
28873
|
+
var EMPTY_ASYNC_ITERABLE = { async *[Symbol.asyncIterator]() {
|
|
28874
|
+
} };
|
|
28611
28875
|
function normalizeWorkspaceChangesPayload(endpoint, payload, harnessVersion) {
|
|
28612
28876
|
if (endpoint !== "workspaceFiles/changes" || !requiresWorkspaceChangePath(harnessVersion)) return payload;
|
|
28613
28877
|
if (!isRecord14(payload) || !isRecord14(payload.args) || Object.hasOwn(payload.args, "path")) return payload;
|
|
@@ -28661,7 +28925,7 @@ async function dispatchCommandForHost(gateway, payload, signal, harnessVersion)
|
|
|
28661
28925
|
);
|
|
28662
28926
|
}
|
|
28663
28927
|
function decodeCanonicalBase643(value) {
|
|
28664
|
-
const bytes =
|
|
28928
|
+
const bytes = Buffer4.from(value, "base64");
|
|
28665
28929
|
if (bytes.toString("base64") !== value) throw new RpcError("INVALID_MESSAGE", "The Harness Remote transfer chunk is invalid.");
|
|
28666
28930
|
return bytes;
|
|
28667
28931
|
}
|