ds-harness-remote 0.4.16 → 0.4.18
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/client-runtime.d.ts.map +1 -1
- package/dist/client-runtime.js +3 -3
- package/dist/client-runtime.js.map +1 -1
- package/dist/client.github.js +77 -36
- package/dist/client.js +77 -36
- package/dist/client.js.map +1 -1
- package/dist/codex/codex-image-codec.d.ts +7 -0
- package/dist/codex/codex-image-codec.d.ts.map +1 -0
- package/dist/codex/codex-image-codec.js +288 -0
- package/dist/codex/codex-image-codec.js.map +1 -0
- package/dist/codex/domain.d.ts +2 -0
- package/dist/codex/domain.d.ts.map +1 -1
- package/dist/codex/domain.js +15 -0
- package/dist/codex/domain.js.map +1 -1
- package/dist/codex/session-id.d.ts +10 -0
- package/dist/codex/session-id.d.ts.map +1 -0
- package/dist/codex/session-id.js +15 -0
- package/dist/codex/session-id.js.map +1 -0
- package/dist/codex/virtual-harness.d.ts +3 -2
- package/dist/codex/virtual-harness.d.ts.map +1 -1
- package/dist/codex/virtual-harness.js +33 -270
- package/dist/codex/virtual-harness.js.map +1 -1
- package/dist/codex-workspace-bridge.d.ts +108 -0
- package/dist/codex-workspace-bridge.d.ts.map +1 -0
- package/dist/codex-workspace-bridge.js +501 -0
- package/dist/codex-workspace-bridge.js.map +1 -0
- package/dist/config.d.ts +13 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +22 -2
- package/dist/config.js.map +1 -1
- package/dist/control-runtime.d.ts +17 -3
- package/dist/control-runtime.d.ts.map +1 -1
- package/dist/control-runtime.js +4 -2
- package/dist/control-runtime.js.map +1 -1
- package/dist/harness-api-bridge.d.ts.map +1 -1
- package/dist/harness-api-bridge.js +2 -53
- package/dist/harness-api-bridge.js.map +1 -1
- package/dist/harness-api-history.d.ts +3 -0
- package/dist/harness-api-history.d.ts.map +1 -0
- package/dist/harness-api-history.js +55 -0
- package/dist/harness-api-history.js.map +1 -0
- package/dist/harness-remote-bridge.d.ts +4 -2
- package/dist/harness-remote-bridge.d.ts.map +1 -1
- package/dist/harness-remote-bridge.js +61 -3
- package/dist/harness-remote-bridge.js.map +1 -1
- package/dist/index.d.ts +24 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1418 -628
- package/dist/index.js.map +4 -4
- package/dist/remote-api-proxy.d.ts +5 -1
- package/dist/remote-api-proxy.d.ts.map +1 -1
- package/dist/remote-api-proxy.js +74 -2
- package/dist/remote-api-proxy.js.map +1 -1
- package/dist/remote-typert-gateway.d.ts +6 -1
- package/dist/remote-typert-gateway.d.ts.map +1 -1
- package/dist/remote-typert-gateway.js +58 -1
- package/dist/remote-typert-gateway.js.map +1 -1
- package/dist/service.d.ts +7 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +8 -2
- package/dist/service.js.map +1 -1
- package/dist/terminal-policy.d.ts.map +1 -1
- package/dist/terminal-policy.js +8 -2
- package/dist/terminal-policy.js.map +1 -1
- package/dist/typert-gateway-contract.d.ts +11 -1
- package/dist/typert-gateway-contract.d.ts.map +1 -1
- package/dist/typert-gateway-switch.d.ts.map +1 -1
- package/dist/typert-gateway-switch.js +65 -4
- package/dist/typert-gateway-switch.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 +18 -18
- package/public.d.ts +2 -2
package/dist/index.js
CHANGED
|
@@ -4695,7 +4695,7 @@ var LoopbackHost = class {
|
|
|
4695
4695
|
const response = handle.response;
|
|
4696
4696
|
let chunk = response.read(Math.min(response.readableLength || LOOPBACK_CHUNK_BYTES, LOOPBACK_CHUNK_BYTES));
|
|
4697
4697
|
if (chunk === null && !response.readableEnded && !response.destroyed) {
|
|
4698
|
-
await new Promise((
|
|
4698
|
+
await new Promise((resolve4, reject) => {
|
|
4699
4699
|
const timer = setTimeout(() => finish(new Error("timeout")), 2e4);
|
|
4700
4700
|
const ready = () => finish();
|
|
4701
4701
|
const fail4 = () => finish(new Error("closed"));
|
|
@@ -4705,7 +4705,7 @@ var LoopbackHost = class {
|
|
|
4705
4705
|
response.off("end", ready);
|
|
4706
4706
|
response.off("close", ready);
|
|
4707
4707
|
response.off("error", fail4);
|
|
4708
|
-
error === void 0 ?
|
|
4708
|
+
error === void 0 ? resolve4() : reject(error);
|
|
4709
4709
|
};
|
|
4710
4710
|
response.once("readable", ready);
|
|
4711
4711
|
response.once("end", ready);
|
|
@@ -4735,22 +4735,22 @@ var LoopbackHost = class {
|
|
|
4735
4735
|
this.close(value.id);
|
|
4736
4736
|
throw new RpcError("RATE_LIMITED", "Preview WebSocket buffer exceeded its limit.");
|
|
4737
4737
|
}
|
|
4738
|
-
await new Promise((
|
|
4738
|
+
await new Promise((resolve4, reject) => handle.socket.send(data2, { binary: value.binary }, (error) => error ? reject(new RpcError("LOOPBACK_CLOSED", "Preview socket closed.")) : resolve4()));
|
|
4739
4739
|
return { sent: true };
|
|
4740
4740
|
}
|
|
4741
4741
|
if (value.op === "ws.read") {
|
|
4742
4742
|
if (handle.reading) throw new RpcError("REQUEST_CONFLICT", "Only one preview read may be pending.");
|
|
4743
4743
|
handle.reading = true;
|
|
4744
4744
|
try {
|
|
4745
|
-
if (handle.messages.length === 0 && !handle.closed) await new Promise((
|
|
4745
|
+
if (handle.messages.length === 0 && !handle.closed) await new Promise((resolve4) => {
|
|
4746
4746
|
const timer = setTimeout(() => {
|
|
4747
4747
|
handle.wake = void 0;
|
|
4748
|
-
|
|
4748
|
+
resolve4();
|
|
4749
4749
|
}, 2e4);
|
|
4750
4750
|
handle.wake = () => {
|
|
4751
4751
|
clearTimeout(timer);
|
|
4752
4752
|
handle.wake = void 0;
|
|
4753
|
-
|
|
4753
|
+
resolve4();
|
|
4754
4754
|
};
|
|
4755
4755
|
});
|
|
4756
4756
|
let bytes = 0;
|
|
@@ -4792,7 +4792,7 @@ var LoopbackHost = class {
|
|
|
4792
4792
|
openHttp(value) {
|
|
4793
4793
|
const body = value.body === void 0 ? void 0 : Buffer.from(value.body, "base64");
|
|
4794
4794
|
if ((body?.length ?? 0) > LOOPBACK_MAX_BODY_BYTES) throw new Error("body limit");
|
|
4795
|
-
return new Promise((
|
|
4795
|
+
return new Promise((resolve4, reject) => {
|
|
4796
4796
|
const headers = Object.fromEntries(cleanHeaders(value.headers));
|
|
4797
4797
|
const request = httpRequest({
|
|
4798
4798
|
hostname: "127.0.0.1",
|
|
@@ -4811,7 +4811,7 @@ var LoopbackHost = class {
|
|
|
4811
4811
|
handle.response = response;
|
|
4812
4812
|
response.on("error", () => void 0);
|
|
4813
4813
|
clearTimeout(timer);
|
|
4814
|
-
|
|
4814
|
+
resolve4({ status: response.statusCode ?? 502, headers: cleanHeaders(headerPairs(response.headers)) });
|
|
4815
4815
|
});
|
|
4816
4816
|
const timer = setTimeout(() => {
|
|
4817
4817
|
request.destroy();
|
|
@@ -4826,7 +4826,7 @@ var LoopbackHost = class {
|
|
|
4826
4826
|
});
|
|
4827
4827
|
}
|
|
4828
4828
|
openWs(value) {
|
|
4829
|
-
return new Promise((
|
|
4829
|
+
return new Promise((resolve4, reject) => {
|
|
4830
4830
|
const socket = new WebSocket2(`ws://127.0.0.1:${value.port}${value.path}`, value.protocols, {
|
|
4831
4831
|
headers: Object.fromEntries(cleanHeaders(value.headers)),
|
|
4832
4832
|
followRedirects: false,
|
|
@@ -4836,7 +4836,7 @@ var LoopbackHost = class {
|
|
|
4836
4836
|
});
|
|
4837
4837
|
const handle = { kind: "ws", socket, messages: [], bytes: 0, reading: false, closed: false, touched: Date.now() };
|
|
4838
4838
|
this.handles.set(value.id, handle);
|
|
4839
|
-
socket.once("open", () =>
|
|
4839
|
+
socket.once("open", () => resolve4({ protocol: socket.protocol }));
|
|
4840
4840
|
socket.on("message", (data2, binary) => {
|
|
4841
4841
|
const message = { data: Buffer.from(data2).toString("base64"), binary };
|
|
4842
4842
|
if (handle.bytes + message.data.length > 1024 * 1024 || handle.messages.length >= 256) {
|
|
@@ -4894,7 +4894,7 @@ var LoopbackPreview = class {
|
|
|
4894
4894
|
for (const client of running.ws.clients) client.terminate();
|
|
4895
4895
|
running.ws.close();
|
|
4896
4896
|
running.server.closeAllConnections();
|
|
4897
|
-
await new Promise((
|
|
4897
|
+
await new Promise((resolve4) => running.server.close(() => resolve4()));
|
|
4898
4898
|
}
|
|
4899
4899
|
this.servers.clear();
|
|
4900
4900
|
}
|
|
@@ -4949,11 +4949,11 @@ var LoopbackPreview = class {
|
|
|
4949
4949
|
void this.release(id4);
|
|
4950
4950
|
});
|
|
4951
4951
|
});
|
|
4952
|
-
await new Promise((
|
|
4952
|
+
await new Promise((resolve4, reject) => {
|
|
4953
4953
|
server.once("error", reject);
|
|
4954
4954
|
server.listen(0, "127.0.0.1", () => {
|
|
4955
4955
|
server.off("error", reject);
|
|
4956
|
-
|
|
4956
|
+
resolve4();
|
|
4957
4957
|
});
|
|
4958
4958
|
});
|
|
4959
4959
|
const address = server.address();
|
|
@@ -5019,10 +5019,10 @@ var LoopbackPreview = class {
|
|
|
5019
5019
|
while (!signal.aborted) {
|
|
5020
5020
|
const chunk = await this.client.rpc("loopback.call", { op: "http.read", id: id4 }, signal);
|
|
5021
5021
|
if (chunk.data !== "" && !res.write(Buffer.from(chunk.data, "base64"))) {
|
|
5022
|
-
await new Promise((
|
|
5022
|
+
await new Promise((resolve4, reject) => {
|
|
5023
5023
|
const ready = () => {
|
|
5024
5024
|
cleanup();
|
|
5025
|
-
|
|
5025
|
+
resolve4();
|
|
5026
5026
|
};
|
|
5027
5027
|
const closed = () => {
|
|
5028
5028
|
cleanup();
|
|
@@ -5082,7 +5082,7 @@ var LoopbackPreview = class {
|
|
|
5082
5082
|
const result = await this.client.rpc("loopback.call", { op: "ws.read", id: id4 }, signal);
|
|
5083
5083
|
for (const message of result.messages) {
|
|
5084
5084
|
if (socket.bufferedAmount > 1024 * 1024) throw new Error("slow preview");
|
|
5085
|
-
await new Promise((
|
|
5085
|
+
await new Promise((resolve4, reject) => socket.send(Buffer.from(message.data, "base64"), { binary: message.binary }, (error) => error ? reject(error) : resolve4()));
|
|
5086
5086
|
}
|
|
5087
5087
|
if (result.closed) break;
|
|
5088
5088
|
}
|
|
@@ -5719,17 +5719,18 @@ var RemoteClientCore = class {
|
|
|
5719
5719
|
throw error;
|
|
5720
5720
|
}
|
|
5721
5721
|
}
|
|
5722
|
-
async rpc(method, params, signal) {
|
|
5722
|
+
async rpc(method, params, signal, options) {
|
|
5723
5723
|
if (signal?.aborted)
|
|
5724
5724
|
throw rpcAbortedError(method, signal.reason);
|
|
5725
|
+
const timeoutMs = callTimeoutMs(this.timeoutMs, options);
|
|
5725
5726
|
const request = createRpcRequest(method, params);
|
|
5726
|
-
const result = new Promise((
|
|
5727
|
+
const result = new Promise((resolve4, reject) => {
|
|
5727
5728
|
const timer = setTimeout(() => {
|
|
5728
|
-
this.rejectPending(request.id, new RemoteClientError("RPC_TIMEOUT", `RPC ${method} timed out after ${
|
|
5729
|
-
},
|
|
5729
|
+
this.rejectPending(request.id, new RemoteClientError("RPC_TIMEOUT", `RPC ${method} timed out after ${timeoutMs}ms`));
|
|
5730
|
+
}, timeoutMs);
|
|
5730
5731
|
const pending = {
|
|
5731
5732
|
method,
|
|
5732
|
-
resolve:
|
|
5733
|
+
resolve: resolve4,
|
|
5733
5734
|
reject,
|
|
5734
5735
|
timer
|
|
5735
5736
|
};
|
|
@@ -5836,6 +5837,12 @@ var RemoteClientCore = class {
|
|
|
5836
5837
|
function rpcAbortedError(method, reason) {
|
|
5837
5838
|
return new RemoteClientError("RPC_ABORTED", `RPC ${method} was aborted`, reason === void 0 ? void 0 : { cause: reason });
|
|
5838
5839
|
}
|
|
5840
|
+
function callTimeoutMs(fallback, options) {
|
|
5841
|
+
const timeoutMs = options?.timeoutMs;
|
|
5842
|
+
if (typeof timeoutMs !== "number")
|
|
5843
|
+
return fallback;
|
|
5844
|
+
return Number.isSafeInteger(timeoutMs) && timeoutMs > 0 && timeoutMs <= 2147483647 ? timeoutMs : fallback;
|
|
5845
|
+
}
|
|
5839
5846
|
function transportSendError(error) {
|
|
5840
5847
|
return error instanceof Error ? error : new Error("remote transport send failed", { cause: error });
|
|
5841
5848
|
}
|
|
@@ -5846,7 +5853,7 @@ async function waitForRelayCapacity(socket) {
|
|
|
5846
5853
|
while ((socket.bufferedAmount ?? 0) > 512 * 1024) {
|
|
5847
5854
|
if (socket.readyState !== 1 || Date.now() - started > 1e4)
|
|
5848
5855
|
throw new Error("Relay consumer is too slow or disconnected");
|
|
5849
|
-
await new Promise((
|
|
5856
|
+
await new Promise((resolve4) => setTimeout(resolve4, 10));
|
|
5850
5857
|
}
|
|
5851
5858
|
if (socket.readyState !== 1)
|
|
5852
5859
|
throw new Error("Relay transport closed");
|
|
@@ -6305,8 +6312,8 @@ var RtcDataChannelTransport = class {
|
|
|
6305
6312
|
if (this.connectPromise !== void 0)
|
|
6306
6313
|
return this.connectPromise;
|
|
6307
6314
|
this.armAbort(signal);
|
|
6308
|
-
this.connectPromise = new Promise((
|
|
6309
|
-
this.openResolve =
|
|
6315
|
+
this.connectPromise = new Promise((resolve4, reject) => {
|
|
6316
|
+
this.openResolve = resolve4;
|
|
6310
6317
|
this.openReject = reject;
|
|
6311
6318
|
this.negotiateTimer = setTimeout(() => {
|
|
6312
6319
|
void this.failOpenAfterStats(new RtcConnectError("RTC_CONNECT_TIMEOUT", `WebRTC negotiation timed out after ${this.negotiateTimeoutMs}ms.`));
|
|
@@ -6521,9 +6528,9 @@ var RtcDataChannelTransport = class {
|
|
|
6521
6528
|
if (this.closed || this.opened)
|
|
6522
6529
|
return;
|
|
6523
6530
|
this.opened = true;
|
|
6524
|
-
const
|
|
6531
|
+
const resolve4 = this.openResolve;
|
|
6525
6532
|
this.clearNegotiation();
|
|
6526
|
-
void this.resolveSelectedTransport().then(() =>
|
|
6533
|
+
void this.resolveSelectedTransport().then(() => resolve4?.());
|
|
6527
6534
|
};
|
|
6528
6535
|
channel.onmessage = (event) => {
|
|
6529
6536
|
if (this.closed || !this.opened)
|
|
@@ -6917,7 +6924,7 @@ function asError(error) {
|
|
|
6917
6924
|
return error instanceof Error ? error : new RtcConnectError("RTC_FAILED", "WebRTC negotiation failed.");
|
|
6918
6925
|
}
|
|
6919
6926
|
function sleep(ms) {
|
|
6920
|
-
return new Promise((
|
|
6927
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
6921
6928
|
}
|
|
6922
6929
|
|
|
6923
6930
|
// ../webrtc/dist/adaptive-transport.js
|
|
@@ -6955,8 +6962,8 @@ var AdaptiveTransport = class extends BaseTransport {
|
|
|
6955
6962
|
this.socket = new WebSocket(this.url);
|
|
6956
6963
|
this.controlFrameLimits = {};
|
|
6957
6964
|
this.socket.binaryType = "arraybuffer";
|
|
6958
|
-
await new Promise((
|
|
6959
|
-
this.readyResolve =
|
|
6965
|
+
await new Promise((resolve4, reject) => {
|
|
6966
|
+
this.readyResolve = resolve4;
|
|
6960
6967
|
this.readyReject = reject;
|
|
6961
6968
|
this.handshakeTimer = setTimeout(() => this.failConnection(new Error("Adaptive control handshake timed out")), this.options.handshakeTimeoutMs ?? 15e3);
|
|
6962
6969
|
const socket = this.socket;
|
|
@@ -14558,7 +14565,7 @@ var ClientSecureTransport = class {
|
|
|
14558
14565
|
}
|
|
14559
14566
|
};
|
|
14560
14567
|
async function waitForResponder(inner, noise) {
|
|
14561
|
-
await new Promise((
|
|
14568
|
+
await new Promise((resolve4, reject) => {
|
|
14562
14569
|
let settled = false;
|
|
14563
14570
|
const timer = setTimeout(() => finish(new Error("Noise IK handshake timed out.")), 1e4);
|
|
14564
14571
|
const unsubscribe = inner.onHandshake((step, data2) => {
|
|
@@ -14577,7 +14584,7 @@ async function waitForResponder(inner, noise) {
|
|
|
14577
14584
|
settled = true;
|
|
14578
14585
|
clearTimeout(timer);
|
|
14579
14586
|
unsubscribe();
|
|
14580
|
-
if (error === void 0)
|
|
14587
|
+
if (error === void 0) resolve4();
|
|
14581
14588
|
else reject(error);
|
|
14582
14589
|
};
|
|
14583
14590
|
void inner.sendHandshake(1, noise.writeHandshake()).catch((error) => {
|
|
@@ -14686,14 +14693,14 @@ function requestSignal(req) {
|
|
|
14686
14693
|
}
|
|
14687
14694
|
function clientRequest(value) {
|
|
14688
14695
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return void 0;
|
|
14689
|
-
const
|
|
14690
|
-
if (
|
|
14691
|
-
return { type: "client-request", rpcId:
|
|
14696
|
+
const record7 = value;
|
|
14697
|
+
if (record7.type !== "client-request" || typeof record7.rpcId !== "string" || typeof record7.method !== "string") return void 0;
|
|
14698
|
+
return { type: "client-request", rpcId: record7.rpcId, method: record7.method, payload: record7.payload };
|
|
14692
14699
|
}
|
|
14693
14700
|
function rpcId(value) {
|
|
14694
14701
|
if (typeof value !== "object" || value === null || Array.isArray(value)) return INVALID_REQUEST_RPC_ID;
|
|
14695
|
-
const
|
|
14696
|
-
return typeof
|
|
14702
|
+
const record7 = value;
|
|
14703
|
+
return typeof record7.rpcId === "string" ? record7.rpcId : INVALID_REQUEST_RPC_ID;
|
|
14697
14704
|
}
|
|
14698
14705
|
function errorResponse(rpcId2, error) {
|
|
14699
14706
|
return fullResponse(rpcId2, { ok: false, error });
|
|
@@ -14773,9 +14780,13 @@ var AGENT_PRESET_SETTINGS_NS = "agent-presets";
|
|
|
14773
14780
|
var LEGACY_AGENT_PRESET_ALIASES = {
|
|
14774
14781
|
code: "ptc"
|
|
14775
14782
|
};
|
|
14783
|
+
var WELCOME_NOTICE_NAMESPACE = "ui-settings-general";
|
|
14784
|
+
var WELCOME_NOTICE_FIELD = "welcomeNoticeVersion";
|
|
14785
|
+
var WELCOME_NOTICE_VERSION = "2026-08-13.1";
|
|
14776
14786
|
var RemoteHarnessApiProxy = class {
|
|
14777
|
-
constructor(client) {
|
|
14787
|
+
constructor(client, harnessVersion) {
|
|
14778
14788
|
this.client = client;
|
|
14789
|
+
this.harnessVersion = harnessVersion;
|
|
14779
14790
|
const call = (method) => (request, signal) => this.call(method, request, signal);
|
|
14780
14791
|
this.api = {
|
|
14781
14792
|
sessions: {
|
|
@@ -14857,6 +14868,8 @@ var RemoteHarnessApiProxy = class {
|
|
|
14857
14868
|
};
|
|
14858
14869
|
}
|
|
14859
14870
|
api;
|
|
14871
|
+
legacyWelcomeAcknowledged = false;
|
|
14872
|
+
settingsDescribeValue;
|
|
14860
14873
|
async call(method, request, signal) {
|
|
14861
14874
|
const params = {
|
|
14862
14875
|
method,
|
|
@@ -14868,7 +14881,18 @@ var RemoteHarnessApiProxy = class {
|
|
|
14868
14881
|
if (String(response.rpcId) !== String(request.rpcId) || typeof response.result !== "object" || response.result === null) {
|
|
14869
14882
|
throw new Error("The remote Host returned an invalid Harness API response.");
|
|
14870
14883
|
}
|
|
14871
|
-
|
|
14884
|
+
const normalized = normalizeLegacyResponse(method, response);
|
|
14885
|
+
return this.normalizeLegacyWelcomeSettings(method, params.payload, normalized);
|
|
14886
|
+
}
|
|
14887
|
+
normalizeLegacyWelcomeSettings(method, payload, response) {
|
|
14888
|
+
if (!isLegacyRemoteHost(this.harnessVersion)) return response;
|
|
14889
|
+
if (method === "settings.describe" && response.result.ok && isRecord2(response.result.value)) {
|
|
14890
|
+
this.settingsDescribeValue = response.result.value;
|
|
14891
|
+
return this.legacyWelcomeAcknowledged ? patchWelcomeDescribe(response) : response;
|
|
14892
|
+
}
|
|
14893
|
+
if (method !== "settings.mutate" || !isWelcomeNoticeRequest(payload)) return response;
|
|
14894
|
+
this.legacyWelcomeAcknowledged = true;
|
|
14895
|
+
return patchWelcomeMutate(this.settingsDescribeValue ?? { namespaces: [] }, response.rpcId);
|
|
14872
14896
|
}
|
|
14873
14897
|
async callTransferred(encoded, signal) {
|
|
14874
14898
|
if (encoded.byteLength > MAX_HARNESS_API_TRANSFER_BYTES) {
|
|
@@ -14993,6 +15017,45 @@ function replaceAgentPresetSettings(payload) {
|
|
|
14993
15017
|
const patch = replaceAgentPreset(payload.patch, "default");
|
|
14994
15018
|
return patch === payload.patch ? payload : { ...payload, patch };
|
|
14995
15019
|
}
|
|
15020
|
+
function isLegacyRemoteHost(version) {
|
|
15021
|
+
if (version === void 0) return false;
|
|
15022
|
+
const match = /^(?:dsh-)?v?(\d+)\.(\d+)\.(\d+)(?:-|$)/u.exec(version.trim());
|
|
15023
|
+
return match !== null && Number(match[1]) === 0 && Number(match[2]) === 1 && Number(match[3]) < 7;
|
|
15024
|
+
}
|
|
15025
|
+
function isWelcomeNoticeRequest(payload) {
|
|
15026
|
+
if (!isRecord2(payload) || payload.ns !== WELCOME_NOTICE_NAMESPACE || !Array.isArray(payload.ops)) return false;
|
|
15027
|
+
return payload.ops.some((operation) => isRecord2(operation) && operation.op === "set" && Array.isArray(operation.path) && operation.path.length === 1 && operation.path[0] === WELCOME_NOTICE_FIELD && operation.value === WELCOME_NOTICE_VERSION);
|
|
15028
|
+
}
|
|
15029
|
+
function patchWelcomeDescribe(response) {
|
|
15030
|
+
if (!response.result.ok || !isRecord2(response.result.value) || !Array.isArray(response.result.value.namespaces)) return response;
|
|
15031
|
+
return {
|
|
15032
|
+
...response,
|
|
15033
|
+
result: {
|
|
15034
|
+
...response.result,
|
|
15035
|
+
value: {
|
|
15036
|
+
...response.result.value,
|
|
15037
|
+
namespaces: response.result.value.namespaces.map((namespace) => {
|
|
15038
|
+
if (!isRecord2(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE) return namespace;
|
|
15039
|
+
const value = isRecord2(namespace.value) ? namespace.value : {};
|
|
15040
|
+
return { ...namespace, value: { ...value, [WELCOME_NOTICE_FIELD]: WELCOME_NOTICE_VERSION } };
|
|
15041
|
+
})
|
|
15042
|
+
}
|
|
15043
|
+
}
|
|
15044
|
+
};
|
|
15045
|
+
}
|
|
15046
|
+
function patchWelcomeMutate(value, rpcId2) {
|
|
15047
|
+
const response = {
|
|
15048
|
+
rpcId: rpcId2,
|
|
15049
|
+
result: { ok: true, value: { ...value, namespaces: [] } }
|
|
15050
|
+
};
|
|
15051
|
+
const namespaces = Array.isArray(value.namespaces) ? value.namespaces : [];
|
|
15052
|
+
response.result.value.namespaces = namespaces.map((namespace) => {
|
|
15053
|
+
if (!isRecord2(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE) return namespace;
|
|
15054
|
+
const current = isRecord2(namespace.value) ? namespace.value : {};
|
|
15055
|
+
return { ...namespace, value: { ...current, [WELCOME_NOTICE_FIELD]: WELCOME_NOTICE_VERSION } };
|
|
15056
|
+
});
|
|
15057
|
+
return response;
|
|
15058
|
+
}
|
|
14996
15059
|
function isRemoteDisconnect(error) {
|
|
14997
15060
|
return error instanceof RemoteClientError && (error.code === "TRANSPORT_CLOSED" || error.code === "CLIENT_CLOSED");
|
|
14998
15061
|
}
|
|
@@ -15022,7 +15085,7 @@ var AsyncFrameQueue = class {
|
|
|
15022
15085
|
continue;
|
|
15023
15086
|
}
|
|
15024
15087
|
if (this.closed) return;
|
|
15025
|
-
const next = await new Promise((
|
|
15088
|
+
const next = await new Promise((resolve4) => this.waiters.push(resolve4));
|
|
15026
15089
|
if (next.done) return;
|
|
15027
15090
|
yield next.value;
|
|
15028
15091
|
}
|
|
@@ -15087,15 +15150,15 @@ function normalizeRecords(value) {
|
|
|
15087
15150
|
if (!Array.isArray(value)) return value;
|
|
15088
15151
|
const records = [];
|
|
15089
15152
|
let previousSeq;
|
|
15090
|
-
for (const
|
|
15091
|
-
if (!isEventEntry(
|
|
15092
|
-
const seq = entrySeq(
|
|
15153
|
+
for (const record7 of value) {
|
|
15154
|
+
if (!isEventEntry(record7)) continue;
|
|
15155
|
+
const seq = entrySeq(record7);
|
|
15093
15156
|
if (previousSeq !== void 0 && seq !== void 0 && seq > previousSeq + 1) {
|
|
15094
15157
|
for (let fillerSeq = previousSeq + 1; fillerSeq < seq; fillerSeq += 1) {
|
|
15095
|
-
records.push(createLegacyGapRecord(fillerSeq,
|
|
15158
|
+
records.push(createLegacyGapRecord(fillerSeq, record7));
|
|
15096
15159
|
}
|
|
15097
15160
|
}
|
|
15098
|
-
records.push(normalizeEntry(
|
|
15161
|
+
records.push(normalizeEntry(record7));
|
|
15099
15162
|
if (seq !== void 0) previousSeq = seq;
|
|
15100
15163
|
}
|
|
15101
15164
|
return records;
|
|
@@ -15219,10 +15282,14 @@ function isEventSeq(value) {
|
|
|
15219
15282
|
|
|
15220
15283
|
// src/remote-typert-gateway.ts
|
|
15221
15284
|
var DIRECT_REMOTE_CALL_BYTES2 = 2 * 1024 * 1024;
|
|
15285
|
+
var WELCOME_NOTICE_NAMESPACE2 = "ui-settings-general";
|
|
15286
|
+
var WELCOME_NOTICE_FIELD2 = "welcomeNoticeVersion";
|
|
15287
|
+
var WELCOME_NOTICE_VERSION2 = "2026-08-13.1";
|
|
15222
15288
|
var RemoteTypertGateway2 = class {
|
|
15223
|
-
constructor(client, compatibility) {
|
|
15289
|
+
constructor(client, compatibility, harnessVersion) {
|
|
15224
15290
|
this.client = client;
|
|
15225
15291
|
this.compatibility = compatibility;
|
|
15292
|
+
this.harnessVersion = harnessVersion;
|
|
15226
15293
|
}
|
|
15227
15294
|
async invoke(request) {
|
|
15228
15295
|
const result = await this.dispatch(
|
|
@@ -15248,11 +15315,29 @@ var RemoteTypertGateway2 = class {
|
|
|
15248
15315
|
}
|
|
15249
15316
|
}
|
|
15250
15317
|
const result = parseRpcResult(response);
|
|
15318
|
+
const settingsResult = this.normalizeLegacyWelcomeSettings(endpoint, payload, result);
|
|
15319
|
+
if (settingsResult !== void 0) return settingsResult;
|
|
15251
15320
|
if (result.ok && this.compatibility === "legacy-to-v3") {
|
|
15252
15321
|
return { ...result, value: normalizeLegacySessionGatewayValue(endpoint, result.value) };
|
|
15253
15322
|
}
|
|
15254
15323
|
return result;
|
|
15255
15324
|
}
|
|
15325
|
+
legacyWelcomeAcknowledged = false;
|
|
15326
|
+
settingsDescribeValue;
|
|
15327
|
+
/** DSH <=0.1.6 cannot persist the 0.1.7 welcome acknowledgement remotely. */
|
|
15328
|
+
normalizeLegacyWelcomeSettings(endpoint, payload, result) {
|
|
15329
|
+
if (!isLegacyRemoteHost2(this.harnessVersion)) return void 0;
|
|
15330
|
+
if (endpoint === "settings/describe" && result.ok && isRecord4(result.value)) {
|
|
15331
|
+
this.settingsDescribeValue = result.value;
|
|
15332
|
+
return this.legacyWelcomeAcknowledged ? { ...result, value: patchWelcomeDescribe2(result.value) } : void 0;
|
|
15333
|
+
}
|
|
15334
|
+
if (endpoint !== "settings/mutate" || !isRecord4(payload) || !isRecord4(payload.args)) return void 0;
|
|
15335
|
+
const args = payload.args;
|
|
15336
|
+
if (args.ns !== WELCOME_NOTICE_NAMESPACE2 || !isWelcomeNoticeOperation(args.ops)) return void 0;
|
|
15337
|
+
const value = patchWelcomeDescribe2(this.settingsDescribeValue ?? { namespaces: [] });
|
|
15338
|
+
this.legacyWelcomeAcknowledged = true;
|
|
15339
|
+
return { ok: true, value };
|
|
15340
|
+
}
|
|
15256
15341
|
async open(endpoint, payload, signal) {
|
|
15257
15342
|
const streamId = uuidV7();
|
|
15258
15343
|
const queue = new AsyncValueQueue();
|
|
@@ -15387,7 +15472,7 @@ var AsyncValueQueue = class {
|
|
|
15387
15472
|
if (this.error !== void 0) throw this.error;
|
|
15388
15473
|
return;
|
|
15389
15474
|
}
|
|
15390
|
-
const next = await new Promise((
|
|
15475
|
+
const next = await new Promise((resolve4) => this.waiters.push(resolve4));
|
|
15391
15476
|
if (next.done) {
|
|
15392
15477
|
if (this.error !== void 0) throw this.error;
|
|
15393
15478
|
return;
|
|
@@ -15459,6 +15544,24 @@ function isRecord4(value) {
|
|
|
15459
15544
|
function hasErrorCode(error, code) {
|
|
15460
15545
|
return error instanceof Error && "code" in error && error.code === code;
|
|
15461
15546
|
}
|
|
15547
|
+
function isLegacyRemoteHost2(version) {
|
|
15548
|
+
if (version === void 0) return false;
|
|
15549
|
+
const match = /^(?:dsh-)?v?(\d+)\.(\d+)\.(\d+)(?:-|$)/u.exec(version.trim());
|
|
15550
|
+
if (match === null) return false;
|
|
15551
|
+
return Number(match[1]) === 0 && Number(match[2]) === 1 && Number(match[3]) < 7;
|
|
15552
|
+
}
|
|
15553
|
+
function isWelcomeNoticeOperation(value) {
|
|
15554
|
+
return Array.isArray(value) && value.some((operation) => isRecord4(operation) && operation.op === "set" && Array.isArray(operation.path) && operation.path.length === 1 && operation.path[0] === WELCOME_NOTICE_FIELD2 && operation.value === WELCOME_NOTICE_VERSION2);
|
|
15555
|
+
}
|
|
15556
|
+
function patchWelcomeDescribe2(value) {
|
|
15557
|
+
if (!Array.isArray(value.namespaces)) return value;
|
|
15558
|
+
const namespaces = value.namespaces.map((namespace) => {
|
|
15559
|
+
if (!isRecord4(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE2) return namespace;
|
|
15560
|
+
const current = isRecord4(namespace.value) ? namespace.value : {};
|
|
15561
|
+
return { ...namespace, value: { ...current, [WELCOME_NOTICE_FIELD2]: WELCOME_NOTICE_VERSION2 } };
|
|
15562
|
+
});
|
|
15563
|
+
return { ...value, namespaces };
|
|
15564
|
+
}
|
|
15462
15565
|
|
|
15463
15566
|
// src/codex/permissions.ts
|
|
15464
15567
|
function codexPermissionPresetFromResponse(value) {
|
|
@@ -15479,6 +15582,232 @@ function record(value) {
|
|
|
15479
15582
|
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : {};
|
|
15480
15583
|
}
|
|
15481
15584
|
|
|
15585
|
+
// src/codex/codex-image-codec.ts
|
|
15586
|
+
var CODEX_IMAGE_MEDIA_TYPES2 = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp", "image/gif"]);
|
|
15587
|
+
var CODEX_IMAGE_ATTACHMENT_PREFIX = "codex-image:";
|
|
15588
|
+
var MAX_CODEX_IMAGE_BASE64 = 288 * 1024 * 1024;
|
|
15589
|
+
var DATA_IMAGE_URL2 = /^data:(image\/(?:png|jpeg|webp|gif));base64,([A-Za-z0-9+/]+={0,2})$/u;
|
|
15590
|
+
function string(value) {
|
|
15591
|
+
return typeof value === "string" ? value : void 0;
|
|
15592
|
+
}
|
|
15593
|
+
function isRecord5(value) {
|
|
15594
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
15595
|
+
}
|
|
15596
|
+
function record2(value) {
|
|
15597
|
+
return isRecord5(value) ? value : {};
|
|
15598
|
+
}
|
|
15599
|
+
function toolOutputImageBlocks(item) {
|
|
15600
|
+
const candidates = [
|
|
15601
|
+
record2(item.result).content,
|
|
15602
|
+
record2(item.output).content,
|
|
15603
|
+
item.contentItems,
|
|
15604
|
+
Array.isArray(item.output) ? item.output : void 0
|
|
15605
|
+
];
|
|
15606
|
+
for (const candidate of candidates) {
|
|
15607
|
+
if (!Array.isArray(candidate)) continue;
|
|
15608
|
+
const images = candidate.flatMap((value) => {
|
|
15609
|
+
const block = record2(value);
|
|
15610
|
+
return isImageContent2(block) && parseImageBlock(block) !== void 0 ? [block] : [];
|
|
15611
|
+
});
|
|
15612
|
+
if (images.length > 0) return images;
|
|
15613
|
+
}
|
|
15614
|
+
return [];
|
|
15615
|
+
}
|
|
15616
|
+
function contentBlocks(value, attachmentSeed) {
|
|
15617
|
+
if (typeof value === "string") return [{ type: "text", text: value }];
|
|
15618
|
+
if (!Array.isArray(value)) return [];
|
|
15619
|
+
const blocks = [];
|
|
15620
|
+
let imageIndex = 0;
|
|
15621
|
+
for (const raw of value) {
|
|
15622
|
+
if (typeof raw === "string") {
|
|
15623
|
+
blocks.push({ type: "text", text: raw });
|
|
15624
|
+
continue;
|
|
15625
|
+
}
|
|
15626
|
+
const block = record2(raw);
|
|
15627
|
+
const image = imageContentBlock(block, attachmentSeed, imageIndex);
|
|
15628
|
+
if (image !== void 0) {
|
|
15629
|
+
imageIndex += 1;
|
|
15630
|
+
blocks.push(image);
|
|
15631
|
+
continue;
|
|
15632
|
+
}
|
|
15633
|
+
const text = string(block.text) ?? string(block.content);
|
|
15634
|
+
if (text !== void 0) blocks.push({ type: block.type === "reasoning" ? "reasoning" : "text", text });
|
|
15635
|
+
}
|
|
15636
|
+
return blocks;
|
|
15637
|
+
}
|
|
15638
|
+
function imageContentBlock(block, attachmentSeed, index) {
|
|
15639
|
+
if (!isImageContent2(block)) return void 0;
|
|
15640
|
+
const image = parseImageBlock(block);
|
|
15641
|
+
if (image === void 0) return void 0;
|
|
15642
|
+
const dimensions = imageDimensions(image.mediaType, image.data);
|
|
15643
|
+
const name2 = string(block.name);
|
|
15644
|
+
const attachment = {
|
|
15645
|
+
attachmentId: `${CODEX_IMAGE_ATTACHMENT_PREFIX}${hashString(`${attachmentSeed}:${index}`)}:${index}`,
|
|
15646
|
+
mediaType: image.mediaType,
|
|
15647
|
+
bytes: base64ByteLength(image.data),
|
|
15648
|
+
width: dimensions.width,
|
|
15649
|
+
height: dimensions.height,
|
|
15650
|
+
...name2 === void 0 ? {} : { name: name2 }
|
|
15651
|
+
};
|
|
15652
|
+
return {
|
|
15653
|
+
type: "image",
|
|
15654
|
+
attachment,
|
|
15655
|
+
mediaType: image.mediaType,
|
|
15656
|
+
data: image.data,
|
|
15657
|
+
url: image.url,
|
|
15658
|
+
...name2 === void 0 ? {} : { name: name2 }
|
|
15659
|
+
};
|
|
15660
|
+
}
|
|
15661
|
+
function isImageContent2(block) {
|
|
15662
|
+
return block.type === "image" || block.type === "input_image";
|
|
15663
|
+
}
|
|
15664
|
+
function parseImageBlock(block) {
|
|
15665
|
+
const url = string(block.url) ?? string(block.image_url) ?? string(record2(block.image_url).url);
|
|
15666
|
+
const parsed = url === void 0 ? void 0 : parseDataImageUrl2(url);
|
|
15667
|
+
if (parsed !== void 0) return parsed;
|
|
15668
|
+
const data2 = string(block.data);
|
|
15669
|
+
if (data2 === void 0 || !isCanonicalBase642(data2)) return void 0;
|
|
15670
|
+
if (data2.length > MAX_CODEX_IMAGE_BASE64) return void 0;
|
|
15671
|
+
const mediaType = string(block.mediaType) ?? string(block.mimeType) ?? sniffImageMediaType2(data2);
|
|
15672
|
+
return mediaType !== void 0 && CODEX_IMAGE_MEDIA_TYPES2.has(mediaType) ? { mediaType, data: data2, url: `data:${mediaType};base64,${data2}` } : void 0;
|
|
15673
|
+
}
|
|
15674
|
+
function parseDataImageUrl2(value) {
|
|
15675
|
+
const match = DATA_IMAGE_URL2.exec(value);
|
|
15676
|
+
if (match === null) return void 0;
|
|
15677
|
+
const mediaType = match[1];
|
|
15678
|
+
const data2 = match[2];
|
|
15679
|
+
if (!CODEX_IMAGE_MEDIA_TYPES2.has(mediaType) || !isCanonicalBase642(data2)) return void 0;
|
|
15680
|
+
return { mediaType, data: data2, url: `data:${mediaType};base64,${data2}` };
|
|
15681
|
+
}
|
|
15682
|
+
function collectImageBlocks(value, output = []) {
|
|
15683
|
+
if (Array.isArray(value)) {
|
|
15684
|
+
for (const item of value) collectImageBlocks(item, output);
|
|
15685
|
+
return output;
|
|
15686
|
+
}
|
|
15687
|
+
if (!isRecord5(value)) return output;
|
|
15688
|
+
if (value.type === "image") output.push(value);
|
|
15689
|
+
for (const [key, child] of Object.entries(value)) {
|
|
15690
|
+
if (key === "attachment") continue;
|
|
15691
|
+
if (key === "content" || key === "message" || key === "inserted" || key === "chunk" || key === "block") {
|
|
15692
|
+
collectImageBlocks(child, output);
|
|
15693
|
+
}
|
|
15694
|
+
}
|
|
15695
|
+
return output;
|
|
15696
|
+
}
|
|
15697
|
+
function base64ByteLength(value) {
|
|
15698
|
+
const padding = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0;
|
|
15699
|
+
return Math.max(1, Math.floor(value.length * 3 / 4) - padding);
|
|
15700
|
+
}
|
|
15701
|
+
function imageDimensions(mediaType, data2) {
|
|
15702
|
+
const bytes = base64PrefixBytes2(data2, 256 * 1024);
|
|
15703
|
+
const parsed = mediaType === "image/png" ? pngDimensions(bytes) : mediaType === "image/jpeg" ? jpegDimensions(bytes) : mediaType === "image/gif" ? gifDimensions(bytes) : mediaType === "image/webp" ? webpDimensions(bytes) : void 0;
|
|
15704
|
+
return parsed ?? { width: 1, height: 1 };
|
|
15705
|
+
}
|
|
15706
|
+
function pngDimensions(bytes) {
|
|
15707
|
+
if (bytes.length < 24 || bytes[0] !== 137 || bytes[1] !== 80 || bytes[2] !== 78 || bytes[3] !== 71 || bytes[4] !== 13 || bytes[5] !== 10 || bytes[6] !== 26 || bytes[7] !== 10) return void 0;
|
|
15708
|
+
return positiveDimensions(readUint32BE(bytes, 16), readUint32BE(bytes, 20));
|
|
15709
|
+
}
|
|
15710
|
+
function jpegDimensions(bytes) {
|
|
15711
|
+
if (bytes.length < 4 || bytes[0] !== 255 || bytes[1] !== 216) return void 0;
|
|
15712
|
+
let offset = 2;
|
|
15713
|
+
while (offset + 9 < bytes.length) {
|
|
15714
|
+
if (bytes[offset] !== 255) {
|
|
15715
|
+
offset += 1;
|
|
15716
|
+
continue;
|
|
15717
|
+
}
|
|
15718
|
+
const marker = bytes[offset + 1];
|
|
15719
|
+
offset += 2;
|
|
15720
|
+
if (marker === 216 || marker === 217) continue;
|
|
15721
|
+
if (offset + 2 > bytes.length) return void 0;
|
|
15722
|
+
const length = readUint16BE(bytes, offset);
|
|
15723
|
+
if (length < 2 || offset + length > bytes.length) return void 0;
|
|
15724
|
+
if (isJpegSof(marker) && length >= 7) {
|
|
15725
|
+
return positiveDimensions(readUint16BE(bytes, offset + 5), readUint16BE(bytes, offset + 3));
|
|
15726
|
+
}
|
|
15727
|
+
offset += length;
|
|
15728
|
+
}
|
|
15729
|
+
return void 0;
|
|
15730
|
+
}
|
|
15731
|
+
function gifDimensions(bytes) {
|
|
15732
|
+
if (bytes.length < 10 || bytes[0] !== 71 || bytes[1] !== 73 || bytes[2] !== 70 || bytes[3] !== 56 || bytes[4] !== 55 && bytes[4] !== 57 || bytes[5] !== 97) return void 0;
|
|
15733
|
+
return positiveDimensions(readUint16LE(bytes, 6), readUint16LE(bytes, 8));
|
|
15734
|
+
}
|
|
15735
|
+
function webpDimensions(bytes) {
|
|
15736
|
+
if (bytes.length < 30 || stringFromBytes(bytes, 0, 4) !== "RIFF" || stringFromBytes(bytes, 8, 12) !== "WEBP") return void 0;
|
|
15737
|
+
const chunk = stringFromBytes(bytes, 12, 16);
|
|
15738
|
+
if (chunk === "VP8X") {
|
|
15739
|
+
return positiveDimensions(1 + readUint24LE(bytes, 24), 1 + readUint24LE(bytes, 27));
|
|
15740
|
+
}
|
|
15741
|
+
if (chunk === "VP8L" && bytes[20] === 47) {
|
|
15742
|
+
const b0 = bytes[21];
|
|
15743
|
+
const b1 = bytes[22];
|
|
15744
|
+
const b2 = bytes[23];
|
|
15745
|
+
const b3 = bytes[24];
|
|
15746
|
+
const width = 1 + b0 + ((b1 & 63) << 8);
|
|
15747
|
+
const height = 1 + ((b1 & 192) >> 6) + (b2 << 2) + ((b3 & 15) << 10);
|
|
15748
|
+
return positiveDimensions(width, height);
|
|
15749
|
+
}
|
|
15750
|
+
if (chunk === "VP8 " && bytes[23] === 157 && bytes[24] === 1 && bytes[25] === 42) {
|
|
15751
|
+
return positiveDimensions(readUint16LE(bytes, 26) & 16383, readUint16LE(bytes, 28) & 16383);
|
|
15752
|
+
}
|
|
15753
|
+
return void 0;
|
|
15754
|
+
}
|
|
15755
|
+
function sniffImageMediaType2(data2) {
|
|
15756
|
+
const bytes = base64PrefixBytes2(data2, 32);
|
|
15757
|
+
if (pngDimensions(bytes) !== void 0) return "image/png";
|
|
15758
|
+
if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return "image/jpeg";
|
|
15759
|
+
if (gifDimensions(bytes) !== void 0) return "image/gif";
|
|
15760
|
+
if (bytes.length >= 12 && stringFromBytes(bytes, 0, 4) === "RIFF" && stringFromBytes(bytes, 8, 12) === "WEBP") return "image/webp";
|
|
15761
|
+
return void 0;
|
|
15762
|
+
}
|
|
15763
|
+
function base64PrefixBytes2(value, maxBytes) {
|
|
15764
|
+
const chars = value.slice(0, Math.ceil(maxBytes / 3) * 4);
|
|
15765
|
+
let binary;
|
|
15766
|
+
try {
|
|
15767
|
+
binary = atob(chars);
|
|
15768
|
+
} catch {
|
|
15769
|
+
return new Uint8Array();
|
|
15770
|
+
}
|
|
15771
|
+
const bytes = new Uint8Array(Math.min(binary.length, maxBytes));
|
|
15772
|
+
for (let index = 0; index < bytes.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
15773
|
+
return bytes;
|
|
15774
|
+
}
|
|
15775
|
+
function readUint16BE(bytes, offset) {
|
|
15776
|
+
return (bytes[offset] << 8) + bytes[offset + 1];
|
|
15777
|
+
}
|
|
15778
|
+
function readUint16LE(bytes, offset) {
|
|
15779
|
+
return bytes[offset] + (bytes[offset + 1] << 8);
|
|
15780
|
+
}
|
|
15781
|
+
function readUint24LE(bytes, offset) {
|
|
15782
|
+
return bytes[offset] + (bytes[offset + 1] << 8) + (bytes[offset + 2] << 16);
|
|
15783
|
+
}
|
|
15784
|
+
function readUint32BE(bytes, offset) {
|
|
15785
|
+
return bytes[offset] * 16777216 + bytes[offset + 1] * 65536 + bytes[offset + 2] * 256 + bytes[offset + 3];
|
|
15786
|
+
}
|
|
15787
|
+
function positiveDimensions(width, height) {
|
|
15788
|
+
return width > 0 && height > 0 ? { width, height } : void 0;
|
|
15789
|
+
}
|
|
15790
|
+
function isJpegSof(marker) {
|
|
15791
|
+
return marker >= 192 && marker <= 195 || marker >= 197 && marker <= 199 || marker >= 201 && marker <= 203 || marker >= 205 && marker <= 207;
|
|
15792
|
+
}
|
|
15793
|
+
function stringFromBytes(bytes, start, end) {
|
|
15794
|
+
if (bytes.length < end) return "";
|
|
15795
|
+
let output = "";
|
|
15796
|
+
for (let index = start; index < end; index += 1) output += String.fromCharCode(bytes[index]);
|
|
15797
|
+
return output;
|
|
15798
|
+
}
|
|
15799
|
+
function isCanonicalBase642(value) {
|
|
15800
|
+
return value.length >= 4 && value.length % 4 === 0 && /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value);
|
|
15801
|
+
}
|
|
15802
|
+
function hashString(value) {
|
|
15803
|
+
let hash = 2166136261;
|
|
15804
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
15805
|
+
hash ^= value.charCodeAt(index);
|
|
15806
|
+
hash = Math.imul(hash, 16777619);
|
|
15807
|
+
}
|
|
15808
|
+
return (hash >>> 0).toString(16).padStart(8, "0");
|
|
15809
|
+
}
|
|
15810
|
+
|
|
15482
15811
|
// src/codex/virtual-harness.ts
|
|
15483
15812
|
var CODEX_SESSION_PREFIX = "codex:";
|
|
15484
15813
|
var CODEX_WORKSPACE_PREFIX = "codex-workspace:";
|
|
@@ -15493,10 +15822,32 @@ var SESSION_SEARCH_SNIPPET_CODE_POINTS = 240;
|
|
|
15493
15822
|
var CODEX_DEFAULT_PERMISSION = "workspace-write";
|
|
15494
15823
|
var MAX_CODEX_PROMPT_PARTS = 16;
|
|
15495
15824
|
var MAX_CODEX_PROMPT_TEXT = 256 * 1024;
|
|
15496
|
-
var
|
|
15497
|
-
var
|
|
15498
|
-
var
|
|
15499
|
-
var
|
|
15825
|
+
var MAX_CODEX_IMAGE_BASE642 = 288 * 1024 * 1024;
|
|
15826
|
+
var CODEX_IMAGE_MEDIA_TYPES3 = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp", "image/gif"]);
|
|
15827
|
+
var CODEX_IMAGE_ATTACHMENT_PREFIX2 = "codex-image:";
|
|
15828
|
+
var HOST_WORKSPACE_ENDPOINTS = /* @__PURE__ */ new Set([
|
|
15829
|
+
"workspaceFiles/list",
|
|
15830
|
+
"workspaceFiles/stat",
|
|
15831
|
+
"workspaceFiles/read",
|
|
15832
|
+
"workspaceFiles/readBytes",
|
|
15833
|
+
"workspaceFiles/readAll",
|
|
15834
|
+
"workspaceFiles/readRelated",
|
|
15835
|
+
"terminal/environment",
|
|
15836
|
+
"terminal/shells",
|
|
15837
|
+
"terminal/list",
|
|
15838
|
+
"terminal/create",
|
|
15839
|
+
"terminal/write",
|
|
15840
|
+
"terminal/resize",
|
|
15841
|
+
"terminal/rename",
|
|
15842
|
+
"terminal/close"
|
|
15843
|
+
]);
|
|
15844
|
+
var HOST_WORKSPACE_STREAM_ENDPOINTS = /* @__PURE__ */ new Set(["workspaceFiles/changes", "terminal/follow", "terminal/retain"]);
|
|
15845
|
+
function isHostWorkspaceEndpoint(endpoint) {
|
|
15846
|
+
return HOST_WORKSPACE_ENDPOINTS.has(endpoint);
|
|
15847
|
+
}
|
|
15848
|
+
function isHostWorkspaceStreamEndpoint(endpoint) {
|
|
15849
|
+
return HOST_WORKSPACE_STREAM_ENDPOINTS.has(endpoint);
|
|
15850
|
+
}
|
|
15500
15851
|
function codexProjectWorkspaceId(projectId) {
|
|
15501
15852
|
return `${CODEX_WORKSPACE_PREFIX}project:${projectId}`;
|
|
15502
15853
|
}
|
|
@@ -15504,10 +15855,11 @@ async function discoverCodexVirtualWorkspaces(client, signal) {
|
|
|
15504
15855
|
return (await loadCatalog(client, signal)).workspaces;
|
|
15505
15856
|
}
|
|
15506
15857
|
var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
15507
|
-
constructor(client, host, sessionGeneration = "legacy") {
|
|
15858
|
+
constructor(client, host, sessionGeneration = "legacy", hostCarrier) {
|
|
15508
15859
|
this.client = client;
|
|
15509
15860
|
this.host = host;
|
|
15510
15861
|
this.sessionGeneration = sessionGeneration;
|
|
15862
|
+
this.hostCarrier = hostCarrier;
|
|
15511
15863
|
this.api = this.createApiProxy();
|
|
15512
15864
|
}
|
|
15513
15865
|
api;
|
|
@@ -15531,8 +15883,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15531
15883
|
commandSeq = 0;
|
|
15532
15884
|
selectedWorkspaceId;
|
|
15533
15885
|
closed = false;
|
|
15534
|
-
static remote(core, host, sessionGeneration = "legacy") {
|
|
15535
|
-
return new _CodexVirtualHarness(new CodexRemoteClient(core), host, sessionGeneration);
|
|
15886
|
+
static remote(core, host, sessionGeneration = "legacy", hostCarrier) {
|
|
15887
|
+
return new _CodexVirtualHarness(new CodexRemoteClient(core), host, sessionGeneration, hostCarrier);
|
|
15536
15888
|
}
|
|
15537
15889
|
async workspaces(signal) {
|
|
15538
15890
|
return (await this.refreshCatalog(signal)).workspaces;
|
|
@@ -15579,6 +15931,10 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15579
15931
|
}
|
|
15580
15932
|
async dispatch(endpoint, payload, signal) {
|
|
15581
15933
|
try {
|
|
15934
|
+
if (isHostWorkspaceEndpoint(endpoint)) {
|
|
15935
|
+
if (this.hostCarrier === void 0) return fail("method-not-found", `CodeX virtual Harness does not implement ${endpoint}.`);
|
|
15936
|
+
return await this.hostCarrier.dispatch(endpoint, payload, signal);
|
|
15937
|
+
}
|
|
15582
15938
|
const args = carrierArgs(payload);
|
|
15583
15939
|
switch (endpoint) {
|
|
15584
15940
|
case "$events/result":
|
|
@@ -15665,6 +16021,16 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15665
16021
|
}
|
|
15666
16022
|
}
|
|
15667
16023
|
async open(endpoint, payload, signal) {
|
|
16024
|
+
if (isHostWorkspaceStreamEndpoint(endpoint)) {
|
|
16025
|
+
if (this.hostCarrier === void 0) {
|
|
16026
|
+
throw Object.assign(new Error(`CodeX virtual Harness does not implement stream ${endpoint}.`), {
|
|
16027
|
+
isDSHRemoteError: true,
|
|
16028
|
+
code: "method-not-found",
|
|
16029
|
+
details: {}
|
|
16030
|
+
});
|
|
16031
|
+
}
|
|
16032
|
+
return this.hostCarrier.open(endpoint, payload, signal);
|
|
16033
|
+
}
|
|
15668
16034
|
const args = carrierArgs(payload);
|
|
15669
16035
|
if (endpoint === "workspace/follow") return this.workspaceFollow(signal);
|
|
15670
16036
|
if (endpoint === "session/control") return this.sessionControl(signal);
|
|
@@ -15783,7 +16149,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15783
16149
|
nativeThreadId(sessionId);
|
|
15784
16150
|
const provider = requiredString(request.provider, "provider");
|
|
15785
16151
|
const model = requiredString(request.model, "model");
|
|
15786
|
-
const reasoningEffort =
|
|
16152
|
+
const reasoningEffort = string2(request.reasoningEffort);
|
|
15787
16153
|
const directory = await this.models(signal);
|
|
15788
16154
|
const available = directory.models.get(model);
|
|
15789
16155
|
if (provider !== CODEX_PROVIDER || available === void 0) {
|
|
@@ -15816,7 +16182,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15816
16182
|
const pending = this.pendingThreads.get(threadId);
|
|
15817
16183
|
if (pending !== void 0) this.pendingThreads.set(threadId, { ...pending, name: name2 });
|
|
15818
16184
|
if (this.catalog === void 0) return;
|
|
15819
|
-
const threads = this.catalog.threads.map((thread) =>
|
|
16185
|
+
const threads = this.catalog.threads.map((thread) => string2(thread.id) === threadId ? { ...thread, name: name2 } : thread);
|
|
15820
16186
|
const sessions = this.catalog.sessions.map((session) => {
|
|
15821
16187
|
if (session.nativeId !== threadId) return session;
|
|
15822
16188
|
const { title: _title, ...rest } = session;
|
|
@@ -15903,7 +16269,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15903
16269
|
return queue.iterate(() => this.eventStreams.delete(clientId));
|
|
15904
16270
|
}
|
|
15905
16271
|
async sessionFollow(request, signal) {
|
|
15906
|
-
const sessionId = sessionIdFromAddress(
|
|
16272
|
+
const sessionId = sessionIdFromAddress(record3(request.address));
|
|
15907
16273
|
const threadId = nativeThreadId(sessionId);
|
|
15908
16274
|
const history = await this.readHistoryPage(threadId, {
|
|
15909
16275
|
maxMessages: optionalPositiveInteger(request.maxMessages)
|
|
@@ -15968,9 +16334,9 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15968
16334
|
});
|
|
15969
16335
|
}
|
|
15970
16336
|
acceptCodexFrame(follow, frame) {
|
|
15971
|
-
const params =
|
|
16337
|
+
const params = record3(frame.params);
|
|
15972
16338
|
if (frame.method === "thread/name/updated") {
|
|
15973
|
-
const name2 =
|
|
16339
|
+
const name2 = string2(params.threadName);
|
|
15974
16340
|
if (name2 === void 0) return;
|
|
15975
16341
|
const seq = this.nextProjectionSeq();
|
|
15976
16342
|
this.updateThreadName(follow.threadId, name2);
|
|
@@ -15984,39 +16350,39 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
15984
16350
|
return;
|
|
15985
16351
|
}
|
|
15986
16352
|
if (frame.method === "turn/started") {
|
|
15987
|
-
const turn =
|
|
16353
|
+
const turn = record3(params.turn);
|
|
15988
16354
|
this.endAssistantAttempt(follow, { kind: "abandoned" });
|
|
15989
16355
|
this.resetLiveTurn(follow);
|
|
15990
16356
|
follow.turn += 1;
|
|
15991
|
-
follow.activeTurnId =
|
|
16357
|
+
follow.activeTurnId = string2(turn.id);
|
|
15992
16358
|
follow.requestId = this.pendingRequestIds.get(follow.sessionId);
|
|
15993
16359
|
follow.stepOpen = true;
|
|
15994
16360
|
this.pushEvent(follow, "turn/start", { turn: follow.turn });
|
|
15995
16361
|
this.pushEvent(follow, "step/start", { turn: follow.turn, step: 1 });
|
|
15996
16362
|
this.emitRemoteEvent("api-session/status", [follow.sessionId, true]);
|
|
15997
|
-
for (const item of array(turn.items)) this.acceptCompletedItem(follow,
|
|
16363
|
+
for (const item of array(turn.items)) this.acceptCompletedItem(follow, record3(item), false);
|
|
15998
16364
|
return;
|
|
15999
16365
|
}
|
|
16000
16366
|
if (frame.method === "item/started" || frame.method === "item/completed") {
|
|
16001
|
-
const item =
|
|
16002
|
-
const itemId =
|
|
16367
|
+
const item = record3(params.item);
|
|
16368
|
+
const itemId = string2(item.id);
|
|
16003
16369
|
if (frame.method === "item/started" && itemId !== void 0) {
|
|
16004
16370
|
follow.startedItems.add(itemId);
|
|
16005
16371
|
follow.liveItems.set(itemId, item);
|
|
16006
|
-
if (isToolItemType2(
|
|
16372
|
+
if (isToolItemType2(string2(item.type))) this.ensureToolStarted(follow, item);
|
|
16007
16373
|
}
|
|
16008
16374
|
if (frame.method === "item/completed") this.acceptCompletedItem(follow, item, true);
|
|
16009
16375
|
return;
|
|
16010
16376
|
}
|
|
16011
16377
|
if (frame.method === "item/agentMessage/delta") {
|
|
16012
|
-
const itemId =
|
|
16013
|
-
const delta =
|
|
16378
|
+
const itemId = string2(params.itemId) ?? `assistant:${follow.turn}`;
|
|
16379
|
+
const delta = string2(params.delta);
|
|
16014
16380
|
if (delta === void 0) return;
|
|
16015
16381
|
this.appendStreamDelta(follow, `agent:${itemId}`, itemId, "text", delta);
|
|
16016
16382
|
return;
|
|
16017
16383
|
}
|
|
16018
16384
|
if (frame.method === "item/reasoning/summaryPartAdded") {
|
|
16019
|
-
const itemId =
|
|
16385
|
+
const itemId = string2(params.itemId);
|
|
16020
16386
|
if (itemId !== void 0) this.ensureStreamBlock(
|
|
16021
16387
|
follow,
|
|
16022
16388
|
`reasoning-summary:${itemId}:${integer(params.summaryIndex) ?? 0}`,
|
|
@@ -16026,8 +16392,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16026
16392
|
return;
|
|
16027
16393
|
}
|
|
16028
16394
|
if (frame.method === "item/reasoning/summaryTextDelta" || frame.method === "item/reasoning/textDelta" || frame.method === "item/plan/delta") {
|
|
16029
|
-
const itemId =
|
|
16030
|
-
const delta =
|
|
16395
|
+
const itemId = string2(params.itemId);
|
|
16396
|
+
const delta = string2(params.delta);
|
|
16031
16397
|
if (itemId === void 0 || delta === void 0) return;
|
|
16032
16398
|
const key = frame.method === "item/plan/delta" ? `plan:${itemId}` : frame.method === "item/reasoning/summaryTextDelta" ? `reasoning-summary:${itemId}:${integer(params.summaryIndex) ?? 0}` : `reasoning-content:${itemId}:${integer(params.contentIndex) ?? 0}`;
|
|
16033
16399
|
this.appendStreamDelta(follow, key, itemId, "reasoning", delta);
|
|
@@ -16035,8 +16401,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16035
16401
|
}
|
|
16036
16402
|
if (frame.method === "turn/plan/updated") {
|
|
16037
16403
|
const todos = array(params.plan).flatMap((value) => {
|
|
16038
|
-
const item =
|
|
16039
|
-
const content =
|
|
16404
|
+
const item = record3(value);
|
|
16405
|
+
const content = string2(item.step);
|
|
16040
16406
|
if (content === void 0) return [];
|
|
16041
16407
|
const status2 = item.status === "inProgress" ? "in_progress" : item.status === "completed" ? "completed" : "pending";
|
|
16042
16408
|
return [{ content, status: status2 }];
|
|
@@ -16045,8 +16411,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16045
16411
|
return;
|
|
16046
16412
|
}
|
|
16047
16413
|
if (frame.method === "item/commandExecution/outputDelta" || frame.method === "item/fileChange/outputDelta" || frame.method === "item/mcpToolCall/progress") {
|
|
16048
|
-
const itemId =
|
|
16049
|
-
const delta = frame.method === "item/mcpToolCall/progress" ?
|
|
16414
|
+
const itemId = string2(params.itemId);
|
|
16415
|
+
const delta = frame.method === "item/mcpToolCall/progress" ? string2(params.message) : string2(params.delta);
|
|
16050
16416
|
if (itemId === void 0 || delta === void 0) return;
|
|
16051
16417
|
const type = frame.method === "item/commandExecution/outputDelta" ? "commandExecution" : frame.method === "item/fileChange/outputDelta" ? "fileChange" : "mcpToolCall";
|
|
16052
16418
|
const item = follow.liveItems.get(itemId) ?? { id: itemId, type, status: "inProgress" };
|
|
@@ -16059,7 +16425,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16059
16425
|
return;
|
|
16060
16426
|
}
|
|
16061
16427
|
if (frame.method === "item/fileChange/patchUpdated") {
|
|
16062
|
-
const itemId =
|
|
16428
|
+
const itemId = string2(params.itemId);
|
|
16063
16429
|
if (itemId === void 0) return;
|
|
16064
16430
|
const previous = follow.liveItems.get(itemId) ?? { id: itemId, type: "fileChange", status: "inProgress" };
|
|
16065
16431
|
const item = { ...previous, changes: sanitizedFileChanges(params.changes) };
|
|
@@ -16069,7 +16435,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16069
16435
|
return;
|
|
16070
16436
|
}
|
|
16071
16437
|
if (frame.method === "thread/status/changed") {
|
|
16072
|
-
const status2 =
|
|
16438
|
+
const status2 = record3(params.status);
|
|
16073
16439
|
const running = status2.type === "active";
|
|
16074
16440
|
this.emitRemoteEvent("api-session/status", [follow.sessionId, running]);
|
|
16075
16441
|
if (status2.type === "systemError") {
|
|
@@ -16082,7 +16448,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16082
16448
|
return;
|
|
16083
16449
|
}
|
|
16084
16450
|
if (frame.method === "model/rerouted") {
|
|
16085
|
-
const model =
|
|
16451
|
+
const model = string2(params.toModel);
|
|
16086
16452
|
if (model === void 0) return;
|
|
16087
16453
|
const previous = this.selectedModels.get(follow.sessionId);
|
|
16088
16454
|
const selected = {
|
|
@@ -16096,8 +16462,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16096
16462
|
return;
|
|
16097
16463
|
}
|
|
16098
16464
|
if (frame.method === "turn/completed") {
|
|
16099
|
-
const turn =
|
|
16100
|
-
for (const item of array(turn.items)) this.acceptCompletedItem(follow,
|
|
16465
|
+
const turn = record3(params.turn);
|
|
16466
|
+
for (const item of array(turn.items)) this.acceptCompletedItem(follow, record3(item), true);
|
|
16101
16467
|
if (follow.stepOpen) {
|
|
16102
16468
|
this.closeAllStreamBlocks(follow);
|
|
16103
16469
|
if (follow.streamActive) this.finishStream(follow);
|
|
@@ -16117,7 +16483,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16117
16483
|
return;
|
|
16118
16484
|
}
|
|
16119
16485
|
if (frame.method === "item/commandExecution/requestApproval" || frame.method === "item/fileChange/requestApproval") {
|
|
16120
|
-
const requestHandle =
|
|
16486
|
+
const requestHandle = string2(params.requestHandle);
|
|
16121
16487
|
if (requestHandle === void 0) return;
|
|
16122
16488
|
const command = commandText(params.command);
|
|
16123
16489
|
this.pendingApprovals.set(requestHandle, { requestHandle, sessionId: follow.sessionId });
|
|
@@ -16132,9 +16498,9 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16132
16498
|
}
|
|
16133
16499
|
}
|
|
16134
16500
|
acceptCompletedItem(follow, item, settleAssistant) {
|
|
16135
|
-
const itemId =
|
|
16501
|
+
const itemId = string2(item.id) ?? `item:${follow.nextSeq}`;
|
|
16136
16502
|
if (follow.completedItems.has(itemId)) return;
|
|
16137
|
-
const type =
|
|
16503
|
+
const type = string2(item.type);
|
|
16138
16504
|
if (type === "agentMessage" && !settleAssistant) return;
|
|
16139
16505
|
follow.completedItems.add(itemId);
|
|
16140
16506
|
this.closeItemStreamBlocks(follow, itemId, itemText2(item));
|
|
@@ -16181,7 +16547,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16181
16547
|
time: Date.now(),
|
|
16182
16548
|
data: adaptEventData(
|
|
16183
16549
|
type,
|
|
16184
|
-
type === "assistant/message" && this.sessionGeneration === "v3" && follow.assistantAttempt !== void 0 ? { ...
|
|
16550
|
+
type === "assistant/message" && this.sessionGeneration === "v3" && follow.assistantAttempt !== void 0 ? { ...record3(data2), stream: follow.assistantAttempt.stream } : data2,
|
|
16185
16551
|
this.sessionGeneration
|
|
16186
16552
|
),
|
|
16187
16553
|
...isSurfaceEvent(type) ? placement === void 0 ? { surfaceOp: "append" } : {
|
|
@@ -16207,10 +16573,10 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16207
16573
|
}
|
|
16208
16574
|
cacheImageBlocks(sessionId, value) {
|
|
16209
16575
|
for (const block of collectImageBlocks(value)) {
|
|
16210
|
-
const attachment =
|
|
16211
|
-
const attachmentId =
|
|
16212
|
-
const data2 =
|
|
16213
|
-
if (attachmentId === void 0 || data2 === void 0 || !attachmentId.startsWith(
|
|
16576
|
+
const attachment = record3(block.attachment);
|
|
16577
|
+
const attachmentId = string2(attachment.attachmentId);
|
|
16578
|
+
const data2 = string2(block.data);
|
|
16579
|
+
if (attachmentId === void 0 || data2 === void 0 || !attachmentId.startsWith(CODEX_IMAGE_ATTACHMENT_PREFIX2)) continue;
|
|
16214
16580
|
this.imageAttachments.set(attachmentId, { sessionId, attachment, data: data2 });
|
|
16215
16581
|
}
|
|
16216
16582
|
}
|
|
@@ -16320,7 +16686,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16320
16686
|
}
|
|
16321
16687
|
}
|
|
16322
16688
|
ensureToolStarted(follow, item) {
|
|
16323
|
-
const itemId =
|
|
16689
|
+
const itemId = string2(item.id);
|
|
16324
16690
|
if (itemId === void 0) return;
|
|
16325
16691
|
if (!follow.startedItems.has(itemId)) follow.startedItems.add(itemId);
|
|
16326
16692
|
if (follow.liveItems.get(itemId) !== item) follow.liveItems.set(itemId, item);
|
|
@@ -16338,7 +16704,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16338
16704
|
}
|
|
16339
16705
|
}
|
|
16340
16706
|
emitToolResult(follow, item, resultText) {
|
|
16341
|
-
const itemId =
|
|
16707
|
+
const itemId = string2(item.id);
|
|
16342
16708
|
if (itemId === void 0) return;
|
|
16343
16709
|
const result = toolResultEvent(item, follow.turn, 1, itemId, resultText);
|
|
16344
16710
|
this.pushToolResult(follow, itemId, result);
|
|
@@ -16374,7 +16740,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16374
16740
|
this.broadcastRcHost({ type: "host/session-status", sessionId, running: args[1] });
|
|
16375
16741
|
} else if (event === "api-session/removed" && sessionId !== void 0) {
|
|
16376
16742
|
this.broadcastRcHost({ type: "host/session-removed", sessionId });
|
|
16377
|
-
} else if (event === "api-session/added" &&
|
|
16743
|
+
} else if (event === "api-session/added" && isRecord6(args[0])) {
|
|
16378
16744
|
const summary = args[0];
|
|
16379
16745
|
this.broadcastRcHost({
|
|
16380
16746
|
type: "host/session-added",
|
|
@@ -16396,13 +16762,13 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16396
16762
|
type: "approval/requested",
|
|
16397
16763
|
sessionId: input2.agentId,
|
|
16398
16764
|
approvalId: input2.eventId,
|
|
16399
|
-
toolName:
|
|
16765
|
+
toolName: string2(input2.request.toolName) ?? "CodeX",
|
|
16400
16766
|
...typeof input2.request.reason === "string" ? { reason: input2.request.reason } : {}
|
|
16401
16767
|
}, input2.eventId);
|
|
16402
16768
|
}
|
|
16403
16769
|
async answerRemoteEvent(args, signal) {
|
|
16404
|
-
const eventId =
|
|
16405
|
-
const outcome =
|
|
16770
|
+
const eventId = string2(args.eventId);
|
|
16771
|
+
const outcome = record3(args.outcome);
|
|
16406
16772
|
if (eventId === void 0) throw new Error("The CodeX approval result is missing its event id.");
|
|
16407
16773
|
const pending = this.pendingApprovals.get(eventId);
|
|
16408
16774
|
if (pending === void 0) return void 0;
|
|
@@ -16412,7 +16778,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16412
16778
|
return void 0;
|
|
16413
16779
|
}
|
|
16414
16780
|
async createWorkspace(request, signal) {
|
|
16415
|
-
const path =
|
|
16781
|
+
const path = string2(request.path);
|
|
16416
16782
|
if (path === void 0 || path.trim() === "") return failure("bad-request", "A CodeX working directory is required.");
|
|
16417
16783
|
const catalog = await this.currentCatalog(signal);
|
|
16418
16784
|
const existing = catalog.workspaces.find((item) => item.path === path);
|
|
@@ -16420,10 +16786,10 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16420
16786
|
return failure("workspace-not-found", "The selected directory is not visible to CodeX Remote.");
|
|
16421
16787
|
}
|
|
16422
16788
|
async renameWorkspace(request) {
|
|
16423
|
-
return failure("workspace-read-only", `CodeX virtual Workspace ${
|
|
16789
|
+
return failure("workspace-read-only", `CodeX virtual Workspace ${string2(request.workspaceId) ?? ""} cannot be renamed.`);
|
|
16424
16790
|
}
|
|
16425
16791
|
async workspaceForSession(request, signal) {
|
|
16426
|
-
const sessionId =
|
|
16792
|
+
const sessionId = string2(request.sessionId);
|
|
16427
16793
|
const catalog = await this.currentCatalog(signal);
|
|
16428
16794
|
const workspace = catalog.workspaces.find((item) => sessionId !== void 0 && item.sessionIds.includes(sessionId));
|
|
16429
16795
|
return workspace === void 0 ? failure("workspace-not-found", "The CodeX virtual Workspace was not found.") : success({ workspace: nativeWorkspace(workspace) });
|
|
@@ -16449,11 +16815,11 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16449
16815
|
const catalog = await this.currentCatalog(signal);
|
|
16450
16816
|
const workspace = this.selectedWorkspace(catalog);
|
|
16451
16817
|
if (workspace === void 0) return failure("workspace-not-found", "The CodeX virtual Workspace was not found.");
|
|
16452
|
-
const path =
|
|
16818
|
+
const path = string2(request.path) ?? workspace.path;
|
|
16453
16819
|
if (!containsPath(workspace.path, path)) {
|
|
16454
16820
|
return failure("workspace-not-found", "The selected directory is outside the current CodeX virtual Workspace.");
|
|
16455
16821
|
}
|
|
16456
|
-
const listing =
|
|
16822
|
+
const listing = record3(await this.client.request("dsh/directoryList", { path }, signal));
|
|
16457
16823
|
if (!isCodexDirectoryListing(listing)) {
|
|
16458
16824
|
return failure("internal", "CodeX Remote returned an invalid directory listing.");
|
|
16459
16825
|
}
|
|
@@ -16477,9 +16843,9 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16477
16843
|
}
|
|
16478
16844
|
async createSession(request, signal) {
|
|
16479
16845
|
const catalog = await this.currentCatalog(signal);
|
|
16480
|
-
const workspaceId =
|
|
16846
|
+
const workspaceId = string2(request.workspaceId) ?? this.selectedWorkspaceId;
|
|
16481
16847
|
const workspace = workspaceId === void 0 ? void 0 : catalog.workspaces.find((item) => item.workspaceId === workspaceId);
|
|
16482
|
-
const cwd =
|
|
16848
|
+
const cwd = string2(request.cwd) ?? workspace?.path;
|
|
16483
16849
|
if (cwd === void 0) return failure("workspace-not-found", "The CodeX virtual Workspace was not found.");
|
|
16484
16850
|
if (workspace !== void 0 && !containsPath(workspace.path, cwd)) {
|
|
16485
16851
|
return failure("workspace-not-found", "The selected directory is outside the current CodeX virtual Workspace.");
|
|
@@ -16487,13 +16853,13 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16487
16853
|
const directory = await this.models(signal);
|
|
16488
16854
|
const selection = directory.default;
|
|
16489
16855
|
const requestedPreset = CODEX_DEFAULT_PERMISSION;
|
|
16490
|
-
const result =
|
|
16856
|
+
const result = record3(await this.client.request("thread/start", {
|
|
16491
16857
|
cwd,
|
|
16492
16858
|
model: selection.model,
|
|
16493
16859
|
permissionPreset: requestedPreset
|
|
16494
16860
|
}, signal));
|
|
16495
16861
|
const permissionPreset2 = codexPermissionPresetFromResponse(result) ?? requestedPreset;
|
|
16496
|
-
const thread = { ...
|
|
16862
|
+
const thread = { ...record3(result.thread), cwd, turns: array(record3(result.thread).turns) };
|
|
16497
16863
|
const projected = projectCodexThread(thread);
|
|
16498
16864
|
if (projected === void 0) return failure("internal", "CodeX returned an invalid Thread.");
|
|
16499
16865
|
this.pendingThreads.set(projected.nativeId, thread);
|
|
@@ -16513,11 +16879,11 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16513
16879
|
}
|
|
16514
16880
|
async forkSession(request, signal) {
|
|
16515
16881
|
const sessionId = requiredString(request.sessionId, "sessionId");
|
|
16516
|
-
const result =
|
|
16882
|
+
const result = record3(await this.client.request("thread/fork", {
|
|
16517
16883
|
threadId: nativeThreadId(sessionId)
|
|
16518
16884
|
}, signal));
|
|
16519
16885
|
const permissionPreset2 = codexPermissionPresetFromResponse(result);
|
|
16520
|
-
const projected = projectCodexThread(
|
|
16886
|
+
const projected = projectCodexThread(record3(result.thread));
|
|
16521
16887
|
if (projected === void 0) return failure("internal", "CodeX returned an invalid forked Thread.");
|
|
16522
16888
|
this.selectedModels.set(projected.id, this.modelSelection(sessionId, await this.models(signal)));
|
|
16523
16889
|
this.setPermissionSelection(projected.id, permissionPreset2);
|
|
@@ -16545,7 +16911,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16545
16911
|
this.setPermissionSelection(sessionId, serverPreset);
|
|
16546
16912
|
}
|
|
16547
16913
|
}
|
|
16548
|
-
this.pendingRequestIds.set(sessionId,
|
|
16914
|
+
this.pendingRequestIds.set(sessionId, string2(request.requestId) ?? "");
|
|
16549
16915
|
const mode = request.mode === "steer" ? "turn/steer" : "turn/start";
|
|
16550
16916
|
if (mode === "turn/steer") {
|
|
16551
16917
|
const active = this.activeTurnId(threadId);
|
|
@@ -16564,7 +16930,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16564
16930
|
async attachment(request, signal) {
|
|
16565
16931
|
const sessionId = requiredString(request.sessionId, "sessionId");
|
|
16566
16932
|
const attachmentId = requiredString(request.attachmentId, "attachmentId");
|
|
16567
|
-
if (!attachmentId.startsWith(
|
|
16933
|
+
if (!attachmentId.startsWith(CODEX_IMAGE_ATTACHMENT_PREFIX2)) {
|
|
16568
16934
|
return failure("attachment-error", "The CodeX image is not available in this virtual Session.", { reason: "not-referenced" });
|
|
16569
16935
|
}
|
|
16570
16936
|
nativeThreadId(sessionId);
|
|
@@ -16576,9 +16942,9 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16576
16942
|
}
|
|
16577
16943
|
async hydrateImageAttachments(sessionId, signal) {
|
|
16578
16944
|
const threadId = nativeThreadId(sessionId);
|
|
16579
|
-
const result =
|
|
16580
|
-
const thread =
|
|
16581
|
-
if (
|
|
16945
|
+
const result = record3(await this.client.request("thread/read", { threadId, includeTurns: true }, signal));
|
|
16946
|
+
const thread = record3(result.thread);
|
|
16947
|
+
if (string2(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
|
|
16582
16948
|
this.cacheHistoryImages(projectCodexNativeHistory(thread, sessionId));
|
|
16583
16949
|
}
|
|
16584
16950
|
async cancel(request, signal) {
|
|
@@ -16599,7 +16965,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16599
16965
|
return success({ title, seq });
|
|
16600
16966
|
}
|
|
16601
16967
|
async sessionPage(request, signal) {
|
|
16602
|
-
const sessionId = sessionIdFromAddress(
|
|
16968
|
+
const sessionId = sessionIdFromAddress(record3(request.address));
|
|
16603
16969
|
const page = await this.readHistoryPage(nativeThreadId(sessionId), {
|
|
16604
16970
|
beforeSeq: optionalNonNegativeInteger(request.beforeSeq),
|
|
16605
16971
|
throughSeq: optionalInteger(request.throughSeq),
|
|
@@ -16612,15 +16978,15 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16612
16978
|
return void 0;
|
|
16613
16979
|
}
|
|
16614
16980
|
async fetchThread(threadId, signal) {
|
|
16615
|
-
const result =
|
|
16616
|
-
const thread =
|
|
16617
|
-
if (
|
|
16981
|
+
const result = record3(await this.client.request("thread/read", { threadId, includeTurns: false }, signal));
|
|
16982
|
+
const thread = record3(result.thread);
|
|
16983
|
+
if (string2(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
|
|
16618
16984
|
return thread;
|
|
16619
16985
|
}
|
|
16620
16986
|
async readHistoryPage(threadId, page, signal) {
|
|
16621
16987
|
let value;
|
|
16622
16988
|
try {
|
|
16623
|
-
value =
|
|
16989
|
+
value = record3(await this.client.request("dsh/sessionHistory", {
|
|
16624
16990
|
threadId,
|
|
16625
16991
|
...page.beforeSeq === void 0 ? {} : { beforeSeq: page.beforeSeq },
|
|
16626
16992
|
...page.throughSeq === void 0 ? {} : { throughSeq: page.throughSeq },
|
|
@@ -16628,9 +16994,9 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16628
16994
|
}, signal));
|
|
16629
16995
|
} catch (error) {
|
|
16630
16996
|
if (!isLegacySessionHistoryUnsupported(error)) throw error;
|
|
16631
|
-
const result =
|
|
16632
|
-
const thread =
|
|
16633
|
-
if (
|
|
16997
|
+
const result = record3(await this.client.request("thread/read", { threadId, includeTurns: true }, signal));
|
|
16998
|
+
const thread = record3(result.thread);
|
|
16999
|
+
if (string2(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
|
|
16634
17000
|
value = paginateCodexNativeHistory(
|
|
16635
17001
|
projectCodexNativeHistory(thread, `codex:${threadId}`, this.sessionGeneration),
|
|
16636
17002
|
{
|
|
@@ -16759,7 +17125,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
|
|
|
16759
17125
|
}
|
|
16760
17126
|
createApiProxy() {
|
|
16761
17127
|
const call = (endpoint) => async (request, signal) => {
|
|
16762
|
-
const payload = endpoint === "session.prompt" &&
|
|
17128
|
+
const payload = endpoint === "session.prompt" && isRecord6(request.payload) ? { ...request.payload, requestId: String(request.rpcId) } : request.payload;
|
|
16763
17129
|
const result = await this.dispatch(rcEndpoint(endpoint), { args: { request: payload } }, signal ?? new AbortController().signal);
|
|
16764
17130
|
return {
|
|
16765
17131
|
rpcId: request.rpcId,
|
|
@@ -16856,7 +17222,7 @@ async function loadCatalog(client, signal, pendingThreads) {
|
|
|
16856
17222
|
const threads = [];
|
|
16857
17223
|
let cursor2;
|
|
16858
17224
|
for (let page = 0; page < MAX_CODEX_PAGES; page += 1) {
|
|
16859
|
-
const result =
|
|
17225
|
+
const result = record3(await client.request("thread/list", {
|
|
16860
17226
|
limit: CODEX_PAGE_LIMIT,
|
|
16861
17227
|
sortKey: "updated_at",
|
|
16862
17228
|
sortDirection: "desc",
|
|
@@ -16864,14 +17230,14 @@ async function loadCatalog(client, signal, pendingThreads) {
|
|
|
16864
17230
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
16865
17231
|
}, signal));
|
|
16866
17232
|
for (const value of array(result.data)) {
|
|
16867
|
-
const thread =
|
|
16868
|
-
if (
|
|
17233
|
+
const thread = record3(value);
|
|
17234
|
+
if (string2(thread.id) !== void 0) threads.push(thread);
|
|
16869
17235
|
}
|
|
16870
17236
|
cursor2 = typeof result.nextCursor === "string" && result.nextCursor.length > 0 ? result.nextCursor : void 0;
|
|
16871
17237
|
if (cursor2 === void 0) break;
|
|
16872
17238
|
}
|
|
16873
17239
|
if (pendingThreads !== void 0) {
|
|
16874
|
-
const listedIds = new Set(threads.map((thread) =>
|
|
17240
|
+
const listedIds = new Set(threads.map((thread) => string2(thread.id)).filter((id4) => id4 !== void 0));
|
|
16875
17241
|
for (const [threadId, thread] of pendingThreads) {
|
|
16876
17242
|
if (listedIds.has(threadId)) pendingThreads.delete(threadId);
|
|
16877
17243
|
else threads.unshift(thread);
|
|
@@ -16916,7 +17282,7 @@ async function loadCodexProjects(client, signal) {
|
|
|
16916
17282
|
let cursor2;
|
|
16917
17283
|
try {
|
|
16918
17284
|
for (let page = 0; page < MAX_CODEX_PAGES; page += 1) {
|
|
16919
|
-
const result =
|
|
17285
|
+
const result = record3(await client.request("project/list", {
|
|
16920
17286
|
limit: CODEX_PAGE_LIMIT,
|
|
16921
17287
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
16922
17288
|
}, signal));
|
|
@@ -16938,32 +17304,32 @@ async function loadModelDirectory(client, signal) {
|
|
|
16938
17304
|
let defaultModelId;
|
|
16939
17305
|
let cursor2;
|
|
16940
17306
|
for (let page = 0; page < MAX_CODEX_PAGES; page += 1) {
|
|
16941
|
-
const result =
|
|
17307
|
+
const result = record3(await client.request("model/list", {
|
|
16942
17308
|
limit: CODEX_PAGE_LIMIT,
|
|
16943
17309
|
includeHidden: false,
|
|
16944
17310
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
16945
17311
|
}, signal));
|
|
16946
17312
|
for (const value of array(result.data)) {
|
|
16947
|
-
const source =
|
|
17313
|
+
const source = record3(value);
|
|
16948
17314
|
if (source.hidden === true) continue;
|
|
16949
|
-
const id4 =
|
|
17315
|
+
const id4 = string2(source.model) ?? string2(source.id);
|
|
16950
17316
|
if (id4 === void 0 || models.has(id4)) continue;
|
|
16951
17317
|
const efforts = array(source.supportedReasoningEfforts).map((value2) => {
|
|
16952
|
-
const effort =
|
|
16953
|
-
const effortId =
|
|
17318
|
+
const effort = record3(value2);
|
|
17319
|
+
const effortId = string2(effort.reasoningEffort);
|
|
16954
17320
|
if (effortId === void 0) return void 0;
|
|
16955
|
-
const description2 =
|
|
17321
|
+
const description2 = string2(effort.description);
|
|
16956
17322
|
return {
|
|
16957
17323
|
id: effortId,
|
|
16958
17324
|
name: reasoningEffortName(effortId),
|
|
16959
17325
|
...description2 === void 0 ? {} : { description: description2 }
|
|
16960
17326
|
};
|
|
16961
17327
|
}).filter((value2) => value2 !== void 0);
|
|
16962
|
-
const defaultEffort2 =
|
|
16963
|
-
const description =
|
|
17328
|
+
const defaultEffort2 = string2(source.defaultReasoningEffort);
|
|
17329
|
+
const description = string2(source.description);
|
|
16964
17330
|
const model = {
|
|
16965
17331
|
id: id4,
|
|
16966
|
-
name:
|
|
17332
|
+
name: string2(source.displayName) ?? id4,
|
|
16967
17333
|
...description === void 0 ? {} : { description },
|
|
16968
17334
|
...efforts.length === 0 ? {} : {
|
|
16969
17335
|
reasoning: {
|
|
@@ -17013,8 +17379,8 @@ function projectCodexNativeHistory(thread, sessionId, sessionGeneration = "legac
|
|
|
17013
17379
|
return eventSeq;
|
|
17014
17380
|
};
|
|
17015
17381
|
for (const rawTurn of array(thread.turns)) {
|
|
17016
|
-
const turn =
|
|
17017
|
-
const turnItems = array(turn.items).map(
|
|
17382
|
+
const turn = record3(rawTurn);
|
|
17383
|
+
const turnItems = array(turn.items).map(record3);
|
|
17018
17384
|
const toolImages = turnItems.flatMap(toolOutputImageBlocks);
|
|
17019
17385
|
let imageOwner = -1;
|
|
17020
17386
|
for (let index = 0; index < turnItems.length; index += 1) {
|
|
@@ -17096,18 +17462,18 @@ function paginateCodexNativeHistory(history, request) {
|
|
|
17096
17462
|
}
|
|
17097
17463
|
function adaptEventData(type, data2, sessionGeneration) {
|
|
17098
17464
|
if (sessionGeneration !== "v3" || type !== "assistant/message") return data2;
|
|
17099
|
-
const value =
|
|
17465
|
+
const value = record3(data2);
|
|
17100
17466
|
return Array.isArray(value.stream) ? value : { ...value, stream: [] };
|
|
17101
17467
|
}
|
|
17102
17468
|
function adaptCodexHistoryPage(value, sessionGeneration) {
|
|
17103
17469
|
if (sessionGeneration !== "v3") return value;
|
|
17104
|
-
const page =
|
|
17105
|
-
const sourceHeader =
|
|
17470
|
+
const page = record3(value);
|
|
17471
|
+
const sourceHeader = record3(page.header);
|
|
17106
17472
|
const { seedLength: _seedLength, ...header } = sourceHeader;
|
|
17107
17473
|
const records = Array.isArray(page.records) ? page.records.map((raw) => {
|
|
17108
|
-
const entry =
|
|
17109
|
-
const sourceEvent =
|
|
17110
|
-
const sourceSurfaceOp =
|
|
17474
|
+
const entry = record3(raw);
|
|
17475
|
+
const sourceEvent = record3(entry.event);
|
|
17476
|
+
const sourceSurfaceOp = record3(sourceEvent.surfaceOp);
|
|
17111
17477
|
const surfaceOp = sourceEvent.surfaceOp === "append" ? "append" : sourceSurfaceOp.op === "replace" && integer(sourceSurfaceOp.startSeq) !== void 0 && integer(sourceSurfaceOp.endSeq) !== void 0 ? sourceSurfaceOp : sourceSurfaceOp.op === "replace" && integer(sourceSurfaceOp.start) !== void 0 && integer(sourceSurfaceOp.end) !== void 0 ? {
|
|
17112
17478
|
op: "replace",
|
|
17113
17479
|
startSeq: sourceSurfaceOp.start,
|
|
@@ -17117,7 +17483,7 @@ function adaptCodexHistoryPage(value, sessionGeneration) {
|
|
|
17117
17483
|
...entry,
|
|
17118
17484
|
event: {
|
|
17119
17485
|
...sourceEvent,
|
|
17120
|
-
data: adaptEventData(
|
|
17486
|
+
data: adaptEventData(string2(sourceEvent.type) ?? "", sourceEvent.data, sessionGeneration),
|
|
17121
17487
|
...surfaceOp === void 0 ? {} : { surfaceOp }
|
|
17122
17488
|
}
|
|
17123
17489
|
};
|
|
@@ -17129,8 +17495,8 @@ function adaptCodexHistoryPage(value, sessionGeneration) {
|
|
|
17129
17495
|
};
|
|
17130
17496
|
}
|
|
17131
17497
|
function itemEvents(item, turn, step, requestId, selection = modelSelection(), sessionId = CODEX_SESSION_PREFIX, supplementalImages = []) {
|
|
17132
|
-
const type =
|
|
17133
|
-
const id4 =
|
|
17498
|
+
const type = string2(item.type);
|
|
17499
|
+
const id4 = string2(item.id) ?? `${turn}:${step}:${hashString2(JSON.stringify(item))}`;
|
|
17134
17500
|
const text = itemText2(item);
|
|
17135
17501
|
if (type === "userMessage") return [{
|
|
17136
17502
|
type: "user/message",
|
|
@@ -17196,208 +17562,8 @@ function messageContent(item, attachmentSeed, fallbackType, fallbackText, supple
|
|
|
17196
17562
|
}
|
|
17197
17563
|
return [{ type: fallbackType, text: fallbackText ?? "" }];
|
|
17198
17564
|
}
|
|
17199
|
-
function toolOutputImageBlocks(item) {
|
|
17200
|
-
const candidates = [
|
|
17201
|
-
record2(item.result).content,
|
|
17202
|
-
record2(item.output).content,
|
|
17203
|
-
item.contentItems,
|
|
17204
|
-
Array.isArray(item.output) ? item.output : void 0
|
|
17205
|
-
];
|
|
17206
|
-
for (const candidate of candidates) {
|
|
17207
|
-
if (!Array.isArray(candidate)) continue;
|
|
17208
|
-
const images = candidate.flatMap((value) => {
|
|
17209
|
-
const block = record2(value);
|
|
17210
|
-
return isImageContent2(block) && parseImageBlock(block) !== void 0 ? [block] : [];
|
|
17211
|
-
});
|
|
17212
|
-
if (images.length > 0) return images;
|
|
17213
|
-
}
|
|
17214
|
-
return [];
|
|
17215
|
-
}
|
|
17216
|
-
function contentBlocks(value, attachmentSeed) {
|
|
17217
|
-
if (typeof value === "string") return [{ type: "text", text: value }];
|
|
17218
|
-
if (!Array.isArray(value)) return [];
|
|
17219
|
-
const blocks = [];
|
|
17220
|
-
let imageIndex = 0;
|
|
17221
|
-
for (const raw of value) {
|
|
17222
|
-
if (typeof raw === "string") {
|
|
17223
|
-
blocks.push({ type: "text", text: raw });
|
|
17224
|
-
continue;
|
|
17225
|
-
}
|
|
17226
|
-
const block = record2(raw);
|
|
17227
|
-
const image = imageContentBlock(block, attachmentSeed, imageIndex);
|
|
17228
|
-
if (image !== void 0) {
|
|
17229
|
-
imageIndex += 1;
|
|
17230
|
-
blocks.push(image);
|
|
17231
|
-
continue;
|
|
17232
|
-
}
|
|
17233
|
-
const text = string(block.text) ?? string(block.content);
|
|
17234
|
-
if (text !== void 0) blocks.push({ type: block.type === "reasoning" ? "reasoning" : "text", text });
|
|
17235
|
-
}
|
|
17236
|
-
return blocks;
|
|
17237
|
-
}
|
|
17238
|
-
function imageContentBlock(block, attachmentSeed, index) {
|
|
17239
|
-
if (!isImageContent2(block)) return void 0;
|
|
17240
|
-
const image = parseImageBlock(block);
|
|
17241
|
-
if (image === void 0) return void 0;
|
|
17242
|
-
const dimensions = imageDimensions(image.mediaType, image.data);
|
|
17243
|
-
const name2 = string(block.name);
|
|
17244
|
-
const attachment = {
|
|
17245
|
-
attachmentId: `${CODEX_IMAGE_ATTACHMENT_PREFIX}${hashString(`${attachmentSeed}:${index}`)}:${index}`,
|
|
17246
|
-
mediaType: image.mediaType,
|
|
17247
|
-
bytes: base64ByteLength(image.data),
|
|
17248
|
-
width: dimensions.width,
|
|
17249
|
-
height: dimensions.height,
|
|
17250
|
-
...name2 === void 0 ? {} : { name: name2 }
|
|
17251
|
-
};
|
|
17252
|
-
return {
|
|
17253
|
-
type: "image",
|
|
17254
|
-
attachment,
|
|
17255
|
-
mediaType: image.mediaType,
|
|
17256
|
-
data: image.data,
|
|
17257
|
-
url: image.url,
|
|
17258
|
-
...name2 === void 0 ? {} : { name: name2 }
|
|
17259
|
-
};
|
|
17260
|
-
}
|
|
17261
|
-
function isImageContent2(block) {
|
|
17262
|
-
return block.type === "image" || block.type === "input_image";
|
|
17263
|
-
}
|
|
17264
|
-
function parseImageBlock(block) {
|
|
17265
|
-
const url = string(block.url) ?? string(block.image_url) ?? string(record2(block.image_url).url);
|
|
17266
|
-
const parsed = url === void 0 ? void 0 : parseDataImageUrl2(url);
|
|
17267
|
-
if (parsed !== void 0) return parsed;
|
|
17268
|
-
const data2 = string(block.data);
|
|
17269
|
-
if (data2 === void 0 || !isCanonicalBase642(data2)) return void 0;
|
|
17270
|
-
if (data2.length > MAX_CODEX_IMAGE_BASE64) return void 0;
|
|
17271
|
-
const mediaType = string(block.mediaType) ?? string(block.mimeType) ?? sniffImageMediaType2(data2);
|
|
17272
|
-
return mediaType !== void 0 && CODEX_IMAGE_MEDIA_TYPES2.has(mediaType) ? { mediaType, data: data2, url: `data:${mediaType};base64,${data2}` } : void 0;
|
|
17273
|
-
}
|
|
17274
|
-
function parseDataImageUrl2(value) {
|
|
17275
|
-
const match = DATA_IMAGE_URL2.exec(value);
|
|
17276
|
-
if (match === null) return void 0;
|
|
17277
|
-
const mediaType = match[1];
|
|
17278
|
-
const data2 = match[2];
|
|
17279
|
-
if (!CODEX_IMAGE_MEDIA_TYPES2.has(mediaType) || !isCanonicalBase642(data2)) return void 0;
|
|
17280
|
-
return { mediaType, data: data2, url: `data:${mediaType};base64,${data2}` };
|
|
17281
|
-
}
|
|
17282
|
-
function collectImageBlocks(value, output = []) {
|
|
17283
|
-
if (Array.isArray(value)) {
|
|
17284
|
-
for (const item of value) collectImageBlocks(item, output);
|
|
17285
|
-
return output;
|
|
17286
|
-
}
|
|
17287
|
-
if (!isRecord5(value)) return output;
|
|
17288
|
-
if (value.type === "image") output.push(value);
|
|
17289
|
-
for (const [key, child] of Object.entries(value)) {
|
|
17290
|
-
if (key === "attachment") continue;
|
|
17291
|
-
if (key === "content" || key === "message" || key === "inserted" || key === "chunk" || key === "block") {
|
|
17292
|
-
collectImageBlocks(child, output);
|
|
17293
|
-
}
|
|
17294
|
-
}
|
|
17295
|
-
return output;
|
|
17296
|
-
}
|
|
17297
|
-
function base64ByteLength(value) {
|
|
17298
|
-
const padding = value.endsWith("==") ? 2 : value.endsWith("=") ? 1 : 0;
|
|
17299
|
-
return Math.max(1, Math.floor(value.length * 3 / 4) - padding);
|
|
17300
|
-
}
|
|
17301
|
-
function imageDimensions(mediaType, data2) {
|
|
17302
|
-
const bytes = base64PrefixBytes2(data2, 256 * 1024);
|
|
17303
|
-
const parsed = mediaType === "image/png" ? pngDimensions(bytes) : mediaType === "image/jpeg" ? jpegDimensions(bytes) : mediaType === "image/gif" ? gifDimensions(bytes) : mediaType === "image/webp" ? webpDimensions(bytes) : void 0;
|
|
17304
|
-
return parsed ?? { width: 1, height: 1 };
|
|
17305
|
-
}
|
|
17306
|
-
function pngDimensions(bytes) {
|
|
17307
|
-
if (bytes.length < 24 || bytes[0] !== 137 || bytes[1] !== 80 || bytes[2] !== 78 || bytes[3] !== 71 || bytes[4] !== 13 || bytes[5] !== 10 || bytes[6] !== 26 || bytes[7] !== 10) return void 0;
|
|
17308
|
-
return positiveDimensions(readUint32BE(bytes, 16), readUint32BE(bytes, 20));
|
|
17309
|
-
}
|
|
17310
|
-
function jpegDimensions(bytes) {
|
|
17311
|
-
if (bytes.length < 4 || bytes[0] !== 255 || bytes[1] !== 216) return void 0;
|
|
17312
|
-
let offset = 2;
|
|
17313
|
-
while (offset + 9 < bytes.length) {
|
|
17314
|
-
if (bytes[offset] !== 255) {
|
|
17315
|
-
offset += 1;
|
|
17316
|
-
continue;
|
|
17317
|
-
}
|
|
17318
|
-
const marker = bytes[offset + 1];
|
|
17319
|
-
offset += 2;
|
|
17320
|
-
if (marker === 216 || marker === 217) continue;
|
|
17321
|
-
if (offset + 2 > bytes.length) return void 0;
|
|
17322
|
-
const length = readUint16BE(bytes, offset);
|
|
17323
|
-
if (length < 2 || offset + length > bytes.length) return void 0;
|
|
17324
|
-
if (isJpegSof(marker) && length >= 7) {
|
|
17325
|
-
return positiveDimensions(readUint16BE(bytes, offset + 5), readUint16BE(bytes, offset + 3));
|
|
17326
|
-
}
|
|
17327
|
-
offset += length;
|
|
17328
|
-
}
|
|
17329
|
-
return void 0;
|
|
17330
|
-
}
|
|
17331
|
-
function gifDimensions(bytes) {
|
|
17332
|
-
if (bytes.length < 10 || bytes[0] !== 71 || bytes[1] !== 73 || bytes[2] !== 70 || bytes[3] !== 56 || bytes[4] !== 55 && bytes[4] !== 57 || bytes[5] !== 97) return void 0;
|
|
17333
|
-
return positiveDimensions(readUint16LE(bytes, 6), readUint16LE(bytes, 8));
|
|
17334
|
-
}
|
|
17335
|
-
function webpDimensions(bytes) {
|
|
17336
|
-
if (bytes.length < 30 || stringFromBytes(bytes, 0, 4) !== "RIFF" || stringFromBytes(bytes, 8, 12) !== "WEBP") return void 0;
|
|
17337
|
-
const chunk = stringFromBytes(bytes, 12, 16);
|
|
17338
|
-
if (chunk === "VP8X") {
|
|
17339
|
-
return positiveDimensions(1 + readUint24LE(bytes, 24), 1 + readUint24LE(bytes, 27));
|
|
17340
|
-
}
|
|
17341
|
-
if (chunk === "VP8L" && bytes[20] === 47) {
|
|
17342
|
-
const b0 = bytes[21];
|
|
17343
|
-
const b1 = bytes[22];
|
|
17344
|
-
const b2 = bytes[23];
|
|
17345
|
-
const b3 = bytes[24];
|
|
17346
|
-
const width = 1 + b0 + ((b1 & 63) << 8);
|
|
17347
|
-
const height = 1 + ((b1 & 192) >> 6) + (b2 << 2) + ((b3 & 15) << 10);
|
|
17348
|
-
return positiveDimensions(width, height);
|
|
17349
|
-
}
|
|
17350
|
-
if (chunk === "VP8 " && bytes[23] === 157 && bytes[24] === 1 && bytes[25] === 42) {
|
|
17351
|
-
return positiveDimensions(readUint16LE(bytes, 26) & 16383, readUint16LE(bytes, 28) & 16383);
|
|
17352
|
-
}
|
|
17353
|
-
return void 0;
|
|
17354
|
-
}
|
|
17355
|
-
function sniffImageMediaType2(data2) {
|
|
17356
|
-
const bytes = base64PrefixBytes2(data2, 32);
|
|
17357
|
-
if (pngDimensions(bytes) !== void 0) return "image/png";
|
|
17358
|
-
if (bytes.length >= 3 && bytes[0] === 255 && bytes[1] === 216 && bytes[2] === 255) return "image/jpeg";
|
|
17359
|
-
if (gifDimensions(bytes) !== void 0) return "image/gif";
|
|
17360
|
-
if (bytes.length >= 12 && stringFromBytes(bytes, 0, 4) === "RIFF" && stringFromBytes(bytes, 8, 12) === "WEBP") return "image/webp";
|
|
17361
|
-
return void 0;
|
|
17362
|
-
}
|
|
17363
|
-
function base64PrefixBytes2(value, maxBytes) {
|
|
17364
|
-
const chars = value.slice(0, Math.ceil(maxBytes / 3) * 4);
|
|
17365
|
-
let binary;
|
|
17366
|
-
try {
|
|
17367
|
-
binary = atob(chars);
|
|
17368
|
-
} catch {
|
|
17369
|
-
return new Uint8Array();
|
|
17370
|
-
}
|
|
17371
|
-
const bytes = new Uint8Array(Math.min(binary.length, maxBytes));
|
|
17372
|
-
for (let index = 0; index < bytes.length; index += 1) bytes[index] = binary.charCodeAt(index);
|
|
17373
|
-
return bytes;
|
|
17374
|
-
}
|
|
17375
|
-
function readUint16BE(bytes, offset) {
|
|
17376
|
-
return (bytes[offset] << 8) + bytes[offset + 1];
|
|
17377
|
-
}
|
|
17378
|
-
function readUint16LE(bytes, offset) {
|
|
17379
|
-
return bytes[offset] + (bytes[offset + 1] << 8);
|
|
17380
|
-
}
|
|
17381
|
-
function readUint24LE(bytes, offset) {
|
|
17382
|
-
return bytes[offset] + (bytes[offset + 1] << 8) + (bytes[offset + 2] << 16);
|
|
17383
|
-
}
|
|
17384
|
-
function readUint32BE(bytes, offset) {
|
|
17385
|
-
return bytes[offset] * 16777216 + bytes[offset + 1] * 65536 + bytes[offset + 2] * 256 + bytes[offset + 3];
|
|
17386
|
-
}
|
|
17387
|
-
function positiveDimensions(width, height) {
|
|
17388
|
-
return width > 0 && height > 0 ? { width, height } : void 0;
|
|
17389
|
-
}
|
|
17390
|
-
function isJpegSof(marker) {
|
|
17391
|
-
return marker >= 192 && marker <= 195 || marker >= 197 && marker <= 199 || marker >= 201 && marker <= 203 || marker >= 205 && marker <= 207;
|
|
17392
|
-
}
|
|
17393
|
-
function stringFromBytes(bytes, start, end) {
|
|
17394
|
-
if (bytes.length < end) return "";
|
|
17395
|
-
let output = "";
|
|
17396
|
-
for (let index = start; index < end; index += 1) output += String.fromCharCode(bytes[index]);
|
|
17397
|
-
return output;
|
|
17398
|
-
}
|
|
17399
17565
|
function toolResultEvent(item, turn, step, id4, resultText) {
|
|
17400
|
-
const type =
|
|
17566
|
+
const type = string2(item.type) ?? "unknown";
|
|
17401
17567
|
return {
|
|
17402
17568
|
type: "tool/result",
|
|
17403
17569
|
data: {
|
|
@@ -17419,10 +17585,10 @@ function toolResultEvent(item, turn, step, id4, resultText) {
|
|
|
17419
17585
|
};
|
|
17420
17586
|
}
|
|
17421
17587
|
function toolResultContentReplacement(event) {
|
|
17422
|
-
const data2 =
|
|
17423
|
-
const message =
|
|
17588
|
+
const data2 = record3(event.data);
|
|
17589
|
+
const message = record3(data2.message);
|
|
17424
17590
|
const content = array(message.content);
|
|
17425
|
-
const result =
|
|
17591
|
+
const result = record3(content[0]);
|
|
17426
17592
|
if (result.isError === void 0) return event;
|
|
17427
17593
|
const { isError: _isError, ...stableResult } = result;
|
|
17428
17594
|
return {
|
|
@@ -17452,19 +17618,19 @@ function toolResultText(item, type, text) {
|
|
|
17452
17618
|
const count = array(item.results).length;
|
|
17453
17619
|
return count === 0 ? "Web search completed." : `Web search returned ${count} result${count === 1 ? "" : "s"}.`;
|
|
17454
17620
|
}
|
|
17455
|
-
if (type === "imageView") return `Viewed image: ${
|
|
17621
|
+
if (type === "imageView") return `Viewed image: ${string2(item.path) ?? "image"}`;
|
|
17456
17622
|
if (type === "imageGeneration") {
|
|
17457
|
-
const savedPath =
|
|
17458
|
-
return savedPath === void 0 ? `Image generation ${
|
|
17623
|
+
const savedPath = string2(item.savedPath);
|
|
17624
|
+
return savedPath === void 0 ? `Image generation ${string2(item.status) ?? "completed"}.` : `Generated image: ${savedPath}`;
|
|
17459
17625
|
}
|
|
17460
17626
|
if (type === "contextCompaction") return "CodeX compacted the conversation context.";
|
|
17461
|
-
if (type === "enteredReviewMode") return `Entered review mode${
|
|
17462
|
-
if (type === "exitedReviewMode") return `Exited review mode${
|
|
17627
|
+
if (type === "enteredReviewMode") return `Entered review mode${string2(item.review) ? `: ${string2(item.review)}` : "."}`;
|
|
17628
|
+
if (type === "exitedReviewMode") return `Exited review mode${string2(item.review) ? `: ${string2(item.review)}` : "."}`;
|
|
17463
17629
|
if (type === "sleep") return `Waited ${integer(item.durationMs) ?? 0} ms.`;
|
|
17464
17630
|
if (type === "subAgentActivity") {
|
|
17465
|
-
return [
|
|
17631
|
+
return [string2(record3(item.kind).type) ?? string2(item.kind) ?? "Subagent activity", string2(item.agentPath)].filter((value) => value !== void 0).join(": ");
|
|
17466
17632
|
}
|
|
17467
|
-
return text ?? itemText2(
|
|
17633
|
+
return text ?? itemText2(record3(item.result)) ?? itemText2(record3(item.output)) ?? string2(item.status) ?? type;
|
|
17468
17634
|
}
|
|
17469
17635
|
function isSurfaceEvent(type) {
|
|
17470
17636
|
return type === "user/message" || type === "assistant/message" || type === "tool/result";
|
|
@@ -17490,13 +17656,13 @@ function toolCallView(item, type, args) {
|
|
|
17490
17656
|
if (type === "webSearch") {
|
|
17491
17657
|
return {
|
|
17492
17658
|
card: "generic",
|
|
17493
|
-
title:
|
|
17659
|
+
title: string2(item.query) ?? "CodeX web search",
|
|
17494
17660
|
kind: "search",
|
|
17495
17661
|
rawInput: args
|
|
17496
17662
|
};
|
|
17497
17663
|
}
|
|
17498
17664
|
if (type === "imageView" || type === "imageGeneration") {
|
|
17499
|
-
const path =
|
|
17665
|
+
const path = string2(item.path) ?? string2(item.savedPath);
|
|
17500
17666
|
return {
|
|
17501
17667
|
card: "generic",
|
|
17502
17668
|
title: type === "imageView" ? "View image" : "Generate image",
|
|
@@ -17507,7 +17673,7 @@ function toolCallView(item, type, args) {
|
|
|
17507
17673
|
if (type === "collabAgentToolCall" || type === "subAgentActivity") {
|
|
17508
17674
|
return {
|
|
17509
17675
|
card: "generic",
|
|
17510
|
-
title: type === "collabAgentToolCall" ? `Subagent: ${
|
|
17676
|
+
title: type === "collabAgentToolCall" ? `Subagent: ${string2(item.tool) ?? "collaboration"}` : `Subagent activity: ${string2(item.agentPath) ?? string2(item.agentThreadId) ?? "agent"}`,
|
|
17511
17677
|
kind: "other",
|
|
17512
17678
|
rawInput: args
|
|
17513
17679
|
};
|
|
@@ -17536,10 +17702,10 @@ function toolResultView(item, type, resultText) {
|
|
|
17536
17702
|
};
|
|
17537
17703
|
}
|
|
17538
17704
|
function toolDisplayName(item, type) {
|
|
17539
|
-
return
|
|
17705
|
+
return string2(item.name) ?? string2(item.tool) ?? string2(record3(item.tool).name) ?? (type === "mcpToolCall" ? "CodeX MCP tool" : humanizeItemType(type));
|
|
17540
17706
|
}
|
|
17541
17707
|
function fileLocations(item) {
|
|
17542
|
-
return array(item.changes).map((value) =>
|
|
17708
|
+
return array(item.changes).map((value) => string2(record3(value).path)).filter((path) => path !== void 0 && path.length > 0).map((path) => ({ path }));
|
|
17543
17709
|
}
|
|
17544
17710
|
function nativeWorkspace(view) {
|
|
17545
17711
|
const { sessionCount: _sessionCount, ...workspace } = view;
|
|
@@ -17561,14 +17727,14 @@ function projectWorkspace(project) {
|
|
|
17561
17727
|
};
|
|
17562
17728
|
}
|
|
17563
17729
|
function projectCodexProject(value, fallbackPosition) {
|
|
17564
|
-
const source =
|
|
17565
|
-
const id4 =
|
|
17730
|
+
const source = record3(value);
|
|
17731
|
+
const id4 = string2(source.id);
|
|
17566
17732
|
if (id4 === void 0) return void 0;
|
|
17567
|
-
const roots = array(source.roots).map((root) =>
|
|
17733
|
+
const roots = array(source.roots).map((root) => string2(record3(root).path)).filter((path) => path !== void 0 && path.length > 0).map((path) => ({ path }));
|
|
17568
17734
|
if (roots.length === 0) return void 0;
|
|
17569
17735
|
return {
|
|
17570
17736
|
id: id4,
|
|
17571
|
-
name:
|
|
17737
|
+
name: string2(source.name) ?? basename(roots[0].path),
|
|
17572
17738
|
roots,
|
|
17573
17739
|
position: finiteNumber(source.position) ?? fallbackPosition,
|
|
17574
17740
|
createdAt: normalizeTime(source.createdAt),
|
|
@@ -17576,7 +17742,7 @@ function projectCodexProject(value, fallbackPosition) {
|
|
|
17576
17742
|
};
|
|
17577
17743
|
}
|
|
17578
17744
|
function findProjectWorkspace(thread, session, projects, workspaceByProjectId) {
|
|
17579
|
-
const explicitProjectId =
|
|
17745
|
+
const explicitProjectId = string2(thread.projectId);
|
|
17580
17746
|
const explicitWorkspace = explicitProjectId === void 0 ? void 0 : workspaceByProjectId.get(explicitProjectId);
|
|
17581
17747
|
if (explicitWorkspace !== void 0) return explicitWorkspace;
|
|
17582
17748
|
if (session.cwd === void 0) return void 0;
|
|
@@ -17614,14 +17780,14 @@ function codexPromptInput(content) {
|
|
|
17614
17780
|
if (content.length === 0 || content.length > MAX_CODEX_PROMPT_PARTS) return void 0;
|
|
17615
17781
|
const input2 = [];
|
|
17616
17782
|
for (const value of content) {
|
|
17617
|
-
if (!
|
|
17783
|
+
if (!isRecord6(value)) return void 0;
|
|
17618
17784
|
if (value.type === "text") {
|
|
17619
17785
|
if (typeof value.text !== "string" || value.text.length === 0 || value.text.length > MAX_CODEX_PROMPT_TEXT) return void 0;
|
|
17620
17786
|
input2.push({ type: "text", text: value.text });
|
|
17621
17787
|
continue;
|
|
17622
17788
|
}
|
|
17623
17789
|
if (value.type === "image") {
|
|
17624
|
-
if (typeof value.mediaType !== "string" || !
|
|
17790
|
+
if (typeof value.mediaType !== "string" || !CODEX_IMAGE_MEDIA_TYPES3.has(value.mediaType) || typeof value.data !== "string" || value.data.length > MAX_CODEX_IMAGE_BASE642 || !isCanonicalBase642(value.data)) return void 0;
|
|
17625
17791
|
input2.push({ type: "image", mediaType: value.mediaType, data: value.data });
|
|
17626
17792
|
continue;
|
|
17627
17793
|
}
|
|
@@ -17629,9 +17795,6 @@ function codexPromptInput(content) {
|
|
|
17629
17795
|
}
|
|
17630
17796
|
return input2;
|
|
17631
17797
|
}
|
|
17632
|
-
function isCanonicalBase642(value) {
|
|
17633
|
-
return value.length >= 4 && value.length % 4 === 0 && /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$/u.test(value);
|
|
17634
|
-
}
|
|
17635
17798
|
function modelSelectionProjection(selection) {
|
|
17636
17799
|
return { lastUsed: selection, next: selection };
|
|
17637
17800
|
}
|
|
@@ -17659,7 +17822,7 @@ function codexImageLimitsProjection() {
|
|
|
17659
17822
|
maxMessageImageBytes: 100 * 1024 * 1024,
|
|
17660
17823
|
maxImagePixels: 4e7,
|
|
17661
17824
|
maxImageDimension: 8192,
|
|
17662
|
-
mediaTypes: [...
|
|
17825
|
+
mediaTypes: [...CODEX_IMAGE_MEDIA_TYPES3]
|
|
17663
17826
|
};
|
|
17664
17827
|
}
|
|
17665
17828
|
function isCodexPermissionPreset(value) {
|
|
@@ -17703,8 +17866,8 @@ function itemText2(value) {
|
|
|
17703
17866
|
if (content !== void 0) {
|
|
17704
17867
|
const text = content.map((part) => {
|
|
17705
17868
|
if (typeof part === "string") return part;
|
|
17706
|
-
const block =
|
|
17707
|
-
return
|
|
17869
|
+
const block = record3(part);
|
|
17870
|
+
return string2(block.text) ?? string2(block.content) ?? "";
|
|
17708
17871
|
}).filter(Boolean).join("\n");
|
|
17709
17872
|
if (text !== "") return text;
|
|
17710
17873
|
}
|
|
@@ -17717,52 +17880,52 @@ function toolArguments(item) {
|
|
|
17717
17880
|
if (item.type === "commandExecution") return { command: commandText(item.command) ?? item.command ?? "" };
|
|
17718
17881
|
if (item.type === "fileChange") return {
|
|
17719
17882
|
changes: array(item.changes).map((value) => {
|
|
17720
|
-
const change =
|
|
17721
|
-
const kind = typeof change.kind === "string" ? change.kind :
|
|
17883
|
+
const change = record3(value);
|
|
17884
|
+
const kind = typeof change.kind === "string" ? change.kind : string2(record3(change.kind).type);
|
|
17722
17885
|
return {
|
|
17723
17886
|
...typeof change.path === "string" ? { path: change.path } : {},
|
|
17724
17887
|
...kind === void 0 ? {} : { kind }
|
|
17725
17888
|
};
|
|
17726
17889
|
})
|
|
17727
17890
|
};
|
|
17728
|
-
if (item.type === "webSearch") return { query:
|
|
17729
|
-
if (item.type === "imageView") return { path:
|
|
17891
|
+
if (item.type === "webSearch") return { query: string2(item.query) ?? "" };
|
|
17892
|
+
if (item.type === "imageView") return { path: string2(item.path) ?? "" };
|
|
17730
17893
|
if (item.type === "imageGeneration") return {
|
|
17731
|
-
...
|
|
17894
|
+
...string2(item.revisedPrompt) === void 0 ? {} : { prompt: string2(item.revisedPrompt) },
|
|
17732
17895
|
transparentBackground: item.transparentBackground === true
|
|
17733
17896
|
};
|
|
17734
17897
|
if (item.type === "collabAgentToolCall") return {
|
|
17735
|
-
tool:
|
|
17898
|
+
tool: string2(item.tool) ?? "collaboration",
|
|
17736
17899
|
receiverThreadIds: array(item.receiverThreadIds).filter((value) => typeof value === "string"),
|
|
17737
|
-
...
|
|
17900
|
+
...string2(item.model) === void 0 ? {} : { model: string2(item.model) }
|
|
17738
17901
|
};
|
|
17739
17902
|
if (item.type === "subAgentActivity") return {
|
|
17740
|
-
agentThreadId:
|
|
17741
|
-
agentPath:
|
|
17742
|
-
kind:
|
|
17903
|
+
agentThreadId: string2(item.agentThreadId) ?? "",
|
|
17904
|
+
agentPath: string2(item.agentPath) ?? "",
|
|
17905
|
+
kind: string2(record3(item.kind).type) ?? string2(item.kind) ?? "activity"
|
|
17743
17906
|
};
|
|
17744
17907
|
if (item.type === "sleep") return { durationMs: integer(item.durationMs) ?? 0 };
|
|
17745
17908
|
if (item.type === "enteredReviewMode" || item.type === "exitedReviewMode") return {
|
|
17746
|
-
review:
|
|
17909
|
+
review: string2(item.review) ?? ""
|
|
17747
17910
|
};
|
|
17748
17911
|
if (item.type === "contextCompaction") return {};
|
|
17749
17912
|
return { name: item.name ?? item.tool ?? item.type ?? "tool", arguments: item.arguments ?? item.input ?? {} };
|
|
17750
17913
|
}
|
|
17751
17914
|
function fileChangeSummary(item) {
|
|
17752
17915
|
const changes = array(item.changes).map((value) => {
|
|
17753
|
-
const change =
|
|
17754
|
-
const path =
|
|
17755
|
-
const kind = typeof change.kind === "string" ? change.kind :
|
|
17916
|
+
const change = record3(value);
|
|
17917
|
+
const path = string2(change.path);
|
|
17918
|
+
const kind = typeof change.kind === "string" ? change.kind : string2(record3(change.kind).type);
|
|
17756
17919
|
return [kind, path].filter((part) => part !== void 0 && part.length > 0).join(" ");
|
|
17757
17920
|
}).filter(Boolean);
|
|
17758
17921
|
return changes.length === 0 ? "File changes completed." : changes.join("\n");
|
|
17759
17922
|
}
|
|
17760
17923
|
function sanitizedFileChanges(value) {
|
|
17761
17924
|
return array(value).flatMap((raw) => {
|
|
17762
|
-
const change =
|
|
17763
|
-
const path =
|
|
17925
|
+
const change = record3(raw);
|
|
17926
|
+
const path = string2(change.path);
|
|
17764
17927
|
if (path === void 0) return [];
|
|
17765
|
-
const kind = typeof change.kind === "string" ? change.kind :
|
|
17928
|
+
const kind = typeof change.kind === "string" ? change.kind : string2(record3(change.kind).type);
|
|
17766
17929
|
return [{ path, ...kind === void 0 ? {} : { kind } }];
|
|
17767
17930
|
});
|
|
17768
17931
|
}
|
|
@@ -17792,8 +17955,8 @@ function humanizeItemType(type) {
|
|
|
17792
17955
|
function commandText(value) {
|
|
17793
17956
|
if (typeof value === "string") return value;
|
|
17794
17957
|
if (Array.isArray(value)) return value.filter((item) => typeof item === "string").join(" ");
|
|
17795
|
-
const source =
|
|
17796
|
-
return
|
|
17958
|
+
const source = record3(value);
|
|
17959
|
+
return string2(source.command) ?? string2(source.text);
|
|
17797
17960
|
}
|
|
17798
17961
|
function sessionIdFromAddress(address) {
|
|
17799
17962
|
if (address.kind === "session") return requiredString(address.sessionId, "sessionId");
|
|
@@ -17808,7 +17971,7 @@ function nativeThreadId(sessionId) {
|
|
|
17808
17971
|
function activeTurnId(value) {
|
|
17809
17972
|
if (!Array.isArray(value)) return void 0;
|
|
17810
17973
|
for (let index = value.length - 1; index >= 0; index -= 1) {
|
|
17811
|
-
const turn =
|
|
17974
|
+
const turn = record3(value[index]);
|
|
17812
17975
|
if (isActiveCodexTurn(turn) && typeof turn.id === "string" && turn.id.length > 0) return turn.id;
|
|
17813
17976
|
}
|
|
17814
17977
|
return void 0;
|
|
@@ -17817,10 +17980,10 @@ function isActiveCodexTurn(turn) {
|
|
|
17817
17980
|
return turn.status === "inProgress" || turn.status === "running";
|
|
17818
17981
|
}
|
|
17819
17982
|
function carrierArgs(payload) {
|
|
17820
|
-
return
|
|
17983
|
+
return record3(record3(payload).args);
|
|
17821
17984
|
}
|
|
17822
17985
|
function requestArg(args) {
|
|
17823
|
-
return
|
|
17986
|
+
return record3(args.request ?? args._request ?? args);
|
|
17824
17987
|
}
|
|
17825
17988
|
function rcEndpoint(endpoint) {
|
|
17826
17989
|
if (endpoint === "workspace.list") return "workspace/list";
|
|
@@ -17836,20 +17999,20 @@ function ok(value) {
|
|
|
17836
17999
|
return value === void 0 ? { ok: true } : { ok: true, value };
|
|
17837
18000
|
}
|
|
17838
18001
|
function business(value) {
|
|
17839
|
-
const result =
|
|
18002
|
+
const result = record3(value);
|
|
17840
18003
|
if (result.ok === true) return ok(result.value);
|
|
17841
18004
|
if (result.ok === false) {
|
|
17842
|
-
const error =
|
|
17843
|
-
return fail(
|
|
18005
|
+
const error = record3(result.error);
|
|
18006
|
+
return fail(string2(error.code) ?? "internal", string2(error.message) ?? "CodeX virtual Harness rejected the request.", record3(error.details));
|
|
17844
18007
|
}
|
|
17845
18008
|
return ok(value);
|
|
17846
18009
|
}
|
|
17847
18010
|
function isCodexDirectoryListing(value) {
|
|
17848
|
-
const listing =
|
|
18011
|
+
const listing = record3(value);
|
|
17849
18012
|
return typeof listing.path === "string" && typeof listing.home === "string" && Array.isArray(listing.crumbs) && listing.crumbs.every(isCodexDirectoryEntry) && Array.isArray(listing.entries) && listing.entries.every(isCodexDirectoryEntry) && typeof listing.truncated === "boolean";
|
|
17850
18013
|
}
|
|
17851
18014
|
function isCodexDirectoryEntry(value) {
|
|
17852
|
-
const entry =
|
|
18015
|
+
const entry = record3(value);
|
|
17853
18016
|
return typeof entry.name === "string" && typeof entry.path === "string" && typeof entry.hidden === "boolean";
|
|
17854
18017
|
}
|
|
17855
18018
|
function fail(code, message, details = {}) {
|
|
@@ -17867,18 +18030,18 @@ function errorCode(error) {
|
|
|
17867
18030
|
return "code" in error && typeof error.code === "string" ? error.code : void 0;
|
|
17868
18031
|
}
|
|
17869
18032
|
function errorDetails(error) {
|
|
17870
|
-
return "details" in error &&
|
|
18033
|
+
return "details" in error && isRecord6(error.details) ? error.details : {};
|
|
17871
18034
|
}
|
|
17872
|
-
function
|
|
17873
|
-
return
|
|
18035
|
+
function record3(value) {
|
|
18036
|
+
return isRecord6(value) ? value : {};
|
|
17874
18037
|
}
|
|
17875
|
-
function
|
|
18038
|
+
function isRecord6(value) {
|
|
17876
18039
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17877
18040
|
}
|
|
17878
18041
|
function array(value) {
|
|
17879
18042
|
return Array.isArray(value) ? value : [];
|
|
17880
18043
|
}
|
|
17881
|
-
function
|
|
18044
|
+
function string2(value) {
|
|
17882
18045
|
return typeof value === "string" ? value : void 0;
|
|
17883
18046
|
}
|
|
17884
18047
|
function integer(value) {
|
|
@@ -17904,8 +18067,8 @@ function optionalPositiveInteger(value) {
|
|
|
17904
18067
|
return parsed;
|
|
17905
18068
|
}
|
|
17906
18069
|
function isCodexNativeHistoryPage(value, sessionId) {
|
|
17907
|
-
const page =
|
|
17908
|
-
const header =
|
|
18070
|
+
const page = record3(value);
|
|
18071
|
+
const header = record3(page.header);
|
|
17909
18072
|
return header.id === sessionId && integer(page.cursor) !== void 0 && integer(page.nextTurn) !== void 0 && Array.isArray(page.records) && typeof page.hasMore === "boolean" && (page.activeTurnId === void 0 || typeof page.activeTurnId === "string");
|
|
17910
18073
|
}
|
|
17911
18074
|
function truncateCodePoints(value, maximum) {
|
|
@@ -17932,7 +18095,7 @@ function basename(path) {
|
|
|
17932
18095
|
const parts = normalized.split(/[\\/]/u);
|
|
17933
18096
|
return parts.at(-1) || path;
|
|
17934
18097
|
}
|
|
17935
|
-
function
|
|
18098
|
+
function hashString2(value) {
|
|
17936
18099
|
let hash = 2166136261;
|
|
17937
18100
|
for (let index = 0; index < value.length; index += 1) {
|
|
17938
18101
|
hash ^= value.charCodeAt(index);
|
|
@@ -17983,7 +18146,7 @@ var AsyncValueQueue2 = class {
|
|
|
17983
18146
|
continue;
|
|
17984
18147
|
}
|
|
17985
18148
|
if (this.closed) return;
|
|
17986
|
-
const next = await new Promise((
|
|
18149
|
+
const next = await new Promise((resolve4) => this.waiters.push(resolve4));
|
|
17987
18150
|
if (next.done) return;
|
|
17988
18151
|
yield next.value;
|
|
17989
18152
|
}
|
|
@@ -18027,7 +18190,7 @@ var ServerCredentialStore = class {
|
|
|
18027
18190
|
} catch (error) {
|
|
18028
18191
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "EEXIST") throw error;
|
|
18029
18192
|
if (Date.now() >= deadline) throw new ServerCredentialsBusyError();
|
|
18030
|
-
await new Promise((
|
|
18193
|
+
await new Promise((resolve4) => setTimeout(resolve4, 50));
|
|
18031
18194
|
}
|
|
18032
18195
|
}
|
|
18033
18196
|
try {
|
|
@@ -18048,10 +18211,10 @@ var ServerCredentialStore = class {
|
|
|
18048
18211
|
return parsed.serverUrl === serverUrl && parsed.deviceId === deviceId ? parsed : void 0;
|
|
18049
18212
|
}
|
|
18050
18213
|
async save(credentials) {
|
|
18051
|
-
const
|
|
18052
|
-
await atomicWrite(this.path, `${JSON.stringify(
|
|
18214
|
+
const record7 = credentialSchema.parse({ schemaVersion: 1, ...credentials });
|
|
18215
|
+
await atomicWrite(this.path, `${JSON.stringify(record7, null, 2)}
|
|
18053
18216
|
`);
|
|
18054
|
-
return
|
|
18217
|
+
return record7;
|
|
18055
18218
|
}
|
|
18056
18219
|
async clear() {
|
|
18057
18220
|
await rm(this.path, { force: true });
|
|
@@ -18096,7 +18259,7 @@ function safeMessage(error) {
|
|
|
18096
18259
|
import { hostname } from "node:os";
|
|
18097
18260
|
import s from "@deepseek-ai/schemastery";
|
|
18098
18261
|
var DEFAULT_REMOTE_SERVER_URL = "https://dsh.r2049.cn";
|
|
18099
|
-
var
|
|
18262
|
+
var entryConfigSchema = s.object({
|
|
18100
18263
|
enabled: s.boolean(),
|
|
18101
18264
|
role: s.union(["host", "client", "both"]),
|
|
18102
18265
|
serverUrl: s.string(),
|
|
@@ -18119,6 +18282,11 @@ var Config = s.object({
|
|
|
18119
18282
|
}),
|
|
18120
18283
|
acp: s.object({ enabled: s.boolean(), backends: s.array(s.object({ id: s.string(), enabled: s.boolean(), command: s.string(), args: s.array(s.string()), cwd: s.string() })) })
|
|
18121
18284
|
});
|
|
18285
|
+
function withVolatileSchema(schema) {
|
|
18286
|
+
const volatile = schema.volatile;
|
|
18287
|
+
return typeof volatile === "function" ? volatile.call(schema) : schema;
|
|
18288
|
+
}
|
|
18289
|
+
var Config = withVolatileSchema(entryConfigSchema);
|
|
18122
18290
|
var reconnectSchema = external_exports.union([
|
|
18123
18291
|
external_exports.boolean(),
|
|
18124
18292
|
external_exports.object({
|
|
@@ -18198,7 +18366,7 @@ function normalizeServerUrl(value) {
|
|
|
18198
18366
|
}
|
|
18199
18367
|
|
|
18200
18368
|
// src/version.ts
|
|
18201
|
-
var PLUGIN_VERSION = "0.4.
|
|
18369
|
+
var PLUGIN_VERSION = "0.4.18";
|
|
18202
18370
|
|
|
18203
18371
|
// src/server-api.ts
|
|
18204
18372
|
var TERMINAL_CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/u;
|
|
@@ -18654,7 +18822,7 @@ var TypertGatewaySwitch = class {
|
|
|
18654
18822
|
this.originalDispatch = this.runtime.dispatchRpc;
|
|
18655
18823
|
this.localDispatch = this.runtime.dispatchRpc?.bind(gateway);
|
|
18656
18824
|
this.originalOpen = this.runtime.openWireStream;
|
|
18657
|
-
this.localOpen =
|
|
18825
|
+
this.localOpen = createLocalOpen(gateway, this.runtime);
|
|
18658
18826
|
}
|
|
18659
18827
|
/** Original local dispatcher, used by the Host bridge without switch recursion. */
|
|
18660
18828
|
local() {
|
|
@@ -18695,7 +18863,16 @@ var TypertGatewaySwitch = class {
|
|
|
18695
18863
|
this.runtime.dispatchRpc = (endpoint, payload, signal) => this.remoteTarget === void 0 || isLocalOnlyEndpoint(endpoint) ? this.localDispatch(endpoint, payload, signal) : this.remoteTarget.dispatch(endpoint, payload, signal);
|
|
18696
18864
|
}
|
|
18697
18865
|
if (this.originalOpen !== void 0) {
|
|
18698
|
-
|
|
18866
|
+
const open = this.originalOpen;
|
|
18867
|
+
const rc1 = usesRc1Arity(open);
|
|
18868
|
+
this.runtime.openWireStream = (...callArgs) => {
|
|
18869
|
+
const endpoint = callArgs[0];
|
|
18870
|
+
if (this.remoteTarget === void 0 || isLocalOnlyEndpoint(endpoint)) {
|
|
18871
|
+
return rc1 ? Reflect.apply(open, this.runtime, callArgs) : open.call(this.runtime, endpoint, callArgs[1], callArgs[2]);
|
|
18872
|
+
}
|
|
18873
|
+
const signal = rc1 ? callArgs[4] : callArgs[2];
|
|
18874
|
+
return this.remoteTarget.open(endpoint, callArgs[1], signal ?? new AbortController().signal);
|
|
18875
|
+
};
|
|
18699
18876
|
}
|
|
18700
18877
|
this.installed = true;
|
|
18701
18878
|
}
|
|
@@ -18736,16 +18913,47 @@ var TypertGatewaySwitch = class {
|
|
|
18736
18913
|
if (normalized !== void 0) return normalized;
|
|
18737
18914
|
const source = error instanceof Error ? error : new Error("The Harness Gateway rejected the request.");
|
|
18738
18915
|
const code = "code" in source && typeof source.code === "string" ? source.code : "internal";
|
|
18739
|
-
const details = "details" in source &&
|
|
18916
|
+
const details = "details" in source && isRecord7(source.details) ? source.details : {};
|
|
18740
18917
|
return { code, message: source.message, details };
|
|
18741
18918
|
}
|
|
18742
18919
|
};
|
|
18920
|
+
function usesRc1Arity(open) {
|
|
18921
|
+
return open.length >= 5;
|
|
18922
|
+
}
|
|
18923
|
+
function endedUplink() {
|
|
18924
|
+
return {
|
|
18925
|
+
[Symbol.asyncIterator]() {
|
|
18926
|
+
return { next: () => Promise.resolve({ done: true, value: void 0 }) };
|
|
18927
|
+
}
|
|
18928
|
+
};
|
|
18929
|
+
}
|
|
18930
|
+
function linkControl(signal) {
|
|
18931
|
+
const control = new AbortController();
|
|
18932
|
+
if (signal.aborted) control.abort(signal.reason);
|
|
18933
|
+
else signal.addEventListener("abort", () => control.abort(signal.reason), { once: true });
|
|
18934
|
+
return control;
|
|
18935
|
+
}
|
|
18936
|
+
function createLocalOpen(gateway, runtime) {
|
|
18937
|
+
const open = runtime.openWireStream;
|
|
18938
|
+
if (open !== void 0) {
|
|
18939
|
+
return usesRc1Arity(open) ? (endpoint, payload, signal) => open.call(runtime, endpoint, payload, endedUplink(), void 0, signal, linkControl(signal)) : (endpoint, payload, signal) => open.call(runtime, endpoint, payload, signal);
|
|
18940
|
+
}
|
|
18941
|
+
const wire = gateway.wireStream;
|
|
18942
|
+
if (wire === void 0) return void 0;
|
|
18943
|
+
const wireOpen = wire.open;
|
|
18944
|
+
if (usesRc1Arity(wireOpen)) {
|
|
18945
|
+
const rc1 = wireOpen;
|
|
18946
|
+
return (endpoint, payload, signal) => rc1.call(wire, endpoint, payload, endedUplink(), void 0, signal);
|
|
18947
|
+
}
|
|
18948
|
+
const legacy = wireOpen;
|
|
18949
|
+
return (endpoint, payload, signal) => legacy.call(wire, endpoint, payload, signal);
|
|
18950
|
+
}
|
|
18743
18951
|
function requestFromCarrier(endpoint, payload, signal) {
|
|
18744
18952
|
const segments = endpoint.split("/");
|
|
18745
18953
|
if (segments.length !== 2 || segments.some((segment) => segment.length === 0)) {
|
|
18746
18954
|
throw new Error("The Harness Gateway endpoint is invalid.");
|
|
18747
18955
|
}
|
|
18748
|
-
if (!
|
|
18956
|
+
if (!isRecord7(payload) || !isRecord7(payload.args)) {
|
|
18749
18957
|
throw new Error("The Harness Gateway payload is invalid.");
|
|
18750
18958
|
}
|
|
18751
18959
|
return { namespace: segments[0], method: segments[1], args: payload.args, signal };
|
|
@@ -18760,7 +18968,7 @@ function isLocalOnlyEndpoint(endpoint) {
|
|
|
18760
18968
|
function isRemoteCommandMethod(method) {
|
|
18761
18969
|
return REMOTE_COMMAND_METHODS.includes(method);
|
|
18762
18970
|
}
|
|
18763
|
-
function
|
|
18971
|
+
function isRecord7(value) {
|
|
18764
18972
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
18765
18973
|
}
|
|
18766
18974
|
|
|
@@ -18867,10 +19075,10 @@ function isUsableExternalNode(candidate, requireFrom) {
|
|
|
18867
19075
|
}
|
|
18868
19076
|
function isExecutableFile(candidate) {
|
|
18869
19077
|
try {
|
|
18870
|
-
const
|
|
18871
|
-
if (!
|
|
19078
|
+
const stat7 = statSync(candidate);
|
|
19079
|
+
if (!stat7.isFile()) return false;
|
|
18872
19080
|
if (process.platform === "win32") return true;
|
|
18873
|
-
return (
|
|
19081
|
+
return (stat7.mode & 73) !== 0;
|
|
18874
19082
|
} catch {
|
|
18875
19083
|
return false;
|
|
18876
19084
|
}
|
|
@@ -18959,8 +19167,8 @@ var ExternalNativePeerConnection = class {
|
|
|
18959
19167
|
request(method, payload) {
|
|
18960
19168
|
if (this.closed) return Promise.reject(new Error("native rtc helper is closed"));
|
|
18961
19169
|
const id4 = this.nextRequestId++;
|
|
18962
|
-
const promise = new Promise((
|
|
18963
|
-
this.pending.set(id4, { resolve:
|
|
19170
|
+
const promise = new Promise((resolve4, reject) => {
|
|
19171
|
+
this.pending.set(id4, { resolve: resolve4, reject });
|
|
18964
19172
|
});
|
|
18965
19173
|
this.write({ id: id4, method, payload });
|
|
18966
19174
|
return promise;
|
|
@@ -19754,10 +19962,10 @@ function parseRouteTarget(value) {
|
|
|
19754
19962
|
async function detectRouteHostIpv4(target2, timeoutMs) {
|
|
19755
19963
|
const socket = createSocket("udp4");
|
|
19756
19964
|
try {
|
|
19757
|
-
return await new Promise((
|
|
19965
|
+
return await new Promise((resolve4, reject) => {
|
|
19758
19966
|
const timer = setTimeout(() => {
|
|
19759
19967
|
cleanup();
|
|
19760
|
-
|
|
19968
|
+
resolve4(void 0);
|
|
19761
19969
|
}, timeoutMs);
|
|
19762
19970
|
const cleanup = () => {
|
|
19763
19971
|
clearTimeout(timer);
|
|
@@ -19771,7 +19979,7 @@ async function detectRouteHostIpv4(target2, timeoutMs) {
|
|
|
19771
19979
|
socket.connect(target2.port, target2.host, () => {
|
|
19772
19980
|
cleanup();
|
|
19773
19981
|
const address = socket.address();
|
|
19774
|
-
|
|
19982
|
+
resolve4(typeof address === "string" ? void 0 : address.address);
|
|
19775
19983
|
});
|
|
19776
19984
|
});
|
|
19777
19985
|
} finally {
|
|
@@ -20097,7 +20305,7 @@ var ClientModeRuntime = class {
|
|
|
20097
20305
|
const virtual = CodexVirtualHarness.remote(remote.client, {
|
|
20098
20306
|
deviceId: remote.target.deviceId,
|
|
20099
20307
|
name: remote.target.name
|
|
20100
|
-
}, harnessSessionGeneration(this.host?.localHarnessVersion?.()));
|
|
20308
|
+
}, harnessSessionGeneration(this.host?.localHarnessVersion?.()), new RemoteTypertGateway2(remote.client));
|
|
20101
20309
|
let workspace;
|
|
20102
20310
|
try {
|
|
20103
20311
|
workspace = await virtual.selectWorkspace(workspaceId, signal);
|
|
@@ -20127,12 +20335,12 @@ var ClientModeRuntime = class {
|
|
|
20127
20335
|
throw new ClientModeError("FEATURE_NOT_SUPPORTED", "The selected Host does not provide CodeX workspaces.");
|
|
20128
20336
|
}
|
|
20129
20337
|
this.assertLocalHarnessCarrierAvailable();
|
|
20130
|
-
const result =
|
|
20338
|
+
const result = record4(await new CodexRemoteClient(remote.client).request("project/create", {
|
|
20131
20339
|
name: remoteWorkspaceTitle(trimmedPath),
|
|
20132
20340
|
roots: [{ path: trimmedPath }],
|
|
20133
20341
|
idempotencyKey: uuidV7()
|
|
20134
20342
|
}, signal));
|
|
20135
|
-
const project =
|
|
20343
|
+
const project = record4(result.project);
|
|
20136
20344
|
if (typeof project.id !== "string" || project.id.length === 0) {
|
|
20137
20345
|
throw new ClientModeError("INVALID_MESSAGE", "The Host returned an invalid CodeX project.");
|
|
20138
20346
|
}
|
|
@@ -20184,7 +20392,7 @@ var ClientModeRuntime = class {
|
|
|
20184
20392
|
}
|
|
20185
20393
|
async openCodexStream(payload, signal) {
|
|
20186
20394
|
const remote = this.activeCodexRemote();
|
|
20187
|
-
const value =
|
|
20395
|
+
const value = record4(payload);
|
|
20188
20396
|
if (typeof value.streamId !== "string" || value.streamId.length === 0 || value.streamId.length > 128 || typeof value.threadId !== "string" || value.threadId.length === 0) {
|
|
20189
20397
|
throw new ClientModeError("INVALID_MESSAGE", "A Codex stream and thread are required.");
|
|
20190
20398
|
}
|
|
@@ -20216,10 +20424,10 @@ var ClientModeRuntime = class {
|
|
|
20216
20424
|
}
|
|
20217
20425
|
}
|
|
20218
20426
|
stream.unsubscribe = remote.client.onEvent((event) => {
|
|
20219
|
-
if (event.event === "codex.app.frame" &&
|
|
20427
|
+
if (event.event === "codex.app.frame" && isRecord8(event.data) && event.data.streamId === value.streamId) {
|
|
20220
20428
|
this.appendCodexFrame(stream, event.data);
|
|
20221
20429
|
}
|
|
20222
|
-
if (event.event === "codex.app.stream.closed" &&
|
|
20430
|
+
if (event.event === "codex.app.stream.closed" && isRecord8(event.data) && event.data.streamId === value.streamId) {
|
|
20223
20431
|
stream.closed = typeof event.data.reason === "string" ? event.data.reason : "closed";
|
|
20224
20432
|
stream.wake();
|
|
20225
20433
|
}
|
|
@@ -20246,7 +20454,7 @@ var ClientModeRuntime = class {
|
|
|
20246
20454
|
stream.wake();
|
|
20247
20455
|
};
|
|
20248
20456
|
appendCodexFrame(stream, data2) {
|
|
20249
|
-
if (!
|
|
20457
|
+
if (!isRecord8(data2) || !isRecord8(data2.frame) || typeof data2.frame.method !== "string") return;
|
|
20250
20458
|
if (stream.frames.length >= 256) {
|
|
20251
20459
|
stream.closed = "overflow";
|
|
20252
20460
|
} else {
|
|
@@ -20269,7 +20477,7 @@ var ClientModeRuntime = class {
|
|
|
20269
20477
|
};
|
|
20270
20478
|
}
|
|
20271
20479
|
async nextCodexFrames(payload, signal) {
|
|
20272
|
-
const value =
|
|
20480
|
+
const value = record4(payload);
|
|
20273
20481
|
if (typeof value.streamId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Codex stream is required.");
|
|
20274
20482
|
const stream = this.codexStreams.get(value.streamId);
|
|
20275
20483
|
if (stream === void 0) throw new ClientModeError("STREAM_NOT_FOUND", "The Codex stream is not open.");
|
|
@@ -20283,7 +20491,7 @@ var ClientModeRuntime = class {
|
|
|
20283
20491
|
};
|
|
20284
20492
|
}
|
|
20285
20493
|
async closeCodexStream(payload) {
|
|
20286
|
-
const value =
|
|
20494
|
+
const value = record4(payload);
|
|
20287
20495
|
if (typeof value.streamId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Codex stream is required.");
|
|
20288
20496
|
const stream = this.codexStreams.get(value.streamId);
|
|
20289
20497
|
if (stream === void 0) return { closed: false, streamId: value.streamId };
|
|
@@ -20309,7 +20517,7 @@ var ClientModeRuntime = class {
|
|
|
20309
20517
|
this.gatewaySwitch.selectRemote(this.remoteTypertGateway(remote), void 0, target2);
|
|
20310
20518
|
return;
|
|
20311
20519
|
}
|
|
20312
|
-
this.proxySwitch?.selectRemote(new RemoteHarnessApiProxy(remote.client).api, target2);
|
|
20520
|
+
this.proxySwitch?.selectRemote(new RemoteHarnessApiProxy(remote.client, remote.harnessVersion).api, target2);
|
|
20313
20521
|
this.gatewaySwitch.selectRemote((request) => invokeRemoteCommand(remote.client, request), {
|
|
20314
20522
|
execute: true,
|
|
20315
20523
|
list: remote.features.commandList
|
|
@@ -20319,7 +20527,8 @@ var ClientModeRuntime = class {
|
|
|
20319
20527
|
const localSessionGeneration = harnessSessionGeneration(this.host?.localHarnessVersion?.());
|
|
20320
20528
|
return new RemoteTypertGateway2(
|
|
20321
20529
|
remote.client,
|
|
20322
|
-
localSessionGeneration === "v3" && remote.features.sessionFormat !== 3 ? "legacy-to-v3" : void 0
|
|
20530
|
+
localSessionGeneration === "v3" && remote.features.sessionFormat !== 3 ? "legacy-to-v3" : void 0,
|
|
20531
|
+
remote.harnessVersion
|
|
20323
20532
|
);
|
|
20324
20533
|
}
|
|
20325
20534
|
selectCodexTarget(virtual, remote) {
|
|
@@ -20535,14 +20744,14 @@ var ClientModeRuntime = class {
|
|
|
20535
20744
|
if (endpoint === "status") return ok2(await this.detailedStatus());
|
|
20536
20745
|
if (endpoint === "devices") return ok2(await this.devices());
|
|
20537
20746
|
if (endpoint === "client.account.login") {
|
|
20538
|
-
const value =
|
|
20747
|
+
const value = record4(payload);
|
|
20539
20748
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
20540
20749
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
20541
20750
|
}
|
|
20542
20751
|
return ok2(await this.authorizeClientWithAccount(value.email, value.password));
|
|
20543
20752
|
}
|
|
20544
20753
|
if (endpoint === "client.account.qr.start") {
|
|
20545
|
-
const value =
|
|
20754
|
+
const value = record4(payload);
|
|
20546
20755
|
const provider = value.provider ?? "zhihu";
|
|
20547
20756
|
if (provider !== "zhihu" && provider !== "github") {
|
|
20548
20757
|
throw new ClientModeError("INVALID_MESSAGE", "A supported OAuth provider is required.");
|
|
@@ -20550,7 +20759,7 @@ var ClientModeRuntime = class {
|
|
|
20550
20759
|
return ok2(await this.startClientOAuthQrLogin(provider));
|
|
20551
20760
|
}
|
|
20552
20761
|
if (endpoint === "client.account.qr.poll") {
|
|
20553
|
-
const value =
|
|
20762
|
+
const value = record4(payload);
|
|
20554
20763
|
if (typeof value.qrId !== "string" || value.qrId.length < 20) {
|
|
20555
20764
|
throw new ClientModeError("INVALID_MESSAGE", "A QR login session is required.");
|
|
20556
20765
|
}
|
|
@@ -20560,10 +20769,10 @@ var ClientModeRuntime = class {
|
|
|
20560
20769
|
const remote = this.activeRemote();
|
|
20561
20770
|
if (remote === void 0) throw new ClientModeError("TRANSPORT_CLOSED", "Connect to a Remote Host first.");
|
|
20562
20771
|
this.preview ??= new LoopbackPreview(remote.client);
|
|
20563
|
-
return ok2(await this.preview.open(
|
|
20772
|
+
return ok2(await this.preview.open(record4(payload).port));
|
|
20564
20773
|
}
|
|
20565
20774
|
if (endpoint === "directory.list") {
|
|
20566
|
-
const value =
|
|
20775
|
+
const value = record4(payload);
|
|
20567
20776
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
20568
20777
|
return ok2(await this.listRemoteDirectory(
|
|
20569
20778
|
value.targetDeviceId,
|
|
@@ -20572,38 +20781,38 @@ var ClientModeRuntime = class {
|
|
|
20572
20781
|
));
|
|
20573
20782
|
}
|
|
20574
20783
|
if (endpoint === "workspaces.list") {
|
|
20575
|
-
const value =
|
|
20784
|
+
const value = record4(payload);
|
|
20576
20785
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
20577
20786
|
return ok2(await this.listRemoteWorkspaces(value.targetDeviceId, signal));
|
|
20578
20787
|
}
|
|
20579
20788
|
if (endpoint === "codex.workspaces.list") {
|
|
20580
|
-
const value =
|
|
20789
|
+
const value = record4(payload);
|
|
20581
20790
|
if (typeof value.targetDeviceId !== "string") throw new ClientModeError("INVALID_MESSAGE", "A Host is required.");
|
|
20582
20791
|
return ok2(await this.listCodexWorkspaces(value.targetDeviceId, signal));
|
|
20583
20792
|
}
|
|
20584
20793
|
if (endpoint === "workspace.open") {
|
|
20585
|
-
const value =
|
|
20794
|
+
const value = record4(payload);
|
|
20586
20795
|
if (typeof value.targetDeviceId !== "string" || typeof value.path !== "string") {
|
|
20587
20796
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and working directory are required.");
|
|
20588
20797
|
}
|
|
20589
20798
|
return ok2(await this.openRemoteWorkspace(value.targetDeviceId, value.path, signal));
|
|
20590
20799
|
}
|
|
20591
20800
|
if (endpoint === "codex.workspace.open") {
|
|
20592
|
-
const value =
|
|
20801
|
+
const value = record4(payload);
|
|
20593
20802
|
if (typeof value.targetDeviceId !== "string" || typeof value.workspaceId !== "string") {
|
|
20594
20803
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and CodeX Workspace are required.");
|
|
20595
20804
|
}
|
|
20596
20805
|
return ok2(await this.openCodexWorkspace(value.targetDeviceId, value.workspaceId, signal));
|
|
20597
20806
|
}
|
|
20598
20807
|
if (endpoint === "codex.workspace.create") {
|
|
20599
|
-
const value =
|
|
20808
|
+
const value = record4(payload);
|
|
20600
20809
|
if (typeof value.targetDeviceId !== "string" || typeof value.path !== "string") {
|
|
20601
20810
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and CodeX project directory are required.");
|
|
20602
20811
|
}
|
|
20603
20812
|
return ok2(await this.createCodexWorkspace(value.targetDeviceId, value.path, signal));
|
|
20604
20813
|
}
|
|
20605
20814
|
if (endpoint === "workspace.selection.consume") {
|
|
20606
|
-
const value =
|
|
20815
|
+
const value = record4(payload);
|
|
20607
20816
|
if (typeof value.targetDeviceId !== "string" || typeof value.workspaceId !== "string") {
|
|
20608
20817
|
throw new ClientModeError("INVALID_MESSAGE", "A Host and Workspace are required.");
|
|
20609
20818
|
}
|
|
@@ -20619,7 +20828,7 @@ var ClientModeRuntime = class {
|
|
|
20619
20828
|
return ok2(await this.callRemoteFileViewer(method, payload, signal));
|
|
20620
20829
|
}
|
|
20621
20830
|
if (endpoint === "codex.call") {
|
|
20622
|
-
const value =
|
|
20831
|
+
const value = record4(payload);
|
|
20623
20832
|
if (typeof value.method !== "string" || !("params" in value)) {
|
|
20624
20833
|
throw new ClientModeError("INVALID_MESSAGE", "A Codex method and params are required.");
|
|
20625
20834
|
}
|
|
@@ -20643,7 +20852,7 @@ var ClientModeRuntime = class {
|
|
|
20643
20852
|
return ok2({ supported: local || remoteSupported, local, remote: remoteSupported });
|
|
20644
20853
|
}
|
|
20645
20854
|
if (endpoint === "codex.respond") {
|
|
20646
|
-
const value =
|
|
20855
|
+
const value = record4(payload);
|
|
20647
20856
|
const remote = this.activeCodexRemote();
|
|
20648
20857
|
if (remote !== void 0) return ok2(await remote.client.rpc("codex.app.respond", value, signal));
|
|
20649
20858
|
const host = this.requireLocalCodex();
|
|
@@ -20654,14 +20863,14 @@ var ClientModeRuntime = class {
|
|
|
20654
20863
|
if (endpoint === "codex.stream.close") return ok2(await this.closeCodexStream(payload));
|
|
20655
20864
|
if (endpoint === "host.account.login") {
|
|
20656
20865
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
20657
|
-
const value =
|
|
20866
|
+
const value = record4(payload);
|
|
20658
20867
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
20659
20868
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
20660
20869
|
}
|
|
20661
20870
|
return ok2(await this.host.authorizeHostWithAccount(value.email, value.password));
|
|
20662
20871
|
}
|
|
20663
20872
|
if (endpoint === "host.authorization.set") {
|
|
20664
|
-
const value =
|
|
20873
|
+
const value = record4(payload);
|
|
20665
20874
|
if (typeof value.enabled !== "boolean") {
|
|
20666
20875
|
throw new ClientModeError("INVALID_MESSAGE", "Host authorization state is required.");
|
|
20667
20876
|
}
|
|
@@ -20669,14 +20878,14 @@ var ClientModeRuntime = class {
|
|
|
20669
20878
|
}
|
|
20670
20879
|
if (endpoint === "host.registration-code.submit") {
|
|
20671
20880
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
20672
|
-
const value =
|
|
20881
|
+
const value = record4(payload);
|
|
20673
20882
|
if (typeof value.code !== "string" || value.code.trim() === "") {
|
|
20674
20883
|
throw new ClientModeError("INVALID_MESSAGE", "A Host registration code is required.");
|
|
20675
20884
|
}
|
|
20676
20885
|
return ok2(await this.host.authorizeHostWithCode(value.code));
|
|
20677
20886
|
}
|
|
20678
20887
|
if (endpoint === "mode.set") {
|
|
20679
|
-
const value =
|
|
20888
|
+
const value = record4(payload);
|
|
20680
20889
|
if (value.mode !== "local" && value.mode !== "remote") throw new ClientModeError("INVALID_MESSAGE", "Mode must be local or remote.");
|
|
20681
20890
|
return ok2(await this.setMode(value.mode, typeof value.targetDeviceId === "string" ? value.targetDeviceId : void 0, signal));
|
|
20682
20891
|
}
|
|
@@ -20740,13 +20949,13 @@ function webrtcDiagnosticsLogFields(diagnostics) {
|
|
|
20740
20949
|
...diagnostics.selectedPath === void 0 ? {} : { rtcSelectedPath: diagnostics.selectedPath }
|
|
20741
20950
|
};
|
|
20742
20951
|
}
|
|
20743
|
-
function
|
|
20952
|
+
function record4(value) {
|
|
20744
20953
|
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
20745
20954
|
throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
|
|
20746
20955
|
}
|
|
20747
20956
|
return value;
|
|
20748
20957
|
}
|
|
20749
|
-
function
|
|
20958
|
+
function isRecord8(value) {
|
|
20750
20959
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
20751
20960
|
}
|
|
20752
20961
|
function ok2(value) {
|
|
@@ -20771,11 +20980,11 @@ async function readRemoteWorkspaceBaseline(gateway, signal) {
|
|
|
20771
20980
|
const iterator = source[Symbol.asyncIterator]();
|
|
20772
20981
|
try {
|
|
20773
20982
|
const first = await iterator.next();
|
|
20774
|
-
if (first.done || !
|
|
20983
|
+
if (first.done || !isRecord8(first.value) || first.value.type !== "baseline" || !isRecord8(first.value.value) || !Array.isArray(first.value.value.items)) {
|
|
20775
20984
|
throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned an invalid Workspace baseline.");
|
|
20776
20985
|
}
|
|
20777
20986
|
return first.value.value.items.map((item) => {
|
|
20778
|
-
if (!
|
|
20987
|
+
if (!isRecord8(item) || typeof item.workspaceId !== "string" || typeof item.path !== "string" || typeof item.title !== "string") {
|
|
20779
20988
|
throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned an invalid Workspace row.");
|
|
20780
20989
|
}
|
|
20781
20990
|
return { workspaceId: item.workspaceId, path: item.path, title: item.title };
|
|
@@ -20841,7 +21050,7 @@ async function probeRemoteHostFeatures(client, clientVersion) {
|
|
|
20841
21050
|
if (error instanceof Error && "code" in error && error.code === "METHOD_NOT_FOUND") return fallback;
|
|
20842
21051
|
throw error;
|
|
20843
21052
|
}
|
|
20844
|
-
if (!
|
|
21053
|
+
if (!isRecord8(value) || !Array.isArray(value.capabilities) || value.capabilities.some((capability) => typeof capability !== "string")) {
|
|
20845
21054
|
throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned invalid transport capabilities.");
|
|
20846
21055
|
}
|
|
20847
21056
|
const capabilities = new Set(value.capabilities);
|
|
@@ -20870,7 +21079,7 @@ async function probeRemoteHostFeatures(client, clientVersion) {
|
|
|
20870
21079
|
}
|
|
20871
21080
|
async function waitForCodexFrames(stream, signal) {
|
|
20872
21081
|
if (signal?.aborted) throw new ClientModeError("RPC_ABORTED", "The Codex event poll was cancelled.");
|
|
20873
|
-
await new Promise((
|
|
21082
|
+
await new Promise((resolve4, reject) => {
|
|
20874
21083
|
const previousWake = stream.wake;
|
|
20875
21084
|
const timer = setTimeout(done, 25e3);
|
|
20876
21085
|
const onAbort = () => {
|
|
@@ -20884,7 +21093,7 @@ async function waitForCodexFrames(stream, signal) {
|
|
|
20884
21093
|
}
|
|
20885
21094
|
function done() {
|
|
20886
21095
|
cleanup();
|
|
20887
|
-
|
|
21096
|
+
resolve4();
|
|
20888
21097
|
}
|
|
20889
21098
|
stream.wake = () => {
|
|
20890
21099
|
previousWake();
|
|
@@ -20977,24 +21186,24 @@ var IdentityStore = class {
|
|
|
20977
21186
|
}
|
|
20978
21187
|
if (!hasDevice) {
|
|
20979
21188
|
const keys = generateKeyPair();
|
|
20980
|
-
const
|
|
20981
|
-
await atomicJsonWrite(devicePath,
|
|
21189
|
+
const record7 = { schemaVersion: 1, deviceId: uuidV7(), name: deviceName, publicKey: keys.publicKey };
|
|
21190
|
+
await atomicJsonWrite(devicePath, record7, 384);
|
|
20982
21191
|
await atomicTextWrite(keyPath, `${keys.privateKey}
|
|
20983
21192
|
`, 384);
|
|
20984
21193
|
}
|
|
20985
21194
|
await assertPrivateMode2(keyPath);
|
|
20986
21195
|
try {
|
|
20987
|
-
let
|
|
21196
|
+
let record7 = identitySchema.parse(JSON.parse(await readFile3(devicePath, "utf8")));
|
|
20988
21197
|
const privateKey = (await readFile3(keyPath, "utf8")).trim();
|
|
20989
21198
|
const regenerated = generateKeyPair(fromBase64Url2(privateKey));
|
|
20990
|
-
if (regenerated.publicKey !==
|
|
21199
|
+
if (regenerated.publicKey !== record7.publicKey) {
|
|
20991
21200
|
throw new IdentityInvalidError("device public and private keys do not match");
|
|
20992
21201
|
}
|
|
20993
|
-
if (
|
|
20994
|
-
|
|
20995
|
-
await atomicJsonWrite(devicePath,
|
|
21202
|
+
if (record7.name !== deviceName) {
|
|
21203
|
+
record7 = { ...record7, name: deviceName };
|
|
21204
|
+
await atomicJsonWrite(devicePath, record7, 384);
|
|
20996
21205
|
}
|
|
20997
|
-
this.identity = { ...
|
|
21206
|
+
this.identity = { ...record7, privateKey, fingerprint: fingerprint(record7.publicKey) };
|
|
20998
21207
|
await this.loadPeers();
|
|
20999
21208
|
return this.identity;
|
|
21000
21209
|
} catch (error) {
|
|
@@ -21298,7 +21507,7 @@ var PluginControlRuntime = class {
|
|
|
21298
21507
|
if (endpoint === "devices") return ok3([]);
|
|
21299
21508
|
if (endpoint === "host.account.login") {
|
|
21300
21509
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
21301
|
-
const value =
|
|
21510
|
+
const value = record5(payload);
|
|
21302
21511
|
if (typeof value.email !== "string" || typeof value.password !== "string") {
|
|
21303
21512
|
throw new ClientModeError("INVALID_MESSAGE", "Email and password are required.");
|
|
21304
21513
|
}
|
|
@@ -21306,13 +21515,13 @@ var PluginControlRuntime = class {
|
|
|
21306
21515
|
}
|
|
21307
21516
|
if (endpoint === "host.registration-code.submit") {
|
|
21308
21517
|
if (this.host === void 0) throw new ClientModeError("METHOD_NOT_ALLOWED", "This plugin is not running as a Host.");
|
|
21309
|
-
const value =
|
|
21518
|
+
const value = record5(payload);
|
|
21310
21519
|
if (typeof value.code !== "string" || value.code.trim() === "") {
|
|
21311
21520
|
throw new ClientModeError("INVALID_MESSAGE", "A Host registration code is required.");
|
|
21312
21521
|
}
|
|
21313
21522
|
return ok3(await this.host.authorizeHostWithCode(value.code));
|
|
21314
21523
|
}
|
|
21315
|
-
if (endpoint === "mode.set" &&
|
|
21524
|
+
if (endpoint === "mode.set" && record5(payload).mode === "local") return ok3(this.hostOnlyStatus());
|
|
21316
21525
|
throw new ClientModeError("METHOD_NOT_ALLOWED", "Remote Client mode is disabled by the plugin role.");
|
|
21317
21526
|
} catch (error) {
|
|
21318
21527
|
return fail3(error);
|
|
@@ -21322,7 +21531,7 @@ var PluginControlRuntime = class {
|
|
|
21322
21531
|
if (this.settings === void 0) {
|
|
21323
21532
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
21324
21533
|
}
|
|
21325
|
-
const value =
|
|
21534
|
+
const value = record5(payload);
|
|
21326
21535
|
if (value.role !== "host" && value.role !== "client") {
|
|
21327
21536
|
throw new ClientModeError("INVALID_MESSAGE", "Role must be Host or Client.");
|
|
21328
21537
|
}
|
|
@@ -21357,7 +21566,7 @@ var PluginControlRuntime = class {
|
|
|
21357
21566
|
if (this.settings === void 0) {
|
|
21358
21567
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
21359
21568
|
}
|
|
21360
|
-
const value =
|
|
21569
|
+
const value = record5(payload);
|
|
21361
21570
|
if (typeof value.serverUrl !== "string") {
|
|
21362
21571
|
throw new ClientModeError("INVALID_MESSAGE", "Server URL is required.");
|
|
21363
21572
|
}
|
|
@@ -21370,7 +21579,7 @@ var PluginControlRuntime = class {
|
|
|
21370
21579
|
if (this.settings === void 0) {
|
|
21371
21580
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
21372
21581
|
}
|
|
21373
|
-
const role =
|
|
21582
|
+
const role = record5(payload).role;
|
|
21374
21583
|
if (role !== "host" && role !== "client") {
|
|
21375
21584
|
throw new ClientModeError("INVALID_MESSAGE", "Role must be Host or Client.");
|
|
21376
21585
|
}
|
|
@@ -21384,7 +21593,7 @@ var PluginControlRuntime = class {
|
|
|
21384
21593
|
}
|
|
21385
21594
|
async setDevelopment(payload) {
|
|
21386
21595
|
if (this.settings === void 0) throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
21387
|
-
const value =
|
|
21596
|
+
const value = record5(payload);
|
|
21388
21597
|
if (value.terminalEnabled !== void 0 && typeof value.terminalEnabled !== "boolean") throw new ClientModeError("INVALID_MESSAGE", "The terminal switch must be a boolean.");
|
|
21389
21598
|
if (value.ports !== void 0 && (!Array.isArray(value.ports) || value.ports.some((port) => !Number.isInteger(port)))) throw new ClientModeError("INVALID_MESSAGE", "Loopback ports must be integers.");
|
|
21390
21599
|
if (value.terminalEnabled === void 0 && value.ports === void 0) throw new ClientModeError("INVALID_MESSAGE", "A terminal switch or loopback ports are required.");
|
|
@@ -21403,7 +21612,7 @@ var PluginControlRuntime = class {
|
|
|
21403
21612
|
if (this.settings === void 0) {
|
|
21404
21613
|
throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
21405
21614
|
}
|
|
21406
|
-
const enabled =
|
|
21615
|
+
const enabled = record5(payload).enabled;
|
|
21407
21616
|
if (typeof enabled !== "boolean") {
|
|
21408
21617
|
throw new ClientModeError("INVALID_MESSAGE", "Codex Remote enabled must be a boolean.");
|
|
21409
21618
|
}
|
|
@@ -21417,16 +21626,18 @@ var PluginControlRuntime = class {
|
|
|
21417
21626
|
}
|
|
21418
21627
|
async setAcp(payload) {
|
|
21419
21628
|
if (this.settings === void 0) throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
21420
|
-
const value =
|
|
21421
|
-
|
|
21629
|
+
const value = record5(payload);
|
|
21630
|
+
const backend = value.backend;
|
|
21631
|
+
const enabled = value.enabled;
|
|
21632
|
+
if (typeof backend !== "string" || typeof enabled !== "boolean") throw new ClientModeError("INVALID_MESSAGE", "ACP backend and enabled are required.");
|
|
21422
21633
|
const current = resolveConfig(this.settings.get());
|
|
21423
|
-
const backends = current.acp?.backends.map((item) => item.id ===
|
|
21634
|
+
const backends = current.acp?.backends.map((item) => item.id === backend ? { ...item, enabled } : item) ?? [];
|
|
21424
21635
|
await this.settings.replace({ ...editableConfig(current), acp: { enabled: current.acp?.enabled ?? true, backends } });
|
|
21425
21636
|
return this.settingsView();
|
|
21426
21637
|
}
|
|
21427
21638
|
async addAcp(payload) {
|
|
21428
21639
|
if (this.settings === void 0) throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
21429
|
-
const value =
|
|
21640
|
+
const value = record5(payload);
|
|
21430
21641
|
if (typeof value.id !== "string" || typeof value.command !== "string" || !Array.isArray(value.args) || !value.args.every((item) => typeof item === "string")) {
|
|
21431
21642
|
throw new ClientModeError("INVALID_MESSAGE", "ACP name, command, and arguments are required.");
|
|
21432
21643
|
}
|
|
@@ -21439,7 +21650,7 @@ var PluginControlRuntime = class {
|
|
|
21439
21650
|
}
|
|
21440
21651
|
async removeAcp(payload) {
|
|
21441
21652
|
if (this.settings === void 0) throw new ClientModeError("SETTINGS_UNAVAILABLE", "DSH user settings are unavailable in this profile.");
|
|
21442
|
-
const id4 =
|
|
21653
|
+
const id4 = record5(payload).id;
|
|
21443
21654
|
if (typeof id4 !== "string" || ["codex", "cursor", "kimi"].includes(id4)) throw new ClientModeError("INVALID_MESSAGE", "Only custom ACP backends can be removed.");
|
|
21444
21655
|
const current = resolveConfig(this.settings.get());
|
|
21445
21656
|
const backends = (current.acp?.backends ?? []).filter((item) => item.id !== id4);
|
|
@@ -21552,11 +21763,11 @@ function editableConfig(config) {
|
|
|
21552
21763
|
...config.acp === void 0 ? {} : { acp: { enabled: config.acp.enabled, backends: config.acp.backends } }
|
|
21553
21764
|
};
|
|
21554
21765
|
}
|
|
21555
|
-
function
|
|
21766
|
+
function isRecord9(value) {
|
|
21556
21767
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
21557
21768
|
}
|
|
21558
|
-
function
|
|
21559
|
-
if (!
|
|
21769
|
+
function record5(value) {
|
|
21770
|
+
if (!isRecord9(value)) throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
|
|
21560
21771
|
return value;
|
|
21561
21772
|
}
|
|
21562
21773
|
function ok3(value) {
|
|
@@ -21608,6 +21819,13 @@ function redact(value, key = "") {
|
|
|
21608
21819
|
return Object.fromEntries(Object.entries(value).map(([childKey, child]) => [childKey, redact(child, childKey)]));
|
|
21609
21820
|
}
|
|
21610
21821
|
|
|
21822
|
+
// src/codex/session-id.ts
|
|
21823
|
+
function parseCodexSessionId(value) {
|
|
21824
|
+
if (typeof value !== "string") return void 0;
|
|
21825
|
+
const match = /^codex:([A-Za-z0-9][A-Za-z0-9._-]{0,255})$/.exec(value);
|
|
21826
|
+
return match === null ? void 0 : { sessionId: value, threadId: match[1] };
|
|
21827
|
+
}
|
|
21828
|
+
|
|
21611
21829
|
// src/terminal-policy.ts
|
|
21612
21830
|
var TERMINAL_CALLS = /* @__PURE__ */ new Set([
|
|
21613
21831
|
"terminal/environment",
|
|
@@ -21620,7 +21838,7 @@ var TERMINAL_CALLS = /* @__PURE__ */ new Set([
|
|
|
21620
21838
|
"terminal/close"
|
|
21621
21839
|
]);
|
|
21622
21840
|
var TERMINAL_STREAMS = /* @__PURE__ */ new Set(["terminal/follow", "terminal/retain"]);
|
|
21623
|
-
var id2 = external_exports.string().regex(/^[
|
|
21841
|
+
var id2 = external_exports.string().regex(/^[A-Za-z0-9_:-]{1,256}$/);
|
|
21624
21842
|
var TerminalPolicy = class {
|
|
21625
21843
|
constructor(enabled, deviceId, owners) {
|
|
21626
21844
|
this.enabled = enabled;
|
|
@@ -21634,7 +21852,10 @@ var TerminalPolicy = class {
|
|
|
21634
21852
|
"Remote terminal is disabled on this Host. Enable Remote terminal in the Host Remote settings; the switch saves and applies immediately. / \u8FDC\u7A0B\u7EC8\u7AEF\u672A\u5F00\u542F\uFF0C\u8BF7\u5728 Host \u7684 Remote \u8BBE\u7F6E\u4E2D\u5F00\u542F\u300C\u8FDC\u7A0B\u7EC8\u7AEF\u300D\uFF0C\u5F00\u5173\u5207\u6362\u540E\u7ACB\u5373\u4FDD\u5B58\u5E76\u751F\u6548\u3002"
|
|
21635
21853
|
);
|
|
21636
21854
|
const args = external_exports.object({ args: external_exports.record(external_exports.unknown()) }).strict().parse(payload).args;
|
|
21637
|
-
const
|
|
21855
|
+
const rawSessionId = args.agentId ?? args.sessionId;
|
|
21856
|
+
const sessionId = id2.parse(rawSessionId);
|
|
21857
|
+
const codexSession = parseCodexSessionId(sessionId);
|
|
21858
|
+
void codexSession;
|
|
21638
21859
|
if (endpoint === "terminal/environment" || endpoint === "terminal/shells" || endpoint === "terminal/list") return {};
|
|
21639
21860
|
const request = endpoint === "terminal/create" ? external_exports.object({ id: id2 }).passthrough().parse(args.request) : void 0;
|
|
21640
21861
|
const terminalId = id2.parse(request?.id ?? args.id);
|
|
@@ -22334,7 +22555,7 @@ var HostServerConnection = class {
|
|
|
22334
22555
|
this.controlFrameLimits = {};
|
|
22335
22556
|
let acknowledged = false;
|
|
22336
22557
|
let messageQueue = Promise.resolve();
|
|
22337
|
-
await new Promise((
|
|
22558
|
+
await new Promise((resolve4, reject) => {
|
|
22338
22559
|
let settled = false;
|
|
22339
22560
|
const helloTimer = setTimeout(() => socket.close(4001, "hello timeout"), 1e4);
|
|
22340
22561
|
const finish = (error) => {
|
|
@@ -22343,7 +22564,7 @@ var HostServerConnection = class {
|
|
|
22343
22564
|
clearTimeout(helloTimer);
|
|
22344
22565
|
this.online = false;
|
|
22345
22566
|
if (this.socket === socket) this.socket = void 0;
|
|
22346
|
-
void this.dropTunnels().finally(() => error === void 0 ?
|
|
22567
|
+
void this.dropTunnels().finally(() => error === void 0 ? resolve4() : reject(error));
|
|
22347
22568
|
};
|
|
22348
22569
|
socket.onopen = () => {
|
|
22349
22570
|
this.sendControl("hello", {
|
|
@@ -22881,14 +23102,14 @@ var HostServerConnection = class {
|
|
|
22881
23102
|
waitBeforeRetry(baseDelay) {
|
|
22882
23103
|
const spread = baseDelay * this.config.reconnect.jitter;
|
|
22883
23104
|
const delay = Math.max(0, Math.round(baseDelay - spread + Math.random() * spread * 2));
|
|
22884
|
-
return new Promise((
|
|
23105
|
+
return new Promise((resolve4) => {
|
|
22885
23106
|
const timer = setTimeout(() => {
|
|
22886
23107
|
this.retryWake = void 0;
|
|
22887
|
-
|
|
23108
|
+
resolve4();
|
|
22888
23109
|
}, delay);
|
|
22889
23110
|
this.retryWake = () => {
|
|
22890
23111
|
clearTimeout(timer);
|
|
22891
|
-
|
|
23112
|
+
resolve4();
|
|
22892
23113
|
};
|
|
22893
23114
|
});
|
|
22894
23115
|
}
|
|
@@ -23142,6 +23363,58 @@ function crumbs(path) {
|
|
|
23142
23363
|
return result;
|
|
23143
23364
|
}
|
|
23144
23365
|
|
|
23366
|
+
// src/harness-api-history.ts
|
|
23367
|
+
var SESSION_HISTORY_PAGE_SIZES = [50, 30, 20, 12, 6, 3, 1];
|
|
23368
|
+
function callSessionHistory(callWithTimeout, payload, rpcId2) {
|
|
23369
|
+
const fallbackPageSizes = sessionHistoryFallbackPageSizes(payloadMaxMessages(payload));
|
|
23370
|
+
return callHistoryWithRetry(callWithTimeout, payload, rpcId2, fallbackPageSizes);
|
|
23371
|
+
}
|
|
23372
|
+
async function callHistoryWithRetry(callWithTimeout, payload, rpcId2, pageSizes) {
|
|
23373
|
+
for (const maxMessages of pageSizes) {
|
|
23374
|
+
const requestPayload = historyRequestPayload(payload, maxMessages);
|
|
23375
|
+
const response = await callWithTimeout(requestPayload);
|
|
23376
|
+
const request = createRpcResponse(rpcId2, response.result);
|
|
23377
|
+
if (encodeMessage(request).byteLength <= MAX_SECURE_MESSAGE_BYTES) return response;
|
|
23378
|
+
if (maxMessages === pageSizes[pageSizes.length - 1]) {
|
|
23379
|
+
throw new RpcError(
|
|
23380
|
+
"RESPONSE_TOO_LARGE",
|
|
23381
|
+
"The Host response is too large for the remote channel. Request a smaller page.",
|
|
23382
|
+
{ maxBytes: MAX_SECURE_MESSAGE_BYTES },
|
|
23383
|
+
true
|
|
23384
|
+
);
|
|
23385
|
+
}
|
|
23386
|
+
}
|
|
23387
|
+
throw new RpcError("INTERNAL_ERROR", "Failed to load session history with a fallback page size.");
|
|
23388
|
+
}
|
|
23389
|
+
function sessionHistoryFallbackPageSizes(requestedMaxMessages) {
|
|
23390
|
+
const requested = normalizeSessionHistoryPageSize(requestedMaxMessages);
|
|
23391
|
+
const sizes = [];
|
|
23392
|
+
if (requested === void 0) {
|
|
23393
|
+
sizes.push(...SESSION_HISTORY_PAGE_SIZES);
|
|
23394
|
+
return sizes;
|
|
23395
|
+
}
|
|
23396
|
+
sizes.push(requested);
|
|
23397
|
+
for (const value of SESSION_HISTORY_PAGE_SIZES) {
|
|
23398
|
+
if (value < requested && !sizes.includes(value)) sizes.push(value);
|
|
23399
|
+
}
|
|
23400
|
+
return sizes;
|
|
23401
|
+
}
|
|
23402
|
+
function normalizeSessionHistoryPageSize(value) {
|
|
23403
|
+
if (value === void 0) return void 0;
|
|
23404
|
+
if (!Number.isInteger(value)) return void 0;
|
|
23405
|
+
if (value <= 0) return void 0;
|
|
23406
|
+
return Math.max(1, value);
|
|
23407
|
+
}
|
|
23408
|
+
function payloadMaxMessages(payload) {
|
|
23409
|
+
if (payload === null || typeof payload !== "object") return void 0;
|
|
23410
|
+
const value = payload.maxMessages;
|
|
23411
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
|
|
23412
|
+
}
|
|
23413
|
+
function historyRequestPayload(payload, maxMessages) {
|
|
23414
|
+
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) return { maxMessages };
|
|
23415
|
+
return { ...payload, maxMessages };
|
|
23416
|
+
}
|
|
23417
|
+
|
|
23145
23418
|
// src/harness-api-bridge.ts
|
|
23146
23419
|
var callSchema2 = external_exports.object({
|
|
23147
23420
|
method: external_exports.string().min(1).max(80),
|
|
@@ -23313,7 +23586,6 @@ var NATIVE_CALL_TIMEOUT_MS = 3e4;
|
|
|
23313
23586
|
var MAX_ACTIVE_API_TRANSFERS = MAX_ACTIVE_TRANSFERS_PER_DIRECTION;
|
|
23314
23587
|
var API_TRANSFER_IDLE_MS = TRANSFER_IDLE_MS;
|
|
23315
23588
|
var INLINE_TRANSFER_RESPONSE_BYTES = 2 * 1024 * 1024;
|
|
23316
|
-
var SESSION_HISTORY_PAGE_SIZES = [50, 30, 20, 12, 6, 3, 1];
|
|
23317
23589
|
var HarnessApiBridge = class {
|
|
23318
23590
|
constructor(api, publish, maxStreams = 8, logger, typertGateway, harnessVersion) {
|
|
23319
23591
|
this.api = api;
|
|
@@ -23871,57 +24143,8 @@ function frameSessionId(frame) {
|
|
|
23871
24143
|
const payload = frame.payload;
|
|
23872
24144
|
return typeof payload.sessionId === "string" && payload.sessionId.length > 0 ? payload.sessionId : void 0;
|
|
23873
24145
|
}
|
|
23874
|
-
function callSessionHistory(callWithTimeout, payload, rpcId2) {
|
|
23875
|
-
const fallbackPageSizes = sessionHistoryFallbackPageSizes(payloadMaxMessages(payload));
|
|
23876
|
-
return callHistoryWithRetry(callWithTimeout, payload, rpcId2, fallbackPageSizes);
|
|
23877
|
-
}
|
|
23878
|
-
async function callHistoryWithRetry(callWithTimeout, payload, rpcId2, pageSizes) {
|
|
23879
|
-
for (const maxMessages of pageSizes) {
|
|
23880
|
-
const requestPayload = historyRequestPayload(payload, maxMessages);
|
|
23881
|
-
const response = await callWithTimeout(requestPayload);
|
|
23882
|
-
const request = createRpcResponse(rpcId2, response.result);
|
|
23883
|
-
if (encodeMessage(request).byteLength <= MAX_SECURE_MESSAGE_BYTES) return response;
|
|
23884
|
-
if (maxMessages === pageSizes[pageSizes.length - 1]) {
|
|
23885
|
-
throw new RpcError(
|
|
23886
|
-
"RESPONSE_TOO_LARGE",
|
|
23887
|
-
"The Host response is too large for the remote channel. Request a smaller page.",
|
|
23888
|
-
{ maxBytes: MAX_SECURE_MESSAGE_BYTES },
|
|
23889
|
-
true
|
|
23890
|
-
);
|
|
23891
|
-
}
|
|
23892
|
-
}
|
|
23893
|
-
throw new RpcError("INTERNAL_ERROR", "Failed to load session history with a fallback page size.");
|
|
23894
|
-
}
|
|
23895
|
-
function sessionHistoryFallbackPageSizes(requestedMaxMessages) {
|
|
23896
|
-
const requested = normalizeSessionHistoryPageSize(requestedMaxMessages);
|
|
23897
|
-
const sizes = [];
|
|
23898
|
-
if (requested === void 0) {
|
|
23899
|
-
sizes.push(...SESSION_HISTORY_PAGE_SIZES);
|
|
23900
|
-
return sizes;
|
|
23901
|
-
}
|
|
23902
|
-
sizes.push(requested);
|
|
23903
|
-
for (const value of SESSION_HISTORY_PAGE_SIZES) {
|
|
23904
|
-
if (value < requested && !sizes.includes(value)) sizes.push(value);
|
|
23905
|
-
}
|
|
23906
|
-
return sizes;
|
|
23907
|
-
}
|
|
23908
|
-
function normalizeSessionHistoryPageSize(value) {
|
|
23909
|
-
if (value === void 0) return void 0;
|
|
23910
|
-
if (!Number.isInteger(value)) return void 0;
|
|
23911
|
-
if (value <= 0) return void 0;
|
|
23912
|
-
return Math.max(1, value);
|
|
23913
|
-
}
|
|
23914
|
-
function payloadMaxMessages(payload) {
|
|
23915
|
-
if (payload === null || typeof payload !== "object") return void 0;
|
|
23916
|
-
const value = payload.maxMessages;
|
|
23917
|
-
return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
|
|
23918
|
-
}
|
|
23919
|
-
function historyRequestPayload(payload, maxMessages) {
|
|
23920
|
-
if (payload === null || typeof payload !== "object" || Array.isArray(payload)) return { maxMessages };
|
|
23921
|
-
return { ...payload, maxMessages };
|
|
23922
|
-
}
|
|
23923
24146
|
function withTimeout(promise, ms, message) {
|
|
23924
|
-
return new Promise((
|
|
24147
|
+
return new Promise((resolve4, reject) => {
|
|
23925
24148
|
const timer = setTimeout(() => {
|
|
23926
24149
|
reject(new RpcError("TIMEOUT", message, void 0, true));
|
|
23927
24150
|
}, ms);
|
|
@@ -23929,7 +24152,7 @@ function withTimeout(promise, ms, message) {
|
|
|
23929
24152
|
promise.then(
|
|
23930
24153
|
(value) => {
|
|
23931
24154
|
clearTimeout(timer);
|
|
23932
|
-
|
|
24155
|
+
resolve4(value);
|
|
23933
24156
|
},
|
|
23934
24157
|
(error) => {
|
|
23935
24158
|
clearTimeout(timer);
|
|
@@ -24032,6 +24255,7 @@ var HARNESS_REMOTE_ALLOWLIST = [
|
|
|
24032
24255
|
"messageFeedback/list",
|
|
24033
24256
|
"messageFeedback/put",
|
|
24034
24257
|
"pluginInventory/list",
|
|
24258
|
+
"permissionPresets/catalog",
|
|
24035
24259
|
"session/attachment",
|
|
24036
24260
|
"session/cancel",
|
|
24037
24261
|
"session/canOpenWorkspacePath",
|
|
@@ -24075,12 +24299,13 @@ var HARNESS_REMOTE_ALLOWLIST = [
|
|
|
24075
24299
|
];
|
|
24076
24300
|
var allowedEndpoints = new Set(HARNESS_REMOTE_ALLOWLIST);
|
|
24077
24301
|
var HarnessRemoteBridge = class {
|
|
24078
|
-
constructor(gateway, publish, logger, harnessVersion, terminal = new TerminalPolicy(() => false, "", /* @__PURE__ */ new Map())) {
|
|
24302
|
+
constructor(gateway, publish, logger, harnessVersion, terminal = new TerminalPolicy(() => false, "", /* @__PURE__ */ new Map()), codexWorkspace) {
|
|
24079
24303
|
this.gateway = gateway;
|
|
24080
24304
|
this.publish = publish;
|
|
24081
24305
|
this.logger = logger;
|
|
24082
24306
|
this.harnessVersion = harnessVersion;
|
|
24083
24307
|
this.terminal = terminal;
|
|
24308
|
+
this.codexWorkspace = codexWorkspace;
|
|
24084
24309
|
}
|
|
24085
24310
|
streams = /* @__PURE__ */ new Map();
|
|
24086
24311
|
incomingTransfers = /* @__PURE__ */ new Map();
|
|
@@ -24096,13 +24321,26 @@ var HarnessRemoteBridge = class {
|
|
|
24096
24321
|
}
|
|
24097
24322
|
}
|
|
24098
24323
|
const reservation = params.endpoint.startsWith("terminal/") ? this.terminal.check(params.endpoint, params.payload) : void 0;
|
|
24324
|
+
let codexResult;
|
|
24325
|
+
if (this.codexWorkspace !== void 0) {
|
|
24326
|
+
try {
|
|
24327
|
+
codexResult = await this.codexWorkspace.call(params.endpoint, params.payload, AbortSignal.timeout(6e4));
|
|
24328
|
+
} catch (error) {
|
|
24329
|
+
if (reservation !== void 0) {
|
|
24330
|
+
this.terminal.result(params.endpoint, params.payload, { ok: false, error: { code: "FAILED", message: "", details: {} } }, reservation);
|
|
24331
|
+
}
|
|
24332
|
+
throw error;
|
|
24333
|
+
}
|
|
24334
|
+
}
|
|
24335
|
+
if (codexResult !== void 0) return reservation === void 0 ? codexResult : this.terminal.result(params.endpoint, params.payload, codexResult, reservation);
|
|
24099
24336
|
if (params.endpoint === "session/canOpenWorkspacePath") {
|
|
24100
24337
|
return { ok: true, value: true };
|
|
24101
24338
|
}
|
|
24102
24339
|
const startedAt = performance.now();
|
|
24103
24340
|
const signal = AbortSignal.timeout(6e4);
|
|
24104
24341
|
try {
|
|
24105
|
-
const
|
|
24342
|
+
const nativePayload = normalizeWorkspaceRequestPayload(params.endpoint, params.payload, this.harnessVersion);
|
|
24343
|
+
const nativeResult = params.endpoint === "commands/execute" ? await dispatchCommandForHost(this.gateway, params.payload, signal, this.harnessVersion) : await this.gateway.dispatch(params.endpoint, nativePayload, signal);
|
|
24106
24344
|
const result = params.endpoint === "directoryPicker/list" && needsDirectoryFallback(nativeResult) ? await this.directoryList(params.payload, signal) : nativeResult;
|
|
24107
24345
|
this.logger?.debug("harness remote call ok", {
|
|
24108
24346
|
endpoint: params.endpoint,
|
|
@@ -24248,7 +24486,7 @@ var HarnessRemoteBridge = class {
|
|
|
24248
24486
|
this.streams.set(params.streamId, { controller });
|
|
24249
24487
|
let source;
|
|
24250
24488
|
try {
|
|
24251
|
-
source = await this.gateway.open(params.endpoint, params.payload, controller.signal);
|
|
24489
|
+
source = (this.codexWorkspace === void 0 ? void 0 : await this.codexWorkspace.open(params.endpoint, params.payload, controller.signal)) ?? await this.gateway.open(params.endpoint, normalizeWorkspaceChangesPayload(params.endpoint, params.payload, this.harnessVersion), controller.signal);
|
|
24252
24490
|
controller.signal.throwIfAborted();
|
|
24253
24491
|
} catch (error) {
|
|
24254
24492
|
this.streams.delete(params.streamId);
|
|
@@ -24273,6 +24511,7 @@ var HarnessRemoteBridge = class {
|
|
|
24273
24511
|
this.incomingTransfers.clear();
|
|
24274
24512
|
this.outgoingTransfers.clear();
|
|
24275
24513
|
for (const [, stream] of streams) stream.controller.abort(reason);
|
|
24514
|
+
await this.codexWorkspace?.closeAll();
|
|
24276
24515
|
}
|
|
24277
24516
|
assertAllowed(endpoint) {
|
|
24278
24517
|
if (!allowedEndpoints.has(endpoint) && !TERMINAL_CALLS.has(endpoint) && !TERMINAL_STREAMS.has(endpoint)) {
|
|
@@ -24313,6 +24552,24 @@ var HarnessRemoteBridge = class {
|
|
|
24313
24552
|
for (const [id4, transfer] of this.outgoingTransfers) if (transfer.touchedAt < cutoff) this.outgoingTransfers.delete(id4);
|
|
24314
24553
|
}
|
|
24315
24554
|
};
|
|
24555
|
+
function normalizeWorkspaceChangesPayload(endpoint, payload, harnessVersion) {
|
|
24556
|
+
if (endpoint !== "workspaceFiles/changes" || !requiresWorkspaceChangePath(harnessVersion)) return payload;
|
|
24557
|
+
if (!isRecord10(payload) || !isRecord10(payload.args) || Object.hasOwn(payload.args, "path")) return payload;
|
|
24558
|
+
return { ...payload, args: { ...payload.args, path: "." } };
|
|
24559
|
+
}
|
|
24560
|
+
function normalizeWorkspaceRequestPayload(endpoint, payload, harnessVersion) {
|
|
24561
|
+
if (endpoint !== "workspaceFiles/readBytes" || !requiresWorkspaceChangePath(harnessVersion)) return payload;
|
|
24562
|
+
if (!isRecord10(payload) || !isRecord10(payload.args)) return payload;
|
|
24563
|
+
const args = payload.args;
|
|
24564
|
+
if (!Object.hasOwn(args, "range") || Object.hasOwn(args, "options")) return payload;
|
|
24565
|
+
const { range, ...rest } = args;
|
|
24566
|
+
return { ...payload, args: { ...rest, options: { range } } };
|
|
24567
|
+
}
|
|
24568
|
+
function requiresWorkspaceChangePath(version) {
|
|
24569
|
+
const match = /^(?:dsh-)?v?(\d+)\.(\d+)\.(\d+)(?:-|$)/u.exec(version?.trim() ?? "");
|
|
24570
|
+
if (match === null) return false;
|
|
24571
|
+
return Number(match[1]) === 0 && Number(match[2]) === 1 && Number(match[3]) >= 7;
|
|
24572
|
+
}
|
|
24316
24573
|
async function dispatchCommandForHost(gateway, payload, signal, harnessVersion) {
|
|
24317
24574
|
const parsed = commandExecutePayloadSchema.parse(payload);
|
|
24318
24575
|
const legacyPayload = {
|
|
@@ -24357,14 +24614,14 @@ function needsDirectoryFallback(result) {
|
|
|
24357
24614
|
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");
|
|
24358
24615
|
}
|
|
24359
24616
|
function requestArgs(payload) {
|
|
24360
|
-
const root =
|
|
24361
|
-
const args =
|
|
24362
|
-
return
|
|
24617
|
+
const root = record6(payload);
|
|
24618
|
+
const args = isRecord10(root.args) ? root.args : root;
|
|
24619
|
+
return record6(args.request ?? args._request ?? args);
|
|
24363
24620
|
}
|
|
24364
|
-
function
|
|
24365
|
-
return
|
|
24621
|
+
function record6(value) {
|
|
24622
|
+
return isRecord10(value) ? value : {};
|
|
24366
24623
|
}
|
|
24367
|
-
function
|
|
24624
|
+
function isRecord10(value) {
|
|
24368
24625
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24369
24626
|
}
|
|
24370
24627
|
|
|
@@ -24445,15 +24702,15 @@ var CodexAppServerClient = class {
|
|
|
24445
24702
|
const child = this.process;
|
|
24446
24703
|
this.process = void 0;
|
|
24447
24704
|
if (child === void 0 || child.exitCode !== null || child.killed) return;
|
|
24448
|
-
await new Promise((
|
|
24705
|
+
await new Promise((resolve4) => {
|
|
24449
24706
|
const timer = setTimeout(() => {
|
|
24450
24707
|
child.kill("SIGKILL");
|
|
24451
|
-
|
|
24708
|
+
resolve4();
|
|
24452
24709
|
}, 2e3);
|
|
24453
24710
|
timer.unref?.();
|
|
24454
24711
|
child.once("exit", () => {
|
|
24455
24712
|
clearTimeout(timer);
|
|
24456
|
-
|
|
24713
|
+
resolve4();
|
|
24457
24714
|
});
|
|
24458
24715
|
child.kill("SIGTERM");
|
|
24459
24716
|
});
|
|
@@ -24509,13 +24766,13 @@ var CodexAppServerClient = class {
|
|
|
24509
24766
|
}
|
|
24510
24767
|
request(method, params, timeoutMs) {
|
|
24511
24768
|
const id4 = this.nextId++;
|
|
24512
|
-
const result = new Promise((
|
|
24769
|
+
const result = new Promise((resolve4, reject) => {
|
|
24513
24770
|
const timer = setTimeout(() => {
|
|
24514
24771
|
this.pending.delete(id4);
|
|
24515
24772
|
reject(new CodexAppServerError("CODEX_REQUEST_TIMEOUT", "Codex App Server request timed out."));
|
|
24516
24773
|
}, timeoutMs);
|
|
24517
24774
|
timer.unref?.();
|
|
24518
|
-
this.pending.set(id4, { resolve:
|
|
24775
|
+
this.pending.set(id4, { resolve: resolve4, reject, timer });
|
|
24519
24776
|
});
|
|
24520
24777
|
try {
|
|
24521
24778
|
this.write({ id: id4, method, params });
|
|
@@ -24558,7 +24815,7 @@ var CodexAppServerClient = class {
|
|
|
24558
24815
|
this.handleProcessFailure("CODEX_INVALID_RESPONSE", new Error("Codex App Server emitted invalid JSON."));
|
|
24559
24816
|
return;
|
|
24560
24817
|
}
|
|
24561
|
-
if (!
|
|
24818
|
+
if (!isRecord11(value)) {
|
|
24562
24819
|
this.handleProcessFailure("CODEX_INVALID_RESPONSE", new Error("Codex App Server emitted an invalid message."));
|
|
24563
24820
|
return;
|
|
24564
24821
|
}
|
|
@@ -24603,12 +24860,12 @@ var CodexAppServerClient = class {
|
|
|
24603
24860
|
}
|
|
24604
24861
|
};
|
|
24605
24862
|
function safeUpstreamError(value) {
|
|
24606
|
-
if (!
|
|
24863
|
+
if (!isRecord11(value) || typeof value.message !== "string") return "Codex App Server rejected the request.";
|
|
24607
24864
|
const message = value.message.toLowerCase();
|
|
24608
24865
|
if (message.includes("active writer")) return "Codex thread already has an active writer.";
|
|
24609
24866
|
return message.includes("not initialized") ? "Codex App Server is not initialized." : "Codex App Server rejected the request.";
|
|
24610
24867
|
}
|
|
24611
|
-
function
|
|
24868
|
+
function isRecord11(value) {
|
|
24612
24869
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24613
24870
|
}
|
|
24614
24871
|
|
|
@@ -24977,15 +25234,15 @@ function decodeCanonicalBase643(value) {
|
|
|
24977
25234
|
}
|
|
24978
25235
|
return decoded;
|
|
24979
25236
|
}
|
|
24980
|
-
function
|
|
25237
|
+
function isRecord12(value) {
|
|
24981
25238
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24982
25239
|
}
|
|
24983
25240
|
function safeErrorCode2(error) {
|
|
24984
|
-
if (
|
|
25241
|
+
if (isRecord12(error) && typeof error.code === "string") return error.code;
|
|
24985
25242
|
return "UNKNOWN";
|
|
24986
25243
|
}
|
|
24987
25244
|
function safeMethod(input2) {
|
|
24988
|
-
return
|
|
25245
|
+
return isRecord12(input2) && typeof input2.method === "string" ? input2.method : "invalid";
|
|
24989
25246
|
}
|
|
24990
25247
|
function concatChunks3(chunks, totalBytes) {
|
|
24991
25248
|
const output = new Uint8Array(totalBytes);
|
|
@@ -25053,6 +25310,19 @@ var CodexRemoteDomain = class {
|
|
|
25053
25310
|
...this.unavailableCode === void 0 ? {} : { error: this.unavailableCode }
|
|
25054
25311
|
};
|
|
25055
25312
|
}
|
|
25313
|
+
/** Resolve a thread cwd for Host-owned workspace/terminal carriers. */
|
|
25314
|
+
async resolveThreadWorkspace(connectionId, threadId) {
|
|
25315
|
+
if (!this.peers.has(connectionId)) throw new RpcError("CODEX_THREAD_UNAVAILABLE", "The CodeX thread is not available on this connection.");
|
|
25316
|
+
try {
|
|
25317
|
+
const known = await this.readKnownThread(threadId);
|
|
25318
|
+
return known.cwd;
|
|
25319
|
+
} catch (error) {
|
|
25320
|
+
if (error instanceof RpcError && error.code === "CODEX_THREAD_NOT_ALLOWED") {
|
|
25321
|
+
throw new RpcError("CODEX_THREAD_UNAVAILABLE", "The CodeX thread is not available.");
|
|
25322
|
+
}
|
|
25323
|
+
throw new RpcError("CODEX_THREAD_UNAVAILABLE", "The CodeX thread is not available.");
|
|
25324
|
+
}
|
|
25325
|
+
}
|
|
25056
25326
|
createPeer(context, publish) {
|
|
25057
25327
|
if (!this.config.enabled) return void 0;
|
|
25058
25328
|
const bridge = new CodexPeerBridge(this, context, publish, this.logger);
|
|
@@ -25402,14 +25672,14 @@ var CodexRemoteDomain = class {
|
|
|
25402
25672
|
await this.assertResultThreadAllowed(result);
|
|
25403
25673
|
if (codexPermissionPresetFromResponse(result) !== params.permissionPreset) {
|
|
25404
25674
|
await this.callUpstream("thread/settings/update", { threadId, ...settings });
|
|
25405
|
-
result = { ...
|
|
25675
|
+
result = { ...isRecord13(result) ? result : {}, ...settings, sandbox: settings.sandboxPolicy };
|
|
25406
25676
|
}
|
|
25407
25677
|
}
|
|
25408
25678
|
await this.publishPermission(threadId, result);
|
|
25409
25679
|
return result;
|
|
25410
25680
|
}
|
|
25411
25681
|
async publishPermission(threadId, value) {
|
|
25412
|
-
const source =
|
|
25682
|
+
const source = isRecord13(value) ? value : {};
|
|
25413
25683
|
const threadSettings = { approvalPolicy: source.approvalPolicy, sandboxPolicy: source.sandboxPolicy ?? source.sandbox };
|
|
25414
25684
|
await this.handleInbound({ kind: "notification", method: "thread/settings/updated", params: { threadId, threadSettings } });
|
|
25415
25685
|
}
|
|
@@ -25505,9 +25775,9 @@ var CodexRemoteDomain = class {
|
|
|
25505
25775
|
itemsView,
|
|
25506
25776
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
25507
25777
|
});
|
|
25508
|
-
const pageResult =
|
|
25778
|
+
const pageResult = isRecord13(result) ? result : {};
|
|
25509
25779
|
for (const rawTurn of array2(pageResult.data)) {
|
|
25510
|
-
if (!
|
|
25780
|
+
if (!isRecord13(rawTurn)) continue;
|
|
25511
25781
|
const turnId = typeof rawTurn.id === "string" ? rawTurn.id : void 0;
|
|
25512
25782
|
const items = rawTurn.itemsView === "full" || turnId === void 0 ? array2(rawTurn.items) : await this.readThreadItems(connectionId, threadId, turnId, array2(rawTurn.items));
|
|
25513
25783
|
turns.push({ ...rawTurn, items });
|
|
@@ -25529,9 +25799,9 @@ var CodexRemoteDomain = class {
|
|
|
25529
25799
|
sortDirection: "asc",
|
|
25530
25800
|
...cursor2 === void 0 ? {} : { cursor: cursor2 }
|
|
25531
25801
|
});
|
|
25532
|
-
const pageResult =
|
|
25802
|
+
const pageResult = isRecord13(result) ? result : {};
|
|
25533
25803
|
for (const entry of array2(pageResult.data)) {
|
|
25534
|
-
if (
|
|
25804
|
+
if (isRecord13(entry) && entry.item !== void 0) items.push(entry.item);
|
|
25535
25805
|
}
|
|
25536
25806
|
cursor2 = typeof pageResult.nextCursor === "string" && pageResult.nextCursor.length > 0 ? pageResult.nextCursor : void 0;
|
|
25537
25807
|
if (cursor2 === void 0) break;
|
|
@@ -25595,7 +25865,7 @@ var CodexRemoteDomain = class {
|
|
|
25595
25865
|
return [...this.peers.values()].some((peer) => peer.hasThreadSubscription(threadId));
|
|
25596
25866
|
}
|
|
25597
25867
|
resolveUpstreamApproval(params) {
|
|
25598
|
-
if (!
|
|
25868
|
+
if (!isRecord13(params) || typeof params.requestId !== "string" && typeof params.requestId !== "number") return;
|
|
25599
25869
|
for (const [handle, approval] of this.approvals) {
|
|
25600
25870
|
if (approval.upstreamId === params.requestId) this.approvals.delete(handle);
|
|
25601
25871
|
}
|
|
@@ -25812,24 +26082,24 @@ function codexBinaryCandidates(configured, hostPlatform = process.platform, user
|
|
|
25812
26082
|
])];
|
|
25813
26083
|
}
|
|
25814
26084
|
function parseCallEnvelope(input2) {
|
|
25815
|
-
if (!
|
|
26085
|
+
if (!isRecord13(input2) || typeof input2.method !== "string" || !("params" in input2) || Object.keys(input2).some((key) => key !== "method" && key !== "params")) {
|
|
25816
26086
|
throw new RpcError("INVALID_MESSAGE", "The Codex call envelope is invalid.");
|
|
25817
26087
|
}
|
|
25818
26088
|
return { method: input2.method, params: input2.params };
|
|
25819
26089
|
}
|
|
25820
26090
|
function parseRespond(input2) {
|
|
25821
|
-
if (!
|
|
26091
|
+
if (!isRecord13(input2) || typeof input2.requestHandle !== "string" || !["accept", "decline", "cancel"].includes(String(input2.decision)) || Object.keys(input2).some((key) => key !== "requestHandle" && key !== "decision")) {
|
|
25822
26092
|
throw new RpcError("INVALID_MESSAGE", "The Codex approval response is invalid.");
|
|
25823
26093
|
}
|
|
25824
26094
|
return input2;
|
|
25825
26095
|
}
|
|
25826
26096
|
function accountCanRun(result) {
|
|
25827
|
-
if (!
|
|
25828
|
-
return result.requiresOpenaiAuth === false ||
|
|
26097
|
+
if (!isRecord13(result) || typeof result.requiresOpenaiAuth !== "boolean") return false;
|
|
26098
|
+
return result.requiresOpenaiAuth === false || isRecord13(result.account);
|
|
25829
26099
|
}
|
|
25830
26100
|
function sanitizeAccount(result) {
|
|
25831
|
-
if (!
|
|
25832
|
-
const account =
|
|
26101
|
+
if (!isRecord13(result)) throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned invalid account state.");
|
|
26102
|
+
const account = isRecord13(result.account) ? result.account : void 0;
|
|
25833
26103
|
return {
|
|
25834
26104
|
authenticated: account !== void 0 || result.requiresOpenaiAuth === false,
|
|
25835
26105
|
requiresOpenaiAuth: result.requiresOpenaiAuth === true,
|
|
@@ -25842,11 +26112,11 @@ function sanitizeAccount(result) {
|
|
|
25842
26112
|
};
|
|
25843
26113
|
}
|
|
25844
26114
|
function sanitizeThreadList(result) {
|
|
25845
|
-
if (!
|
|
26115
|
+
if (!isRecord13(result) || !Array.isArray(result.data)) {
|
|
25846
26116
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid thread list.");
|
|
25847
26117
|
}
|
|
25848
26118
|
const data2 = result.data.flatMap((value) => {
|
|
25849
|
-
if (!
|
|
26119
|
+
if (!isRecord13(value) || typeof value.id !== "string") return [];
|
|
25850
26120
|
return [{
|
|
25851
26121
|
id: value.id,
|
|
25852
26122
|
...typeof value.sessionId === "string" ? { sessionId: value.sessionId } : {},
|
|
@@ -25858,7 +26128,7 @@ function sanitizeThreadList(result) {
|
|
|
25858
26128
|
...typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt) ? { updatedAt: value.updatedAt } : {},
|
|
25859
26129
|
...typeof value.archived === "boolean" ? { archived: value.archived } : {},
|
|
25860
26130
|
...typeof value.isPinned === "boolean" ? { isPinned: value.isPinned } : {},
|
|
25861
|
-
...
|
|
26131
|
+
...isRecord13(value.status) ? { status: value.status } : {}
|
|
25862
26132
|
}];
|
|
25863
26133
|
});
|
|
25864
26134
|
return {
|
|
@@ -25868,18 +26138,18 @@ function sanitizeThreadList(result) {
|
|
|
25868
26138
|
};
|
|
25869
26139
|
}
|
|
25870
26140
|
function filterThreadListByWorkspaceAuthority(result, authority) {
|
|
25871
|
-
if (!
|
|
26141
|
+
if (!isRecord13(result) || !Array.isArray(result.data)) {
|
|
25872
26142
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid thread list.");
|
|
25873
26143
|
}
|
|
25874
26144
|
return {
|
|
25875
26145
|
...result,
|
|
25876
|
-
data: result.data.map((
|
|
26146
|
+
data: result.data.map((record7) => isRecord13(record7) ? record7 : void 0).filter((thread) => thread !== void 0 && isThreadAllowedByWorkspaceAuthority(thread, authority))
|
|
25877
26147
|
};
|
|
25878
26148
|
}
|
|
25879
26149
|
function sanitizeProject(value) {
|
|
25880
|
-
if (!
|
|
26150
|
+
if (!isRecord13(value) || typeof value.id !== "string" || typeof value.name !== "string") return void 0;
|
|
25881
26151
|
const roots = Array.isArray(value.roots) ? value.roots.flatMap((root) => {
|
|
25882
|
-
const path =
|
|
26152
|
+
const path = isRecord13(root) && typeof root.path === "string" && root.path.length > 0 ? root.path : void 0;
|
|
25883
26153
|
return path === void 0 || !isAbsolute3(path) ? [] : [{ path }];
|
|
25884
26154
|
}) : [];
|
|
25885
26155
|
if (roots.length === 0) return void 0;
|
|
@@ -25893,7 +26163,7 @@ function sanitizeProject(value) {
|
|
|
25893
26163
|
};
|
|
25894
26164
|
}
|
|
25895
26165
|
function sanitizeProjectList(result) {
|
|
25896
|
-
if (!
|
|
26166
|
+
if (!isRecord13(result) || !Array.isArray(result.data)) {
|
|
25897
26167
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid project list.");
|
|
25898
26168
|
}
|
|
25899
26169
|
const data2 = result.data.flatMap((value) => sanitizeProject(value) ?? []);
|
|
@@ -25903,7 +26173,7 @@ function sanitizeProjectList(result) {
|
|
|
25903
26173
|
};
|
|
25904
26174
|
}
|
|
25905
26175
|
function sanitizeProjectCreate(result) {
|
|
25906
|
-
const project =
|
|
26176
|
+
const project = isRecord13(result) ? sanitizeProject(result.project) : void 0;
|
|
25907
26177
|
if (project === void 0) {
|
|
25908
26178
|
throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid created project.");
|
|
25909
26179
|
}
|
|
@@ -25935,19 +26205,19 @@ function codexDirectoryCrumbs(root, path) {
|
|
|
25935
26205
|
return crumbs2;
|
|
25936
26206
|
}
|
|
25937
26207
|
function extractThread(result) {
|
|
25938
|
-
return
|
|
26208
|
+
return isRecord13(result) && isRecord13(result.thread) ? result.thread : void 0;
|
|
25939
26209
|
}
|
|
25940
26210
|
function extractTurnId(result) {
|
|
25941
|
-
if (!
|
|
26211
|
+
if (!isRecord13(result)) return void 0;
|
|
25942
26212
|
if (typeof result.turnId === "string" && result.turnId.length > 0) return result.turnId;
|
|
25943
|
-
if (
|
|
26213
|
+
if (isRecord13(result.turn) && typeof result.turn.id === "string" && result.turn.id.length > 0) return result.turn.id;
|
|
25944
26214
|
return void 0;
|
|
25945
26215
|
}
|
|
25946
26216
|
function extractThreadId(params) {
|
|
25947
|
-
if (!
|
|
26217
|
+
if (!isRecord13(params)) return void 0;
|
|
25948
26218
|
if (typeof params.threadId === "string") return params.threadId;
|
|
25949
|
-
if (
|
|
25950
|
-
if (
|
|
26219
|
+
if (isRecord13(params.thread) && typeof params.thread.id === "string") return params.thread.id;
|
|
26220
|
+
if (isRecord13(params.turn) && typeof params.turn.threadId === "string") return params.turn.threadId;
|
|
25951
26221
|
return void 0;
|
|
25952
26222
|
}
|
|
25953
26223
|
function optionalInteger2(value) {
|
|
@@ -25989,13 +26259,13 @@ function mapCodexImageInputs(params) {
|
|
|
25989
26259
|
return {
|
|
25990
26260
|
...params,
|
|
25991
26261
|
input: params.input.map((value) => {
|
|
25992
|
-
if (!
|
|
26262
|
+
if (!isRecord13(value) || value.type !== "image" || typeof value.mediaType !== "string" || typeof value.data !== "string") return value;
|
|
25993
26263
|
return { type: "image", url: `data:${value.mediaType};base64,${value.data}` };
|
|
25994
26264
|
})
|
|
25995
26265
|
};
|
|
25996
26266
|
}
|
|
25997
26267
|
function sanitizeApprovalParams(params, requestHandle) {
|
|
25998
|
-
if (!
|
|
26268
|
+
if (!isRecord13(params)) return { requestHandle };
|
|
25999
26269
|
const safe = { ...params };
|
|
26000
26270
|
delete safe.proposedExecpolicyAmendment;
|
|
26001
26271
|
delete safe.additionalPermissions;
|
|
@@ -26026,7 +26296,7 @@ function isProjectListFallbackError(error) {
|
|
|
26026
26296
|
function canTryNextBinary(error) {
|
|
26027
26297
|
return !(error instanceof RpcError) || !["CODEX_AUTH_REQUIRED", "CODEX_CLOSED"].includes(error.code);
|
|
26028
26298
|
}
|
|
26029
|
-
function
|
|
26299
|
+
function isRecord13(value) {
|
|
26030
26300
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26031
26301
|
}
|
|
26032
26302
|
function array2(value) {
|
|
@@ -26127,7 +26397,7 @@ var StdioAcpAdapter = class {
|
|
|
26127
26397
|
const c = this.ensure();
|
|
26128
26398
|
const id4 = this.nextId++;
|
|
26129
26399
|
c.stdin.write(JSON.stringify({ jsonrpc: "2.0", id: id4, method, params }) + "\n");
|
|
26130
|
-
return new Promise((
|
|
26400
|
+
return new Promise((resolve4, reject) => {
|
|
26131
26401
|
let buf = "";
|
|
26132
26402
|
const onData = async (d) => {
|
|
26133
26403
|
buf += d;
|
|
@@ -26138,7 +26408,7 @@ var StdioAcpAdapter = class {
|
|
|
26138
26408
|
const m = JSON.parse(l);
|
|
26139
26409
|
if (m.id === id4) {
|
|
26140
26410
|
c.stdout.off("data", onData);
|
|
26141
|
-
m.error ? reject(new Error(m.error.message ?? "ACP error")) :
|
|
26411
|
+
m.error ? reject(new Error(m.error.message ?? "ACP error")) : resolve4(m.result);
|
|
26142
26412
|
} else if (m.method && onNotification) await onNotification(m.params);
|
|
26143
26413
|
} catch {
|
|
26144
26414
|
}
|
|
@@ -26152,14 +26422,480 @@ var StdioAcpAdapter = class {
|
|
|
26152
26422
|
|
|
26153
26423
|
// src/service.ts
|
|
26154
26424
|
import { execFileSync as execFileSync2 } from "node:child_process";
|
|
26425
|
+
|
|
26426
|
+
// src/codex-workspace-bridge.ts
|
|
26427
|
+
import { spawn as spawn4 } from "node:child_process";
|
|
26428
|
+
import { realpath as realpath2, lstat, readdir as readdir3, readFile as readFile4, stat as stat5, watch } from "node:fs/promises";
|
|
26429
|
+
import { isAbsolute as isAbsolute4, join as join6, relative as relative2, resolve as resolve3 } from "node:path";
|
|
26430
|
+
var MAX_READ_BYTES = 4 * 1024 * 1024;
|
|
26431
|
+
var MAX_INPUT_BYTES = 64 * 1024;
|
|
26432
|
+
var MAX_COLS = 240;
|
|
26433
|
+
var MAX_ROWS = 100;
|
|
26434
|
+
var MAX_TERMINALS = 256;
|
|
26435
|
+
var MAX_SCREEN_BYTES = 256 * 1024;
|
|
26436
|
+
var TERMINAL_SCROLLBACK = 2e3;
|
|
26437
|
+
var TERMINAL_TYPE = "xterm-256color";
|
|
26438
|
+
var CodexWorkspaceState = class {
|
|
26439
|
+
terminals = /* @__PURE__ */ new Map();
|
|
26440
|
+
};
|
|
26441
|
+
var DEFAULT_SHELL = process.platform === "win32" ? { path: "cmd.exe", args: [], name: "Command Prompt" } : { path: "/bin/sh", args: [], name: "sh" };
|
|
26442
|
+
var AsyncQueue = class {
|
|
26443
|
+
values = [];
|
|
26444
|
+
waiters = [];
|
|
26445
|
+
ended = false;
|
|
26446
|
+
push(value) {
|
|
26447
|
+
if (this.ended) return;
|
|
26448
|
+
const waiter = this.waiters.shift();
|
|
26449
|
+
if (waiter) waiter({ done: false, value });
|
|
26450
|
+
else this.values.push(value);
|
|
26451
|
+
}
|
|
26452
|
+
end() {
|
|
26453
|
+
this.ended = true;
|
|
26454
|
+
while (this.waiters.length) this.waiters.shift()({ done: true, value: void 0 });
|
|
26455
|
+
}
|
|
26456
|
+
next() {
|
|
26457
|
+
const value = this.values.shift();
|
|
26458
|
+
if (value !== void 0) return Promise.resolve({ done: false, value });
|
|
26459
|
+
if (this.ended) return Promise.resolve({ done: true, value: void 0 });
|
|
26460
|
+
return new Promise((resolve4) => this.waiters.push(resolve4));
|
|
26461
|
+
}
|
|
26462
|
+
[Symbol.asyncIterator]() {
|
|
26463
|
+
return this;
|
|
26464
|
+
}
|
|
26465
|
+
};
|
|
26466
|
+
var CodexWorkspaceBridge = class {
|
|
26467
|
+
constructor(resolveCwd, terminalEnabled, state = new CodexWorkspaceState(), spawnTerminal = pipeTerminalSpawner()) {
|
|
26468
|
+
this.resolveCwd = resolveCwd;
|
|
26469
|
+
this.terminalEnabled = terminalEnabled;
|
|
26470
|
+
this.terminals = state.terminals;
|
|
26471
|
+
this.spawnTerminal = spawnTerminal;
|
|
26472
|
+
}
|
|
26473
|
+
terminals;
|
|
26474
|
+
ownedSubscribers = /* @__PURE__ */ new Set();
|
|
26475
|
+
spawnTerminal;
|
|
26476
|
+
isCodeXScope(value) {
|
|
26477
|
+
return parseCodexSessionId(value) !== void 0;
|
|
26478
|
+
}
|
|
26479
|
+
async call(endpoint, payload, signal) {
|
|
26480
|
+
const args = argsOf(payload);
|
|
26481
|
+
const scope = args.workspaceFileScopeId;
|
|
26482
|
+
const session = args.agentId ?? args.sessionId;
|
|
26483
|
+
const raw = scope ?? session;
|
|
26484
|
+
const codex = parseCodexSessionId(raw);
|
|
26485
|
+
if (codex === void 0) {
|
|
26486
|
+
if (typeof raw === "string" && raw.startsWith("codex:")) throw new RpcError("CODEX_SESSION_INVALID", "The CodeX session identifier is invalid.");
|
|
26487
|
+
return void 0;
|
|
26488
|
+
}
|
|
26489
|
+
if (endpoint.startsWith("workspaceFiles/")) return this.fileCall(endpoint, codex.sessionId, args, signal);
|
|
26490
|
+
if (endpoint.startsWith("terminal/")) return this.terminalCall(endpoint, codex.sessionId, args, signal);
|
|
26491
|
+
return void 0;
|
|
26492
|
+
}
|
|
26493
|
+
async open(endpoint, payload, signal) {
|
|
26494
|
+
const args = argsOf(payload);
|
|
26495
|
+
const raw = args.workspaceFileScopeId ?? args.agentId ?? args.sessionId;
|
|
26496
|
+
const codex = parseCodexSessionId(raw);
|
|
26497
|
+
if (codex === void 0) {
|
|
26498
|
+
if (typeof raw === "string" && raw.startsWith("codex:")) throw new RpcError("CODEX_SESSION_INVALID", "The CodeX session identifier is invalid.");
|
|
26499
|
+
return void 0;
|
|
26500
|
+
}
|
|
26501
|
+
if (endpoint === "workspaceFiles/changes") return this.watchChanges(codex.sessionId, args, signal);
|
|
26502
|
+
if (endpoint === "terminal/retain") return this.retain(codex.sessionId, args, signal);
|
|
26503
|
+
if (endpoint === "terminal/follow") return this.follow(codex.sessionId, args, signal);
|
|
26504
|
+
return void 0;
|
|
26505
|
+
}
|
|
26506
|
+
async closeAll() {
|
|
26507
|
+
for (const queue of this.ownedSubscribers) queue.end();
|
|
26508
|
+
this.ownedSubscribers.clear();
|
|
26509
|
+
}
|
|
26510
|
+
async fileCall(endpoint, sessionId, args, signal) {
|
|
26511
|
+
const root = await this.rootFor(sessionId, signal);
|
|
26512
|
+
const path = typeof args.path === "string" ? args.path : ".";
|
|
26513
|
+
const target2 = await this.safePath(root, path, endpoint === "workspaceFiles/list");
|
|
26514
|
+
try {
|
|
26515
|
+
if (endpoint === "workspaceFiles/list") {
|
|
26516
|
+
const entries = await readdir3(target2, { withFileTypes: true });
|
|
26517
|
+
const result = [];
|
|
26518
|
+
for (const entry of entries.slice(0, 500)) {
|
|
26519
|
+
const item = join6(target2, entry.name);
|
|
26520
|
+
const info2 = await lstat(item);
|
|
26521
|
+
if (info2.isSymbolicLink()) continue;
|
|
26522
|
+
result.push({ name: entry.name, type: info2.isDirectory() ? "directory" : info2.isFile() ? "file" : "other", ...info2.isFile() ? { size: info2.size } : {} });
|
|
26523
|
+
}
|
|
26524
|
+
return { ok: true, value: { path, entries: result, truncated: entries.length > 500 } };
|
|
26525
|
+
}
|
|
26526
|
+
const info = await stat5(target2);
|
|
26527
|
+
const absolutePath = target2;
|
|
26528
|
+
const version = `${info.mtimeMs}:${info.size}`;
|
|
26529
|
+
if (endpoint === "workspaceFiles/stat") {
|
|
26530
|
+
return { ok: true, value: { absolutePath, version, bytes: info.size } };
|
|
26531
|
+
}
|
|
26532
|
+
if (!info.isFile()) throw new RpcError("CODEX_WORKSPACE_INVALID_PATH", "The requested workspace path is not a file.");
|
|
26533
|
+
const offset = readOffset(args);
|
|
26534
|
+
const limit = readLimit(args);
|
|
26535
|
+
const bytes = await readFile4(target2);
|
|
26536
|
+
if (bytes.byteLength > MAX_READ_BYTES) throw new RpcError("CODEX_WORKSPACE_TOO_LARGE", "The requested workspace file is too large.");
|
|
26537
|
+
if (endpoint === "workspaceFiles/readBytes") {
|
|
26538
|
+
const slice2 = bytes.subarray(offset, Math.min(offset + limit, bytes.length));
|
|
26539
|
+
return {
|
|
26540
|
+
ok: true,
|
|
26541
|
+
value: {
|
|
26542
|
+
absolutePath,
|
|
26543
|
+
version,
|
|
26544
|
+
bytes: bytes.length,
|
|
26545
|
+
offset,
|
|
26546
|
+
data: slice2.toString("base64"),
|
|
26547
|
+
eof: offset + slice2.length >= bytes.length
|
|
26548
|
+
}
|
|
26549
|
+
};
|
|
26550
|
+
}
|
|
26551
|
+
const text = bytes.toString("utf8");
|
|
26552
|
+
const slice = text.slice(offset, offset + limit);
|
|
26553
|
+
return { ok: true, value: { absolutePath: target2, version: `${info.mtimeMs}:${info.size}`, text: slice, offset, lines: slice.split("\n").length, eof: offset + slice.length >= text.length } };
|
|
26554
|
+
} catch (error) {
|
|
26555
|
+
if (error instanceof RpcError) throw error;
|
|
26556
|
+
throw new RpcError("CODEX_WORKSPACE_UNAVAILABLE", "The CodeX workspace file is unavailable.");
|
|
26557
|
+
}
|
|
26558
|
+
}
|
|
26559
|
+
async watchChanges(sessionId, args, signal) {
|
|
26560
|
+
const root = await this.rootFor(sessionId, signal);
|
|
26561
|
+
const target2 = await this.safePath(root, typeof args.path === "string" ? args.path : ".", true);
|
|
26562
|
+
const queue = new AsyncQueue();
|
|
26563
|
+
const watcher = watch(target2, { recursive: false });
|
|
26564
|
+
const abort = () => {
|
|
26565
|
+
watcher.return?.();
|
|
26566
|
+
queue.end();
|
|
26567
|
+
};
|
|
26568
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
26569
|
+
void (async () => {
|
|
26570
|
+
try {
|
|
26571
|
+
for await (const event of watcher) queue.push({ type: event.eventType, path: event.filename ?? "" });
|
|
26572
|
+
} catch {
|
|
26573
|
+
} finally {
|
|
26574
|
+
signal.removeEventListener("abort", abort);
|
|
26575
|
+
queue.end();
|
|
26576
|
+
}
|
|
26577
|
+
})();
|
|
26578
|
+
return queue;
|
|
26579
|
+
}
|
|
26580
|
+
/**
|
|
26581
|
+
* `terminal/retain` only acknowledges the retention window: it never takes
|
|
26582
|
+
* input ownership and never replays output. Recovery reads the next snapshot.
|
|
26583
|
+
*/
|
|
26584
|
+
async retain(sessionId, args, signal) {
|
|
26585
|
+
this.assertTerminalEnabled();
|
|
26586
|
+
await this.rootFor(sessionId, signal);
|
|
26587
|
+
this.requireTerminal(sessionId, String(args.id));
|
|
26588
|
+
const queue = new AsyncQueue();
|
|
26589
|
+
queue.push({ type: "retained" });
|
|
26590
|
+
this.ownedSubscribers.add(queue);
|
|
26591
|
+
signal.addEventListener("abort", () => {
|
|
26592
|
+
this.ownedSubscribers.delete(queue);
|
|
26593
|
+
queue.end();
|
|
26594
|
+
}, { once: true });
|
|
26595
|
+
return queue;
|
|
26596
|
+
}
|
|
26597
|
+
/** `terminal/follow` takes input ownership and starts with a screen snapshot. */
|
|
26598
|
+
async follow(sessionId, args, signal) {
|
|
26599
|
+
this.assertTerminalEnabled();
|
|
26600
|
+
await this.rootFor(sessionId, signal);
|
|
26601
|
+
const attachmentId = typeof args.attachmentId === "string" && args.attachmentId.length > 0 ? args.attachmentId : void 0;
|
|
26602
|
+
if (attachmentId === void 0) throw new RpcError("INVALID_MESSAGE", "The terminal attachment is invalid.");
|
|
26603
|
+
const terminal = this.requireTerminal(sessionId, String(args.id));
|
|
26604
|
+
const queue = new AsyncQueue();
|
|
26605
|
+
if (terminal.controllerId !== attachmentId) {
|
|
26606
|
+
terminal.controllerId = attachmentId;
|
|
26607
|
+
this.emit(terminal, { type: "state", info: terminalInfo(terminal) });
|
|
26608
|
+
}
|
|
26609
|
+
queue.push({ type: "snapshot", sequence: terminal.sequence, screen: screenOf(terminal), info: terminalInfo(terminal) });
|
|
26610
|
+
terminal.subscribers.add(queue);
|
|
26611
|
+
this.ownedSubscribers.add(queue);
|
|
26612
|
+
signal.addEventListener("abort", () => {
|
|
26613
|
+
terminal.subscribers.delete(queue);
|
|
26614
|
+
this.ownedSubscribers.delete(queue);
|
|
26615
|
+
queue.end();
|
|
26616
|
+
if (terminal.controllerId === attachmentId) {
|
|
26617
|
+
terminal.controllerId = void 0;
|
|
26618
|
+
this.emit(terminal, { type: "state", info: terminalInfo(terminal) });
|
|
26619
|
+
}
|
|
26620
|
+
}, { once: true });
|
|
26621
|
+
return queue;
|
|
26622
|
+
}
|
|
26623
|
+
async terminalCall(endpoint, sessionId, args, signal) {
|
|
26624
|
+
this.assertTerminalEnabled();
|
|
26625
|
+
const cwd = await this.rootFor(sessionId, signal);
|
|
26626
|
+
if (endpoint === "terminal/environment") {
|
|
26627
|
+
return { ok: true, value: { cwd, maxInputBytes: MAX_INPUT_BYTES, maxCols: MAX_COLS, maxRows: MAX_ROWS, scrollback: TERMINAL_SCROLLBACK } };
|
|
26628
|
+
}
|
|
26629
|
+
if (endpoint === "terminal/shells") return { ok: true, value: [shellInfo(DEFAULT_SHELL)] };
|
|
26630
|
+
if (endpoint === "terminal/list") return { ok: true, value: [...this.terminals.values()].filter((item) => item.sessionId === sessionId).map(terminalInfo) };
|
|
26631
|
+
if (endpoint === "terminal/create") return this.createTerminal(sessionId, cwd, args);
|
|
26632
|
+
const id4 = stringId(args.id);
|
|
26633
|
+
const terminal = this.requireTerminal(sessionId, id4);
|
|
26634
|
+
if (endpoint === "terminal/write") {
|
|
26635
|
+
const data2 = typeof args.data === "string" ? args.data : "";
|
|
26636
|
+
if (Buffer.byteLength(data2) > MAX_INPUT_BYTES) throw new RpcError("INVALID_MESSAGE", "Terminal input is too large.");
|
|
26637
|
+
if (terminal.process === void 0) throw new RpcError("CODEX_TERMINAL_NOT_FOUND", "The CodeX terminal is no longer available.");
|
|
26638
|
+
await terminal.process.write(data2);
|
|
26639
|
+
return { ok: true };
|
|
26640
|
+
}
|
|
26641
|
+
if (endpoint === "terminal/resize") {
|
|
26642
|
+
terminal.cols = bounded(args.cols, terminal.cols, MAX_COLS);
|
|
26643
|
+
terminal.rows = bounded(args.rows, terminal.rows, MAX_ROWS);
|
|
26644
|
+
await terminal.process?.resize(terminal.cols, terminal.rows);
|
|
26645
|
+
return { ok: true };
|
|
26646
|
+
}
|
|
26647
|
+
if (endpoint === "terminal/rename") {
|
|
26648
|
+
if (typeof args.title === "string" && args.title.length > 0) terminal.title = args.title.slice(0, 128);
|
|
26649
|
+
return { ok: true };
|
|
26650
|
+
}
|
|
26651
|
+
if (endpoint === "terminal/close") {
|
|
26652
|
+
this.disposeTerminal(terminal);
|
|
26653
|
+
this.terminals.delete(`${sessionId}/${id4}`);
|
|
26654
|
+
return { ok: true };
|
|
26655
|
+
}
|
|
26656
|
+
throw new RpcError("METHOD_NOT_FOUND", "The requested terminal method does not exist.");
|
|
26657
|
+
}
|
|
26658
|
+
async createTerminal(sessionId, cwd, args) {
|
|
26659
|
+
const request = isRecord14(args.request) ? args.request : {};
|
|
26660
|
+
const id4 = stringId(request.id);
|
|
26661
|
+
if ([...this.terminals.values()].some((item) => item.sessionId === sessionId && item.id === id4)) throw new RpcError("REQUEST_CONFLICT", "The terminal id is already active.");
|
|
26662
|
+
if (this.terminals.size >= MAX_TERMINALS) throw new RpcError("RATE_LIMITED", "Too many remote terminals are active.", void 0, true);
|
|
26663
|
+
if (request.shellPath !== void 0 && request.shellPath !== DEFAULT_SHELL.path) throw new RpcError("INVALID_MESSAGE", "The requested shell is not available for this workspace.");
|
|
26664
|
+
const cols = bounded(request.cols, 80, MAX_COLS);
|
|
26665
|
+
const rows = bounded(request.rows, 24, MAX_ROWS);
|
|
26666
|
+
const terminal = {
|
|
26667
|
+
sessionId,
|
|
26668
|
+
id: id4,
|
|
26669
|
+
title: DEFAULT_SHELL.name,
|
|
26670
|
+
shell: DEFAULT_SHELL,
|
|
26671
|
+
cwd,
|
|
26672
|
+
cols,
|
|
26673
|
+
rows,
|
|
26674
|
+
sequence: 0,
|
|
26675
|
+
screen: [],
|
|
26676
|
+
screenBytes: 0,
|
|
26677
|
+
truncated: false,
|
|
26678
|
+
subscribers: /* @__PURE__ */ new Set(),
|
|
26679
|
+
state: "running",
|
|
26680
|
+
exitCode: null
|
|
26681
|
+
};
|
|
26682
|
+
this.terminals.set(`${sessionId}/${id4}`, terminal);
|
|
26683
|
+
try {
|
|
26684
|
+
terminal.process = await this.spawnTerminal({
|
|
26685
|
+
argv: [DEFAULT_SHELL.path, ...DEFAULT_SHELL.args],
|
|
26686
|
+
cwd,
|
|
26687
|
+
cols,
|
|
26688
|
+
rows,
|
|
26689
|
+
terminalType: TERMINAL_TYPE,
|
|
26690
|
+
env: { DSH_SESSION_ID: sessionId }
|
|
26691
|
+
});
|
|
26692
|
+
} catch {
|
|
26693
|
+
this.terminals.delete(`${sessionId}/${id4}`);
|
|
26694
|
+
throw new RpcError("CODEX_TERMINAL_UNAVAILABLE", "The CodeX terminal could not be started.");
|
|
26695
|
+
}
|
|
26696
|
+
void this.pump(terminal, terminal.process);
|
|
26697
|
+
return { ok: true, value: terminalInfo(terminal) };
|
|
26698
|
+
}
|
|
26699
|
+
/** Streams process output as ordered `output` frames, then reports the exit. */
|
|
26700
|
+
async pump(terminal, process2) {
|
|
26701
|
+
try {
|
|
26702
|
+
for await (const chunk of process2.output) {
|
|
26703
|
+
if (chunk.length === 0) continue;
|
|
26704
|
+
terminal.sequence += 1;
|
|
26705
|
+
this.appendScreen(terminal, chunk);
|
|
26706
|
+
this.emit(terminal, { type: "output", sequence: terminal.sequence, data: chunk });
|
|
26707
|
+
}
|
|
26708
|
+
} catch {
|
|
26709
|
+
terminal.state = "failed";
|
|
26710
|
+
terminal.error = "The terminal output stream failed.";
|
|
26711
|
+
}
|
|
26712
|
+
const outcome = await process2.completed;
|
|
26713
|
+
terminal.exitCode = outcome.exitCode;
|
|
26714
|
+
if (terminal.state === "running") terminal.state = "exited";
|
|
26715
|
+
this.emit(terminal, { type: "state", info: terminalInfo(terminal) });
|
|
26716
|
+
this.endSubscribers(terminal);
|
|
26717
|
+
}
|
|
26718
|
+
appendScreen(terminal, chunk) {
|
|
26719
|
+
terminal.screen.push(chunk);
|
|
26720
|
+
terminal.screenBytes += Buffer.byteLength(chunk);
|
|
26721
|
+
while (terminal.screenBytes > MAX_SCREEN_BYTES && terminal.screen.length > 1) {
|
|
26722
|
+
terminal.screenBytes -= Buffer.byteLength(terminal.screen.shift());
|
|
26723
|
+
terminal.truncated = true;
|
|
26724
|
+
}
|
|
26725
|
+
}
|
|
26726
|
+
async rootFor(sessionId, signal) {
|
|
26727
|
+
const parsed = parseCodexSessionId(sessionId);
|
|
26728
|
+
if (!parsed) throw new RpcError("CODEX_SESSION_INVALID", "The CodeX session identifier is invalid.");
|
|
26729
|
+
const cwd = await this.resolveCwd(parsed.threadId, signal);
|
|
26730
|
+
if (!cwd) throw new RpcError("CODEX_WORKSPACE_UNAVAILABLE", "The CodeX thread has no available workspace.");
|
|
26731
|
+
try {
|
|
26732
|
+
const root = await realpath2(cwd);
|
|
26733
|
+
const info = await stat5(root);
|
|
26734
|
+
if (!info.isDirectory()) throw new Error();
|
|
26735
|
+
return root;
|
|
26736
|
+
} catch {
|
|
26737
|
+
throw new RpcError("CODEX_WORKSPACE_UNAVAILABLE", "The CodeX workspace is unavailable.");
|
|
26738
|
+
}
|
|
26739
|
+
}
|
|
26740
|
+
async safePath(root, path, directory) {
|
|
26741
|
+
if (isAbsolute4(path)) throw new RpcError("CODEX_WORKSPACE_PATH_DENIED", "The requested workspace path is outside the CodeX workspace.");
|
|
26742
|
+
const candidate = resolve3(root, path);
|
|
26743
|
+
const rel = relative2(root, candidate);
|
|
26744
|
+
if (rel.startsWith("..") || isAbsolute4(rel)) throw new RpcError("CODEX_WORKSPACE_PATH_DENIED", "The requested workspace path is outside the CodeX workspace.");
|
|
26745
|
+
try {
|
|
26746
|
+
const info = await lstat(candidate);
|
|
26747
|
+
if (info.isSymbolicLink()) throw new Error();
|
|
26748
|
+
const canonical = await realpath2(candidate);
|
|
26749
|
+
const canonicalRel = relative2(root, canonical);
|
|
26750
|
+
if (canonicalRel.startsWith("..") || isAbsolute4(canonicalRel)) throw new Error();
|
|
26751
|
+
if (directory && !info.isDirectory()) throw new Error();
|
|
26752
|
+
return canonical;
|
|
26753
|
+
} catch {
|
|
26754
|
+
throw new RpcError("CODEX_WORKSPACE_PATH_DENIED", "The requested workspace path is unavailable.");
|
|
26755
|
+
}
|
|
26756
|
+
}
|
|
26757
|
+
emit(terminal, value) {
|
|
26758
|
+
for (const subscriber of terminal.subscribers) subscriber.push(value);
|
|
26759
|
+
}
|
|
26760
|
+
endSubscribers(terminal) {
|
|
26761
|
+
for (const subscriber of terminal.subscribers) subscriber.end();
|
|
26762
|
+
terminal.subscribers.clear();
|
|
26763
|
+
}
|
|
26764
|
+
requireTerminal(sessionId, id4) {
|
|
26765
|
+
const terminal = this.terminals.get(`${sessionId}/${id4}`);
|
|
26766
|
+
if (!terminal) throw new RpcError("CODEX_TERMINAL_NOT_FOUND", "The CodeX terminal is no longer available.");
|
|
26767
|
+
return terminal;
|
|
26768
|
+
}
|
|
26769
|
+
assertTerminalEnabled() {
|
|
26770
|
+
if (!this.terminalEnabled()) throw new RpcError("TERMINAL_DISABLED", "Remote terminal is disabled on this Host.");
|
|
26771
|
+
}
|
|
26772
|
+
disposeTerminal(terminal) {
|
|
26773
|
+
void Promise.resolve(terminal.process?.terminate()).catch(() => void 0);
|
|
26774
|
+
if (terminal.state === "running") {
|
|
26775
|
+
terminal.state = "exited";
|
|
26776
|
+
this.emit(terminal, { type: "state", info: terminalInfo(terminal) });
|
|
26777
|
+
}
|
|
26778
|
+
this.endSubscribers(terminal);
|
|
26779
|
+
}
|
|
26780
|
+
};
|
|
26781
|
+
function pipeTerminalSpawner() {
|
|
26782
|
+
return async (spec) => {
|
|
26783
|
+
const child = spawn4(spec.argv[0], spec.argv.slice(1), {
|
|
26784
|
+
cwd: spec.cwd,
|
|
26785
|
+
stdio: "pipe",
|
|
26786
|
+
windowsHide: true,
|
|
26787
|
+
env: { ...process.env, ...spec.env }
|
|
26788
|
+
});
|
|
26789
|
+
const queue = new AsyncQueue();
|
|
26790
|
+
child.stdout.on("data", (data2) => queue.push(Buffer.from(data2).toString("utf8")));
|
|
26791
|
+
child.stderr.on("data", (data2) => queue.push(Buffer.from(data2).toString("utf8")));
|
|
26792
|
+
child.on("error", () => queue.end());
|
|
26793
|
+
const completed = new Promise((resolve4) => {
|
|
26794
|
+
child.on("error", () => {
|
|
26795
|
+
queue.end();
|
|
26796
|
+
resolve4({ exitCode: null });
|
|
26797
|
+
});
|
|
26798
|
+
child.on("exit", (code) => {
|
|
26799
|
+
queue.end();
|
|
26800
|
+
resolve4({ exitCode: code });
|
|
26801
|
+
});
|
|
26802
|
+
});
|
|
26803
|
+
return {
|
|
26804
|
+
output: queue,
|
|
26805
|
+
write: (data2) => {
|
|
26806
|
+
child.stdin.write(data2);
|
|
26807
|
+
},
|
|
26808
|
+
resize: () => void 0,
|
|
26809
|
+
terminate: () => {
|
|
26810
|
+
if (!child.killed) child.kill();
|
|
26811
|
+
},
|
|
26812
|
+
completed
|
|
26813
|
+
};
|
|
26814
|
+
};
|
|
26815
|
+
}
|
|
26816
|
+
function subprocessTerminalSpawner(subprocess) {
|
|
26817
|
+
return async (spec) => {
|
|
26818
|
+
const handle = await subprocess.spawnTerminal({
|
|
26819
|
+
argv: [...spec.argv],
|
|
26820
|
+
cwd: spec.cwd,
|
|
26821
|
+
cols: spec.cols,
|
|
26822
|
+
rows: spec.rows,
|
|
26823
|
+
terminalType: spec.terminalType,
|
|
26824
|
+
env: spec.env
|
|
26825
|
+
});
|
|
26826
|
+
const queue = new AsyncQueue();
|
|
26827
|
+
handle.output.setEncoding?.("utf8");
|
|
26828
|
+
handle.output.on("data", (chunk) => queue.push(typeof chunk === "string" ? chunk : Buffer.from(chunk).toString("utf8")));
|
|
26829
|
+
handle.output.once("close", () => queue.end());
|
|
26830
|
+
handle.output.once("error", () => queue.end());
|
|
26831
|
+
return {
|
|
26832
|
+
output: queue,
|
|
26833
|
+
write: (data2) => handle.write(data2),
|
|
26834
|
+
resize: (cols, rows) => handle.resize(cols, rows),
|
|
26835
|
+
terminate: () => handle.terminate(),
|
|
26836
|
+
completed: handle.done.then((outcome) => ({ exitCode: typeof outcome?.exitCode === "number" ? outcome.exitCode : null })).catch(() => ({ exitCode: null }))
|
|
26837
|
+
};
|
|
26838
|
+
};
|
|
26839
|
+
}
|
|
26840
|
+
function shellInfo(shell) {
|
|
26841
|
+
return { path: shell.path, args: [...shell.args], name: shell.name };
|
|
26842
|
+
}
|
|
26843
|
+
function terminalInfo(terminal) {
|
|
26844
|
+
return {
|
|
26845
|
+
id: terminal.id,
|
|
26846
|
+
title: terminal.title,
|
|
26847
|
+
shell: shellInfo(terminal.shell),
|
|
26848
|
+
cwd: terminal.cwd,
|
|
26849
|
+
cols: terminal.cols,
|
|
26850
|
+
rows: terminal.rows,
|
|
26851
|
+
state: terminal.state,
|
|
26852
|
+
exitCode: terminal.exitCode,
|
|
26853
|
+
...terminal.error === void 0 ? {} : { error: terminal.error },
|
|
26854
|
+
...terminal.controllerId === void 0 ? {} : { controllerId: terminal.controllerId }
|
|
26855
|
+
};
|
|
26856
|
+
}
|
|
26857
|
+
function screenOf(terminal) {
|
|
26858
|
+
return (terminal.truncated ? "\x1Bc" : "") + terminal.screen.join("");
|
|
26859
|
+
}
|
|
26860
|
+
function argsOf(payload) {
|
|
26861
|
+
const value = isRecord14(payload) ? payload : {};
|
|
26862
|
+
return isRecord14(value.args) ? value.args : value;
|
|
26863
|
+
}
|
|
26864
|
+
function isRecord14(value) {
|
|
26865
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26866
|
+
}
|
|
26867
|
+
function stringId(value) {
|
|
26868
|
+
if (typeof value !== "string" || !/^[A-Za-z0-9_.:-]{1,128}$/.test(value)) throw new RpcError("INVALID_MESSAGE", "The terminal identifier is invalid.");
|
|
26869
|
+
return value;
|
|
26870
|
+
}
|
|
26871
|
+
function bounded(value, fallback, max) {
|
|
26872
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? Math.min(value, max) : fallback;
|
|
26873
|
+
}
|
|
26874
|
+
function byteOrLineRange(args) {
|
|
26875
|
+
const options = isRecord14(args.options) ? args.options : void 0;
|
|
26876
|
+
if (options !== void 0 && isRecord14(options.range)) return options.range;
|
|
26877
|
+
return isRecord14(args.range) ? args.range : args;
|
|
26878
|
+
}
|
|
26879
|
+
function readOffset(args) {
|
|
26880
|
+
const range = byteOrLineRange(args);
|
|
26881
|
+
return typeof range.offset === "number" && Number.isInteger(range.offset) && range.offset >= 0 ? range.offset : 0;
|
|
26882
|
+
}
|
|
26883
|
+
function readLimit(args) {
|
|
26884
|
+
const range = byteOrLineRange(args);
|
|
26885
|
+
const value = typeof range.length === "number" ? range.length : range.limit;
|
|
26886
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 ? Math.min(value, MAX_READ_BYTES) : MAX_READ_BYTES;
|
|
26887
|
+
}
|
|
26888
|
+
|
|
26889
|
+
// src/service.ts
|
|
26155
26890
|
var HostPluginRuntime = class {
|
|
26156
|
-
constructor(config, identities, apiProxy, logger, localGateway, fileViewerHost) {
|
|
26891
|
+
constructor(config, identities, apiProxy, logger, localGateway, fileViewerHost, terminalSpawner) {
|
|
26157
26892
|
this.config = config;
|
|
26158
26893
|
this.identities = identities;
|
|
26159
26894
|
this.apiProxy = apiProxy;
|
|
26160
26895
|
this.logger = logger;
|
|
26161
26896
|
this.localGateway = localGateway;
|
|
26162
26897
|
this.fileViewerHost = fileViewerHost;
|
|
26898
|
+
this.terminalSpawner = terminalSpawner;
|
|
26163
26899
|
this.terminalEnabled = config.terminal.enabled;
|
|
26164
26900
|
this.loopback = new LoopbackHost(config.loopback.ports);
|
|
26165
26901
|
this.codex = new CodexRemoteDomain(config.codex, logger);
|
|
@@ -26177,7 +26913,13 @@ var HostPluginRuntime = class {
|
|
|
26177
26913
|
(event, data2) => send(createEvent(event, data2)),
|
|
26178
26914
|
this.logger,
|
|
26179
26915
|
this.harnessVersion,
|
|
26180
|
-
new TerminalPolicy(() => this.terminalEnabled, context.peerDeviceId, this.terminalOwners)
|
|
26916
|
+
new TerminalPolicy(() => this.terminalEnabled, context.peerDeviceId, this.terminalOwners),
|
|
26917
|
+
new CodexWorkspaceBridge(
|
|
26918
|
+
(threadId, signal) => this.codex.resolveThreadWorkspace(context.connectionId, threadId),
|
|
26919
|
+
() => this.terminalEnabled,
|
|
26920
|
+
this.codexWorkspaceState,
|
|
26921
|
+
this.terminalSpawner
|
|
26922
|
+
)
|
|
26181
26923
|
) : void 0;
|
|
26182
26924
|
const fileViewer = new RemoteFileViewerBridge(
|
|
26183
26925
|
() => this.fileViewerHost?.(),
|
|
@@ -26215,6 +26957,7 @@ var HostPluginRuntime = class {
|
|
|
26215
26957
|
harnessVersion;
|
|
26216
26958
|
closed = false;
|
|
26217
26959
|
codex;
|
|
26960
|
+
codexWorkspaceState = new CodexWorkspaceState();
|
|
26218
26961
|
localCodexPeer;
|
|
26219
26962
|
localCodexPublish = async () => void 0;
|
|
26220
26963
|
setTerminalEnabled(enabled) {
|
|
@@ -26498,9 +27241,9 @@ function isPlainRecord(value) {
|
|
|
26498
27241
|
}
|
|
26499
27242
|
|
|
26500
27243
|
// src/cli.ts
|
|
26501
|
-
import { stat as
|
|
27244
|
+
import { stat as stat6 } from "node:fs/promises";
|
|
26502
27245
|
import { hostname as hostname3 } from "node:os";
|
|
26503
|
-
import { join as
|
|
27246
|
+
import { join as join7 } from "node:path";
|
|
26504
27247
|
var QR_POLL_INTERVAL_MS = 2e3;
|
|
26505
27248
|
var TERMINAL_QR_MARGIN = 4;
|
|
26506
27249
|
async function runCli(args = process.argv.slice(2), dependencies = {}) {
|
|
@@ -26577,7 +27320,7 @@ async function status(args, runtime) {
|
|
|
26577
27320
|
`Server: ${serverUrl}`,
|
|
26578
27321
|
"Host control: enabled (dsh-TUI default)"
|
|
26579
27322
|
];
|
|
26580
|
-
if (!await exists3(
|
|
27323
|
+
if (!await exists3(join7(directory, "device.json"))) {
|
|
26581
27324
|
lines.push("Device: not initialized", "Authorization: logged out", "Credential: unavailable");
|
|
26582
27325
|
write(runtime.stdout, `${lines.join("\n")}
|
|
26583
27326
|
|
|
@@ -26621,7 +27364,7 @@ async function logout(args, runtime) {
|
|
|
26621
27364
|
const serverUrl = selectedServer();
|
|
26622
27365
|
const root = new IdentityStore({ env: runtime.env }).directory;
|
|
26623
27366
|
const directory = serverStorageDirectory(root, serverUrl, "host");
|
|
26624
|
-
if (!await exists3(
|
|
27367
|
+
if (!await exists3(join7(directory, "device.json"))) {
|
|
26625
27368
|
await new ServerCredentialStore(directory).clear();
|
|
26626
27369
|
write(runtime.stdout, "This Host is already logged out.\n");
|
|
26627
27370
|
return 0;
|
|
@@ -26663,7 +27406,7 @@ function resolveDependencies(input2) {
|
|
|
26663
27406
|
stdout: input2.stdout ?? process.stdout,
|
|
26664
27407
|
stderr: input2.stderr ?? process.stderr,
|
|
26665
27408
|
now: input2.now ?? Date.now,
|
|
26666
|
-
wait: input2.wait ?? ((milliseconds) => new Promise((
|
|
27409
|
+
wait: input2.wait ?? ((milliseconds) => new Promise((resolve4) => setTimeout(resolve4, milliseconds))),
|
|
26667
27410
|
renderQr: input2.renderQr ?? renderTerminalQr,
|
|
26668
27411
|
createIdentityStore: input2.createIdentityStore ?? ((options) => new IdentityStore(options)),
|
|
26669
27412
|
createHostApi: input2.createHostApi ?? ((serverUrl, store) => new HostServerApi(serverUrl, store))
|
|
@@ -26749,7 +27492,7 @@ function terminalLink(url, target2) {
|
|
|
26749
27492
|
}
|
|
26750
27493
|
async function exists3(path) {
|
|
26751
27494
|
try {
|
|
26752
|
-
await
|
|
27495
|
+
await stat6(path);
|
|
26753
27496
|
return true;
|
|
26754
27497
|
} catch (error) {
|
|
26755
27498
|
if (error instanceof Error && "code" in error && error.code === "ENOENT") return false;
|
|
@@ -27108,7 +27851,7 @@ function errorCode4(error) {
|
|
|
27108
27851
|
return "CONNECTION_FAILED";
|
|
27109
27852
|
}
|
|
27110
27853
|
function wait(milliseconds) {
|
|
27111
|
-
return new Promise((
|
|
27854
|
+
return new Promise((resolve4) => setTimeout(resolve4, milliseconds));
|
|
27112
27855
|
}
|
|
27113
27856
|
|
|
27114
27857
|
// src/remote-file-content-provider.ts
|
|
@@ -27189,7 +27932,16 @@ var name = "ds-harness-remote";
|
|
|
27189
27932
|
var legacyLoaderModuleNames = /* @__PURE__ */ new Set(["dsh-remote", "@dsh-remote/plugin"]);
|
|
27190
27933
|
var pluginSettingsNamespace = "ds-harness-remote";
|
|
27191
27934
|
var legacySettingsNamespace = "dsh-remote";
|
|
27192
|
-
|
|
27935
|
+
var DEFAULT_ENTRY_ID = "ds-harness-remote";
|
|
27936
|
+
var INCLUDE_ENTRY_PREFIX = "include:";
|
|
27937
|
+
function apply(ctx, entry = void 0) {
|
|
27938
|
+
const readConfig = () => readEntryConfig(entry);
|
|
27939
|
+
const entryId = locateEntryId(ctx);
|
|
27940
|
+
ctx.inject(["settings"], (settingsContext) => {
|
|
27941
|
+
const settings = settingsContext.settings;
|
|
27942
|
+
if (isLegacySettingsProvider(settings)) return;
|
|
27943
|
+
settingsContext.effect(() => settings.configure({ auto: false }, ctx.fiber));
|
|
27944
|
+
});
|
|
27193
27945
|
const tuiCommandsAvailable = ctx.get("commands", false) !== void 0 && ctx.get("tuiScenes", false) !== void 0;
|
|
27194
27946
|
const tuiBinding = tuiCommandsAvailable ? {} : void 0;
|
|
27195
27947
|
if (tuiBinding !== void 0) installTuiRemoteCommand(ctx, () => tuiBinding.target);
|
|
@@ -27202,7 +27954,7 @@ function apply(ctx, input2 = {}) {
|
|
|
27202
27954
|
if (connection === void 0 || disposePendingControl !== void 0) return;
|
|
27203
27955
|
disposePendingControl = runtimeContext.effect(() => {
|
|
27204
27956
|
const control = new PluginControlRuntime(
|
|
27205
|
-
resolveConfig(
|
|
27957
|
+
resolveConfig(readConfig()),
|
|
27206
27958
|
new IdentityStore().directory,
|
|
27207
27959
|
void 0,
|
|
27208
27960
|
void 0,
|
|
@@ -27214,7 +27966,7 @@ function apply(ctx, input2 = {}) {
|
|
|
27214
27966
|
const startActiveRuntime = async (activeContext) => {
|
|
27215
27967
|
await disposePendingControl?.();
|
|
27216
27968
|
disposePendingControl = void 0;
|
|
27217
|
-
await activate(activeContext,
|
|
27969
|
+
await activate(activeContext, readConfig, entryId, tuiBinding);
|
|
27218
27970
|
};
|
|
27219
27971
|
if (tuiCommandsAvailable || runtimeContext.get("apiProxy") !== void 0 || new TypertGatewaySwitch(gateway).supportsCarrier()) {
|
|
27220
27972
|
return startActiveRuntime(runtimeContext);
|
|
@@ -27228,27 +27980,17 @@ function apply(ctx, input2 = {}) {
|
|
|
27228
27980
|
ctx.inject(["settings", "connection", "typertGateway"], activateWhenCarrierReady);
|
|
27229
27981
|
}
|
|
27230
27982
|
}
|
|
27231
|
-
async function activate(ctx,
|
|
27983
|
+
async function activate(ctx, readConfig, entryId, tuiBinding) {
|
|
27232
27984
|
const settings = ctx.get("settings");
|
|
27233
|
-
const
|
|
27234
|
-
base: input2,
|
|
27235
|
-
applies: "restart",
|
|
27236
|
-
validate: (value) => {
|
|
27237
|
-
resolveConfig(value);
|
|
27238
|
-
}
|
|
27239
|
-
});
|
|
27240
|
-
if (settings !== void 0 && settingsScope !== void 0) {
|
|
27241
|
-
const migration = migrateLegacySettings(settings, settingsScope);
|
|
27242
|
-
reportSettingsMigration(ctx, await migration);
|
|
27243
|
-
}
|
|
27985
|
+
const settingsBinding = await createSettingsBinding(ctx, settings, readConfig, entryId);
|
|
27244
27986
|
const connection = ctx.get("connection");
|
|
27245
27987
|
const webServer = ctx.get("webServer");
|
|
27246
|
-
const resolvedConfig = resolveConfig(
|
|
27988
|
+
const resolvedConfig = resolveConfig(settingsBinding?.get() ?? readConfig());
|
|
27247
27989
|
const config = connection === void 0 && resolvedConfig.serverUrl === void 0 ? { ...resolvedConfig, serverUrl: DEFAULT_REMOTE_SERVER_URL } : resolvedConfig;
|
|
27248
27990
|
const defaultIdentityDirectory = new IdentityStore().directory;
|
|
27249
27991
|
if (!config.enabled) {
|
|
27250
27992
|
if (connection !== void 0) {
|
|
27251
|
-
const controlRuntime2 = new PluginControlRuntime(config, defaultIdentityDirectory,
|
|
27993
|
+
const controlRuntime2 = new PluginControlRuntime(config, defaultIdentityDirectory, settingsBinding, void 0, void 0);
|
|
27252
27994
|
ctx.effect(() => controlRuntime2.register(connection, webServer), "dsh-remote disabled control");
|
|
27253
27995
|
}
|
|
27254
27996
|
return;
|
|
@@ -27277,13 +28019,15 @@ async function activate(ctx, input2, tuiBinding) {
|
|
|
27277
28019
|
const apiProxy = ctx.get("apiProxy");
|
|
27278
28020
|
const nativeTypertGateway = ctx.get("typertGateway");
|
|
27279
28021
|
const localTypertGateway = new TypertGatewaySwitch(nativeTypertGateway).local();
|
|
28022
|
+
const subprocess = ctx.get("subprocess", false);
|
|
27280
28023
|
const runtime = new HostPluginRuntime(
|
|
27281
28024
|
config,
|
|
27282
28025
|
hostIdentities,
|
|
27283
28026
|
apiProxy,
|
|
27284
28027
|
logger,
|
|
27285
28028
|
localTypertGateway,
|
|
27286
|
-
() => ctx.get("fileViewerHost")
|
|
28029
|
+
() => ctx.get("fileViewerHost"),
|
|
28030
|
+
subprocess === void 0 ? void 0 : subprocessTerminalSpawner(subprocess)
|
|
27287
28031
|
);
|
|
27288
28032
|
let clientRuntime;
|
|
27289
28033
|
const hostControl = runtime;
|
|
@@ -27301,7 +28045,7 @@ async function activate(ctx, input2, tuiBinding) {
|
|
|
27301
28045
|
hostControl
|
|
27302
28046
|
);
|
|
27303
28047
|
}
|
|
27304
|
-
const controlRuntime = connection === void 0 ? void 0 : new PluginControlRuntime(config, defaultIdentityDirectory,
|
|
28048
|
+
const controlRuntime = connection === void 0 ? void 0 : new PluginControlRuntime(config, defaultIdentityDirectory, settingsBinding, clientRuntime, hostControl);
|
|
27305
28049
|
ctx.provide("dshRemote", runtime);
|
|
27306
28050
|
if (clientRuntime !== void 0) ctx.provide("dshRemoteClient", clientRuntime);
|
|
27307
28051
|
const tuiTarget = { runtime, config };
|
|
@@ -27336,6 +28080,52 @@ async function activate(ctx, input2, tuiBinding) {
|
|
|
27336
28080
|
};
|
|
27337
28081
|
}, "dsh-remote lifecycle");
|
|
27338
28082
|
}
|
|
28083
|
+
function readEntryConfig(entry) {
|
|
28084
|
+
if (entry === void 0) return {};
|
|
28085
|
+
return isEntryConfig(entry) ? entry.get() : entry;
|
|
28086
|
+
}
|
|
28087
|
+
function isEntryConfig(value) {
|
|
28088
|
+
return typeof value.get === "function";
|
|
28089
|
+
}
|
|
28090
|
+
function locateEntryId(ctx) {
|
|
28091
|
+
const loader = ctx.get("loader");
|
|
28092
|
+
const located = loader?.locate?.(ctx.fiber);
|
|
28093
|
+
if (located === void 0) return DEFAULT_ENTRY_ID;
|
|
28094
|
+
if (typeof loader?.entries === "function") {
|
|
28095
|
+
for (const entry of loader.entries()) {
|
|
28096
|
+
if (entry.id === located) return entry.options.id;
|
|
28097
|
+
}
|
|
28098
|
+
}
|
|
28099
|
+
return located.startsWith(INCLUDE_ENTRY_PREFIX) ? located.slice(INCLUDE_ENTRY_PREFIX.length) : located;
|
|
28100
|
+
}
|
|
28101
|
+
async function createSettingsBinding(ctx, settings, readConfig, entryId) {
|
|
28102
|
+
if (settings === void 0) return void 0;
|
|
28103
|
+
if (!isLegacySettingsProvider(settings)) {
|
|
28104
|
+
return {
|
|
28105
|
+
get: readConfig,
|
|
28106
|
+
replace: async (section) => {
|
|
28107
|
+
await settings.replace(entryId, section);
|
|
28108
|
+
}
|
|
28109
|
+
};
|
|
28110
|
+
}
|
|
28111
|
+
const scope = settings.register(pluginSettingsNamespace, Config, {
|
|
28112
|
+
base: readConfig(),
|
|
28113
|
+
applies: "restart",
|
|
28114
|
+
validate: (value) => {
|
|
28115
|
+
resolveConfig(value);
|
|
28116
|
+
}
|
|
28117
|
+
});
|
|
28118
|
+
reportSettingsMigration(ctx, await migrateLegacySettings(settings, scope));
|
|
28119
|
+
return {
|
|
28120
|
+
get: () => scope.get(),
|
|
28121
|
+
replace: async (section) => {
|
|
28122
|
+
await scope.replace(section);
|
|
28123
|
+
}
|
|
28124
|
+
};
|
|
28125
|
+
}
|
|
28126
|
+
function isLegacySettingsProvider(value) {
|
|
28127
|
+
return typeof value === "object" && value !== null && typeof value.register === "function";
|
|
28128
|
+
}
|
|
27339
28129
|
function reportSettingsMigration(ctx, migration) {
|
|
27340
28130
|
if (migration === "migrated") ctx.logger.info("migrated legacy Remote settings namespace");
|
|
27341
28131
|
if (migration === "failed") ctx.logger.warn("failed to migrate legacy Remote settings namespace");
|
|
@@ -27364,6 +28154,9 @@ async function migrateLegacySettings(settings, currentScope) {
|
|
|
27364
28154
|
return "failed";
|
|
27365
28155
|
}
|
|
27366
28156
|
}
|
|
28157
|
+
function isPlainRecord2(value) {
|
|
28158
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
28159
|
+
}
|
|
27367
28160
|
async function disableLegacyLoaderEntries(ctx, logger) {
|
|
27368
28161
|
const loader = ctx.get("loader");
|
|
27369
28162
|
if (!isLoaderLike(loader)) return;
|
|
@@ -27387,9 +28180,6 @@ async function disableLegacyLoaderEntries(ctx, logger) {
|
|
|
27387
28180
|
function isLoaderLike(value) {
|
|
27388
28181
|
return typeof value === "object" && value !== null && typeof value.entries === "function" && typeof value.update === "function";
|
|
27389
28182
|
}
|
|
27390
|
-
function isPlainRecord2(value) {
|
|
27391
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
27392
|
-
}
|
|
27393
28183
|
export {
|
|
27394
28184
|
AcpGateway,
|
|
27395
28185
|
ApiProxySwitch,
|