ds-harness-remote 0.5.13 → 0.5.15
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/acp/peer-bridge.d.ts +1 -0
- package/dist/acp/peer-bridge.d.ts.map +1 -1
- package/dist/acp/peer-bridge.js +4 -1
- package/dist/acp/peer-bridge.js.map +1 -1
- package/dist/client/settings.d.ts.map +1 -1
- package/dist/client/settings.js +30 -11
- package/dist/client/settings.js.map +1 -1
- package/dist/client/shell.d.ts.map +1 -1
- package/dist/client/shell.js +8 -10
- package/dist/client/shell.js.map +1 -1
- package/dist/client/types.d.ts +1 -0
- package/dist/client/types.d.ts.map +1 -1
- package/dist/client/workspaces.d.ts.map +1 -1
- package/dist/client/workspaces.js +86 -20
- package/dist/client/workspaces.js.map +1 -1
- package/dist/client-connection.d.ts.map +1 -1
- package/dist/client-connection.js +14 -9
- package/dist/client-connection.js.map +1 -1
- package/dist/client-locale.d.ts +2 -1
- package/dist/client-locale.d.ts.map +1 -1
- package/dist/client-locale.js +4 -2
- package/dist/client-locale.js.map +1 -1
- package/dist/client-runtime.d.ts +3 -0
- package/dist/client-runtime.d.ts.map +1 -1
- package/dist/client-runtime.js +112 -65
- package/dist/client-runtime.js.map +1 -1
- package/dist/client.github.js +107 -55
- package/dist/client.js +107 -55
- package/dist/codex/history-preview.d.ts +3 -0
- package/dist/codex/history-preview.d.ts.map +1 -0
- package/dist/codex/history-preview.js +71 -0
- package/dist/codex/history-preview.js.map +1 -0
- package/dist/codex/peer-bridge.d.ts +1 -0
- package/dist/codex/peer-bridge.d.ts.map +1 -1
- package/dist/codex/peer-bridge.js +5 -1
- package/dist/codex/peer-bridge.js.map +1 -1
- package/dist/compact-history.d.ts +2 -0
- package/dist/compact-history.d.ts.map +1 -0
- package/dist/compact-history.js +71 -0
- package/dist/compact-history.js.map +1 -0
- package/dist/connection-controller.d.ts +10 -1
- package/dist/connection-controller.d.ts.map +1 -1
- package/dist/connection-controller.js +5 -3
- package/dist/connection-controller.js.map +1 -1
- package/dist/control-runtime.d.ts +12 -4
- package/dist/control-runtime.d.ts.map +1 -1
- package/dist/control-runtime.js +52 -8
- package/dist/control-runtime.js.map +1 -1
- package/dist/harness-api-bridge.d.ts +1 -0
- package/dist/harness-api-bridge.d.ts.map +1 -1
- package/dist/harness-api-bridge.js +8 -2
- package/dist/harness-api-bridge.js.map +1 -1
- package/dist/harness-remote-bridge.d.ts +3 -1
- package/dist/harness-remote-bridge.d.ts.map +1 -1
- package/dist/harness-remote-bridge.js +76 -6
- package/dist/harness-remote-bridge.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +610 -266
- package/dist/index.js.map +4 -4
- package/dist/plugin-route-bridge.d.ts +1 -1
- package/dist/plugin-route-bridge.d.ts.map +1 -1
- package/dist/plugin-route-bridge.js +1 -1
- package/dist/plugin-route-bridge.js.map +1 -1
- package/dist/remote-directory-browser.d.ts +6 -0
- package/dist/remote-directory-browser.d.ts.map +1 -1
- package/dist/remote-directory-browser.js +16 -1
- package/dist/remote-directory-browser.js.map +1 -1
- package/dist/rpc-router.d.ts.map +1 -1
- package/dist/rpc-router.js +11 -1
- package/dist/rpc-router.js.map +1 -1
- package/dist/server-connection.d.ts.map +1 -1
- package/dist/server-connection.js +12 -4
- package/dist/server-connection.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dsh-plugin.json +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -5586,10 +5586,10 @@ var util;
|
|
|
5586
5586
|
return obj[e];
|
|
5587
5587
|
});
|
|
5588
5588
|
};
|
|
5589
|
-
util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (
|
|
5589
|
+
util2.objectKeys = typeof Object.keys === "function" ? (obj) => Object.keys(obj) : (object3) => {
|
|
5590
5590
|
const keys = [];
|
|
5591
|
-
for (const key in
|
|
5592
|
-
if (Object.prototype.hasOwnProperty.call(
|
|
5591
|
+
for (const key in object3) {
|
|
5592
|
+
if (Object.prototype.hasOwnProperty.call(object3, key)) {
|
|
5593
5593
|
keys.push(key);
|
|
5594
5594
|
}
|
|
5595
5595
|
}
|
|
@@ -8692,8 +8692,8 @@ var ZodSet = class _ZodSet extends ZodType {
|
|
|
8692
8692
|
maxSize: { value: maxSize, message: errorUtil.toString(message) }
|
|
8693
8693
|
});
|
|
8694
8694
|
}
|
|
8695
|
-
size(
|
|
8696
|
-
return this.min(
|
|
8695
|
+
size(size2, message) {
|
|
8696
|
+
return this.min(size2, message).max(size2, message);
|
|
8697
8697
|
}
|
|
8698
8698
|
nonempty(message) {
|
|
8699
8699
|
return this.min(1, message);
|
|
@@ -9579,6 +9579,7 @@ var rpcMethods = [
|
|
|
9579
9579
|
"workspace.upload.commit",
|
|
9580
9580
|
"workspace.upload.abort",
|
|
9581
9581
|
"harness.transport.describe",
|
|
9582
|
+
"remote.history.configure",
|
|
9582
9583
|
"harness.api.call",
|
|
9583
9584
|
"harness.api.transfer.open",
|
|
9584
9585
|
"harness.api.transfer.chunk",
|
|
@@ -9943,8 +9944,8 @@ function createRpcRequest(method, params, id5) {
|
|
|
9943
9944
|
function createRpcResponse(requestId, result) {
|
|
9944
9945
|
return createMessage("rpc.response", { requestId, result });
|
|
9945
9946
|
}
|
|
9946
|
-
function createRpcError(requestId, code, message,
|
|
9947
|
-
return createMessage("rpc.error", { requestId, code, message, details, retryable });
|
|
9947
|
+
function createRpcError(requestId, code, message, details2, retryable) {
|
|
9948
|
+
return createMessage("rpc.error", { requestId, code, message, details: details2, retryable });
|
|
9948
9949
|
}
|
|
9949
9950
|
function createEvent(event, data2, options = {}) {
|
|
9950
9951
|
return createMessage("event", { event, data: data2, ...options });
|
|
@@ -10099,10 +10100,10 @@ function remoteWorkspaceTypeAvailable(capabilities, workspaceTypes, id5, capabil
|
|
|
10099
10100
|
var RemoteGatewayError = class extends Error {
|
|
10100
10101
|
code;
|
|
10101
10102
|
details;
|
|
10102
|
-
constructor(code, message,
|
|
10103
|
+
constructor(code, message, details2 = {}, options) {
|
|
10103
10104
|
super(message, options);
|
|
10104
10105
|
this.code = code;
|
|
10105
|
-
this.details =
|
|
10106
|
+
this.details = details2;
|
|
10106
10107
|
this.name = "RemoteGatewayError";
|
|
10107
10108
|
}
|
|
10108
10109
|
};
|
|
@@ -10119,12 +10120,26 @@ var CODEX_IMAGE_MEDIA_TYPES = /* @__PURE__ */ new Set(["image/png", "image/jpeg"
|
|
|
10119
10120
|
var DATA_IMAGE_URL = /^data:(image\/(?:png|jpeg|webp|gif));base64,([A-Za-z0-9+/]+={0,2})$/u;
|
|
10120
10121
|
var CodexRemoteClient = class {
|
|
10121
10122
|
core;
|
|
10122
|
-
|
|
10123
|
+
historyPreview;
|
|
10124
|
+
constructor(core, historyPreview = false) {
|
|
10123
10125
|
this.core = core;
|
|
10126
|
+
this.historyPreview = historyPreview;
|
|
10124
10127
|
}
|
|
10125
10128
|
/** Low-level allowlisted request used by the Desktop Web loopback facade. */
|
|
10126
|
-
|
|
10127
|
-
|
|
10129
|
+
previewSupported = true;
|
|
10130
|
+
async request(method, params, signal) {
|
|
10131
|
+
if (method === "dsh/sessionHistory" && this.historyPreview && this.previewSupported) {
|
|
10132
|
+
try {
|
|
10133
|
+
return await this.core.rpc("codex.app.call", { method, params, previewHistory: true }, signal);
|
|
10134
|
+
} catch (error) {
|
|
10135
|
+
const code = error?.code;
|
|
10136
|
+
if (code !== "INVALID_MESSAGE" && code !== "RESPONSE_TOO_LARGE")
|
|
10137
|
+
throw error;
|
|
10138
|
+
if (code === "INVALID_MESSAGE")
|
|
10139
|
+
this.previewSupported = false;
|
|
10140
|
+
}
|
|
10141
|
+
}
|
|
10142
|
+
const largeHistory = method === "dsh/historyDetail" || method === "dsh/sessionHistory" || method === "thread/read" && isRecord(params) && params.includeTurns === true;
|
|
10128
10143
|
return this.call(method, params, largeHistory || hasImageInput(params), signal);
|
|
10129
10144
|
}
|
|
10130
10145
|
async account(signal) {
|
|
@@ -11316,8 +11331,8 @@ function rcEndpoint(endpoint) {
|
|
|
11316
11331
|
function success(value) {
|
|
11317
11332
|
return { ok: true, value };
|
|
11318
11333
|
}
|
|
11319
|
-
function failure(code, message,
|
|
11320
|
-
return { ok: false, error: { code, message, details } };
|
|
11334
|
+
function failure(code, message, details2 = {}) {
|
|
11335
|
+
return { ok: false, error: { code, message, details: details2 } };
|
|
11321
11336
|
}
|
|
11322
11337
|
function business(value) {
|
|
11323
11338
|
if (isRecord3(value) && value.ok === false && isRecord3(value.error)) {
|
|
@@ -11333,8 +11348,8 @@ function business(value) {
|
|
|
11333
11348
|
if (isRecord3(value) && value.ok === true) return { ok: true, value: value.value };
|
|
11334
11349
|
return { ok: true, value };
|
|
11335
11350
|
}
|
|
11336
|
-
function fail(code, message,
|
|
11337
|
-
return { ok: false, error: { code, message, details } };
|
|
11351
|
+
function fail(code, message, details2 = {}) {
|
|
11352
|
+
return { ok: false, error: { code, message, details: details2 } };
|
|
11338
11353
|
}
|
|
11339
11354
|
function failFrom(error) {
|
|
11340
11355
|
const source = error instanceof Error ? error : new Error(String(error));
|
|
@@ -11476,12 +11491,12 @@ var AcpEventCarrier = class {
|
|
|
11476
11491
|
} else if (event === "api-session/removed" && sessionId !== void 0) {
|
|
11477
11492
|
this.broadcastRcHost({ type: "host/session-removed", sessionId });
|
|
11478
11493
|
} else if (event === "api-session/added" && isRecord3(args[0])) {
|
|
11479
|
-
const
|
|
11494
|
+
const summary2 = args[0];
|
|
11480
11495
|
this.broadcastRcHost({
|
|
11481
11496
|
type: "host/session-added",
|
|
11482
|
-
sessionId:
|
|
11483
|
-
blank:
|
|
11484
|
-
...typeof
|
|
11497
|
+
sessionId: summary2.sessionId,
|
|
11498
|
+
blank: summary2.blank === true,
|
|
11499
|
+
...typeof summary2.cwd === "string" ? { cwd: summary2.cwd } : {}
|
|
11485
11500
|
});
|
|
11486
11501
|
}
|
|
11487
11502
|
}
|
|
@@ -13311,10 +13326,10 @@ function normalizeProtocol(value) {
|
|
|
13311
13326
|
return value.toLowerCase();
|
|
13312
13327
|
}
|
|
13313
13328
|
function relatedAddressSummary(address) {
|
|
13314
|
-
const
|
|
13329
|
+
const summary2 = summarizeAddress(address);
|
|
13315
13330
|
return {
|
|
13316
|
-
relatedAddressFamily:
|
|
13317
|
-
relatedAddressScope:
|
|
13331
|
+
relatedAddressFamily: summary2.addressFamily,
|
|
13332
|
+
relatedAddressScope: summary2.addressScope
|
|
13318
13333
|
};
|
|
13319
13334
|
}
|
|
13320
13335
|
function summarizeIpv4Scope(parts) {
|
|
@@ -13789,19 +13804,19 @@ var RtcDataChannelTransport = class {
|
|
|
13789
13804
|
}
|
|
13790
13805
|
}
|
|
13791
13806
|
async handleIce(candidate) {
|
|
13792
|
-
const
|
|
13807
|
+
const summary2 = summarizeIceCandidate(candidate);
|
|
13793
13808
|
if (!this.remoteDescriptionSet) {
|
|
13794
|
-
recordCandidate(this.remoteCandidateTelemetry,
|
|
13795
|
-
this.emitDiagnostic({ type: "remote-candidate", candidate:
|
|
13809
|
+
recordCandidate(this.remoteCandidateTelemetry, summary2);
|
|
13810
|
+
this.emitDiagnostic({ type: "remote-candidate", candidate: summary2, action: "buffered", diagnostics: this.diagnostics() });
|
|
13796
13811
|
this.remoteCandidates.push(candidate);
|
|
13797
13812
|
return;
|
|
13798
13813
|
}
|
|
13799
13814
|
try {
|
|
13800
13815
|
await this.pc.addIceCandidate(candidate);
|
|
13801
|
-
recordCandidate(this.remoteCandidateTelemetry,
|
|
13802
|
-
this.emitDiagnostic({ type: "remote-candidate", candidate:
|
|
13816
|
+
recordCandidate(this.remoteCandidateTelemetry, summary2);
|
|
13817
|
+
this.emitDiagnostic({ type: "remote-candidate", candidate: summary2, action: "added", diagnostics: this.diagnostics() });
|
|
13803
13818
|
} catch {
|
|
13804
|
-
this.emitDiagnostic({ type: "remote-candidate", candidate:
|
|
13819
|
+
this.emitDiagnostic({ type: "remote-candidate", candidate: summary2, action: "ignored", diagnostics: this.diagnostics() });
|
|
13805
13820
|
}
|
|
13806
13821
|
}
|
|
13807
13822
|
async flushRemoteCandidates() {
|
|
@@ -14203,19 +14218,19 @@ function isExplicitlyNonLanScope(scope2) {
|
|
|
14203
14218
|
function increment(map, key) {
|
|
14204
14219
|
map[key] = (map[key] ?? 0) + 1;
|
|
14205
14220
|
}
|
|
14206
|
-
function selectedPathTelemetry(
|
|
14221
|
+
function selectedPathTelemetry(details2) {
|
|
14207
14222
|
return {
|
|
14208
|
-
...
|
|
14209
|
-
...
|
|
14210
|
-
...
|
|
14211
|
-
...
|
|
14212
|
-
...
|
|
14213
|
-
...
|
|
14214
|
-
...
|
|
14215
|
-
...
|
|
14216
|
-
...
|
|
14217
|
-
...
|
|
14218
|
-
...
|
|
14223
|
+
...details2.transport === void 0 ? {} : { transport: details2.transport },
|
|
14224
|
+
...details2.mode === void 0 ? {} : { mode: details2.mode },
|
|
14225
|
+
...details2.relayUrl === void 0 ? {} : { relayUrl: details2.relayUrl },
|
|
14226
|
+
...details2.localCandidateType === void 0 ? {} : { localCandidateType: details2.localCandidateType },
|
|
14227
|
+
...details2.remoteCandidateType === void 0 ? {} : { remoteCandidateType: details2.remoteCandidateType },
|
|
14228
|
+
...details2.localAddressScope === void 0 ? {} : { localAddressScope: details2.localAddressScope },
|
|
14229
|
+
...details2.remoteAddressScope === void 0 ? {} : { remoteAddressScope: details2.remoteAddressScope },
|
|
14230
|
+
...details2.protocol === void 0 ? {} : { protocol: details2.protocol },
|
|
14231
|
+
...details2.relayProtocol === void 0 ? {} : { relayProtocol: details2.relayProtocol },
|
|
14232
|
+
...details2.currentRoundTripTimeMs === void 0 ? {} : { currentRoundTripTimeMs: details2.currentRoundTripTimeMs },
|
|
14233
|
+
...details2.availableOutgoingBitrate === void 0 ? {} : { availableOutgoingBitrate: details2.availableOutgoingBitrate }
|
|
14219
14234
|
};
|
|
14220
14235
|
}
|
|
14221
14236
|
function requireSdp(description) {
|
|
@@ -14309,11 +14324,11 @@ var AdaptiveTransport = class extends BaseTransport {
|
|
|
14309
14324
|
};
|
|
14310
14325
|
socket.onerror = () => {
|
|
14311
14326
|
if (this.lifetime === lifetime)
|
|
14312
|
-
this.failConnection(new Error(`AdaptiveTransport failed to connect to ${this.url}`));
|
|
14327
|
+
this.failConnection(new Error(`AdaptiveTransport failed to connect to ${this.url}`), { reason: "control-error" });
|
|
14313
14328
|
};
|
|
14314
14329
|
socket.onclose = (event) => {
|
|
14315
14330
|
if (this.lifetime === lifetime)
|
|
14316
|
-
this.failConnection(adaptiveControlCloseError(event));
|
|
14331
|
+
this.failConnection(adaptiveControlCloseError(event), { reason: "control-closed", closeCode: event.code });
|
|
14317
14332
|
};
|
|
14318
14333
|
});
|
|
14319
14334
|
}
|
|
@@ -14483,7 +14498,7 @@ var AdaptiveTransport = class extends BaseTransport {
|
|
|
14483
14498
|
if (frame.type === "ping")
|
|
14484
14499
|
this.sendControl("pong", frame.payload);
|
|
14485
14500
|
} catch (error) {
|
|
14486
|
-
this.failConnection(error instanceof Error ? error : new Error("Invalid adaptive control frame"));
|
|
14501
|
+
this.failConnection(error instanceof Error ? error : new Error("Invalid adaptive control frame"), { reason: "invalid-control-frame" });
|
|
14487
14502
|
}
|
|
14488
14503
|
}
|
|
14489
14504
|
handleRelay(payload) {
|
|
@@ -14596,8 +14611,9 @@ var AdaptiveTransport = class extends BaseTransport {
|
|
|
14596
14611
|
this.emit(data2);
|
|
14597
14612
|
});
|
|
14598
14613
|
rtc.onClose(() => {
|
|
14599
|
-
if (this.rtc === rtc && this.dataMode === "webrtc")
|
|
14600
|
-
this.
|
|
14614
|
+
if (this.rtc === rtc && this.dataMode === "webrtc") {
|
|
14615
|
+
this.failConnection(new Error("Active WebRTC channel closed"), { reason: "webrtc-closed" });
|
|
14616
|
+
}
|
|
14601
14617
|
});
|
|
14602
14618
|
try {
|
|
14603
14619
|
await rtc.connect(signal);
|
|
@@ -14688,7 +14704,8 @@ var AdaptiveTransport = class extends BaseTransport {
|
|
|
14688
14704
|
this.readyResolve = void 0;
|
|
14689
14705
|
this.readyReject = void 0;
|
|
14690
14706
|
}
|
|
14691
|
-
failConnection(error) {
|
|
14707
|
+
failConnection(error, diagnostic) {
|
|
14708
|
+
const established = this.connectedAt !== void 0;
|
|
14692
14709
|
this.clearHandshake();
|
|
14693
14710
|
const reject = this.readyReject;
|
|
14694
14711
|
this.readyResolve = void 0;
|
|
@@ -14707,6 +14724,12 @@ var AdaptiveTransport = class extends BaseTransport {
|
|
|
14707
14724
|
reject?.(error);
|
|
14708
14725
|
void rtc?.close();
|
|
14709
14726
|
socket?.close();
|
|
14727
|
+
if (established && diagnostic !== void 0) {
|
|
14728
|
+
try {
|
|
14729
|
+
this.options.onDisconnect?.(diagnostic);
|
|
14730
|
+
} catch {
|
|
14731
|
+
}
|
|
14732
|
+
}
|
|
14710
14733
|
if (socket !== void 0)
|
|
14711
14734
|
this.emitClose();
|
|
14712
14735
|
}
|
|
@@ -15686,11 +15709,11 @@ function bitLen(n) {
|
|
|
15686
15709
|
return len;
|
|
15687
15710
|
}
|
|
15688
15711
|
var bitMask = (n) => (_1n << BigInt(n)) - _1n;
|
|
15689
|
-
function _validateObject(
|
|
15690
|
-
if (!
|
|
15712
|
+
function _validateObject(object3, fields, optFields = {}) {
|
|
15713
|
+
if (!object3 || typeof object3 !== "object")
|
|
15691
15714
|
throw new Error("expected valid options object");
|
|
15692
15715
|
function checkField(fieldName, expectedType, isOpt) {
|
|
15693
|
-
const val =
|
|
15716
|
+
const val = object3[fieldName];
|
|
15694
15717
|
if (isOpt && val === void 0)
|
|
15695
15718
|
return;
|
|
15696
15719
|
const current = typeof val;
|
|
@@ -16786,18 +16809,18 @@ function eddsa(Point, cHash, eddsaOpts = {}) {
|
|
|
16786
16809
|
*/
|
|
16787
16810
|
toMontgomery(publicKey) {
|
|
16788
16811
|
const { y } = Point.fromBytes(publicKey);
|
|
16789
|
-
const
|
|
16790
|
-
const is25519 =
|
|
16791
|
-
if (!is25519 &&
|
|
16812
|
+
const size2 = lengths.publicKey;
|
|
16813
|
+
const is25519 = size2 === 32;
|
|
16814
|
+
if (!is25519 && size2 !== 57)
|
|
16792
16815
|
throw new Error("only defined for 25519 and 448");
|
|
16793
16816
|
const u = is25519 ? Fp2.div(_1n4 + y, _1n4 - y) : Fp2.div(y - _1n4, y + _1n4);
|
|
16794
16817
|
return Fp2.toBytes(u);
|
|
16795
16818
|
},
|
|
16796
16819
|
toMontgomerySecret(secretKey2) {
|
|
16797
|
-
const
|
|
16798
|
-
_abytes2(secretKey2,
|
|
16799
|
-
const hashed = cHash(secretKey2.subarray(0,
|
|
16800
|
-
return adjustScalarBytes3(hashed).subarray(0,
|
|
16820
|
+
const size2 = lengths.secretKey;
|
|
16821
|
+
_abytes2(secretKey2, size2);
|
|
16822
|
+
const hashed = cHash(secretKey2.subarray(0, size2));
|
|
16823
|
+
return adjustScalarBytes3(hashed).subarray(0, size2);
|
|
16801
16824
|
},
|
|
16802
16825
|
/** @deprecated */
|
|
16803
16826
|
randomPrivateKey: randomSecretKey,
|
|
@@ -18592,14 +18615,14 @@ var bitMask2 = (n) => {
|
|
|
18592
18615
|
asafenumber(n, "n");
|
|
18593
18616
|
return (_1n7 << BigInt(n)) - _1n7;
|
|
18594
18617
|
};
|
|
18595
|
-
function validateObject2(
|
|
18596
|
-
aobject2(
|
|
18618
|
+
function validateObject2(object3, fields = {}, optFields = {}, title = "object") {
|
|
18619
|
+
aobject2(object3, title);
|
|
18597
18620
|
aobject2(fields, "fields");
|
|
18598
18621
|
aobject2(optFields, "optFields");
|
|
18599
18622
|
function checkField(fieldName, expectedType, isOpt) {
|
|
18600
18623
|
const label = title === "object" ? `param "${String(fieldName)}"` : `"${title}.${String(fieldName)}"`;
|
|
18601
|
-
const val =
|
|
18602
|
-
if (!Object.hasOwn(
|
|
18624
|
+
const val = object3[fieldName];
|
|
18625
|
+
if (!Object.hasOwn(object3, fieldName) && (isOpt ? val !== void 0 : expectedType !== "function")) {
|
|
18603
18626
|
throw new TypeError(`${label} is invalid: expected own property`);
|
|
18604
18627
|
}
|
|
18605
18628
|
if (isOpt && val === void 0)
|
|
@@ -19110,24 +19133,24 @@ var pointWindowSizes2 = /* @__PURE__ */ new WeakMap();
|
|
|
19110
19133
|
function getWindowSize(P) {
|
|
19111
19134
|
return pointWindowSizes2.get(P) || 1;
|
|
19112
19135
|
}
|
|
19113
|
-
function oddMultiples(p,
|
|
19136
|
+
function oddMultiples(p, size2) {
|
|
19114
19137
|
const dbl = p.double();
|
|
19115
19138
|
const t = [p];
|
|
19116
|
-
for (let j = 1; j <
|
|
19139
|
+
for (let j = 1; j < size2; j++)
|
|
19117
19140
|
t.push(t[j - 1].add(dbl));
|
|
19118
19141
|
return t;
|
|
19119
19142
|
}
|
|
19120
19143
|
function wnafDigits(n, W) {
|
|
19121
|
-
const
|
|
19122
|
-
const half =
|
|
19123
|
-
const mask = BigInt(
|
|
19144
|
+
const size2 = 2 ** W;
|
|
19145
|
+
const half = size2 / 2;
|
|
19146
|
+
const mask = BigInt(size2 - 1);
|
|
19124
19147
|
const d = [];
|
|
19125
19148
|
while (n > _0n9) {
|
|
19126
19149
|
let w = 0;
|
|
19127
19150
|
if (n & _1n9) {
|
|
19128
19151
|
w = Number(n & mask);
|
|
19129
19152
|
if (w >= half)
|
|
19130
|
-
w -=
|
|
19153
|
+
w -= size2;
|
|
19131
19154
|
n -= BigInt(w);
|
|
19132
19155
|
}
|
|
19133
19156
|
d.push(w);
|
|
@@ -19136,16 +19159,16 @@ function wnafDigits(n, W) {
|
|
|
19136
19159
|
return d;
|
|
19137
19160
|
}
|
|
19138
19161
|
function signedWindowDigits(n, W, windows) {
|
|
19139
|
-
const
|
|
19140
|
-
const half =
|
|
19141
|
-
const mask = BigInt(
|
|
19162
|
+
const size2 = 2 ** W;
|
|
19163
|
+
const half = size2 / 2;
|
|
19164
|
+
const mask = BigInt(size2 - 1);
|
|
19142
19165
|
const shiftBy = BigInt(W);
|
|
19143
19166
|
const d = [];
|
|
19144
19167
|
for (let w = 0; w < windows; w++) {
|
|
19145
19168
|
let v = Number(n & mask);
|
|
19146
19169
|
n >>= shiftBy;
|
|
19147
19170
|
if (v > half) {
|
|
19148
|
-
v -=
|
|
19171
|
+
v -= size2;
|
|
19149
19172
|
n += _1n9;
|
|
19150
19173
|
}
|
|
19151
19174
|
d.push(v);
|
|
@@ -19316,11 +19339,11 @@ var ScalarMultiplier = class {
|
|
|
19316
19339
|
*/
|
|
19317
19340
|
fixedWindowCT(point, n, bits) {
|
|
19318
19341
|
const W = FW_WINDOW;
|
|
19319
|
-
const
|
|
19342
|
+
const size2 = 1 << W;
|
|
19320
19343
|
const mask = bitMask2(W);
|
|
19321
|
-
const table = new Array(
|
|
19344
|
+
const table = new Array(size2);
|
|
19322
19345
|
table[0] = this.ZERO;
|
|
19323
|
-
for (let i = 1; i <
|
|
19346
|
+
for (let i = 1; i < size2; i++)
|
|
19324
19347
|
table[i] = table[i - 1].add(point);
|
|
19325
19348
|
const windows = Math.ceil(bits / W);
|
|
19326
19349
|
let acc = this.ZERO;
|
|
@@ -19330,7 +19353,7 @@ var ScalarMultiplier = class {
|
|
|
19330
19353
|
acc = acc.double();
|
|
19331
19354
|
const digit = Number(n >> BigInt(window2 * W) & mask);
|
|
19332
19355
|
let sel = table[0];
|
|
19333
|
-
for (let i = 1; i <
|
|
19356
|
+
for (let i = 1; i < size2; i++)
|
|
19334
19357
|
sel = i === digit ? table[i] : sel;
|
|
19335
19358
|
acc = acc.add(sel);
|
|
19336
19359
|
}
|
|
@@ -22260,16 +22283,24 @@ var ClientConnection = class {
|
|
|
22260
22283
|
this.context.connectionProgress = { runId: progressRunId, targetDeviceId, phase: "checking-host" };
|
|
22261
22284
|
const identity2 = this.context.requireIdentity();
|
|
22262
22285
|
let client;
|
|
22286
|
+
const onAbort = () => {
|
|
22287
|
+
void client?.close().catch(() => void 0);
|
|
22288
|
+
};
|
|
22289
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
22263
22290
|
try {
|
|
22264
22291
|
const serverDevice = (await this.context.server.listDevices()).find((device) => device.deviceId === targetDeviceId);
|
|
22292
|
+
signal?.throwIfAborted();
|
|
22265
22293
|
if (serverDevice === void 0) {
|
|
22266
22294
|
throw new ClientModeError("MEMBERSHIP_REQUIRED", "The selected Host is not authorized for this account.");
|
|
22267
22295
|
}
|
|
22268
22296
|
this.updateConnectionProgress(progressRunId, "authorizing-peer");
|
|
22269
22297
|
const target2 = await this.authorizeHostPeer(serverDevice);
|
|
22298
|
+
signal?.throwIfAborted();
|
|
22270
22299
|
const presence = await this.context.server.presenceFor(targetDeviceId);
|
|
22300
|
+
signal?.throwIfAborted();
|
|
22271
22301
|
if (!presence.online) throw new ClientModeError("HOST_OFFLINE", "The selected Host is offline.", true);
|
|
22272
22302
|
const credentials = await this.context.server.authenticate(identity2);
|
|
22303
|
+
signal?.throwIfAborted();
|
|
22273
22304
|
const rtcFactory = this.context.config.forceRelay ? void 0 : await this.context.rtcFactoryProvider({ routeTargets: [this.context.server.baseUrl] }).catch(() => void 0);
|
|
22274
22305
|
if (!this.context.config.forceRelay && rtcFactory === void 0) {
|
|
22275
22306
|
this.context.logger.warn("remote Harness WebRTC backend unavailable; using relay", {
|
|
@@ -22315,16 +22346,8 @@ var ClientConnection = class {
|
|
|
22315
22346
|
transport = createTransport(attempt);
|
|
22316
22347
|
client = new RemoteClientCore(new ClientSecureTransport(transport, identity2, target2), 6e4);
|
|
22317
22348
|
const attemptClient = client;
|
|
22318
|
-
|
|
22319
|
-
|
|
22320
|
-
};
|
|
22321
|
-
signal?.addEventListener("abort", onAbort, { once: true });
|
|
22322
|
-
try {
|
|
22323
|
-
signal?.throwIfAborted();
|
|
22324
|
-
await attemptClient.connect();
|
|
22325
|
-
} finally {
|
|
22326
|
-
signal?.removeEventListener("abort", onAbort);
|
|
22327
|
-
}
|
|
22349
|
+
signal?.throwIfAborted();
|
|
22350
|
+
await attemptClient.connect();
|
|
22328
22351
|
signal?.throwIfAborted();
|
|
22329
22352
|
} finally {
|
|
22330
22353
|
stopProgressTimer();
|
|
@@ -22382,6 +22405,7 @@ var ClientConnection = class {
|
|
|
22382
22405
|
});
|
|
22383
22406
|
}
|
|
22384
22407
|
const features = await probeRemoteHostFeatures(connectedClient, serverDevice.clientVersion);
|
|
22408
|
+
signal?.throwIfAborted();
|
|
22385
22409
|
return {
|
|
22386
22410
|
client: connectedClient,
|
|
22387
22411
|
target: target2,
|
|
@@ -22395,6 +22419,8 @@ var ClientConnection = class {
|
|
|
22395
22419
|
this.clearConnectionProgress(progressRunId);
|
|
22396
22420
|
await client?.close().catch(() => void 0);
|
|
22397
22421
|
throw error;
|
|
22422
|
+
} finally {
|
|
22423
|
+
signal?.removeEventListener("abort", onAbort);
|
|
22398
22424
|
}
|
|
22399
22425
|
}
|
|
22400
22426
|
beginAttemptProgress(runId, attempt) {
|
|
@@ -22453,10 +22479,10 @@ import { WebSocket as WebSocket2 } from "ws";
|
|
|
22453
22479
|
|
|
22454
22480
|
// src/safe-error.ts
|
|
22455
22481
|
var RpcError = class extends Error {
|
|
22456
|
-
constructor(code, message,
|
|
22482
|
+
constructor(code, message, details2, retryable = false) {
|
|
22457
22483
|
super(message);
|
|
22458
22484
|
this.code = code;
|
|
22459
|
-
this.details =
|
|
22485
|
+
this.details = details2;
|
|
22460
22486
|
this.retryable = retryable;
|
|
22461
22487
|
}
|
|
22462
22488
|
};
|
|
@@ -22985,6 +23011,7 @@ var BOT_REMOTE_OPERATIONS = [
|
|
|
22985
23011
|
"send",
|
|
22986
23012
|
"answer-question",
|
|
22987
23013
|
"dismiss-question",
|
|
23014
|
+
"view-reply",
|
|
22988
23015
|
"approval-answer",
|
|
22989
23016
|
"stop-member-work"
|
|
22990
23017
|
];
|
|
@@ -23529,7 +23556,7 @@ async function loadCatalog(client, signal, pendingThreads) {
|
|
|
23529
23556
|
return session === void 0 ? void 0 : { thread, session };
|
|
23530
23557
|
}).filter((value) => value !== void 0);
|
|
23531
23558
|
const projectWorkspaces = projects.map(projectWorkspace);
|
|
23532
|
-
const workspaceByProjectId = new Map(projects.map((
|
|
23559
|
+
const workspaceByProjectId = new Map(projects.map((project2, index) => [project2.id, projectWorkspaces[index]]));
|
|
23533
23560
|
const visibleSessionIds = /* @__PURE__ */ new Set();
|
|
23534
23561
|
const visibleThreads = [];
|
|
23535
23562
|
for (const { thread, session } of projected) {
|
|
@@ -23558,8 +23585,8 @@ async function loadCodexProjects(client, signal) {
|
|
|
23558
23585
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
23559
23586
|
}, signal));
|
|
23560
23587
|
for (const value of array2(result.data)) {
|
|
23561
|
-
const
|
|
23562
|
-
if (
|
|
23588
|
+
const project2 = projectCodexProject(value, projects.length);
|
|
23589
|
+
if (project2 !== void 0 && !projects.some((item) => item.id === project2.id)) projects.push(project2);
|
|
23563
23590
|
}
|
|
23564
23591
|
cursor2 = typeof result.nextCursor === "string" && result.nextCursor.length > 0 ? result.nextCursor : void 0;
|
|
23565
23592
|
if (cursor2 === void 0) break;
|
|
@@ -23635,16 +23662,16 @@ function nativeWorkspace2(view) {
|
|
|
23635
23662
|
function nativeVisibleWorkspaces(catalog, selectedWorkspaceId) {
|
|
23636
23663
|
return catalog.workspaces.filter((workspace) => workspace.sessionIds.length > 0 || workspace.workspaceId === selectedWorkspaceId);
|
|
23637
23664
|
}
|
|
23638
|
-
function projectWorkspace(
|
|
23639
|
-
const root =
|
|
23665
|
+
function projectWorkspace(project2) {
|
|
23666
|
+
const root = project2.roots[0];
|
|
23640
23667
|
return {
|
|
23641
|
-
workspaceId: codexProjectWorkspaceId(
|
|
23668
|
+
workspaceId: codexProjectWorkspaceId(project2.id),
|
|
23642
23669
|
path: root.path,
|
|
23643
|
-
title:
|
|
23670
|
+
title: project2.name.trim() || basename(root.path),
|
|
23644
23671
|
sessionIds: [],
|
|
23645
23672
|
sessionCount: 0,
|
|
23646
|
-
createdAt: isoTime(
|
|
23647
|
-
updatedAt: isoTime(
|
|
23673
|
+
createdAt: isoTime(project2.createdAt),
|
|
23674
|
+
updatedAt: isoTime(project2.updatedAt || project2.createdAt)
|
|
23648
23675
|
};
|
|
23649
23676
|
}
|
|
23650
23677
|
function projectCodexProject(value, fallbackPosition) {
|
|
@@ -23667,7 +23694,7 @@ function findProjectWorkspace(thread, session, projects, workspaceByProjectId) {
|
|
|
23667
23694
|
const explicitWorkspace = explicitProjectId === void 0 ? void 0 : workspaceByProjectId.get(explicitProjectId);
|
|
23668
23695
|
if (explicitWorkspace !== void 0) return explicitWorkspace;
|
|
23669
23696
|
if (session.cwd === void 0) return void 0;
|
|
23670
|
-
const match = projects.flatMap((
|
|
23697
|
+
const match = projects.flatMap((project2) => project2.roots.map((root) => ({ project: project2, root }))).filter((value) => containsPath(value.root.path, session.cwd)).sort((left, right) => {
|
|
23671
23698
|
const length = right.root.path.length - left.root.path.length;
|
|
23672
23699
|
if (length !== 0) return length;
|
|
23673
23700
|
const position = left.project.position - right.project.position;
|
|
@@ -24069,8 +24096,8 @@ function rcEndpoint2(endpoint) {
|
|
|
24069
24096
|
function success2(value) {
|
|
24070
24097
|
return { ok: true, value };
|
|
24071
24098
|
}
|
|
24072
|
-
function failure2(code, message,
|
|
24073
|
-
return { ok: false, error: { code, message, details } };
|
|
24099
|
+
function failure2(code, message, details2 = {}) {
|
|
24100
|
+
return { ok: false, error: { code, message, details: details2 } };
|
|
24074
24101
|
}
|
|
24075
24102
|
function ok2(value) {
|
|
24076
24103
|
return value === void 0 ? { ok: true } : { ok: true, value };
|
|
@@ -24084,8 +24111,8 @@ function business2(value) {
|
|
|
24084
24111
|
}
|
|
24085
24112
|
return ok2(value);
|
|
24086
24113
|
}
|
|
24087
|
-
function fail3(code, message,
|
|
24088
|
-
return { ok: false, error: { code, message, details } };
|
|
24114
|
+
function fail3(code, message, details2 = {}) {
|
|
24115
|
+
return { ok: false, error: { code, message, details: details2 } };
|
|
24089
24116
|
}
|
|
24090
24117
|
function failFrom2(error) {
|
|
24091
24118
|
const source = error instanceof Error ? error : new Error(String(error));
|
|
@@ -24203,12 +24230,12 @@ var CodexEventCarrier = class {
|
|
|
24203
24230
|
} else if (event === "api-session/removed" && sessionId !== void 0) {
|
|
24204
24231
|
this.broadcastRcHost({ type: "host/session-removed", sessionId });
|
|
24205
24232
|
} else if (event === "api-session/added" && isRecord5(args[0])) {
|
|
24206
|
-
const
|
|
24233
|
+
const summary2 = args[0];
|
|
24207
24234
|
this.broadcastRcHost({
|
|
24208
24235
|
type: "host/session-added",
|
|
24209
|
-
sessionId:
|
|
24210
|
-
blank:
|
|
24211
|
-
...typeof
|
|
24236
|
+
sessionId: summary2.sessionId,
|
|
24237
|
+
blank: summary2.blank === true,
|
|
24238
|
+
...typeof summary2.cwd === "string" ? { cwd: summary2.cwd } : {}
|
|
24212
24239
|
});
|
|
24213
24240
|
}
|
|
24214
24241
|
}
|
|
@@ -27404,7 +27431,7 @@ function normalizeServerUrl(value) {
|
|
|
27404
27431
|
}
|
|
27405
27432
|
|
|
27406
27433
|
// src/version.ts
|
|
27407
|
-
var PLUGIN_VERSION = "0.5.
|
|
27434
|
+
var PLUGIN_VERSION = "0.5.15";
|
|
27408
27435
|
|
|
27409
27436
|
// src/server-api.ts
|
|
27410
27437
|
var TERMINAL_CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/u;
|
|
@@ -28278,8 +28305,8 @@ var TypertGatewaySwitch = class {
|
|
|
28278
28305
|
if (normalized !== void 0) return normalized;
|
|
28279
28306
|
const source = error instanceof Error ? error : new Error("The Harness Gateway rejected the request.");
|
|
28280
28307
|
const code = "code" in source && typeof source.code === "string" ? source.code : "internal";
|
|
28281
|
-
const
|
|
28282
|
-
return { code, message: source.message, details };
|
|
28308
|
+
const details2 = "details" in source && isRecord11(source.details) ? source.details : {};
|
|
28309
|
+
return { code, message: source.message, details: details2 };
|
|
28283
28310
|
}
|
|
28284
28311
|
};
|
|
28285
28312
|
function workspaceConnectionResult(endpoint, result) {
|
|
@@ -29530,8 +29557,16 @@ var ClientModeRuntime = class {
|
|
|
29530
29557
|
this.proxySwitch = apiProxy === void 0 ? void 0 : new ApiProxySwitch(apiProxy);
|
|
29531
29558
|
this.gatewaySwitch = new TypertGatewaySwitch(typertGateway);
|
|
29532
29559
|
}
|
|
29533
|
-
connect(targetDeviceId, signal) {
|
|
29534
|
-
|
|
29560
|
+
async connect(targetDeviceId, signal) {
|
|
29561
|
+
const lifetime = this.remoteLifetime.signal;
|
|
29562
|
+
const connectionSignal = signal === void 0 ? lifetime : AbortSignal.any([lifetime, signal]);
|
|
29563
|
+
connectionSignal.throwIfAborted();
|
|
29564
|
+
const remote = await this.connection.connect(targetDeviceId, connectionSignal);
|
|
29565
|
+
if (connectionSignal.aborted || this.closed) {
|
|
29566
|
+
await remote.client.close().catch(() => void 0);
|
|
29567
|
+
throw new ClientModeError("CANCELLED", "The Remote connection request was superseded or closed.");
|
|
29568
|
+
}
|
|
29569
|
+
return remote;
|
|
29535
29570
|
}
|
|
29536
29571
|
handleControl(endpoint, payload, signal) {
|
|
29537
29572
|
return this.control.handleControl(endpoint, payload, signal);
|
|
@@ -29555,6 +29590,7 @@ var ClientModeRuntime = class {
|
|
|
29555
29590
|
connectionProgress;
|
|
29556
29591
|
connectionProgressRun = 0;
|
|
29557
29592
|
closed = false;
|
|
29593
|
+
remoteLifetime = new AbortController();
|
|
29558
29594
|
async start() {
|
|
29559
29595
|
if (this.closed) throw new Error("client remote-mode runtime is closed");
|
|
29560
29596
|
this.identity = await this.identities.loadOrCreate(this.config.deviceName);
|
|
@@ -29625,12 +29661,12 @@ var ClientModeRuntime = class {
|
|
|
29625
29661
|
async detailedStatus() {
|
|
29626
29662
|
const connected = this.connected;
|
|
29627
29663
|
if (connected === void 0 || this.identity === void 0) return this.status();
|
|
29628
|
-
const
|
|
29664
|
+
const details2 = await connected.transport.connectionDetails();
|
|
29629
29665
|
if (this.connected !== connected) return this.status();
|
|
29630
29666
|
return {
|
|
29631
29667
|
...this.status(),
|
|
29632
29668
|
network: {
|
|
29633
|
-
...
|
|
29669
|
+
...details2,
|
|
29634
29670
|
local: {
|
|
29635
29671
|
deviceId: this.identity.deviceId,
|
|
29636
29672
|
name: this.identity.name,
|
|
@@ -29698,21 +29734,13 @@ var ClientModeRuntime = class {
|
|
|
29698
29734
|
return result;
|
|
29699
29735
|
}
|
|
29700
29736
|
async clearClientAuthorization() {
|
|
29701
|
-
const
|
|
29702
|
-
this.connected = void 0;
|
|
29703
|
-
this.connectionProgress = void 0;
|
|
29704
|
-
this.pendingWorkspaceSelection = void 0;
|
|
29705
|
-
await this.closeCodexVirtual();
|
|
29737
|
+
const cleanup = this.leaveRemote();
|
|
29706
29738
|
this.codexOpenedSessions.clear();
|
|
29707
|
-
await this.
|
|
29708
|
-
this.proxySwitch?.selectLocal();
|
|
29709
|
-
await this.closePreview();
|
|
29710
|
-
this.gatewaySwitch.selectLocal();
|
|
29711
|
-
await this.codexStreamBridge.closeCodexStreams(previous?.client);
|
|
29712
|
-
await previous?.client.close().catch(() => void 0);
|
|
29713
|
-
await this.server.revokeCurrentDevice();
|
|
29739
|
+
const results = await Promise.allSettled([cleanup, this.server.revokeCurrentDevice()]);
|
|
29714
29740
|
this.identity = await this.identities.reset(this.config.deviceName);
|
|
29715
29741
|
this.server.bindIdentity(this.identity);
|
|
29742
|
+
const failure4 = results.find((result) => result.status === "rejected");
|
|
29743
|
+
if (failure4?.status === "rejected") throw failure4.reason;
|
|
29716
29744
|
}
|
|
29717
29745
|
async setHostAuthorization(enabled) {
|
|
29718
29746
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
@@ -29726,23 +29754,14 @@ var ClientModeRuntime = class {
|
|
|
29726
29754
|
}
|
|
29727
29755
|
async setMode(mode2, targetDeviceId, signal) {
|
|
29728
29756
|
if (mode2 === "local") {
|
|
29729
|
-
await this.
|
|
29730
|
-
await this.closeCursorVirtual();
|
|
29731
|
-
this.proxySwitch?.selectLocal();
|
|
29732
|
-
await this.closePreview();
|
|
29733
|
-
this.gatewaySwitch.selectLocal();
|
|
29734
|
-
const previous2 = this.connected;
|
|
29735
|
-
this.connected = void 0;
|
|
29736
|
-
this.connectionProgress = void 0;
|
|
29737
|
-
this.pendingWorkspaceSelection = void 0;
|
|
29738
|
-
await this.codexStreamBridge.closeCodexStreams(previous2?.client);
|
|
29739
|
-
await previous2?.client.close().catch(() => void 0);
|
|
29757
|
+
await this.leaveRemote();
|
|
29740
29758
|
this.logger.info("Harness target switched", { mode: "local" });
|
|
29741
29759
|
return this.status();
|
|
29742
29760
|
}
|
|
29743
29761
|
if (targetDeviceId === void 0 || targetDeviceId.length === 0) {
|
|
29744
29762
|
throw new ClientModeError("INVALID_MESSAGE", "A targetDeviceId is required for remote mode.");
|
|
29745
29763
|
}
|
|
29764
|
+
const lifetime = this.remoteLifetime.signal;
|
|
29746
29765
|
const next = await this.connect(targetDeviceId, signal);
|
|
29747
29766
|
try {
|
|
29748
29767
|
this.assertRemoteCompatible(next);
|
|
@@ -29753,11 +29772,17 @@ var ClientModeRuntime = class {
|
|
|
29753
29772
|
}
|
|
29754
29773
|
const previous = this.connected;
|
|
29755
29774
|
await this.closePreview();
|
|
29775
|
+
if (lifetime.aborted || this.closed) {
|
|
29776
|
+
await next.client.close().catch(() => void 0);
|
|
29777
|
+
throw new ClientModeError("CANCELLED", "The Remote connection request was superseded or closed.");
|
|
29778
|
+
}
|
|
29756
29779
|
this.connected = next;
|
|
29757
29780
|
this.connection.clearConnectionProgress(next.progressRunId);
|
|
29758
29781
|
this.pendingWorkspaceSelection = void 0;
|
|
29759
29782
|
await this.closeCodexVirtual();
|
|
29783
|
+
this.assertRemoteCurrent(next, signal);
|
|
29760
29784
|
await this.closeCursorVirtual();
|
|
29785
|
+
this.assertRemoteCurrent(next, signal);
|
|
29761
29786
|
this.selectRemoteTarget(next);
|
|
29762
29787
|
await this.codexStreamBridge.closeCodexStreams(previous?.client);
|
|
29763
29788
|
await previous?.client.close().catch(() => void 0);
|
|
@@ -29815,8 +29840,11 @@ var ClientModeRuntime = class {
|
|
|
29815
29840
|
});
|
|
29816
29841
|
workspace = unwrapNativeResult(response);
|
|
29817
29842
|
}
|
|
29843
|
+
this.assertRemoteCurrent(remote, signal);
|
|
29818
29844
|
await this.closeCodexVirtual();
|
|
29845
|
+
this.assertRemoteCurrent(remote, signal);
|
|
29819
29846
|
await this.closeCursorVirtual();
|
|
29847
|
+
this.assertRemoteCurrent(remote, signal);
|
|
29820
29848
|
this.selectRemoteTarget(remote, transport);
|
|
29821
29849
|
const workspaceId = workspaceRecordId(workspace.workspace);
|
|
29822
29850
|
this.pendingWorkspaceSelection = { targetDeviceId: remote.target.deviceId, workspaceId };
|
|
@@ -29897,11 +29925,12 @@ var ClientModeRuntime = class {
|
|
|
29897
29925
|
roots: [{ path: trimmedPath }],
|
|
29898
29926
|
idempotencyKey: uuidV7()
|
|
29899
29927
|
}, signal));
|
|
29900
|
-
const
|
|
29901
|
-
|
|
29928
|
+
const project2 = record2(result.project);
|
|
29929
|
+
this.assertRemoteCurrent(remote, signal);
|
|
29930
|
+
if (typeof project2.id !== "string" || project2.id.length === 0) {
|
|
29902
29931
|
throw new ClientModeError("INVALID_MESSAGE", "The Host returned an invalid CodeX project.");
|
|
29903
29932
|
}
|
|
29904
|
-
return this.openCodexWorkspace(targetDeviceId, codexProjectWorkspaceId(
|
|
29933
|
+
return this.openCodexWorkspace(targetDeviceId, codexProjectWorkspaceId(project2.id), signal);
|
|
29905
29934
|
}
|
|
29906
29935
|
async listCursorWorkspaces(targetDeviceId, signal, backend = "cursor") {
|
|
29907
29936
|
const remote = await this.ensureConnected(targetDeviceId, signal);
|
|
@@ -29929,23 +29958,32 @@ var ClientModeRuntime = class {
|
|
|
29929
29958
|
}, backend, remote.features.acpModelLoadsSession ? ["agent.acp.antigravity.model-load.v1"] : [], new RemoteTypertGateway2(remote.client));
|
|
29930
29959
|
let workspace;
|
|
29931
29960
|
try {
|
|
29932
|
-
|
|
29933
|
-
|
|
29961
|
+
try {
|
|
29962
|
+
workspace = await virtual.selectWorkspace(workspaceId);
|
|
29963
|
+
} catch {
|
|
29964
|
+
this.assertRemoteCurrent(remote, signal);
|
|
29965
|
+
throw new ClientModeError("WORKSPACE_NOT_FOUND", `The selected ${backend} workspace is no longer available.`);
|
|
29966
|
+
}
|
|
29967
|
+
this.assertRemoteCurrent(remote, signal);
|
|
29968
|
+
await this.closeCodexVirtual();
|
|
29969
|
+
this.assertRemoteCurrent(remote, signal);
|
|
29970
|
+
await this.closeCursorVirtual();
|
|
29971
|
+
this.assertRemoteCurrent(remote, signal);
|
|
29972
|
+
const preferredSessionId = await virtual.preferredSessionId();
|
|
29973
|
+
this.assertRemoteCurrent(remote, signal);
|
|
29974
|
+
this.cursorVirtual = virtual;
|
|
29975
|
+
this.acpVirtualBackend = backend;
|
|
29976
|
+
this.selectCursorTarget(virtual, remote);
|
|
29977
|
+
this.pendingWorkspaceSelection = {
|
|
29978
|
+
targetDeviceId: remote.target.deviceId,
|
|
29979
|
+
workspaceId: workspace.workspaceId,
|
|
29980
|
+
backend,
|
|
29981
|
+
...preferredSessionId === void 0 ? {} : { sessionId: preferredSessionId }
|
|
29982
|
+
};
|
|
29983
|
+
} catch (error) {
|
|
29934
29984
|
await virtual.close();
|
|
29935
|
-
throw
|
|
29985
|
+
throw error;
|
|
29936
29986
|
}
|
|
29937
|
-
await this.closeCodexVirtual();
|
|
29938
|
-
await this.closeCursorVirtual();
|
|
29939
|
-
this.cursorVirtual = virtual;
|
|
29940
|
-
this.acpVirtualBackend = backend;
|
|
29941
|
-
this.selectCursorTarget(virtual, remote);
|
|
29942
|
-
const preferredSessionId = await virtual.preferredSessionId();
|
|
29943
|
-
this.pendingWorkspaceSelection = {
|
|
29944
|
-
targetDeviceId: remote.target.deviceId,
|
|
29945
|
-
workspaceId: workspace.workspaceId,
|
|
29946
|
-
backend,
|
|
29947
|
-
...preferredSessionId === void 0 ? {} : { sessionId: preferredSessionId }
|
|
29948
|
-
};
|
|
29949
29987
|
this.logger.info(`${backend} virtual workspace opened`, { targetDeviceId: shortId(remote.target.deviceId) });
|
|
29950
29988
|
return { ...this.status(), workspace };
|
|
29951
29989
|
}
|
|
@@ -29962,19 +30000,27 @@ var ClientModeRuntime = class {
|
|
|
29962
30000
|
deviceId: remote.target.deviceId,
|
|
29963
30001
|
name: remote.target.name
|
|
29964
30002
|
}, backend, remote.features.acpModelLoadsSession ? ["agent.acp.antigravity.model-load.v1"] : [], new RemoteTypertGateway2(remote.client));
|
|
29965
|
-
|
|
29966
|
-
|
|
29967
|
-
|
|
29968
|
-
|
|
29969
|
-
|
|
29970
|
-
|
|
29971
|
-
|
|
29972
|
-
|
|
29973
|
-
|
|
29974
|
-
|
|
29975
|
-
|
|
29976
|
-
|
|
29977
|
-
|
|
30003
|
+
try {
|
|
30004
|
+
const workspace = await virtual.selectOrCreateWorkspace(trimmedPath);
|
|
30005
|
+
this.assertRemoteCurrent(remote, signal);
|
|
30006
|
+
await this.closeCodexVirtual();
|
|
30007
|
+
this.assertRemoteCurrent(remote, signal);
|
|
30008
|
+
await this.closeCursorVirtual();
|
|
30009
|
+
this.assertRemoteCurrent(remote, signal);
|
|
30010
|
+
this.cursorVirtual = virtual;
|
|
30011
|
+
this.acpVirtualBackend = backend;
|
|
30012
|
+
this.selectCursorTarget(virtual, remote);
|
|
30013
|
+
this.pendingWorkspaceSelection = {
|
|
30014
|
+
targetDeviceId: remote.target.deviceId,
|
|
30015
|
+
workspaceId: workspace.workspaceId,
|
|
30016
|
+
backend
|
|
30017
|
+
};
|
|
30018
|
+
this.logger.info(`${backend} virtual workspace created`, { targetDeviceId: shortId(remote.target.deviceId) });
|
|
30019
|
+
return { ...this.status(), workspace };
|
|
30020
|
+
} catch (error) {
|
|
30021
|
+
await virtual.close();
|
|
30022
|
+
throw error;
|
|
30023
|
+
}
|
|
29978
30024
|
}
|
|
29979
30025
|
consumeWorkspaceSelection(selection) {
|
|
29980
30026
|
const pending = this.pendingWorkspaceSelection;
|
|
@@ -29984,21 +30030,34 @@ var ClientModeRuntime = class {
|
|
|
29984
30030
|
return this.status();
|
|
29985
30031
|
}
|
|
29986
30032
|
async close() {
|
|
29987
|
-
await this.closePreview();
|
|
29988
30033
|
if (this.closed) return;
|
|
29989
30034
|
this.closed = true;
|
|
29990
|
-
this.
|
|
29991
|
-
|
|
29992
|
-
|
|
29993
|
-
|
|
29994
|
-
|
|
29995
|
-
|
|
29996
|
-
|
|
29997
|
-
|
|
30035
|
+
this.server.close?.();
|
|
30036
|
+
try {
|
|
30037
|
+
await this.leaveRemote();
|
|
30038
|
+
} finally {
|
|
30039
|
+
this.proxySwitch?.restore();
|
|
30040
|
+
this.gatewaySwitch.restore();
|
|
30041
|
+
}
|
|
30042
|
+
}
|
|
30043
|
+
async leaveRemote() {
|
|
30044
|
+
this.remoteLifetime.abort(new ClientModeError("CANCELLED", "The Remote connection was closed."));
|
|
30045
|
+
this.remoteLifetime = new AbortController();
|
|
30046
|
+
const previous = this.connected;
|
|
29998
30047
|
this.connected = void 0;
|
|
29999
30048
|
this.connectionProgress = void 0;
|
|
30000
|
-
this.
|
|
30001
|
-
this.
|
|
30049
|
+
this.pendingWorkspaceSelection = void 0;
|
|
30050
|
+
this.proxySwitch?.selectLocal();
|
|
30051
|
+
this.gatewaySwitch.selectLocal();
|
|
30052
|
+
const results = await Promise.allSettled([
|
|
30053
|
+
this.closeCodexVirtual(),
|
|
30054
|
+
this.closeCursorVirtual(),
|
|
30055
|
+
this.closePreview(),
|
|
30056
|
+
this.codexStreamBridge.closeCodexStreams(previous?.client),
|
|
30057
|
+
previous?.client.close()
|
|
30058
|
+
]);
|
|
30059
|
+
const failure4 = results.find((result) => result.status === "rejected");
|
|
30060
|
+
if (failure4?.status === "rejected") throw failure4.reason;
|
|
30002
30061
|
}
|
|
30003
30062
|
async callRemoteFileViewer(endpoint, payload, signal) {
|
|
30004
30063
|
const remote = this.connected;
|
|
@@ -30111,11 +30170,12 @@ var ClientModeRuntime = class {
|
|
|
30111
30170
|
);
|
|
30112
30171
|
}
|
|
30113
30172
|
async ensureConnected(targetDeviceId, signal, isCurrent) {
|
|
30173
|
+
const lifetime = this.remoteLifetime.signal;
|
|
30114
30174
|
if (this.connected?.target.deviceId === targetDeviceId) return this.connected;
|
|
30115
30175
|
const next = await this.connect(targetDeviceId, signal);
|
|
30116
30176
|
const assertCurrent = () => {
|
|
30117
30177
|
signal?.throwIfAborted();
|
|
30118
|
-
if (this.closed || isCurrent?.() === false) {
|
|
30178
|
+
if (this.closed || lifetime.aborted || isCurrent?.() === false) {
|
|
30119
30179
|
throw new ClientModeError("CANCELLED", "The Remote connection request was superseded or closed.");
|
|
30120
30180
|
}
|
|
30121
30181
|
};
|
|
@@ -30134,6 +30194,12 @@ var ClientModeRuntime = class {
|
|
|
30134
30194
|
await previous?.client.close().catch(() => void 0);
|
|
30135
30195
|
return next;
|
|
30136
30196
|
}
|
|
30197
|
+
assertRemoteCurrent(remote, signal) {
|
|
30198
|
+
signal?.throwIfAborted();
|
|
30199
|
+
if (this.closed || this.connected !== remote) {
|
|
30200
|
+
throw new ClientModeError("CANCELLED", "The Remote workspace request was superseded or closed.");
|
|
30201
|
+
}
|
|
30202
|
+
}
|
|
30137
30203
|
requireIdentity() {
|
|
30138
30204
|
if (this.identity === void 0) throw new ClientModeError("IDENTITY_INVALID", "The client identity is not ready.");
|
|
30139
30205
|
return this.identity;
|
|
@@ -30463,7 +30529,7 @@ var ControlStatusStream = class {
|
|
|
30463
30529
|
};
|
|
30464
30530
|
|
|
30465
30531
|
// src/codex/domain.ts
|
|
30466
|
-
import { randomUUID as
|
|
30532
|
+
import { randomUUID as randomUUID3 } from "node:crypto";
|
|
30467
30533
|
import { accessSync, constants, existsSync as existsSync2, readFileSync } from "node:fs";
|
|
30468
30534
|
import { readdir, realpath, stat as stat3 } from "node:fs/promises";
|
|
30469
30535
|
import { homedir as homedir2 } from "node:os";
|
|
@@ -30835,6 +30901,121 @@ function threadIdFromParams(params) {
|
|
|
30835
30901
|
return typeof params.threadId === "string" ? params.threadId : void 0;
|
|
30836
30902
|
}
|
|
30837
30903
|
|
|
30904
|
+
// src/compact-history.ts
|
|
30905
|
+
var LIMIT = 512;
|
|
30906
|
+
var object = (value) => value !== null && typeof value === "object" && !Array.isArray(value);
|
|
30907
|
+
var summary = (value) => {
|
|
30908
|
+
const text = typeof value === "string" ? value : JSON.stringify(value) ?? "";
|
|
30909
|
+
return text.length > LIMIT ? text.slice(0, LIMIT) + "\n[Compact history: output omitted]" : text;
|
|
30910
|
+
};
|
|
30911
|
+
function toolValue(value) {
|
|
30912
|
+
if (Array.isArray(value)) return value.map(toolValue);
|
|
30913
|
+
if (!object(value)) return value;
|
|
30914
|
+
const result = { ...value };
|
|
30915
|
+
for (const [key, child] of Object.entries(value)) {
|
|
30916
|
+
if (["input", "arguments", "output", "result", "rawInput", "rawOutput", "uiResultMeta", "meta", "argumentsDelta"].includes(key)) {
|
|
30917
|
+
result[key] = typeof child === "string" ? summary(child) : { summary: summary(child) };
|
|
30918
|
+
} else if (key === "content" && Array.isArray(child)) {
|
|
30919
|
+
let previews = 0;
|
|
30920
|
+
const blocks = child.flatMap((block) => {
|
|
30921
|
+
if (object(block) && (block.type === "tool-call" || block.type === "tool-result")) return [toolValue(block)];
|
|
30922
|
+
if (previews++ >= 2) return [];
|
|
30923
|
+
return [{ type: "text", text: summary(object(block) ? block.text ?? block : block) }];
|
|
30924
|
+
});
|
|
30925
|
+
if (child.some((block) => object(block) && block.isError === true) && object(blocks[0])) blocks[0].isError = true;
|
|
30926
|
+
result[key] = blocks;
|
|
30927
|
+
} else if (key === "text" && typeof child === "string") result[key] = summary(child);
|
|
30928
|
+
else result[key] = toolValue(child);
|
|
30929
|
+
}
|
|
30930
|
+
return result;
|
|
30931
|
+
}
|
|
30932
|
+
function messageValue(value) {
|
|
30933
|
+
if (Array.isArray(value)) return value.map(messageValue);
|
|
30934
|
+
if (!object(value)) return value;
|
|
30935
|
+
if (value.type === "tool-call" || value.type === "tool-result") return toolValue(value);
|
|
30936
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, messageValue(child)]));
|
|
30937
|
+
}
|
|
30938
|
+
function project(value) {
|
|
30939
|
+
if (Array.isArray(value)) return value.map(project);
|
|
30940
|
+
if (!object(value)) return value;
|
|
30941
|
+
if (object(value.event) && ["tool/call", "tool/result"].includes(String(value.event.type))) {
|
|
30942
|
+
const { view, ...rest } = value;
|
|
30943
|
+
const event = toolValue(value.event);
|
|
30944
|
+
const data2 = object(event.data) ? event.data : {};
|
|
30945
|
+
const title = object(view) && object(view.view) ? view.view.title : void 0;
|
|
30946
|
+
return { ...rest, event: { ...event, data: { ...data2, ...typeof title === "string" && !data2.name && !data2.toolName ? { toolName: title } : {} } } };
|
|
30947
|
+
}
|
|
30948
|
+
if (typeof value.type === "string" && ["tool/call", "tool/result"].includes(value.type)) return toolValue(value);
|
|
30949
|
+
if (typeof value.type === "string" && ["user/message", "assistant/message"].includes(value.type)) return messageValue(value);
|
|
30950
|
+
return Object.fromEntries(Object.entries(value).map(([key, child]) => [key, project(child)]));
|
|
30951
|
+
}
|
|
30952
|
+
function compactHistory(value) {
|
|
30953
|
+
return project(value);
|
|
30954
|
+
}
|
|
30955
|
+
|
|
30956
|
+
// src/codex/history-preview.ts
|
|
30957
|
+
import { randomUUID as randomUUID2 } from "node:crypto";
|
|
30958
|
+
var object2 = (v) => v !== null && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
30959
|
+
var details = /* @__PURE__ */ new WeakMap();
|
|
30960
|
+
var MAX_CACHE = 16 * 1024 * 1024;
|
|
30961
|
+
var size = (v) => Buffer.byteLength(JSON.stringify(v), "utf8");
|
|
30962
|
+
async function previewCall(peer, input3, invoke) {
|
|
30963
|
+
const call = object2(input3), params = object2(call.params);
|
|
30964
|
+
if (call.method === "dsh/historyDetail") {
|
|
30965
|
+
if (Object.keys(call).some((k) => !["method", "params"].includes(k)) || Object.keys(params).some((k) => !["threadId", "detailId"].includes(k)) || typeof params.threadId !== "string" || typeof params.detailId !== "string") throw new RpcError("INVALID_MESSAGE", "Invalid history detail request.");
|
|
30966
|
+
const detail = details.get(peer)?.get(params.detailId);
|
|
30967
|
+
if (!detail || detail.threadId !== params.threadId || detail.until < Date.now()) throw new RpcError("HISTORY_DETAIL_EXPIRED", "Tool details expired. Reopen the conversation and try again.");
|
|
30968
|
+
await invoke({ method: "thread/read", params: { threadId: detail.threadId, includeTurns: false } });
|
|
30969
|
+
return detail.record;
|
|
30970
|
+
}
|
|
30971
|
+
if (call.previewHistory !== true) return invoke(input3);
|
|
30972
|
+
if (call.method !== "dsh/sessionHistory" || Object.keys(call).some((k) => !["method", "params", "previewHistory"].includes(k)))
|
|
30973
|
+
throw new RpcError("INVALID_MESSAGE", "History preview is read-only.");
|
|
30974
|
+
const result = object2(await invoke({ method: call.method, params: call.params }));
|
|
30975
|
+
if (!Array.isArray(result.records) || typeof params.threadId !== "string") return result;
|
|
30976
|
+
let cache = details.get(peer);
|
|
30977
|
+
if (!cache) details.set(peer, cache = /* @__PURE__ */ new Map());
|
|
30978
|
+
for (const [id5, value] of cache) if (value.until < Date.now()) cache.delete(id5);
|
|
30979
|
+
const pending = /* @__PURE__ */ new Map();
|
|
30980
|
+
let pendingBytes = 0;
|
|
30981
|
+
const records = result.records.map((raw) => {
|
|
30982
|
+
const record9 = object2(raw), event = object2(record9.event), data2 = object2(event.data);
|
|
30983
|
+
if (event.type !== "tool/result" || size(record9) < 4096) return raw;
|
|
30984
|
+
const bytes = size(record9);
|
|
30985
|
+
if (bytes > MAX_CACHE) return raw;
|
|
30986
|
+
if (pending.size >= 64 || pendingBytes + bytes > MAX_CACHE) {
|
|
30987
|
+
throw new RpcError("RESPONSE_TOO_LARGE", "History requires chunked transfer.");
|
|
30988
|
+
}
|
|
30989
|
+
const id5 = randomUUID2();
|
|
30990
|
+
pending.set(id5, { threadId: params.threadId, record: raw, bytes, until: Date.now() + 10 * 6e4 });
|
|
30991
|
+
pendingBytes += bytes;
|
|
30992
|
+
const message = object2(data2.message);
|
|
30993
|
+
return { ...record9, view: void 0, event: { ...event, data: {
|
|
30994
|
+
id: data2.id,
|
|
30995
|
+
callId: data2.callId,
|
|
30996
|
+
name: data2.name,
|
|
30997
|
+
toolName: data2.toolName,
|
|
30998
|
+
turn: data2.turn,
|
|
30999
|
+
step: data2.step,
|
|
31000
|
+
message: { source: message.source, isError: message.isError === true || Array.isArray(message.content) && message.content.some((v) => object2(v).isError === true), content: [{ type: "text", text: "Expand to load tool output" }] },
|
|
31001
|
+
isError: data2.isError === true,
|
|
31002
|
+
failed: data2.failed,
|
|
31003
|
+
error: data2.error ? { message: "Tool execution failed" } : void 0,
|
|
31004
|
+
remoteDetail: { threadId: params.threadId, detailId: id5 }
|
|
31005
|
+
} } };
|
|
31006
|
+
});
|
|
31007
|
+
const preview = { ...result, records };
|
|
31008
|
+
if (size(preview) > 2 * 1024 * 1024) throw new RpcError("RESPONSE_TOO_LARGE", "History requires chunked transfer.");
|
|
31009
|
+
let cachedBytes = [...cache.values()].reduce((n, value) => n + value.bytes, 0);
|
|
31010
|
+
while (cache.size + pending.size > 64 || cachedBytes + pendingBytes > MAX_CACHE) {
|
|
31011
|
+
const oldest = cache.keys().next().value;
|
|
31012
|
+
cachedBytes -= cache.get(oldest).bytes;
|
|
31013
|
+
cache.delete(oldest);
|
|
31014
|
+
}
|
|
31015
|
+
for (const [id5, detail] of pending) cache.set(id5, detail);
|
|
31016
|
+
return preview;
|
|
31017
|
+
}
|
|
31018
|
+
|
|
30838
31019
|
// src/codex/peer-bridge.ts
|
|
30839
31020
|
import { Buffer as Buffer3 } from "node:buffer";
|
|
30840
31021
|
var streamOpenSchema = external_exports.object({
|
|
@@ -30864,6 +31045,7 @@ var CodexPeerBridge = class {
|
|
|
30864
31045
|
this.publish = publish;
|
|
30865
31046
|
this.logger = logger;
|
|
30866
31047
|
}
|
|
31048
|
+
compactHistoryEnabled = false;
|
|
30867
31049
|
streams = /* @__PURE__ */ new Map();
|
|
30868
31050
|
incomingTransfers = /* @__PURE__ */ new Map();
|
|
30869
31051
|
outgoingTransfers = /* @__PURE__ */ new Map();
|
|
@@ -30874,7 +31056,8 @@ var CodexPeerBridge = class {
|
|
|
30874
31056
|
async callDomain(input3, logFailure) {
|
|
30875
31057
|
this.requireOpen();
|
|
30876
31058
|
try {
|
|
30877
|
-
|
|
31059
|
+
const result = await previewCall(this, input3, (value) => this.domain.call(this.context.connectionId, value));
|
|
31060
|
+
return this.compactHistoryEnabled && safeMethod(input3) === "dsh/sessionHistory" ? compactHistory(result) : result;
|
|
30878
31061
|
} catch (error) {
|
|
30879
31062
|
if (logFailure) {
|
|
30880
31063
|
this.logger?.warn("Codex call failed", {
|
|
@@ -31640,7 +31823,7 @@ var CodexRemoteDomain = class {
|
|
|
31640
31823
|
await appServer.respond(message.id, { decision: "decline" });
|
|
31641
31824
|
return;
|
|
31642
31825
|
}
|
|
31643
|
-
const requestHandle =
|
|
31826
|
+
const requestHandle = randomUUID3();
|
|
31644
31827
|
this.approvals.set(requestHandle, {
|
|
31645
31828
|
upstreamId: message.id,
|
|
31646
31829
|
connectionId: owner.connectionId,
|
|
@@ -31893,10 +32076,10 @@ var CodexRemoteDomain = class {
|
|
|
31893
32076
|
limit: CODEX_PAGE_LIMIT2,
|
|
31894
32077
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
31895
32078
|
}));
|
|
31896
|
-
for (const
|
|
31897
|
-
const projectRoots =
|
|
32079
|
+
for (const project2 of result.data) {
|
|
32080
|
+
const projectRoots = project2.roots.map((root) => root.path).filter((path) => isAbsolute2(path));
|
|
31898
32081
|
if (projectRoots.length === 0) continue;
|
|
31899
|
-
projectIds.add(
|
|
32082
|
+
projectIds.add(project2.id);
|
|
31900
32083
|
roots.push(...projectRoots);
|
|
31901
32084
|
}
|
|
31902
32085
|
cursor2 = typeof result.nextCursor === "string" && result.nextCursor.length > 0 ? result.nextCursor : void 0;
|
|
@@ -32194,11 +32377,11 @@ function sanitizeProjectList(result) {
|
|
|
32194
32377
|
};
|
|
32195
32378
|
}
|
|
32196
32379
|
function sanitizeProjectCreate(result) {
|
|
32197
|
-
const
|
|
32198
|
-
if (
|
|
32380
|
+
const project2 = isRecord14(result) ? sanitizeProject(result.project) : void 0;
|
|
32381
|
+
if (project2 === void 0) {
|
|
32199
32382
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid created project.");
|
|
32200
32383
|
}
|
|
32201
|
-
return { project };
|
|
32384
|
+
return { project: project2 };
|
|
32202
32385
|
}
|
|
32203
32386
|
function isThreadAllowedByWorkspaceAuthority(thread, authority) {
|
|
32204
32387
|
const projectId = typeof thread.projectId === "string" ? thread.projectId : void 0;
|
|
@@ -34087,7 +34270,7 @@ var AcpWorkspaceTools = class {
|
|
|
34087
34270
|
};
|
|
34088
34271
|
|
|
34089
34272
|
// src/acp/gateway.ts
|
|
34090
|
-
import { randomUUID as
|
|
34273
|
+
import { randomUUID as randomUUID5 } from "node:crypto";
|
|
34091
34274
|
import { readdir as readdir3, realpath as realpath5, stat as stat5 } from "node:fs/promises";
|
|
34092
34275
|
import { homedir as homedir5 } from "node:os";
|
|
34093
34276
|
import { basename as basename4, isAbsolute as isAbsolute6, join as join11, relative as relative4, resolve as resolve4 } from "node:path";
|
|
@@ -34403,7 +34586,7 @@ function agySelectionArgs(catalog, modelId, effort) {
|
|
|
34403
34586
|
import { promises as fs, realpathSync as realpathSync2, constants as constants3 } from "node:fs";
|
|
34404
34587
|
import { tmpdir } from "node:os";
|
|
34405
34588
|
import { join as join8, basename as basename3 } from "node:path";
|
|
34406
|
-
import { createHash as createHash2, randomUUID as
|
|
34589
|
+
import { createHash as createHash2, randomUUID as randomUUID4 } from "node:crypto";
|
|
34407
34590
|
var EXTENSIONS = { "image/png": "png", "image/jpeg": "jpg", "image/webp": "webp", "image/gif": "gif" };
|
|
34408
34591
|
var IMAGE_NAME = /^[0-9a-f-]{36}\.(png|jpg|webp|gif)$/;
|
|
34409
34592
|
var TTL = 24 * 60 * 60 * 1e3;
|
|
@@ -34448,7 +34631,7 @@ async function stageImages(sessionId, images, root) {
|
|
|
34448
34631
|
const paths = [];
|
|
34449
34632
|
try {
|
|
34450
34633
|
for (const image of parsed) {
|
|
34451
|
-
const path = join8(directory, `${
|
|
34634
|
+
const path = join8(directory, `${randomUUID4()}.${EXTENSIONS[image.mimeType]}`);
|
|
34452
34635
|
await fs.writeFile(path, Buffer.from(image.data, "base64"), { flag: "wx", mode: 384 });
|
|
34453
34636
|
paths.push(path);
|
|
34454
34637
|
}
|
|
@@ -36238,6 +36421,7 @@ var AcpPeerBridge = class {
|
|
|
36238
36421
|
this.publish = publish;
|
|
36239
36422
|
this.logger = logger;
|
|
36240
36423
|
}
|
|
36424
|
+
compactHistoryEnabled = false;
|
|
36241
36425
|
toolControllers = /* @__PURE__ */ new Map();
|
|
36242
36426
|
streams = /* @__PURE__ */ new Map();
|
|
36243
36427
|
incomingTransfers = /* @__PURE__ */ new Map();
|
|
@@ -36252,7 +36436,8 @@ var AcpPeerBridge = class {
|
|
|
36252
36436
|
async callDomain(input3, logFailure) {
|
|
36253
36437
|
this.requireOpen();
|
|
36254
36438
|
try {
|
|
36255
|
-
|
|
36439
|
+
const result = await this.domain.call(this.context.connectionId, input3);
|
|
36440
|
+
return this.compactHistoryEnabled && safeMethod2(input3) === "dsh/sessionHistory" ? compactHistory(result) : result;
|
|
36256
36441
|
} catch (error) {
|
|
36257
36442
|
if (logFailure) {
|
|
36258
36443
|
this.logger?.warn("Cursor call failed", {
|
|
@@ -37358,7 +37543,7 @@ var AcpRemoteGateway = class {
|
|
|
37358
37543
|
await client.respondError(message.id, -32602, "The ACP permission options are invalid.");
|
|
37359
37544
|
return;
|
|
37360
37545
|
}
|
|
37361
|
-
const requestHandle =
|
|
37546
|
+
const requestHandle = randomUUID5();
|
|
37362
37547
|
this.approvals.set(requestHandle, {
|
|
37363
37548
|
upstreamId: message.id,
|
|
37364
37549
|
connectionId: owner,
|
|
@@ -37765,13 +37950,16 @@ function isRecord19(value) {
|
|
|
37765
37950
|
|
|
37766
37951
|
// src/control-runtime.ts
|
|
37767
37952
|
var PluginControlRuntime = class {
|
|
37768
|
-
constructor(config, identityDirectory, settings, client, host) {
|
|
37953
|
+
constructor(config, identityDirectory, settings, client, host, switchServer) {
|
|
37769
37954
|
this.config = config;
|
|
37770
37955
|
this.identityDirectory = identityDirectory;
|
|
37771
37956
|
this.settings = settings;
|
|
37772
37957
|
this.client = client;
|
|
37773
37958
|
this.host = host;
|
|
37959
|
+
this.switchServer = switchServer;
|
|
37774
37960
|
}
|
|
37961
|
+
logoutFlight;
|
|
37962
|
+
serverSwitchFlight;
|
|
37775
37963
|
register(connection, webServer) {
|
|
37776
37964
|
const statusStream = new ControlStatusStream(() => this.streamStatus());
|
|
37777
37965
|
return registerControlRoute(
|
|
@@ -37793,6 +37981,7 @@ var PluginControlRuntime = class {
|
|
|
37793
37981
|
}
|
|
37794
37982
|
async handle(endpoint, payload, signal) {
|
|
37795
37983
|
try {
|
|
37984
|
+
if (endpoint !== "settings.server.set") await this.serverSwitchFlight;
|
|
37796
37985
|
if (endpoint === "settings.development.set") return ok3(await this.setDevelopment(payload));
|
|
37797
37986
|
if (endpoint === "settings.get") return ok3(await this.settingsView());
|
|
37798
37987
|
if (endpoint === "settings.configure") return ok3(await this.configure(payload));
|
|
@@ -37886,6 +38075,19 @@ var PluginControlRuntime = class {
|
|
|
37886
38075
|
};
|
|
37887
38076
|
}
|
|
37888
38077
|
async setServer(payload) {
|
|
38078
|
+
if (this.serverSwitchFlight !== void 0) {
|
|
38079
|
+
throw new ClientModeError("SERVER_SWITCH_BUSY", "A Server switch is already in progress.");
|
|
38080
|
+
}
|
|
38081
|
+
const flight = this.applyServer(payload);
|
|
38082
|
+
this.serverSwitchFlight = flight;
|
|
38083
|
+
try {
|
|
38084
|
+
return await flight;
|
|
38085
|
+
} finally {
|
|
38086
|
+
if (this.serverSwitchFlight === flight) this.serverSwitchFlight = void 0;
|
|
38087
|
+
}
|
|
38088
|
+
}
|
|
38089
|
+
async applyServer(payload) {
|
|
38090
|
+
await this.logoutFlight;
|
|
37889
38091
|
if (this.settings === void 0) {
|
|
37890
38092
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
37891
38093
|
}
|
|
@@ -37896,6 +38098,15 @@ var PluginControlRuntime = class {
|
|
|
37896
38098
|
const current = editableConfig(resolveConfig(this.settings.get()));
|
|
37897
38099
|
const next = resolveConfig({ ...current, serverUrl: value.serverUrl });
|
|
37898
38100
|
await this.settings.replace(editableConfig(next));
|
|
38101
|
+
if (this.switchServer !== void 0) {
|
|
38102
|
+
if (next.serverUrl !== this.config.serverUrl) {
|
|
38103
|
+
const runtimes = await this.switchServer(next);
|
|
38104
|
+
this.client = runtimes.client;
|
|
38105
|
+
this.host = runtimes.host;
|
|
38106
|
+
}
|
|
38107
|
+
this.config = next;
|
|
38108
|
+
return { ...await this.settingsView(), applies: "live" };
|
|
38109
|
+
}
|
|
37899
38110
|
return this.settingsView();
|
|
37900
38111
|
}
|
|
37901
38112
|
async setRole(payload) {
|
|
@@ -38017,20 +38228,28 @@ var PluginControlRuntime = class {
|
|
|
38017
38228
|
const targetApi = targetRole === "host" ? new HostServerApi(serverUrl, new ServerCredentialStore(targetDirectory)) : new ClientServerApi(serverUrl, new ServerCredentialStore(targetDirectory));
|
|
38018
38229
|
await targetApi.authorizeOwnedRole(targetIdentity, sourceCredentials.accessToken, sourceCredentials.account);
|
|
38019
38230
|
}
|
|
38020
|
-
|
|
38021
|
-
if (this.
|
|
38022
|
-
|
|
38023
|
-
|
|
38024
|
-
|
|
38231
|
+
logout() {
|
|
38232
|
+
if (this.logoutFlight !== void 0) return this.logoutFlight;
|
|
38233
|
+
const task = this.clearAuthorization();
|
|
38234
|
+
this.logoutFlight = task;
|
|
38235
|
+
void task.finally(() => {
|
|
38236
|
+
if (this.logoutFlight === task) this.logoutFlight = void 0;
|
|
38237
|
+
}).catch(() => void 0);
|
|
38238
|
+
return task;
|
|
38239
|
+
}
|
|
38240
|
+
async clearAuthorization() {
|
|
38241
|
+
const config = this.settings === void 0 ? this.config : resolveConfig(this.settings.get());
|
|
38025
38242
|
if (config.serverUrl !== void 0) {
|
|
38026
|
-
await Promise.
|
|
38243
|
+
const runtimes = await Promise.allSettled([
|
|
38027
38244
|
this.client?.clearClientAuthorization(),
|
|
38028
38245
|
this.host?.clearHostAuthorization()
|
|
38029
38246
|
]);
|
|
38030
|
-
await Promise.
|
|
38247
|
+
const stores = await Promise.allSettled(["host", "client"].map(async (role) => {
|
|
38031
38248
|
const directory = serverStorageDirectory(this.identityDirectory, config.serverUrl, role);
|
|
38032
38249
|
await new ServerCredentialStore(directory).clear();
|
|
38033
38250
|
}));
|
|
38251
|
+
const failure4 = [...runtimes, ...stores].find((result) => result.status === "rejected");
|
|
38252
|
+
if (failure4?.status === "rejected") throw failure4.reason;
|
|
38034
38253
|
}
|
|
38035
38254
|
return this.settingsView();
|
|
38036
38255
|
}
|
|
@@ -38177,7 +38396,7 @@ function redact(value, key = "") {
|
|
|
38177
38396
|
}
|
|
38178
38397
|
|
|
38179
38398
|
// src/workspace-upload.ts
|
|
38180
|
-
import { randomUUID as
|
|
38399
|
+
import { randomUUID as randomUUID6 } from "node:crypto";
|
|
38181
38400
|
import { constants as constants4 } from "node:fs";
|
|
38182
38401
|
import { link, lstat as lstat2, open as open2, realpath as realpath6, stat as stat6, unlink } from "node:fs/promises";
|
|
38183
38402
|
import { extname, isAbsolute as isAbsolute7, join as join12 } from "node:path";
|
|
@@ -38257,7 +38476,7 @@ var WorkspaceUploadHost = class {
|
|
|
38257
38476
|
const root = await realpath6(sourceRoot);
|
|
38258
38477
|
const directory = await stat6(root);
|
|
38259
38478
|
if (!directory.isDirectory()) throw failure3("UPLOAD_WORKSPACE_UNAVAILABLE");
|
|
38260
|
-
const temp = join12(root, `.dsh-upload-${
|
|
38479
|
+
const temp = join12(root, `.dsh-upload-${randomUUID6()}.part`);
|
|
38261
38480
|
const handle = await open2(temp, constants4.O_CREAT | constants4.O_EXCL | constants4.O_RDWR | (constants4.O_NOFOLLOW ?? 0), 384);
|
|
38262
38481
|
const upload = { ...p, received: 0, touched: Date.now(), root, sourceRoot, dev: directory.dev, ino: directory.ino, temp, handle };
|
|
38263
38482
|
this.uploads.set(p.uploadId, upload);
|
|
@@ -38392,7 +38611,7 @@ function unavailable2() {
|
|
|
38392
38611
|
}
|
|
38393
38612
|
|
|
38394
38613
|
// src/service.ts
|
|
38395
|
-
import { randomUUID as
|
|
38614
|
+
import { randomUUID as randomUUID7 } from "node:crypto";
|
|
38396
38615
|
|
|
38397
38616
|
// src/connection-controller.ts
|
|
38398
38617
|
var ConnectionController = class {
|
|
@@ -38494,10 +38713,10 @@ var ConnectionController = class {
|
|
|
38494
38713
|
const revoked = [...this.active.values()].filter((connection) => connection.channel.peerDeviceId === deviceId);
|
|
38495
38714
|
await Promise.all(revoked.map((connection) => this.disconnect(connection, "DEVICE_REVOKED")));
|
|
38496
38715
|
}
|
|
38497
|
-
async closeConnection(connectionId, code) {
|
|
38716
|
+
async closeConnection(connectionId, code, detail) {
|
|
38498
38717
|
const connection = this.active.get(connectionId);
|
|
38499
38718
|
if (connection === void 0) return false;
|
|
38500
|
-
await this.disconnect(connection, code);
|
|
38719
|
+
await this.disconnect(connection, code, detail);
|
|
38501
38720
|
return true;
|
|
38502
38721
|
}
|
|
38503
38722
|
async close() {
|
|
@@ -38548,7 +38767,7 @@ var ConnectionController = class {
|
|
|
38548
38767
|
throw error instanceof Error ? error : new Error("peer send failed", { cause: error });
|
|
38549
38768
|
}
|
|
38550
38769
|
}
|
|
38551
|
-
async disconnect(connection, code) {
|
|
38770
|
+
async disconnect(connection, code, detail) {
|
|
38552
38771
|
if (!this.isActive(connection)) return;
|
|
38553
38772
|
this.active.delete(connection.channel.security.connectionId);
|
|
38554
38773
|
connection.unsubscribe();
|
|
@@ -38560,7 +38779,9 @@ var ConnectionController = class {
|
|
|
38560
38779
|
this.logger?.info("peer connection disconnected", {
|
|
38561
38780
|
peerDeviceId: shortId2(connection.channel.peerDeviceId),
|
|
38562
38781
|
connectionId: shortId2(connection.channel.security.connectionId),
|
|
38563
|
-
code: code ?? "closed"
|
|
38782
|
+
code: code ?? "closed",
|
|
38783
|
+
closedBy: detail?.closedBy ?? "host",
|
|
38784
|
+
...detail?.retryable === void 0 ? {} : { retryable: detail.retryable }
|
|
38564
38785
|
});
|
|
38565
38786
|
}
|
|
38566
38787
|
isActive(connection) {
|
|
@@ -38584,8 +38805,10 @@ function shortId2(value) {
|
|
|
38584
38805
|
// src/rpc-router.ts
|
|
38585
38806
|
var wireRequestSchema = external_exports.object({ method: external_exports.string().min(1), params: external_exports.unknown() }).strict();
|
|
38586
38807
|
var emptyParamsSchema = external_exports.object({}).strict();
|
|
38808
|
+
var historyConfigureSchema = external_exports.object({ compact: external_exports.boolean() }).strict();
|
|
38587
38809
|
var apiMethods = /* @__PURE__ */ new Set([
|
|
38588
38810
|
"harness.transport.describe",
|
|
38811
|
+
"remote.history.configure",
|
|
38589
38812
|
"harness.api.call",
|
|
38590
38813
|
"harness.api.transfer.open",
|
|
38591
38814
|
"harness.api.transfer.chunk",
|
|
@@ -38710,7 +38933,7 @@ var RpcRouter = class {
|
|
|
38710
38933
|
switch (method) {
|
|
38711
38934
|
case "harness.transport.describe": {
|
|
38712
38935
|
emptyParamsSchema.parse(params);
|
|
38713
|
-
const capabilities = [...this.capabilities()];
|
|
38936
|
+
const capabilities = [.../* @__PURE__ */ new Set([...this.capabilities(), "remote.history.compact.v1"])];
|
|
38714
38937
|
let workspaceTypes;
|
|
38715
38938
|
if (this.workspaceTypes !== void 0) {
|
|
38716
38939
|
try {
|
|
@@ -38724,6 +38947,13 @@ var RpcRouter = class {
|
|
|
38724
38947
|
...workspaceTypes === void 0 ? {} : { workspaceTypes }
|
|
38725
38948
|
};
|
|
38726
38949
|
}
|
|
38950
|
+
case "remote.history.configure": {
|
|
38951
|
+
const { compact } = historyConfigureSchema.parse(params);
|
|
38952
|
+
for (const bridge of [this.harnessApi, this.harnessRemote, this.codex, this.acp]) {
|
|
38953
|
+
if (bridge !== void 0) bridge.compactHistoryEnabled = compact;
|
|
38954
|
+
}
|
|
38955
|
+
return { compact };
|
|
38956
|
+
}
|
|
38727
38957
|
case "harness.api.call":
|
|
38728
38958
|
return this.requireApiProxy().call(params);
|
|
38729
38959
|
case "harness.api.transfer.open":
|
|
@@ -39262,13 +39492,16 @@ var HostServerConnection = class {
|
|
|
39262
39492
|
this.terminalError = payload.code;
|
|
39263
39493
|
this.socket?.close(4004, "device revoked");
|
|
39264
39494
|
} else if (payload.connectionId !== void 0) {
|
|
39265
|
-
await this.dropTunnel(payload.connectionId, payload.code
|
|
39495
|
+
await this.dropTunnel(payload.connectionId, payload.code, {
|
|
39496
|
+
closedBy: "server",
|
|
39497
|
+
retryable: payload.retryable
|
|
39498
|
+
});
|
|
39266
39499
|
const fields = {
|
|
39267
39500
|
code: payload.code,
|
|
39268
39501
|
connectionId: shortId3(payload.connectionId),
|
|
39269
39502
|
retryable: payload.retryable
|
|
39270
39503
|
};
|
|
39271
|
-
if (payload.retryable) this.logger.
|
|
39504
|
+
if (payload.retryable) this.logger.info("server closed a remote connection", fields);
|
|
39272
39505
|
else this.logger.warn("server closed a remote connection", fields);
|
|
39273
39506
|
} else {
|
|
39274
39507
|
this.terminalError = payload.code;
|
|
@@ -39642,7 +39875,7 @@ var HostServerConnection = class {
|
|
|
39642
39875
|
}));
|
|
39643
39876
|
await this.connections.close();
|
|
39644
39877
|
}
|
|
39645
|
-
async dropTunnel(connectionId, code) {
|
|
39878
|
+
async dropTunnel(connectionId, code, detail) {
|
|
39646
39879
|
const tunnel = this.tunnels.get(connectionId);
|
|
39647
39880
|
if (tunnel === void 0) return;
|
|
39648
39881
|
this.tunnels.delete(connectionId);
|
|
@@ -39656,7 +39889,7 @@ var HostServerConnection = class {
|
|
|
39656
39889
|
}
|
|
39657
39890
|
if (tunnel.channel !== void 0) {
|
|
39658
39891
|
try {
|
|
39659
|
-
const closed = await this.connections.closeConnection(connectionId, code);
|
|
39892
|
+
const closed = detail === void 0 ? await this.connections.closeConnection(connectionId, code) : await this.connections.closeConnection(connectionId, code, detail);
|
|
39660
39893
|
if (!closed) await tunnel.channel.close(code);
|
|
39661
39894
|
} catch (error) {
|
|
39662
39895
|
await tunnel.channel.close(code).catch(() => void 0);
|
|
@@ -39896,10 +40129,16 @@ function closeCode(code) {
|
|
|
39896
40129
|
}
|
|
39897
40130
|
|
|
39898
40131
|
// src/remote-directory-browser.ts
|
|
39899
|
-
import { readdir as readdir4, stat as stat7 } from "node:fs/promises";
|
|
40132
|
+
import { mkdir as mkdir3, readdir as readdir4, stat as stat7 } from "node:fs/promises";
|
|
39900
40133
|
import { homedir as homedir6, platform as platform2 } from "node:os";
|
|
39901
40134
|
import { basename as basename5, dirname as dirname5, isAbsolute as isAbsolute8, parse, resolve as resolve5 } from "node:path";
|
|
39902
40135
|
var MAX_ENTRIES = 500;
|
|
40136
|
+
async function ensureHostWorkspaceDirectory(path) {
|
|
40137
|
+
if (typeof path !== "string" || path.trim() === "" || path.includes("\0") || !isAbsolute8(path) || resolve5(path) === parse(path).root) {
|
|
40138
|
+
throw new RpcError("INVALID_MESSAGE", "Workspace path must be an absolute, non-root directory path.");
|
|
40139
|
+
}
|
|
40140
|
+
await mkdir3(path, { recursive: true });
|
|
40141
|
+
}
|
|
39903
40142
|
async function listRemoteDirectory(path, signal) {
|
|
39904
40143
|
signal?.throwIfAborted();
|
|
39905
40144
|
const home = resolve5(homedir6());
|
|
@@ -40175,6 +40414,7 @@ var HarnessApiBridge = class {
|
|
|
40175
40414
|
this.host = api.events.host.bind(api.events);
|
|
40176
40415
|
this.answer = api.respond.bind(api);
|
|
40177
40416
|
}
|
|
40417
|
+
compactHistoryEnabled = false;
|
|
40178
40418
|
methods;
|
|
40179
40419
|
streams = /* @__PURE__ */ new Map();
|
|
40180
40420
|
respondable = /* @__PURE__ */ new Map();
|
|
@@ -40206,7 +40446,10 @@ var HarnessApiBridge = class {
|
|
|
40206
40446
|
);
|
|
40207
40447
|
let response;
|
|
40208
40448
|
if (params.method === "session.history") {
|
|
40209
|
-
response = await callSessionHistory(
|
|
40449
|
+
response = await callSessionHistory(async (payload) => {
|
|
40450
|
+
const result = await callWithTimeout(payload);
|
|
40451
|
+
return this.compactHistoryEnabled ? { ...result, result: compactHistory(result.result) } : result;
|
|
40452
|
+
}, params.payload, params.rpcId);
|
|
40210
40453
|
} else {
|
|
40211
40454
|
response = await callWithTimeout(request.payload);
|
|
40212
40455
|
}
|
|
@@ -40220,7 +40463,7 @@ var HarnessApiBridge = class {
|
|
|
40220
40463
|
method: params.method,
|
|
40221
40464
|
durationMs: Math.round(performance.now() - startedAt)
|
|
40222
40465
|
});
|
|
40223
|
-
return response;
|
|
40466
|
+
return this.compactHistoryEnabled && params.method === "subagent.history" ? { ...response, result: compactHistory(response.result) } : response;
|
|
40224
40467
|
} catch (error) {
|
|
40225
40468
|
const durationMs = Math.round(performance.now() - startedAt);
|
|
40226
40469
|
this.logger?.warn("harness api call failed", {
|
|
@@ -40838,9 +41081,16 @@ var HARNESS_REMOTE_ALLOWLIST = [
|
|
|
40838
41081
|
"messageFeedback/list",
|
|
40839
41082
|
"messageFeedback/put",
|
|
40840
41083
|
"pluginInventory/list",
|
|
41084
|
+
"pluginManager/listBundles",
|
|
41085
|
+
"pluginManager/listPlugins",
|
|
41086
|
+
"pluginManager/setBundleEnabled",
|
|
41087
|
+
"pluginManager/setPluginEnabled",
|
|
40841
41088
|
"permissionPresets/catalog",
|
|
40842
41089
|
"schedule/list",
|
|
40843
41090
|
"schedule/catalog",
|
|
41091
|
+
"schedule/history",
|
|
41092
|
+
"schedule/update",
|
|
41093
|
+
"schedule/delete",
|
|
40844
41094
|
"session/attachment",
|
|
40845
41095
|
"session/cancel",
|
|
40846
41096
|
"session/canOpenWorkspacePath",
|
|
@@ -40905,6 +41155,7 @@ var HarnessRemoteBridge = class {
|
|
|
40905
41155
|
this.codexWorkspace = codexWorkspace;
|
|
40906
41156
|
this.terminalCarrier = usesDuplexTerminal(harnessVersion) ? new TerminalCarrierCompat(gateway) : void 0;
|
|
40907
41157
|
}
|
|
41158
|
+
compactHistoryEnabled = false;
|
|
40908
41159
|
streams = /* @__PURE__ */ new Map();
|
|
40909
41160
|
incomingTransfers = /* @__PURE__ */ new Map();
|
|
40910
41161
|
outgoingTransfers = /* @__PURE__ */ new Map();
|
|
@@ -40919,6 +41170,7 @@ var HarnessRemoteBridge = class {
|
|
|
40919
41170
|
throw new RpcError("PERMISSION_DENIED", "Remote access settings can only be changed locally on the Host.");
|
|
40920
41171
|
}
|
|
40921
41172
|
}
|
|
41173
|
+
await this.checkPluginManagement(params.endpoint, params.payload);
|
|
40922
41174
|
const reservation = params.endpoint.startsWith("terminal/") ? this.terminal.check(params.endpoint, params.payload) : void 0;
|
|
40923
41175
|
let codexResult;
|
|
40924
41176
|
if (this.codexWorkspace !== void 0) {
|
|
@@ -40935,17 +41187,25 @@ var HarnessRemoteBridge = class {
|
|
|
40935
41187
|
if (params.endpoint === "session/canOpenWorkspacePath") {
|
|
40936
41188
|
return { ok: true, value: true };
|
|
40937
41189
|
}
|
|
41190
|
+
if (params.endpoint === "workspace/create") {
|
|
41191
|
+
const request = requestArgs(params.payload);
|
|
41192
|
+
const folder = typeof request.path === "string" ? request.path : "";
|
|
41193
|
+
await ensureHostWorkspaceDirectory(folder);
|
|
41194
|
+
}
|
|
40938
41195
|
const startedAt = performance.now();
|
|
40939
41196
|
const signal = AbortSignal.timeout(6e4);
|
|
40940
41197
|
try {
|
|
40941
41198
|
const nativePayload = normalizeWorkspaceRequestPayload(params.endpoint, params.payload, this.harnessVersion);
|
|
40942
41199
|
const nativeResult = params.endpoint === "commands/execute" ? await dispatchCommandForHost(this.gateway, params.payload, signal, this.harnessVersion) : this.terminalCarrier !== void 0 && (params.endpoint === "terminal/write" || params.endpoint === "terminal/resize") ? await this.terminalCarrier.call(params.endpoint, nativePayload, signal) : await this.gateway.dispatch(params.endpoint, nativePayload, signal);
|
|
40943
|
-
const result = params.endpoint === "directoryPicker/list" && needsDirectoryFallback(nativeResult) ? await this.directoryList(params.payload, signal) : nativeResult;
|
|
41200
|
+
const result = params.endpoint === "directoryPicker/list" && needsDirectoryFallback(nativeResult) ? await this.directoryList(params.payload, signal) : filterRemotePluginInventory(params.endpoint, nativeResult);
|
|
40944
41201
|
this.logger?.debug("harness remote call ok", {
|
|
40945
41202
|
endpoint: params.endpoint,
|
|
40946
41203
|
durationMs: Math.round(performance.now() - startedAt)
|
|
40947
41204
|
});
|
|
40948
|
-
const wireResult = normalizeWorkspaceBinaryResult2(
|
|
41205
|
+
const wireResult = normalizeWorkspaceBinaryResult2(
|
|
41206
|
+
params.endpoint,
|
|
41207
|
+
this.compactHistoryEnabled && ["session/page", "session/history", "subagent/history"].includes(params.endpoint) ? compactHistory(result) : result
|
|
41208
|
+
);
|
|
40949
41209
|
return reservation === void 0 ? wireResult : this.terminal.result(params.endpoint, params.payload, wireResult, reservation);
|
|
40950
41210
|
} catch (error) {
|
|
40951
41211
|
if (reservation !== void 0) this.terminal.result(params.endpoint, params.payload, { ok: false, error: { code: "FAILED", message: "", details: {} } }, reservation);
|
|
@@ -41075,6 +41335,7 @@ var HarnessRemoteBridge = class {
|
|
|
41075
41335
|
async openStream(input3) {
|
|
41076
41336
|
const params = streamOpenSchema4.parse(input3);
|
|
41077
41337
|
this.assertAllowed(params.endpoint);
|
|
41338
|
+
if (params.endpoint.startsWith("pluginManager/")) throw new RpcError("METHOD_NOT_ALLOWED", "Plugin management endpoints are not streams.");
|
|
41078
41339
|
if (params.endpoint.startsWith("settings/")) throw new RpcError("METHOD_NOT_ALLOWED", "Settings endpoints are not streams.");
|
|
41079
41340
|
if (TERMINAL_CALLS.has(params.endpoint)) throw new RpcError("METHOD_NOT_ALLOWED", "This terminal endpoint is not a stream.");
|
|
41080
41341
|
if (TERMINAL_STREAMS.has(params.endpoint)) this.terminal.check(params.endpoint, params.payload);
|
|
@@ -41093,7 +41354,7 @@ var HarnessRemoteBridge = class {
|
|
|
41093
41354
|
controller.abort();
|
|
41094
41355
|
throw error;
|
|
41095
41356
|
}
|
|
41096
|
-
void this.pump(params.streamId, source, controller.signal);
|
|
41357
|
+
void this.pump(params.streamId, source, controller.signal, params.endpoint === "session/follow");
|
|
41097
41358
|
return { opened: true, streamId: params.streamId };
|
|
41098
41359
|
}
|
|
41099
41360
|
closeStream(input3) {
|
|
@@ -41113,6 +41374,25 @@ var HarnessRemoteBridge = class {
|
|
|
41113
41374
|
for (const [, stream] of streams) stream.controller.abort(reason);
|
|
41114
41375
|
await Promise.all([this.gateway.dispose?.(), this.codexWorkspace?.closeAll()]);
|
|
41115
41376
|
}
|
|
41377
|
+
async checkPluginManagement(endpoint, payload) {
|
|
41378
|
+
if (endpoint !== "pluginManager/setPluginEnabled" && endpoint !== "pluginManager/setBundleEnabled") return;
|
|
41379
|
+
const plugin = endpoint === "pluginManager/setPluginEnabled";
|
|
41380
|
+
const key = plugin ? "id" : "name";
|
|
41381
|
+
const parsed = external_exports.object({ args: external_exports.object({
|
|
41382
|
+
[key]: external_exports.string().min(1).max(4096),
|
|
41383
|
+
enabled: external_exports.boolean()
|
|
41384
|
+
}).strict() }).strict().safeParse(payload);
|
|
41385
|
+
if (!parsed.success) throw new RpcError("INVALID_MESSAGE", "Invalid plugin enablement request.");
|
|
41386
|
+
const args = parsed.data.args;
|
|
41387
|
+
const result = await this.gateway.dispatch(plugin ? "pluginManager/listPlugins" : "pluginManager/listBundles", { args: {} }, AbortSignal.timeout(6e4));
|
|
41388
|
+
if (!result.ok || !Array.isArray(result.value)) throw new RpcError("PERMISSION_DENIED", "Cannot verify the Host plugin inventory.");
|
|
41389
|
+
const row = result.value.find((value) => isRecord21(value) && value[plugin ? "entryId" : "name"] === args[key]);
|
|
41390
|
+
if (!isRecord21(row) || row.readOnlyReason !== void 0) throw new RpcError("PERMISSION_DENIED", "The Host plugin cannot be changed remotely.");
|
|
41391
|
+
const remoteModule = (value) => typeof value === "string" && /^(?:ds-harness-remote|dsh-remote)(?:\/|$)/.test(value);
|
|
41392
|
+
if (remoteModule(plugin ? row.moduleName : row.name) || !plugin && (!Array.isArray(row.rows) || row.rows.some((value) => !isRecord21(value) || remoteModule(value.moduleName)) || Array.isArray(row.overrides) && row.overrides.some((value) => remoteModule(value) || value === "ds-harness-remote-tui"))) {
|
|
41393
|
+
throw new RpcError("PERMISSION_DENIED", "The Remote plugin can only be enabled or disabled locally on the Host.");
|
|
41394
|
+
}
|
|
41395
|
+
}
|
|
41116
41396
|
assertAllowed(endpoint) {
|
|
41117
41397
|
if (!allowedEndpoints.has(endpoint) && !TERMINAL_CALLS.has(endpoint) && !TERMINAL_STREAMS.has(endpoint)) {
|
|
41118
41398
|
throw new RpcError("METHOD_NOT_ALLOWED", "The requested Harness Remote endpoint is not allowed.");
|
|
@@ -41121,7 +41401,7 @@ var HarnessRemoteBridge = class {
|
|
|
41121
41401
|
throw new RpcError("FEATURE_NOT_SUPPORTED", "This Harness version does not support Remote event transport.");
|
|
41122
41402
|
}
|
|
41123
41403
|
}
|
|
41124
|
-
async pump(streamId, source, signal) {
|
|
41404
|
+
async pump(streamId, source, signal, historyFollow = false) {
|
|
41125
41405
|
let reason = "completed";
|
|
41126
41406
|
let failure4;
|
|
41127
41407
|
try {
|
|
@@ -41130,7 +41410,7 @@ var HarnessRemoteBridge = class {
|
|
|
41130
41410
|
const frame = {
|
|
41131
41411
|
streamId,
|
|
41132
41412
|
hasValue: true,
|
|
41133
|
-
...value === void 0 ? {} : { value }
|
|
41413
|
+
...value === void 0 ? {} : { value: historyFollow && this.compactHistoryEnabled && isCompactSnapshot(value) ? compactHistory(value) : value }
|
|
41134
41414
|
};
|
|
41135
41415
|
if (encodeMessage(createEvent("harness.remote.frame", frame)).byteLength > MAX_SECURE_MESSAGE_BYTES) {
|
|
41136
41416
|
throw new Error("Oversized Harness Remote frame");
|
|
@@ -41258,6 +41538,21 @@ function needsDirectoryFallback(result) {
|
|
|
41258
41538
|
const message = result.error.message.toLocaleLowerCase();
|
|
41259
41539
|
return code.includes("capability") || code === "directory-picker/unavailable" || code === "directory-picker-unavailable" || message.includes("browse capability") || message.includes("browser capability") || message.includes("brower capability") || message.includes("directory-picker-unavailable");
|
|
41260
41540
|
}
|
|
41541
|
+
function filterRemotePluginInventory(endpoint, result) {
|
|
41542
|
+
if (!result.ok) return result;
|
|
41543
|
+
const isRemote = (value) => typeof value === "string" && /^(?:ds-harness-remote|dsh-remote)(?:\/|$)/.test(value);
|
|
41544
|
+
const filterEntries = (entries) => entries.filter((entry) => !isRecord21(entry) || !isRemote(entry.moduleName));
|
|
41545
|
+
if (endpoint === "pluginManager/listPlugins" && Array.isArray(result.value)) {
|
|
41546
|
+
return { ...result, value: filterEntries(result.value) };
|
|
41547
|
+
}
|
|
41548
|
+
if (endpoint === "pluginManager/listBundles" && Array.isArray(result.value)) {
|
|
41549
|
+
return { ...result, value: result.value.filter((bundle) => !isRecord21(bundle) || !isRemote(bundle.name)).map((bundle) => isRecord21(bundle) && Array.isArray(bundle.rows) ? { ...bundle, rows: filterEntries(bundle.rows) } : bundle) };
|
|
41550
|
+
}
|
|
41551
|
+
if (endpoint === "pluginInventory/list" && isRecord21(result.value) && Array.isArray(result.value.entries)) {
|
|
41552
|
+
return { ...result, value: { ...result.value, entries: filterEntries(result.value.entries) } };
|
|
41553
|
+
}
|
|
41554
|
+
return result;
|
|
41555
|
+
}
|
|
41261
41556
|
function requestArgs(payload) {
|
|
41262
41557
|
const root = record8(payload);
|
|
41263
41558
|
const args = isRecord21(root.args) ? root.args : root;
|
|
@@ -41269,6 +41564,9 @@ function record8(value) {
|
|
|
41269
41564
|
function isRecord21(value) {
|
|
41270
41565
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
41271
41566
|
}
|
|
41567
|
+
function isCompactSnapshot(value) {
|
|
41568
|
+
return value !== null && typeof value === "object" && value.type === "snapshot";
|
|
41569
|
+
}
|
|
41272
41570
|
|
|
41273
41571
|
// src/service.ts
|
|
41274
41572
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
@@ -41662,7 +41960,7 @@ var HostPluginRuntime = class {
|
|
|
41662
41960
|
let reportedVersion;
|
|
41663
41961
|
let errorCode6;
|
|
41664
41962
|
try {
|
|
41665
|
-
const response = await this.apiProxy?.host.describe({ rpcId:
|
|
41963
|
+
const response = await this.apiProxy?.host.describe({ rpcId: randomUUID7(), payload: {} });
|
|
41666
41964
|
if (response === void 0) throw new Error("ApiProxy is unavailable");
|
|
41667
41965
|
if (!response.result.ok) {
|
|
41668
41966
|
errorCode6 = response.result.error.code;
|
|
@@ -42041,16 +42339,16 @@ async function renderTerminalQr(url) {
|
|
|
42041
42339
|
async function renderCompactTerminalQr(url) {
|
|
42042
42340
|
const { default: QRCode } = await import("qrcode");
|
|
42043
42341
|
const modules = QRCode.create(url, { errorCorrectionLevel: "M" }).modules;
|
|
42044
|
-
const
|
|
42342
|
+
const size2 = modules.size + TERMINAL_QR_MARGIN * 2;
|
|
42045
42343
|
const lines = [];
|
|
42046
42344
|
const isBlack = (row, column) => {
|
|
42047
42345
|
const qrRow = row - TERMINAL_QR_MARGIN;
|
|
42048
42346
|
const qrColumn = column - TERMINAL_QR_MARGIN;
|
|
42049
42347
|
return qrRow >= 0 && qrRow < modules.size && qrColumn >= 0 && qrColumn < modules.size && modules.get(qrRow, qrColumn) === 1;
|
|
42050
42348
|
};
|
|
42051
|
-
for (let row = 0; row <
|
|
42349
|
+
for (let row = 0; row < size2; row += 2) {
|
|
42052
42350
|
let line = "\x1B[30;47m";
|
|
42053
|
-
for (let column = 0; column <
|
|
42351
|
+
for (let column = 0; column < size2; column += 1) {
|
|
42054
42352
|
const top = isBlack(row, column);
|
|
42055
42353
|
const bottom = isBlack(row + 1, column);
|
|
42056
42354
|
line += top ? bottom ? "\u2588" : "\u2580" : bottom ? "\u2584" : " ";
|
|
@@ -42704,9 +43002,6 @@ async function activate(ctx, readConfig, entryId, tuiBinding) {
|
|
|
42704
43002
|
console.error(message);
|
|
42705
43003
|
}
|
|
42706
43004
|
}, config.logLevel);
|
|
42707
|
-
const hostIdentities = new IdentityStore({
|
|
42708
|
-
directory: config.serverUrl === void 0 ? defaultIdentityDirectory : serverStorageDirectory(defaultIdentityDirectory, config.serverUrl, "host")
|
|
42709
|
-
});
|
|
42710
43005
|
const apiProxy = ctx.get("apiProxy");
|
|
42711
43006
|
const nativeTypertGateway = ctx.get("typertGateway");
|
|
42712
43007
|
const hostGateway = new TypertGatewaySwitch(nativeTypertGateway);
|
|
@@ -42725,56 +43020,103 @@ async function activate(ctx, readConfig, entryId, tuiBinding) {
|
|
|
42725
43020
|
};
|
|
42726
43021
|
}
|
|
42727
43022
|
const subprocess = ctx.get("subprocess", false);
|
|
42728
|
-
const
|
|
42729
|
-
|
|
42730
|
-
|
|
42731
|
-
apiProxy,
|
|
42732
|
-
logger,
|
|
42733
|
-
localTypertGateway,
|
|
42734
|
-
() => ctx.get("fileViewerHost"),
|
|
42735
|
-
subprocess === void 0 ? void 0 : subprocessTerminalSpawner(subprocess),
|
|
42736
|
-
(peer) => createPluginRouteDispatcher(
|
|
42737
|
-
() => ctx.get("connection"),
|
|
42738
|
-
() => ctx.get("webServer")?.port,
|
|
42739
|
-
peer
|
|
42740
|
-
)
|
|
42741
|
-
);
|
|
42742
|
-
let clientRuntime;
|
|
42743
|
-
const hostControl = runtime;
|
|
42744
|
-
if (config.serverUrl !== void 0 && connection !== void 0) {
|
|
42745
|
-
const clientIdentities = new IdentityStore({
|
|
42746
|
-
directory: serverStorageDirectory(defaultIdentityDirectory, config.serverUrl, "client")
|
|
43023
|
+
const createRuntimes = (config2) => {
|
|
43024
|
+
const hostIdentities = new IdentityStore({
|
|
43025
|
+
directory: config2.serverUrl === void 0 ? defaultIdentityDirectory : serverStorageDirectory(defaultIdentityDirectory, config2.serverUrl, "host")
|
|
42747
43026
|
});
|
|
42748
|
-
|
|
42749
|
-
|
|
42750
|
-
|
|
42751
|
-
new ClientServerApi(config.serverUrl, new ServerCredentialStore(clientIdentities.directory)),
|
|
43027
|
+
const runtime2 = new HostPluginRuntime(
|
|
43028
|
+
config2,
|
|
43029
|
+
hostIdentities,
|
|
42752
43030
|
apiProxy,
|
|
42753
|
-
nativeTypertGateway,
|
|
42754
43031
|
logger,
|
|
42755
|
-
|
|
43032
|
+
localTypertGateway,
|
|
43033
|
+
() => ctx.get("fileViewerHost"),
|
|
43034
|
+
subprocess === void 0 ? void 0 : subprocessTerminalSpawner(subprocess),
|
|
43035
|
+
(peer) => createPluginRouteDispatcher(
|
|
43036
|
+
() => ctx.get("connection"),
|
|
43037
|
+
() => ctx.get("webServer")?.port,
|
|
43038
|
+
peer
|
|
43039
|
+
)
|
|
42756
43040
|
);
|
|
42757
|
-
|
|
42758
|
-
|
|
43041
|
+
let clientRuntime2;
|
|
43042
|
+
if (config2.serverUrl !== void 0 && connection !== void 0) {
|
|
43043
|
+
const clientIdentities = new IdentityStore({
|
|
43044
|
+
directory: serverStorageDirectory(defaultIdentityDirectory, config2.serverUrl, "client")
|
|
43045
|
+
});
|
|
43046
|
+
clientRuntime2 = new ClientModeRuntime(
|
|
43047
|
+
config2,
|
|
43048
|
+
clientIdentities,
|
|
43049
|
+
new ClientServerApi(config2.serverUrl, new ServerCredentialStore(clientIdentities.directory)),
|
|
43050
|
+
apiProxy,
|
|
43051
|
+
nativeTypertGateway,
|
|
43052
|
+
logger,
|
|
43053
|
+
runtime2
|
|
43054
|
+
);
|
|
43055
|
+
}
|
|
43056
|
+
return { runtime: runtime2, clientRuntime: clientRuntime2 };
|
|
43057
|
+
};
|
|
43058
|
+
let { runtime, clientRuntime } = createRuntimes(config);
|
|
43059
|
+
let closed = false;
|
|
43060
|
+
let clientServiceProvided = clientRuntime !== void 0;
|
|
43061
|
+
let startup;
|
|
43062
|
+
let replacement;
|
|
43063
|
+
const replaceServer = (next) => {
|
|
43064
|
+
const operation = async () => {
|
|
43065
|
+
await startup;
|
|
43066
|
+
if (closed) throw new Error("Remote plugin is closed");
|
|
43067
|
+
const shutdown = await Promise.allSettled([clientRuntime?.close(), runtime.close()]);
|
|
43068
|
+
const failure4 = shutdown.find((result) => result.status === "rejected");
|
|
43069
|
+
if (failure4?.status === "rejected") throw failure4.reason;
|
|
43070
|
+
if (closed) throw new Error("Remote plugin is closed");
|
|
43071
|
+
const fresh = createRuntimes(next);
|
|
43072
|
+
try {
|
|
43073
|
+
await fresh.runtime.start();
|
|
43074
|
+
await fresh.clientRuntime?.start();
|
|
43075
|
+
if (closed) throw new Error("Remote plugin is closed");
|
|
43076
|
+
} catch (error) {
|
|
43077
|
+
await Promise.allSettled([fresh.clientRuntime?.close(), fresh.runtime.close()]);
|
|
43078
|
+
throw error;
|
|
43079
|
+
}
|
|
43080
|
+
runtime = fresh.runtime;
|
|
43081
|
+
clientRuntime = fresh.clientRuntime;
|
|
43082
|
+
ctx.dshRemote = runtime;
|
|
43083
|
+
if (clientRuntime !== void 0) {
|
|
43084
|
+
if (clientServiceProvided) ctx.dshRemoteClient = clientRuntime;
|
|
43085
|
+
else {
|
|
43086
|
+
ctx.provide("dshRemoteClient", clientRuntime);
|
|
43087
|
+
clientServiceProvided = true;
|
|
43088
|
+
}
|
|
43089
|
+
}
|
|
43090
|
+
tuiTarget = { runtime, config: next };
|
|
43091
|
+
if (tuiBinding !== void 0) tuiBinding.target = tuiTarget;
|
|
43092
|
+
return { client: clientRuntime, host: runtime };
|
|
43093
|
+
};
|
|
43094
|
+
replacement = operation();
|
|
43095
|
+
return replacement;
|
|
43096
|
+
};
|
|
43097
|
+
const controlRuntime = connection === void 0 ? void 0 : new PluginControlRuntime(config, defaultIdentityDirectory, settingsBinding, clientRuntime, runtime, replaceServer);
|
|
42759
43098
|
ctx.provide("dshRemote", runtime);
|
|
42760
43099
|
if (clientRuntime !== void 0) ctx.provide("dshRemoteClient", clientRuntime);
|
|
42761
|
-
|
|
43100
|
+
let tuiTarget = { runtime, config };
|
|
42762
43101
|
if (tuiBinding !== void 0) tuiBinding.target = tuiTarget;
|
|
42763
43102
|
await disableLegacyLoaderEntries(ctx, logger);
|
|
42764
43103
|
await ctx.effect(async () => {
|
|
42765
43104
|
const disposeControl = controlRuntime?.register(connection, webServer);
|
|
42766
43105
|
try {
|
|
42767
|
-
|
|
42768
|
-
|
|
42769
|
-
|
|
42770
|
-
|
|
42771
|
-
|
|
42772
|
-
|
|
42773
|
-
|
|
42774
|
-
|
|
42775
|
-
|
|
42776
|
-
|
|
42777
|
-
|
|
43106
|
+
startup = (async () => {
|
|
43107
|
+
await runtime.start();
|
|
43108
|
+
if (clientRuntime !== void 0) {
|
|
43109
|
+
await clientRuntime.start();
|
|
43110
|
+
} else {
|
|
43111
|
+
logger.warn("client remote mode is unavailable", {
|
|
43112
|
+
serverConfigured: config.serverUrl !== void 0,
|
|
43113
|
+
apiProxyAvailable: apiProxy !== void 0,
|
|
43114
|
+
remoteGatewayAvailable: localTypertGateway.supportsCarrier,
|
|
43115
|
+
connectionAvailable: connection !== void 0
|
|
43116
|
+
});
|
|
43117
|
+
}
|
|
43118
|
+
})();
|
|
43119
|
+
await startup;
|
|
42778
43120
|
} catch (error) {
|
|
42779
43121
|
if (tuiBinding?.target === tuiTarget) tuiBinding.target = void 0;
|
|
42780
43122
|
await disposeControl?.();
|
|
@@ -42783,6 +43125,8 @@ async function activate(ctx, readConfig, entryId, tuiBinding) {
|
|
|
42783
43125
|
throw error;
|
|
42784
43126
|
}
|
|
42785
43127
|
return async () => {
|
|
43128
|
+
closed = true;
|
|
43129
|
+
await replacement?.catch(() => void 0);
|
|
42786
43130
|
if (tuiBinding?.target === tuiTarget) tuiBinding.target = void 0;
|
|
42787
43131
|
await disposeControl?.();
|
|
42788
43132
|
await clientRuntime?.close();
|