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.
Files changed (74) hide show
  1. package/dist/client-runtime.d.ts.map +1 -1
  2. package/dist/client-runtime.js +3 -3
  3. package/dist/client-runtime.js.map +1 -1
  4. package/dist/client.github.js +77 -36
  5. package/dist/client.js +77 -36
  6. package/dist/client.js.map +1 -1
  7. package/dist/codex/codex-image-codec.d.ts +7 -0
  8. package/dist/codex/codex-image-codec.d.ts.map +1 -0
  9. package/dist/codex/codex-image-codec.js +288 -0
  10. package/dist/codex/codex-image-codec.js.map +1 -0
  11. package/dist/codex/domain.d.ts +2 -0
  12. package/dist/codex/domain.d.ts.map +1 -1
  13. package/dist/codex/domain.js +15 -0
  14. package/dist/codex/domain.js.map +1 -1
  15. package/dist/codex/session-id.d.ts +10 -0
  16. package/dist/codex/session-id.d.ts.map +1 -0
  17. package/dist/codex/session-id.js +15 -0
  18. package/dist/codex/session-id.js.map +1 -0
  19. package/dist/codex/virtual-harness.d.ts +3 -2
  20. package/dist/codex/virtual-harness.d.ts.map +1 -1
  21. package/dist/codex/virtual-harness.js +33 -270
  22. package/dist/codex/virtual-harness.js.map +1 -1
  23. package/dist/codex-workspace-bridge.d.ts +108 -0
  24. package/dist/codex-workspace-bridge.d.ts.map +1 -0
  25. package/dist/codex-workspace-bridge.js +501 -0
  26. package/dist/codex-workspace-bridge.js.map +1 -0
  27. package/dist/config.d.ts +13 -2
  28. package/dist/config.d.ts.map +1 -1
  29. package/dist/config.js +22 -2
  30. package/dist/config.js.map +1 -1
  31. package/dist/control-runtime.d.ts +17 -3
  32. package/dist/control-runtime.d.ts.map +1 -1
  33. package/dist/control-runtime.js +4 -2
  34. package/dist/control-runtime.js.map +1 -1
  35. package/dist/harness-api-bridge.d.ts.map +1 -1
  36. package/dist/harness-api-bridge.js +2 -53
  37. package/dist/harness-api-bridge.js.map +1 -1
  38. package/dist/harness-api-history.d.ts +3 -0
  39. package/dist/harness-api-history.d.ts.map +1 -0
  40. package/dist/harness-api-history.js +55 -0
  41. package/dist/harness-api-history.js.map +1 -0
  42. package/dist/harness-remote-bridge.d.ts +4 -2
  43. package/dist/harness-remote-bridge.d.ts.map +1 -1
  44. package/dist/harness-remote-bridge.js +61 -3
  45. package/dist/harness-remote-bridge.js.map +1 -1
  46. package/dist/index.d.ts +24 -4
  47. package/dist/index.d.ts.map +1 -1
  48. package/dist/index.js +1418 -628
  49. package/dist/index.js.map +4 -4
  50. package/dist/remote-api-proxy.d.ts +5 -1
  51. package/dist/remote-api-proxy.d.ts.map +1 -1
  52. package/dist/remote-api-proxy.js +74 -2
  53. package/dist/remote-api-proxy.js.map +1 -1
  54. package/dist/remote-typert-gateway.d.ts +6 -1
  55. package/dist/remote-typert-gateway.d.ts.map +1 -1
  56. package/dist/remote-typert-gateway.js +58 -1
  57. package/dist/remote-typert-gateway.js.map +1 -1
  58. package/dist/service.d.ts +7 -1
  59. package/dist/service.d.ts.map +1 -1
  60. package/dist/service.js +8 -2
  61. package/dist/service.js.map +1 -1
  62. package/dist/terminal-policy.d.ts.map +1 -1
  63. package/dist/terminal-policy.js +8 -2
  64. package/dist/terminal-policy.js.map +1 -1
  65. package/dist/typert-gateway-contract.d.ts +11 -1
  66. package/dist/typert-gateway-contract.d.ts.map +1 -1
  67. package/dist/typert-gateway-switch.d.ts.map +1 -1
  68. package/dist/typert-gateway-switch.js +65 -4
  69. package/dist/typert-gateway-switch.js.map +1 -1
  70. package/dist/version.d.ts +1 -1
  71. package/dist/version.js +1 -1
  72. package/dsh-plugin.json +1 -1
  73. package/package.json +18 -18
  74. 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((resolve3, reject) => {
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 ? resolve3() : reject(error);
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((resolve3, reject) => handle.socket.send(data2, { binary: value.binary }, (error) => error ? reject(new RpcError("LOOPBACK_CLOSED", "Preview socket closed.")) : resolve3()));
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((resolve3) => {
4745
+ if (handle.messages.length === 0 && !handle.closed) await new Promise((resolve4) => {
4746
4746
  const timer = setTimeout(() => {
4747
4747
  handle.wake = void 0;
4748
- resolve3();
4748
+ resolve4();
4749
4749
  }, 2e4);
4750
4750
  handle.wake = () => {
4751
4751
  clearTimeout(timer);
4752
4752
  handle.wake = void 0;
4753
- resolve3();
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((resolve3, reject) => {
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
- resolve3({ status: response.statusCode ?? 502, headers: cleanHeaders(headerPairs(response.headers)) });
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((resolve3, reject) => {
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", () => resolve3({ protocol: socket.protocol }));
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((resolve3) => running.server.close(() => resolve3()));
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((resolve3, reject) => {
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
- resolve3();
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((resolve3, reject) => {
5022
+ await new Promise((resolve4, reject) => {
5023
5023
  const ready = () => {
5024
5024
  cleanup();
5025
- resolve3();
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((resolve3, reject) => socket.send(Buffer.from(message.data, "base64"), { binary: message.binary }, (error) => error ? reject(error) : resolve3()));
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((resolve3, reject) => {
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 ${this.timeoutMs}ms`));
5729
- }, this.timeoutMs);
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: resolve3,
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((resolve3) => setTimeout(resolve3, 10));
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((resolve3, reject) => {
6309
- this.openResolve = resolve3;
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 resolve3 = this.openResolve;
6531
+ const resolve4 = this.openResolve;
6525
6532
  this.clearNegotiation();
6526
- void this.resolveSelectedTransport().then(() => resolve3?.());
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((resolve3) => setTimeout(resolve3, ms));
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((resolve3, reject) => {
6959
- this.readyResolve = resolve3;
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((resolve3, reject) => {
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) resolve3();
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 record6 = value;
14690
- if (record6.type !== "client-request" || typeof record6.rpcId !== "string" || typeof record6.method !== "string") return void 0;
14691
- return { type: "client-request", rpcId: record6.rpcId, method: record6.method, payload: record6.payload };
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 record6 = value;
14696
- return typeof record6.rpcId === "string" ? record6.rpcId : INVALID_REQUEST_RPC_ID;
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
- return normalizeLegacyResponse(method, response);
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((resolve3) => this.waiters.push(resolve3));
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 record6 of value) {
15091
- if (!isEventEntry(record6)) continue;
15092
- const seq = entrySeq(record6);
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, record6));
15158
+ records.push(createLegacyGapRecord(fillerSeq, record7));
15096
15159
  }
15097
15160
  }
15098
- records.push(normalizeEntry(record6));
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((resolve3) => this.waiters.push(resolve3));
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 MAX_CODEX_IMAGE_BASE64 = 288 * 1024 * 1024;
15497
- var CODEX_IMAGE_MEDIA_TYPES2 = /* @__PURE__ */ new Set(["image/png", "image/jpeg", "image/webp", "image/gif"]);
15498
- var CODEX_IMAGE_ATTACHMENT_PREFIX = "codex-image:";
15499
- var DATA_IMAGE_URL2 = /^data:(image\/(?:png|jpeg|webp|gif));base64,([A-Za-z0-9+/]+={0,2})$/u;
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 = string(request.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) => string(thread.id) === threadId ? { ...thread, name: name2 } : 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(record2(request.address));
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 = record2(frame.params);
16337
+ const params = record3(frame.params);
15972
16338
  if (frame.method === "thread/name/updated") {
15973
- const name2 = string(params.threadName);
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 = record2(params.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 = string(turn.id);
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, record2(item), false);
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 = record2(params.item);
16002
- const itemId = string(item.id);
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(string(item.type))) this.ensureToolStarted(follow, item);
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 = string(params.itemId) ?? `assistant:${follow.turn}`;
16013
- const delta = string(params.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 = string(params.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 = string(params.itemId);
16030
- const delta = string(params.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 = record2(value);
16039
- const content = string(item.step);
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 = string(params.itemId);
16049
- const delta = frame.method === "item/mcpToolCall/progress" ? string(params.message) : string(params.delta);
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 = string(params.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 = record2(params.status);
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 = string(params.toModel);
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 = record2(params.turn);
16100
- for (const item of array(turn.items)) this.acceptCompletedItem(follow, record2(item), true);
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 = string(params.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 = string(item.id) ?? `item:${follow.nextSeq}`;
16501
+ const itemId = string2(item.id) ?? `item:${follow.nextSeq}`;
16136
16502
  if (follow.completedItems.has(itemId)) return;
16137
- const type = string(item.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 ? { ...record2(data2), stream: follow.assistantAttempt.stream } : data2,
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 = record2(block.attachment);
16211
- const attachmentId = string(attachment.attachmentId);
16212
- const data2 = string(block.data);
16213
- if (attachmentId === void 0 || data2 === void 0 || !attachmentId.startsWith(CODEX_IMAGE_ATTACHMENT_PREFIX)) continue;
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 = string(item.id);
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 = string(item.id);
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" && isRecord5(args[0])) {
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: string(input2.request.toolName) ?? "CodeX",
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 = string(args.eventId);
16405
- const outcome = record2(args.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 = string(request.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 ${string(request.workspaceId) ?? ""} cannot be renamed.`);
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 = string(request.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 = string(request.path) ?? workspace.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 = record2(await this.client.request("dsh/directoryList", { path }, signal));
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 = string(request.workspaceId) ?? this.selectedWorkspaceId;
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 = string(request.cwd) ?? workspace?.path;
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 = record2(await this.client.request("thread/start", {
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 = { ...record2(result.thread), cwd, turns: array(record2(result.thread).turns) };
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 = record2(await this.client.request("thread/fork", {
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(record2(result.thread));
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, string(request.requestId) ?? "");
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(CODEX_IMAGE_ATTACHMENT_PREFIX)) {
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 = record2(await this.client.request("thread/read", { threadId, includeTurns: true }, signal));
16580
- const thread = record2(result.thread);
16581
- if (string(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
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(record2(request.address));
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 = record2(await this.client.request("thread/read", { threadId, includeTurns: false }, signal));
16616
- const thread = record2(result.thread);
16617
- if (string(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
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 = record2(await this.client.request("dsh/sessionHistory", {
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 = record2(await this.client.request("thread/read", { threadId, includeTurns: true }, signal));
16632
- const thread = record2(result.thread);
16633
- if (string(thread.id) !== threadId) throw new Error("CodeX returned an invalid Thread history.");
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" && isRecord5(request.payload) ? { ...request.payload, requestId: String(request.rpcId) } : request.payload;
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 = record2(await client.request("thread/list", {
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 = record2(value);
16868
- if (string(thread.id) !== void 0) threads.push(thread);
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) => string(thread.id)).filter((id4) => id4 !== void 0));
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 = record2(await client.request("project/list", {
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 = record2(await client.request("model/list", {
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 = record2(value);
17313
+ const source = record3(value);
16948
17314
  if (source.hidden === true) continue;
16949
- const id4 = string(source.model) ?? string(source.id);
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 = record2(value2);
16953
- const effortId = string(effort.reasoningEffort);
17318
+ const effort = record3(value2);
17319
+ const effortId = string2(effort.reasoningEffort);
16954
17320
  if (effortId === void 0) return void 0;
16955
- const description2 = string(effort.description);
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 = string(source.defaultReasoningEffort);
16963
- const description = string(source.description);
17328
+ const defaultEffort2 = string2(source.defaultReasoningEffort);
17329
+ const description = string2(source.description);
16964
17330
  const model = {
16965
17331
  id: id4,
16966
- name: string(source.displayName) ?? id4,
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 = record2(rawTurn);
17017
- const turnItems = array(turn.items).map(record2);
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 = record2(data2);
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 = record2(value);
17105
- const sourceHeader = record2(page.header);
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 = record2(raw);
17109
- const sourceEvent = record2(entry.event);
17110
- const sourceSurfaceOp = record2(sourceEvent.surfaceOp);
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(string(sourceEvent.type) ?? "", sourceEvent.data, sessionGeneration),
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 = string(item.type);
17133
- const id4 = string(item.id) ?? `${turn}:${step}:${hashString(JSON.stringify(item))}`;
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 = string(item.type) ?? "unknown";
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 = record2(event.data);
17423
- const message = record2(data2.message);
17588
+ const data2 = record3(event.data);
17589
+ const message = record3(data2.message);
17424
17590
  const content = array(message.content);
17425
- const result = record2(content[0]);
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: ${string(item.path) ?? "image"}`;
17621
+ if (type === "imageView") return `Viewed image: ${string2(item.path) ?? "image"}`;
17456
17622
  if (type === "imageGeneration") {
17457
- const savedPath = string(item.savedPath);
17458
- return savedPath === void 0 ? `Image generation ${string(item.status) ?? "completed"}.` : `Generated image: ${savedPath}`;
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${string(item.review) ? `: ${string(item.review)}` : "."}`;
17462
- if (type === "exitedReviewMode") return `Exited review mode${string(item.review) ? `: ${string(item.review)}` : "."}`;
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 [string(record2(item.kind).type) ?? string(item.kind) ?? "Subagent activity", string(item.agentPath)].filter((value) => value !== void 0).join(": ");
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(record2(item.result)) ?? itemText2(record2(item.output)) ?? string(item.status) ?? type;
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: string(item.query) ?? "CodeX web search",
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 = string(item.path) ?? string(item.savedPath);
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: ${string(item.tool) ?? "collaboration"}` : `Subagent activity: ${string(item.agentPath) ?? string(item.agentThreadId) ?? "agent"}`,
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 string(item.name) ?? string(item.tool) ?? string(record2(item.tool).name) ?? (type === "mcpToolCall" ? "CodeX MCP tool" : humanizeItemType(type));
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) => string(record2(value).path)).filter((path) => path !== void 0 && path.length > 0).map((path) => ({ path }));
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 = record2(value);
17565
- const id4 = string(source.id);
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) => string(record2(root).path)).filter((path) => path !== void 0 && path.length > 0).map((path) => ({ path }));
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: string(source.name) ?? basename(roots[0].path),
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 = string(thread.projectId);
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 (!isRecord5(value)) return void 0;
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" || !CODEX_IMAGE_MEDIA_TYPES2.has(value.mediaType) || typeof value.data !== "string" || value.data.length > MAX_CODEX_IMAGE_BASE64 || !isCanonicalBase642(value.data)) return void 0;
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: [...CODEX_IMAGE_MEDIA_TYPES2]
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 = record2(part);
17707
- return string(block.text) ?? string(block.content) ?? "";
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 = record2(value);
17721
- const kind = typeof change.kind === "string" ? change.kind : string(record2(change.kind).type);
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: string(item.query) ?? "" };
17729
- if (item.type === "imageView") return { path: string(item.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
- ...string(item.revisedPrompt) === void 0 ? {} : { prompt: string(item.revisedPrompt) },
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: string(item.tool) ?? "collaboration",
17898
+ tool: string2(item.tool) ?? "collaboration",
17736
17899
  receiverThreadIds: array(item.receiverThreadIds).filter((value) => typeof value === "string"),
17737
- ...string(item.model) === void 0 ? {} : { model: string(item.model) }
17900
+ ...string2(item.model) === void 0 ? {} : { model: string2(item.model) }
17738
17901
  };
17739
17902
  if (item.type === "subAgentActivity") return {
17740
- agentThreadId: string(item.agentThreadId) ?? "",
17741
- agentPath: string(item.agentPath) ?? "",
17742
- kind: string(record2(item.kind).type) ?? string(item.kind) ?? "activity"
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: string(item.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 = record2(value);
17754
- const path = string(change.path);
17755
- const kind = typeof change.kind === "string" ? change.kind : string(record2(change.kind).type);
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 = record2(raw);
17763
- const path = string(change.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 : string(record2(change.kind).type);
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 = record2(value);
17796
- return string(source.command) ?? string(source.text);
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 = record2(value[index]);
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 record2(record2(payload).args);
17983
+ return record3(record3(payload).args);
17821
17984
  }
17822
17985
  function requestArg(args) {
17823
- return record2(args.request ?? args._request ?? args);
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 = record2(value);
18002
+ const result = record3(value);
17840
18003
  if (result.ok === true) return ok(result.value);
17841
18004
  if (result.ok === false) {
17842
- const error = record2(result.error);
17843
- return fail(string(error.code) ?? "internal", string(error.message) ?? "CodeX virtual Harness rejected the request.", record2(error.details));
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 = record2(value);
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 = record2(value);
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 && isRecord5(error.details) ? error.details : {};
18033
+ return "details" in error && isRecord6(error.details) ? error.details : {};
17871
18034
  }
17872
- function record2(value) {
17873
- return isRecord5(value) ? value : {};
18035
+ function record3(value) {
18036
+ return isRecord6(value) ? value : {};
17874
18037
  }
17875
- function isRecord5(value) {
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 string(value) {
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 = record2(value);
17908
- const header = record2(page.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 hashString(value) {
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((resolve3) => this.waiters.push(resolve3));
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((resolve3) => setTimeout(resolve3, 50));
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 record6 = credentialSchema.parse({ schemaVersion: 1, ...credentials });
18052
- await atomicWrite(this.path, `${JSON.stringify(record6, null, 2)}
18214
+ const record7 = credentialSchema.parse({ schemaVersion: 1, ...credentials });
18215
+ await atomicWrite(this.path, `${JSON.stringify(record7, null, 2)}
18053
18216
  `);
18054
- return record6;
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 Config = s.object({
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.16";
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 = this.runtime.openWireStream?.bind(gateway) ?? gateway.wireStream?.open.bind(gateway.wireStream);
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
- this.runtime.openWireStream = (endpoint, payload, signal) => this.remoteTarget === void 0 || isLocalOnlyEndpoint(endpoint) ? this.localOpen(endpoint, payload, signal) : this.remoteTarget.open(endpoint, payload, signal);
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 && isRecord6(source.details) ? source.details : {};
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 (!isRecord6(payload) || !isRecord6(payload.args)) {
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 isRecord6(value) {
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 stat6 = statSync(candidate);
18871
- if (!stat6.isFile()) return false;
19078
+ const stat7 = statSync(candidate);
19079
+ if (!stat7.isFile()) return false;
18872
19080
  if (process.platform === "win32") return true;
18873
- return (stat6.mode & 73) !== 0;
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((resolve3, reject) => {
18963
- this.pending.set(id4, { resolve: resolve3, reject });
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((resolve3, reject) => {
19965
+ return await new Promise((resolve4, reject) => {
19758
19966
  const timer = setTimeout(() => {
19759
19967
  cleanup();
19760
- resolve3(void 0);
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
- resolve3(typeof address === "string" ? void 0 : address.address);
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 = record3(await new CodexRemoteClient(remote.client).request("project/create", {
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 = record3(result.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 = record3(payload);
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" && isRecord7(event.data) && event.data.streamId === value.streamId) {
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" && isRecord7(event.data) && event.data.streamId === value.streamId) {
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 (!isRecord7(data2) || !isRecord7(data2.frame) || typeof data2.frame.method !== "string") return;
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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(record3(payload).port));
20772
+ return ok2(await this.preview.open(record4(payload).port));
20564
20773
  }
20565
20774
  if (endpoint === "directory.list") {
20566
- const value = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 = record3(payload);
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 record3(value) {
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 isRecord7(value) {
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 || !isRecord7(first.value) || first.value.type !== "baseline" || !isRecord7(first.value.value) || !Array.isArray(first.value.value.items)) {
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 (!isRecord7(item) || typeof item.workspaceId !== "string" || typeof item.path !== "string" || typeof item.title !== "string") {
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 (!isRecord7(value) || !Array.isArray(value.capabilities) || value.capabilities.some((capability) => typeof capability !== "string")) {
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((resolve3, reject) => {
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
- resolve3();
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 record6 = { schemaVersion: 1, deviceId: uuidV7(), name: deviceName, publicKey: keys.publicKey };
20981
- await atomicJsonWrite(devicePath, record6, 384);
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 record6 = identitySchema.parse(JSON.parse(await readFile3(devicePath, "utf8")));
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 !== record6.publicKey) {
21199
+ if (regenerated.publicKey !== record7.publicKey) {
20991
21200
  throw new IdentityInvalidError("device public and private keys do not match");
20992
21201
  }
20993
- if (record6.name !== deviceName) {
20994
- record6 = { ...record6, name: deviceName };
20995
- await atomicJsonWrite(devicePath, record6, 384);
21202
+ if (record7.name !== deviceName) {
21203
+ record7 = { ...record7, name: deviceName };
21204
+ await atomicJsonWrite(devicePath, record7, 384);
20996
21205
  }
20997
- this.identity = { ...record6, privateKey, fingerprint: fingerprint(record6.publicKey) };
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 = record4(payload);
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 = record4(payload);
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" && record4(payload).mode === "local") return ok3(this.hostOnlyStatus());
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 = record4(payload);
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 = record4(payload);
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 = record4(payload).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 = record4(payload);
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 = record4(payload).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 = record4(payload);
21421
- if (typeof value.backend !== "string" || typeof value.enabled !== "boolean") throw new ClientModeError("INVALID_MESSAGE", "ACP backend and enabled are required.");
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 === value.backend ? { ...item, enabled: value.enabled } : item) ?? [];
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 = record4(payload);
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 = record4(payload).id;
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 isRecord8(value) {
21766
+ function isRecord9(value) {
21556
21767
  return typeof value === "object" && value !== null && !Array.isArray(value);
21557
21768
  }
21558
- function record4(value) {
21559
- if (!isRecord8(value)) throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
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(/^[\w-]{1,128}$/);
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 sessionId = id2.parse(args.agentId ?? args.sessionId);
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((resolve3, reject) => {
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 ? resolve3() : reject(error));
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((resolve3) => {
23105
+ return new Promise((resolve4) => {
22885
23106
  const timer = setTimeout(() => {
22886
23107
  this.retryWake = void 0;
22887
- resolve3();
23108
+ resolve4();
22888
23109
  }, delay);
22889
23110
  this.retryWake = () => {
22890
23111
  clearTimeout(timer);
22891
- resolve3();
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((resolve3, reject) => {
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
- resolve3(value);
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 nativeResult = params.endpoint === "commands/execute" ? await dispatchCommandForHost(this.gateway, params.payload, signal, this.harnessVersion) : await this.gateway.dispatch(params.endpoint, params.payload, signal);
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 = record5(payload);
24361
- const args = isRecord9(root.args) ? root.args : root;
24362
- return record5(args.request ?? args._request ?? args);
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 record5(value) {
24365
- return isRecord9(value) ? value : {};
24621
+ function record6(value) {
24622
+ return isRecord10(value) ? value : {};
24366
24623
  }
24367
- function isRecord9(value) {
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((resolve3) => {
24705
+ await new Promise((resolve4) => {
24449
24706
  const timer = setTimeout(() => {
24450
24707
  child.kill("SIGKILL");
24451
- resolve3();
24708
+ resolve4();
24452
24709
  }, 2e3);
24453
24710
  timer.unref?.();
24454
24711
  child.once("exit", () => {
24455
24712
  clearTimeout(timer);
24456
- resolve3();
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((resolve3, reject) => {
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: resolve3, reject, timer });
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 (!isRecord10(value)) {
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 (!isRecord10(value) || typeof value.message !== "string") return "Codex App Server rejected the request.";
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 isRecord10(value) {
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 isRecord11(value) {
25237
+ function isRecord12(value) {
24981
25238
  return typeof value === "object" && value !== null && !Array.isArray(value);
24982
25239
  }
24983
25240
  function safeErrorCode2(error) {
24984
- if (isRecord11(error) && typeof error.code === "string") return error.code;
25241
+ if (isRecord12(error) && typeof error.code === "string") return error.code;
24985
25242
  return "UNKNOWN";
24986
25243
  }
24987
25244
  function safeMethod(input2) {
24988
- return isRecord11(input2) && typeof input2.method === "string" ? input2.method : "invalid";
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 = { ...isRecord12(result) ? result : {}, ...settings, sandbox: settings.sandboxPolicy };
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 = isRecord12(value) ? value : {};
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 = isRecord12(result) ? result : {};
25778
+ const pageResult = isRecord13(result) ? result : {};
25509
25779
  for (const rawTurn of array2(pageResult.data)) {
25510
- if (!isRecord12(rawTurn)) continue;
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 = isRecord12(result) ? result : {};
25802
+ const pageResult = isRecord13(result) ? result : {};
25533
25803
  for (const entry of array2(pageResult.data)) {
25534
- if (isRecord12(entry) && entry.item !== void 0) items.push(entry.item);
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 (!isRecord12(params) || typeof params.requestId !== "string" && typeof params.requestId !== "number") return;
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 (!isRecord12(input2) || typeof input2.method !== "string" || !("params" in input2) || Object.keys(input2).some((key) => key !== "method" && key !== "params")) {
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 (!isRecord12(input2) || typeof input2.requestHandle !== "string" || !["accept", "decline", "cancel"].includes(String(input2.decision)) || Object.keys(input2).some((key) => key !== "requestHandle" && key !== "decision")) {
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 (!isRecord12(result) || typeof result.requiresOpenaiAuth !== "boolean") return false;
25828
- return result.requiresOpenaiAuth === false || isRecord12(result.account);
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 (!isRecord12(result)) throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned invalid account state.");
25832
- const account = isRecord12(result.account) ? result.account : void 0;
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 (!isRecord12(result) || !Array.isArray(result.data)) {
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 (!isRecord12(value) || typeof value.id !== "string") return [];
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
- ...isRecord12(value.status) ? { status: value.status } : {}
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 (!isRecord12(result) || !Array.isArray(result.data)) {
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((record6) => isRecord12(record6) ? record6 : void 0).filter((thread) => thread !== void 0 && isThreadAllowedByWorkspaceAuthority(thread, authority))
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 (!isRecord12(value) || typeof value.id !== "string" || typeof value.name !== "string") return void 0;
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 = isRecord12(root) && typeof root.path === "string" && root.path.length > 0 ? root.path : void 0;
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 (!isRecord12(result) || !Array.isArray(result.data)) {
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 = isRecord12(result) ? sanitizeProject(result.project) : void 0;
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 isRecord12(result) && isRecord12(result.thread) ? result.thread : void 0;
26208
+ return isRecord13(result) && isRecord13(result.thread) ? result.thread : void 0;
25939
26209
  }
25940
26210
  function extractTurnId(result) {
25941
- if (!isRecord12(result)) return void 0;
26211
+ if (!isRecord13(result)) return void 0;
25942
26212
  if (typeof result.turnId === "string" && result.turnId.length > 0) return result.turnId;
25943
- if (isRecord12(result.turn) && typeof result.turn.id === "string" && result.turn.id.length > 0) return result.turn.id;
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 (!isRecord12(params)) return void 0;
26217
+ if (!isRecord13(params)) return void 0;
25948
26218
  if (typeof params.threadId === "string") return params.threadId;
25949
- if (isRecord12(params.thread) && typeof params.thread.id === "string") return params.thread.id;
25950
- if (isRecord12(params.turn) && typeof params.turn.threadId === "string") return params.turn.threadId;
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 (!isRecord12(value) || value.type !== "image" || typeof value.mediaType !== "string" || typeof value.data !== "string") return value;
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 (!isRecord12(params)) return { requestHandle };
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 isRecord12(value) {
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((resolve3, reject) => {
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")) : resolve3(m.result);
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 stat5 } from "node:fs/promises";
27244
+ import { stat as stat6 } from "node:fs/promises";
26502
27245
  import { hostname as hostname3 } from "node:os";
26503
- import { join as join6 } from "node:path";
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(join6(directory, "device.json"))) {
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(join6(directory, "device.json"))) {
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((resolve3) => setTimeout(resolve3, milliseconds))),
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 stat5(path);
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((resolve3) => setTimeout(resolve3, milliseconds));
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
- function apply(ctx, input2 = {}) {
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(input2),
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, input2, tuiBinding);
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, input2, tuiBinding) {
27983
+ async function activate(ctx, readConfig, entryId, tuiBinding) {
27232
27984
  const settings = ctx.get("settings");
27233
- const settingsScope = settings?.register(pluginSettingsNamespace, Config, {
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(settingsScope?.get() ?? input2);
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, settingsScope, void 0, void 0);
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, settingsScope, clientRuntime, hostControl);
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,