ds-harness-remote 0.5.18 → 0.5.19

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 (131) hide show
  1. package/README.md +6 -8
  2. package/dist/acp/virtual-contract.d.ts +0 -1
  3. package/dist/acp/virtual-contract.d.ts.map +1 -1
  4. package/dist/acp/virtual-contract.js +0 -5
  5. package/dist/acp/virtual-contract.js.map +1 -1
  6. package/dist/acp/virtual-event-carrier.d.ts +0 -10
  7. package/dist/acp/virtual-event-carrier.d.ts.map +1 -1
  8. package/dist/acp/virtual-event-carrier.js +1 -129
  9. package/dist/acp/virtual-event-carrier.js.map +1 -1
  10. package/dist/acp/virtual-harness.d.ts +0 -4
  11. package/dist/acp/virtual-harness.d.ts.map +1 -1
  12. package/dist/acp/virtual-harness.js +0 -14
  13. package/dist/acp/virtual-harness.js.map +1 -1
  14. package/dist/acp/virtual-live.d.ts +0 -1
  15. package/dist/acp/virtual-live.d.ts.map +1 -1
  16. package/dist/acp/virtual-live.js +0 -5
  17. package/dist/acp/virtual-live.js.map +1 -1
  18. package/dist/client/shell.js +1 -1
  19. package/dist/client/shell.js.map +1 -1
  20. package/dist/client/workspaces.d.ts.map +1 -1
  21. package/dist/client/workspaces.js +38 -28
  22. package/dist/client/workspaces.js.map +1 -1
  23. package/dist/client-capabilities.d.ts +1 -1
  24. package/dist/client-capabilities.d.ts.map +1 -1
  25. package/dist/client-capabilities.js +8 -28
  26. package/dist/client-capabilities.js.map +1 -1
  27. package/dist/client-connection.d.ts +0 -2
  28. package/dist/client-connection.d.ts.map +1 -1
  29. package/dist/client-connection.js +0 -1
  30. package/dist/client-connection.js.map +1 -1
  31. package/dist/client-control.d.ts +3 -3
  32. package/dist/client-control.d.ts.map +1 -1
  33. package/dist/client-runtime-contract.d.ts +4 -6
  34. package/dist/client-runtime-contract.d.ts.map +1 -1
  35. package/dist/client-runtime-contract.js.map +1 -1
  36. package/dist/client-runtime.d.ts +4 -6
  37. package/dist/client-runtime.d.ts.map +1 -1
  38. package/dist/client-runtime.js +25 -89
  39. package/dist/client-runtime.js.map +1 -1
  40. package/dist/client-workspace-queries.d.ts +0 -6
  41. package/dist/client-workspace-queries.d.ts.map +1 -1
  42. package/dist/client-workspace-queries.js +0 -27
  43. package/dist/client-workspace-queries.js.map +1 -1
  44. package/dist/client.github.js +4 -3
  45. package/dist/client.js +4 -3
  46. package/dist/codex/virtual-contract.d.ts +0 -2
  47. package/dist/codex/virtual-contract.d.ts.map +1 -1
  48. package/dist/codex/virtual-contract.js +0 -5
  49. package/dist/codex/virtual-contract.js.map +1 -1
  50. package/dist/codex/virtual-event-carrier.d.ts +0 -10
  51. package/dist/codex/virtual-event-carrier.d.ts.map +1 -1
  52. package/dist/codex/virtual-event-carrier.js +2 -129
  53. package/dist/codex/virtual-event-carrier.js.map +1 -1
  54. package/dist/codex/virtual-harness.d.ts +1 -5
  55. package/dist/codex/virtual-harness.d.ts.map +1 -1
  56. package/dist/codex/virtual-harness.js +1 -21
  57. package/dist/codex/virtual-harness.js.map +1 -1
  58. package/dist/codex/virtual-live.d.ts +0 -4
  59. package/dist/codex/virtual-live.d.ts.map +1 -1
  60. package/dist/codex/virtual-live.js +4 -80
  61. package/dist/codex/virtual-live.js.map +1 -1
  62. package/dist/control-result.d.ts +13 -0
  63. package/dist/control-result.d.ts.map +1 -0
  64. package/dist/control-result.js +2 -0
  65. package/dist/control-result.js.map +1 -0
  66. package/dist/control-route.d.ts +2 -2
  67. package/dist/control-route.d.ts.map +1 -1
  68. package/dist/control-runtime.js.map +1 -1
  69. package/dist/harness-remote-bridge.d.ts +2 -0
  70. package/dist/harness-remote-bridge.d.ts.map +1 -1
  71. package/dist/harness-remote-bridge.js +53 -5
  72. package/dist/harness-remote-bridge.js.map +1 -1
  73. package/dist/harness-target.d.ts +2 -0
  74. package/dist/harness-target.d.ts.map +1 -0
  75. package/dist/harness-target.js +2 -0
  76. package/dist/harness-target.js.map +1 -0
  77. package/dist/harness-version.d.ts +0 -1
  78. package/dist/harness-version.d.ts.map +1 -1
  79. package/dist/harness-version.js +0 -6
  80. package/dist/harness-version.js.map +1 -1
  81. package/dist/index.d.ts +0 -3
  82. package/dist/index.d.ts.map +1 -1
  83. package/dist/index.js +419 -2126
  84. package/dist/index.js.map +4 -4
  85. package/dist/native-rtc-helper.d.ts +1 -0
  86. package/dist/native-rtc-helper.d.ts.map +1 -1
  87. package/dist/native-rtc-helper.js +5 -2
  88. package/dist/native-rtc-helper.js.map +1 -1
  89. package/dist/plugin-route-bridge.d.ts +1 -1
  90. package/dist/plugin-route-bridge.d.ts.map +1 -1
  91. package/dist/plugin-route-bridge.js +1 -1
  92. package/dist/plugin-route-bridge.js.map +1 -1
  93. package/dist/remote-typert-gateway.d.ts +2 -0
  94. package/dist/remote-typert-gateway.d.ts.map +1 -1
  95. package/dist/remote-typert-gateway.js +76 -26
  96. package/dist/remote-typert-gateway.js.map +1 -1
  97. package/dist/rpc-router.d.ts +2 -5
  98. package/dist/rpc-router.d.ts.map +1 -1
  99. package/dist/rpc-router.js +5 -32
  100. package/dist/rpc-router.js.map +1 -1
  101. package/dist/server-connection.d.ts.map +1 -1
  102. package/dist/server-connection.js +1 -1
  103. package/dist/server-connection.js.map +1 -1
  104. package/dist/service.d.ts +1 -3
  105. package/dist/service.d.ts.map +1 -1
  106. package/dist/service.js +9 -38
  107. package/dist/service.js.map +1 -1
  108. package/dist/tui-command.js +5 -7
  109. package/dist/tui-command.js.map +1 -1
  110. package/dist/typert-gateway-contract.d.ts +1 -1
  111. package/dist/typert-gateway-contract.d.ts.map +1 -1
  112. package/dist/version.d.ts +1 -1
  113. package/dist/version.js +1 -1
  114. package/dsh-plugin.json +1 -1
  115. package/package.json +1 -2
  116. package/dist/api-proxy-switch.d.ts +0 -35
  117. package/dist/api-proxy-switch.d.ts.map +0 -1
  118. package/dist/api-proxy-switch.js +0 -118
  119. package/dist/api-proxy-switch.js.map +0 -1
  120. package/dist/harness-api-bridge.d.ts +0 -80
  121. package/dist/harness-api-bridge.d.ts.map +0 -1
  122. package/dist/harness-api-bridge.js +0 -862
  123. package/dist/harness-api-bridge.js.map +0 -1
  124. package/dist/harness-api-history.d.ts +0 -3
  125. package/dist/harness-api-history.d.ts.map +0 -1
  126. package/dist/harness-api-history.js +0 -55
  127. package/dist/harness-api-history.js.map +0 -1
  128. package/dist/remote-api-proxy.d.ts +0 -17
  129. package/dist/remote-api-proxy.d.ts.map +0 -1
  130. package/dist/remote-api-proxy.js +0 -400
  131. package/dist/remote-api-proxy.js.map +0 -1
package/dist/index.js CHANGED
@@ -11324,10 +11324,6 @@ function carrierArgs(payload) {
11324
11324
  function requestArg(args) {
11325
11325
  return record(args.request ?? args._request ?? args);
11326
11326
  }
11327
- function rcEndpoint(endpoint) {
11328
- if (endpoint === "workspace.list") return "workspace/list";
11329
- return endpoint.replace(".", "/");
11330
- }
11331
11327
  function success(value) {
11332
11328
  return { ok: true, value };
11333
11329
  }
@@ -11485,20 +11481,6 @@ var AcpEventCarrier = class {
11485
11481
  }
11486
11482
  emitRemoteEvent(event, args) {
11487
11483
  for (const queue of this.context.eventStreams.values()) queue.push({ type: "emit", event, args });
11488
- const sessionId = typeof args[0] === "string" ? args[0] : void 0;
11489
- if (event === "api-session/status" && sessionId !== void 0 && typeof args[1] === "boolean") {
11490
- this.broadcastRcHost({ type: "host/session-status", sessionId, running: args[1] });
11491
- } else if (event === "api-session/removed" && sessionId !== void 0) {
11492
- this.broadcastRcHost({ type: "host/session-removed", sessionId });
11493
- } else if (event === "api-session/added" && isRecord3(args[0])) {
11494
- const summary2 = args[0];
11495
- this.broadcastRcHost({
11496
- type: "host/session-added",
11497
- sessionId: summary2.sessionId,
11498
- blank: summary2.blank === true,
11499
- ...typeof summary2.cwd === "string" ? { cwd: summary2.cwd } : {}
11500
- });
11501
- }
11502
11484
  }
11503
11485
  emitApproval(input3) {
11504
11486
  for (const queue of this.context.eventStreams.values()) queue.push({
@@ -11508,13 +11490,6 @@ var AcpEventCarrier = class {
11508
11490
  agentId: input3.agentId,
11509
11491
  request: input3.request
11510
11492
  });
11511
- this.broadcastRcMux({
11512
- type: "approval/requested",
11513
- sessionId: input3.agentId,
11514
- approvalId: input3.eventId,
11515
- toolName: string(input3.request.toolName) ?? this.context.backendLabel(),
11516
- ...typeof input3.request.reason === "string" ? { reason: input3.request.reason } : {}
11517
- }, input3.eventId);
11518
11493
  }
11519
11494
  async answerRemoteEvent(args, signal) {
11520
11495
  const eventId = string(args.eventId);
@@ -11527,105 +11502,10 @@ var AcpEventCarrier = class {
11527
11502
  await this.context.client.respond(pending.requestHandle, decision, void 0, signal);
11528
11503
  return void 0;
11529
11504
  }
11530
- createApiProxy() {
11531
- const call = (endpoint) => async (request, signal) => {
11532
- const payload = endpoint === "session.prompt" && isRecord3(request.payload) ? { ...request.payload, requestId: String(request.rpcId) } : request.payload;
11533
- const result = await this.context.dispatch(rcEndpoint(endpoint), { args: { request: payload } }, signal ?? new AbortController().signal);
11534
- return {
11535
- rpcId: request.rpcId,
11536
- result: result.ok ? success(result.value) : failure(result.error.code, result.error.message, result.error.details)
11537
- };
11538
- };
11539
- return {
11540
- sessions: {
11541
- list: call("session.list"),
11542
- search: call("session.search"),
11543
- create: call("session.create"),
11544
- history: call("session.history"),
11545
- models: call("session.models"),
11546
- selectModel: call("session.selectModel"),
11547
- rename: call("session.rename"),
11548
- fork: call("session.fork"),
11549
- prompt: call("session.prompt"),
11550
- attachment: call("session.attachment"),
11551
- updateQueue: call("session.updateQueue"),
11552
- cancel: call("session.cancel")
11553
- },
11554
- workspace: {
11555
- list: call("workspace.list"),
11556
- create: call("workspace.create"),
11557
- rename: call("workspace.rename"),
11558
- delete: call("workspace.delete"),
11559
- insertBefore: call("workspace.insertBefore"),
11560
- insertSessionBefore: call("workspace.insertSessionBefore"),
11561
- archiveSession: call("workspace.archiveSession")
11562
- },
11563
- subagents: {},
11564
- host: {
11565
- describe: call("host.describe"),
11566
- listDirectory: call("host.listDirectory")
11567
- },
11568
- skills: { list: call("skills.list") },
11569
- agentPresets: {},
11570
- goals: {},
11571
- settings: {},
11572
- credentials: {},
11573
- llm: {},
11574
- events: {
11575
- mux: ((request, signal) => this.rcMux(request, signal)),
11576
- host: ((request, signal) => this.rcHost(request, signal))
11577
- },
11578
- downloads: {},
11579
- respond: async (message) => {
11580
- const pending = this.context.pendingApprovals.get(String(message.rpcId)) ?? [...this.context.pendingApprovals.values()].find((item) => item.requestHandle === String(message.rpcId));
11581
- if (pending === void 0) return { accepted: false, reason: "not-pending" };
11582
- const result = message.result;
11583
- const outcome = result.ok ? result.value : void 0;
11584
- const decision = outcome === "allowed-once" ? "allow-once" : outcome === "cancelled" ? "cancel" : "reject-once";
11585
- await this.context.client.respond(pending.requestHandle, decision);
11586
- this.context.pendingApprovals.delete(pending.requestHandle);
11587
- return { accepted: true };
11588
- }
11589
- };
11590
- }
11591
- async *rcMux(request, signal) {
11592
- const queue = new AsyncValueQueue(signal);
11593
- this.context.rcMuxStreams.add(queue);
11594
- for (const session of this.context.sessions.values()) {
11595
- queue.push({
11596
- rpcId: `${String(request.rpcId)}:${session.sessionId}:subscribed`,
11597
- payload: { type: "session/subscribed", sessionId: session.sessionId, lastSeq: -1 }
11598
- });
11599
- }
11600
- try {
11601
- yield* queue;
11602
- } finally {
11603
- this.context.rcMuxStreams.delete(queue);
11604
- queue.close();
11605
- }
11606
- }
11607
- async *rcHost(_request, signal) {
11608
- const queue = new AsyncValueQueue(signal);
11609
- this.context.rcHostStreams.add(queue);
11610
- try {
11611
- yield* queue;
11612
- } finally {
11613
- this.context.rcHostStreams.delete(queue);
11614
- queue.close();
11615
- }
11616
- }
11617
- broadcastRcMux(payload, rpcId2 = `cursor-mux:${Date.now()}:${Math.random()}`) {
11618
- for (const queue of this.context.rcMuxStreams) queue.push({ rpcId: rpcId2, payload });
11619
- }
11620
- broadcastRcHost(payload) {
11621
- const frame = { rpcId: `cursor-host:${Date.now()}:${Math.random()}`, payload };
11622
- for (const queue of this.context.rcHostStreams) queue.push(frame);
11623
- }
11624
11505
  publishProjection(sessionId, key, value, seq = this.context.nextProjectionSeq()) {
11625
11506
  for (const queue of this.context.controlStreams) {
11626
11507
  queue.push({ type: "projection", sessionId, key, value, asOfSeq: seq, seq });
11627
11508
  }
11628
- this.broadcastRcMux({ type: "session/projection", sessionId, key, value, seq });
11629
11509
  }
11630
11510
  };
11631
11511
 
@@ -12127,11 +12007,6 @@ var AcpLiveProjection = class {
12127
12007
  f.nextSeq = seq + 1;
12128
12008
  }
12129
12009
  }
12130
- this.context.broadcastRcMux({
12131
- type: "session/event",
12132
- sessionId: follow.sessionId,
12133
- event
12134
- });
12135
12010
  return seq;
12136
12011
  }
12137
12012
  };
@@ -12254,8 +12129,7 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
12254
12129
  return owner.pendingApprovals;
12255
12130
  },
12256
12131
  emitApproval: (...args) => owner.events.emitApproval(...args),
12257
- modelSelection: (...args) => owner.modelSelection(...args),
12258
- broadcastRcMux: (...args) => owner.events.broadcastRcMux(...args)
12132
+ modelSelection: (...args) => owner.modelSelection(...args)
12259
12133
  });
12260
12134
  this.events = new AcpEventCarrier({
12261
12135
  get archivedSessionIds() {
@@ -12284,16 +12158,9 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
12284
12158
  get client() {
12285
12159
  return owner.client;
12286
12160
  },
12287
- dispatch: (...args) => owner.dispatch(...args),
12288
- get rcMuxStreams() {
12289
- return owner.rcMuxStreams;
12290
- },
12291
12161
  get sessions() {
12292
12162
  return owner.sessions;
12293
12163
  },
12294
- get rcHostStreams() {
12295
- return owner.rcHostStreams;
12296
- },
12297
12164
  nextProjectionSeq: (...args) => owner.nextProjectionSeq(...args)
12298
12165
  });
12299
12166
  this.titles = new AcpSessionTitles(
@@ -12302,7 +12169,6 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
12302
12169
  this.sessions,
12303
12170
  (sessionId, title) => this.events.publishProjection(sessionId, "title", title)
12304
12171
  );
12305
- this.api = this.events.createApiProxy();
12306
12172
  this.unsubscribeArchived = client.onSessionArchived?.((data2) => {
12307
12173
  if (this.closed || data2.backend !== this.backend) return;
12308
12174
  this.applyArchived(`${sessionPrefix(this.backend)}${data2.sessionId}`);
@@ -12311,14 +12177,11 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
12311
12177
  live;
12312
12178
  events;
12313
12179
  titles;
12314
- api;
12315
12180
  workspaceById = /* @__PURE__ */ new Map();
12316
12181
  sessions = /* @__PURE__ */ new Map();
12317
12182
  workspaceStreams = /* @__PURE__ */ new Set();
12318
12183
  controlStreams = /* @__PURE__ */ new Set();
12319
12184
  eventStreams = /* @__PURE__ */ new Map();
12320
- rcMuxStreams = /* @__PURE__ */ new Set();
12321
- rcHostStreams = /* @__PURE__ */ new Set();
12322
12185
  follows = /* @__PURE__ */ new Set();
12323
12186
  pendingApprovals = /* @__PURE__ */ new Map();
12324
12187
  pendingHistory = /* @__PURE__ */ new Map();
@@ -12526,13 +12389,9 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
12526
12389
  for (const stream of this.workspaceStreams) stream.close();
12527
12390
  for (const stream of this.controlStreams) stream.close();
12528
12391
  for (const stream of this.eventStreams.values()) stream.close();
12529
- for (const stream of this.rcMuxStreams) stream.close();
12530
- for (const stream of this.rcHostStreams) stream.close();
12531
12392
  this.workspaceStreams.clear();
12532
12393
  this.controlStreams.clear();
12533
12394
  this.eventStreams.clear();
12534
- this.rcMuxStreams.clear();
12535
- this.rcHostStreams.clear();
12536
12395
  const follows = [...this.follows];
12537
12396
  this.follows.clear();
12538
12397
  for (const follow of follows) {
@@ -13042,110 +12901,6 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
13042
12901
  }
13043
12902
  };
13044
12903
 
13045
- // src/api-proxy-switch.ts
13046
- var SWITCHED_DOMAINS = [
13047
- "sessions",
13048
- "subagents",
13049
- "host",
13050
- "workspace",
13051
- "skills",
13052
- "agentPresets",
13053
- "events",
13054
- "goals",
13055
- "llm",
13056
- "settings",
13057
- "credentials"
13058
- ];
13059
- var ApiProxySwitch = class {
13060
- remote;
13061
- target;
13062
- mode = "local";
13063
- installed = false;
13064
- disconnected = false;
13065
- local;
13066
- originals;
13067
- localRespond;
13068
- constructor(local) {
13069
- this.local = local;
13070
- this.originals = new Map(SWITCHED_DOMAINS.map((domain) => [domain, local[domain]]));
13071
- this.localRespond = local.respond.bind(local);
13072
- }
13073
- install() {
13074
- if (this.installed) return;
13075
- for (const domain of SWITCHED_DOMAINS) {
13076
- const localDomain = this.local[domain];
13077
- const forwarder = new Proxy({}, {
13078
- get: (_target, key) => {
13079
- const selected = this.selected(domain);
13080
- const value = selected[key];
13081
- return typeof value === "function" ? value.bind(selected) : value;
13082
- }
13083
- });
13084
- Object.defineProperty(this.local, domain, {
13085
- configurable: true,
13086
- enumerable: true,
13087
- writable: true,
13088
- value: forwarder
13089
- });
13090
- }
13091
- Object.defineProperty(this.local, "respond", {
13092
- configurable: true,
13093
- enumerable: true,
13094
- writable: true,
13095
- value: (...args) => this.mode === "remote" ? this.requireRemote().respond(...args) : this.localRespond(...args)
13096
- });
13097
- this.installed = true;
13098
- }
13099
- selectRemote(api, target2) {
13100
- if (!this.installed) throw new Error("The Harness API switch is not installed.");
13101
- this.remote = api;
13102
- this.disconnected = false;
13103
- this.target = { ...target2 };
13104
- this.mode = "remote";
13105
- }
13106
- selectLocal() {
13107
- this.disconnected = false;
13108
- this.mode = "local";
13109
- this.remote = void 0;
13110
- this.target = void 0;
13111
- }
13112
- disconnectRemote() {
13113
- if (this.mode === "remote") this.disconnected = true;
13114
- }
13115
- status() {
13116
- return { mode: this.mode, ...this.target === void 0 ? {} : { target: { ...this.target } } };
13117
- }
13118
- restore() {
13119
- if (!this.installed) return;
13120
- this.selectLocal();
13121
- for (const [domain, value] of this.originals) Object.defineProperty(this.local, domain, {
13122
- configurable: true,
13123
- enumerable: true,
13124
- writable: true,
13125
- value
13126
- });
13127
- Object.defineProperty(this.local, "respond", {
13128
- configurable: true,
13129
- enumerable: true,
13130
- writable: true,
13131
- value: this.localRespond
13132
- });
13133
- this.installed = false;
13134
- }
13135
- selected(domain) {
13136
- if (this.mode === "local") return this.originalDomain(domain);
13137
- return this.requireRemote()[domain];
13138
- }
13139
- originalDomain(domain) {
13140
- return this.originals.get(domain);
13141
- }
13142
- requireRemote() {
13143
- if (this.disconnected) throw Object.assign(new Error("The Remote connection was lost. Reconnect to continue."), { code: "remote/disconnected" });
13144
- if (this.remote === void 0) throw new Error("No remote Harness target is selected.");
13145
- return this.remote;
13146
- }
13147
- };
13148
-
13149
12904
  // ../webrtc/dist/websocket-backpressure.js
13150
12905
  async function waitForRelayCapacity(socket) {
13151
12906
  const started = Date.now();
@@ -14906,14 +14661,11 @@ function iceServersForAttempt(attempt, iceServers) {
14906
14661
  }
14907
14662
 
14908
14663
  // src/client-capabilities.ts
14909
- var REMOTE_COMMAND_LIST_MIN_VERSION = [0, 3, 16];
14910
- var REMOTE_FILE_VIEWER_MIN_VERSION = [0, 3, 17];
14911
14664
  function remoteHostFeatures(clientVersion) {
14912
14665
  return {
14913
- commandList: isVersionAtLeast(clientVersion, REMOTE_COMMAND_LIST_MIN_VERSION),
14914
- fileViewer: isVersionAtLeast(clientVersion, REMOTE_FILE_VIEWER_MIN_VERSION),
14666
+ commandList: false,
14667
+ fileViewer: false,
14915
14668
  terminal: false,
14916
- apiProxy: true,
14917
14669
  remoteGateway: false,
14918
14670
  codex: false,
14919
14671
  cursor: false,
@@ -14923,19 +14675,19 @@ function remoteHostFeatures(clientVersion) {
14923
14675
  };
14924
14676
  }
14925
14677
  async function probeRemoteHostFeatures(client, clientVersion) {
14926
- const fallback = remoteHostFeatures(clientVersion);
14927
14678
  let value;
14928
14679
  try {
14929
14680
  value = await client.rpc("harness.transport.describe", {});
14930
14681
  } catch (error) {
14931
- if (error instanceof Error && "code" in error && error.code === "METHOD_NOT_FOUND") return fallback;
14682
+ if (error instanceof Error && "code" in error && error.code === "METHOD_NOT_FOUND") {
14683
+ throw new ClientModeError("FEATURE_NOT_SUPPORTED", "This Host predates Typert Remote capability discovery. Upgrade the Host.");
14684
+ }
14932
14685
  throw error;
14933
14686
  }
14934
14687
  if (!isRecord4(value) || !Array.isArray(value.capabilities) || value.capabilities.some((capability) => typeof capability !== "string")) {
14935
14688
  throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned invalid transport capabilities.");
14936
14689
  }
14937
14690
  const capabilities = new Set(value.capabilities);
14938
- const apiProxy = capabilities.has("harness.api.v1");
14939
14691
  const remoteV1 = capabilities.has("harness.remote.v1");
14940
14692
  const remoteV3 = capabilities.has("harness.remote.v3");
14941
14693
  const terminal = capabilities.has("harness.terminal.v1");
@@ -14952,14 +14704,13 @@ async function probeRemoteHostFeatures(client, clientVersion) {
14952
14704
  }
14953
14705
  const sessionFormat = remoteV3 ? 3 : void 0;
14954
14706
  const remoteGateway = remoteV3 || remoteV1;
14955
- if (!apiProxy && !remoteGateway && !codex && !cursor2 && !antigravity && !pi && !opencode && !claude) {
14707
+ if (!remoteGateway && !codex && !cursor2 && !antigravity && !pi && !opencode && !claude) {
14956
14708
  throw new ClientModeError("FEATURE_NOT_SUPPORTED", "The remote Host exposes no supported Harness transport.");
14957
14709
  }
14958
14710
  return {
14959
- commandList: remoteGateway || apiProxy && fallback.commandList,
14711
+ commandList: remoteGateway,
14960
14712
  fileViewer: capabilities.has("fileviewer.read.v1"),
14961
14713
  terminal,
14962
- apiProxy,
14963
14714
  remoteGateway,
14964
14715
  ...sessionFormat === void 0 ? {} : { sessionFormat },
14965
14716
  codex,
@@ -14973,18 +14724,6 @@ async function probeRemoteHostFeatures(client, clientVersion) {
14973
14724
  pluginRoute: capabilities.has("plugin.route.v1")
14974
14725
  };
14975
14726
  }
14976
- function isVersionAtLeast(value, minimum) {
14977
- const match = value?.match(/^v?(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/);
14978
- if (match === void 0 || match === null) return false;
14979
- const version = match.slice(1, 4).map((part) => Number(part));
14980
- for (let index = 0; index < minimum.length; index += 1) {
14981
- const part = version[index] ?? 0;
14982
- const expected = minimum[index] ?? 0;
14983
- if (part > expected) return true;
14984
- if (part < expected) return false;
14985
- }
14986
- return true;
14987
- }
14988
14727
 
14989
14728
  // src/client-codex-streams.ts
14990
14729
  var ClientCodexStreams = class {
@@ -22381,7 +22120,6 @@ var ClientConnection = class {
22381
22120
  this.context.pendingWorkspaceSelection = void 0;
22382
22121
  void this.context.closeCodexVirtual();
22383
22122
  void this.context.closeCursorVirtual();
22384
- this.context.proxySwitch?.disconnectRemote();
22385
22123
  this.context.gatewaySwitch.disconnectRemote();
22386
22124
  void connectedClient.close().catch(() => void 0);
22387
22125
  this.context.logger.warn("remote Harness transport closed; keeping Remote authority disconnected", {
@@ -23009,6 +22747,9 @@ var BOT_REMOTE_OPERATIONS = [
23009
22747
  "agent-rename",
23010
22748
  "remove-agent",
23011
22749
  "send",
22750
+ "btw",
22751
+ "btw-cancel",
22752
+ "room-continue",
23012
22753
  "answer-question",
23013
22754
  "dismiss-question",
23014
22755
  "view-reply",
@@ -23340,37 +23081,7 @@ var ClientControl = class {
23340
23081
  }
23341
23082
  };
23342
23083
 
23343
- // src/ids.ts
23344
- import { randomBytes as randomBytes7 } from "node:crypto";
23345
- function uuidV7(now = Date.now()) {
23346
- if (!Number.isSafeInteger(now) || now < 0 || now > 281474976710655) {
23347
- throw new RangeError("UUIDv7 timestamp must be a non-negative 48-bit integer");
23348
- }
23349
- const bytes = randomBytes7(16);
23350
- let timestamp = BigInt(now);
23351
- for (let index = 5; index >= 0; index -= 1) {
23352
- bytes[index] = Number(timestamp & 0xffn);
23353
- timestamp >>= 8n;
23354
- }
23355
- bytes[6] = 112 | bytes[6] & 15;
23356
- bytes[8] = 128 | bytes[8] & 63;
23357
- const hex = bytes.toString("hex");
23358
- return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
23359
- }
23360
-
23361
23084
  // src/client-workspace-queries.ts
23362
- async function invokeRemoteCommand(client, request) {
23363
- const rpcId2 = uuidV7();
23364
- const response = await client.rpc("harness.api.call", {
23365
- method: `${request.namespace}.${request.method}`,
23366
- rpcId: rpcId2,
23367
- payload: request.args
23368
- }, request.signal);
23369
- if (response.rpcId !== rpcId2) {
23370
- throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned an invalid command response.");
23371
- }
23372
- return unwrapNativeResult(response);
23373
- }
23374
23085
  async function readRemoteWorkspaceBaseline(gateway, signal) {
23375
23086
  const lifetime = new AbortController();
23376
23087
  const activeSignal = signal === void 0 ? lifetime.signal : AbortSignal.any([signal, lifetime.signal]);
@@ -23392,17 +23103,6 @@ async function readRemoteWorkspaceBaseline(gateway, signal) {
23392
23103
  await iterator.return?.();
23393
23104
  }
23394
23105
  }
23395
- function unwrapNativeResult(response) {
23396
- const result = response.result;
23397
- if (typeof result !== "object" || result === null || !("ok" in result)) {
23398
- throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned an invalid response.");
23399
- }
23400
- if (result.ok !== true || !("value" in result)) {
23401
- const message = "error" in result && typeof result.error === "object" && result.error !== null && "message" in result.error && typeof result.error.message === "string" ? result.error.message : "The remote Host rejected the request.";
23402
- throw new ClientModeError("REMOTE_API_ERROR", message);
23403
- }
23404
- return result.value;
23405
- }
23406
23106
  function workspaceRecordId(value) {
23407
23107
  if (typeof value !== "object" || value === null || !("workspaceId" in value) || typeof value.workspaceId !== "string" || value.workspaceId.length === 0) {
23408
23108
  throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned an invalid Workspace.");
@@ -24089,10 +23789,6 @@ function carrierArgs2(payload) {
24089
23789
  function requestArg2(args) {
24090
23790
  return record4(args.request ?? args._request ?? args);
24091
23791
  }
24092
- function rcEndpoint2(endpoint) {
24093
- if (endpoint === "workspace.list") return "workspace/list";
24094
- return endpoint.replace(".", "/");
24095
- }
24096
23792
  function success2(value) {
24097
23793
  return { ok: true, value };
24098
23794
  }
@@ -24224,20 +23920,6 @@ var CodexEventCarrier = class {
24224
23920
  }
24225
23921
  emitRemoteEvent(event, args) {
24226
23922
  for (const queue of this.context.eventStreams.values()) queue.push({ type: "emit", event, args });
24227
- const sessionId = typeof args[0] === "string" ? args[0] : void 0;
24228
- if (event === "api-session/status" && sessionId !== void 0 && typeof args[1] === "boolean") {
24229
- this.broadcastRcHost({ type: "host/session-status", sessionId, running: args[1] });
24230
- } else if (event === "api-session/removed" && sessionId !== void 0) {
24231
- this.broadcastRcHost({ type: "host/session-removed", sessionId });
24232
- } else if (event === "api-session/added" && isRecord5(args[0])) {
24233
- const summary2 = args[0];
24234
- this.broadcastRcHost({
24235
- type: "host/session-added",
24236
- sessionId: summary2.sessionId,
24237
- blank: summary2.blank === true,
24238
- ...typeof summary2.cwd === "string" ? { cwd: summary2.cwd } : {}
24239
- });
24240
- }
24241
23923
  }
24242
23924
  emitApproval(input3) {
24243
23925
  for (const queue of this.context.eventStreams.values()) queue.push({
@@ -24247,13 +23929,6 @@ var CodexEventCarrier = class {
24247
23929
  agentId: input3.agentId,
24248
23930
  request: input3.request
24249
23931
  });
24250
- this.broadcastRcMux({
24251
- type: "approval/requested",
24252
- sessionId: input3.agentId,
24253
- approvalId: input3.eventId,
24254
- toolName: string2(input3.request.toolName) ?? "CodeX",
24255
- ...typeof input3.request.reason === "string" ? { reason: input3.request.reason } : {}
24256
- }, input3.eventId);
24257
23932
  }
24258
23933
  async answerRemoteEvent(args, signal) {
24259
23934
  const eventId = string2(args.eventId);
@@ -24266,102 +23941,8 @@ var CodexEventCarrier = class {
24266
23941
  await this.context.client.respond(pending.requestHandle, decision, signal);
24267
23942
  return void 0;
24268
23943
  }
24269
- createApiProxy() {
24270
- const call = (endpoint) => async (request, signal) => {
24271
- const payload = endpoint === "session.prompt" && isRecord5(request.payload) ? { ...request.payload, requestId: String(request.rpcId) } : request.payload;
24272
- const result = await this.context.dispatch(rcEndpoint2(endpoint), { args: { request: payload } }, signal ?? new AbortController().signal);
24273
- return {
24274
- rpcId: request.rpcId,
24275
- result: result.ok ? success2(result.value) : failure2(result.error.code, result.error.message, result.error.details)
24276
- };
24277
- };
24278
- return {
24279
- sessions: {
24280
- list: call("session.list"),
24281
- search: call("session.search"),
24282
- create: call("session.create"),
24283
- history: call("session.history"),
24284
- models: call("session.models"),
24285
- selectModel: call("session.selectModel"),
24286
- rename: call("session.rename"),
24287
- fork: call("session.fork"),
24288
- prompt: call("session.prompt"),
24289
- attachment: call("session.attachment"),
24290
- updateQueue: call("session.updateQueue"),
24291
- cancel: call("session.cancel")
24292
- },
24293
- workspace: {
24294
- list: call("workspace.list"),
24295
- create: call("workspace.create"),
24296
- rename: call("workspace.rename"),
24297
- delete: call("workspace.delete"),
24298
- insertBefore: call("workspace.insertBefore"),
24299
- insertSessionBefore: call("workspace.insertSessionBefore"),
24300
- archiveSession: call("workspace.archiveSession")
24301
- },
24302
- subagents: {},
24303
- host: {
24304
- describe: call("host.describe"),
24305
- listDirectory: call("host.listDirectory")
24306
- },
24307
- skills: { list: call("skills.list") },
24308
- agentPresets: {},
24309
- goals: {},
24310
- settings: {},
24311
- credentials: {},
24312
- llm: {},
24313
- events: {
24314
- mux: ((request, signal) => this.rcMux(request, signal)),
24315
- host: ((request, signal) => this.rcHost(request, signal))
24316
- },
24317
- downloads: {},
24318
- respond: async (message) => {
24319
- const pending = this.context.pendingApprovals.get(String(message.rpcId));
24320
- if (pending === void 0) return { accepted: false, reason: "not-pending" };
24321
- const result = message.result;
24322
- const outcome = result.ok ? result.value : void 0;
24323
- const decision = outcome === "allowed-once" ? "accept" : outcome === "cancelled" ? "cancel" : "decline";
24324
- await this.context.client.respond(pending.requestHandle, decision);
24325
- this.context.pendingApprovals.delete(pending.requestHandle);
24326
- return { accepted: true };
24327
- }
24328
- };
24329
- }
24330
- async *rcMux(request, signal) {
24331
- const queue = new AsyncValueQueue2(signal);
24332
- this.context.rcMuxStreams.add(queue);
24333
- const catalog = await this.context.currentCatalog(signal);
24334
- for (const session of catalog.sessions) queue.push({
24335
- rpcId: `${String(request.rpcId)}:${session.id}:subscribed`,
24336
- payload: { type: "session/subscribed", sessionId: session.id, lastSeq: -1 }
24337
- });
24338
- try {
24339
- yield* queue;
24340
- } finally {
24341
- this.context.rcMuxStreams.delete(queue);
24342
- queue.close();
24343
- }
24344
- }
24345
- async *rcHost(_request, signal) {
24346
- const queue = new AsyncValueQueue2(signal);
24347
- this.context.rcHostStreams.add(queue);
24348
- try {
24349
- yield* queue;
24350
- } finally {
24351
- this.context.rcHostStreams.delete(queue);
24352
- queue.close();
24353
- }
24354
- }
24355
- broadcastRcMux(payload, rpcId2 = `codex-mux:${Date.now()}:${Math.random()}`) {
24356
- for (const queue of this.context.rcMuxStreams) queue.push({ rpcId: rpcId2, payload });
24357
- }
24358
- broadcastRcHost(payload) {
24359
- const frame = { rpcId: `codex-host:${Date.now()}:${Math.random()}`, payload };
24360
- for (const queue of this.context.rcHostStreams) queue.push(frame);
24361
- }
24362
23944
  publishProjection(sessionId, key, value, seq) {
24363
23945
  for (const queue of this.context.controlStreams) queue.push({ type: "projection", sessionId, key, value, seq });
24364
- this.broadcastRcMux({ type: "session/projection", sessionId, key, value, seq });
24365
23946
  }
24366
23947
  };
24367
23948
 
@@ -25015,13 +24596,6 @@ var CodexLiveProjection = class {
25015
24596
  const status2 = record4(params.status);
25016
24597
  const running = status2.type === "active";
25017
24598
  this.context.emitRemoteEvent("api-session/status", [follow.sessionId, running]);
25018
- if (status2.type === "systemError") {
25019
- this.context.broadcastRcHost({
25020
- type: "host/agent-error",
25021
- sessionId: follow.sessionId,
25022
- message: "CodeX reported a thread system error."
25023
- });
25024
- }
25025
24599
  return;
25026
24600
  }
25027
24601
  if (frame.method === "model/rerouted") {
@@ -25133,16 +24707,8 @@ var CodexLiveProjection = class {
25133
24707
  } : {}
25134
24708
  };
25135
24709
  this.cacheImageBlocks(follow.sessionId, event.data);
25136
- if (!follow.rcOnly) {
25137
- follow.queue.push({
25138
- type: "event",
25139
- event,
25140
- ...view === void 0 ? {} : { view }
25141
- });
25142
- }
25143
- this.context.broadcastRcMux({
25144
- type: "session/event",
25145
- sessionId: follow.sessionId,
24710
+ follow.queue.push({
24711
+ type: "event",
25146
24712
  event,
25147
24713
  ...view === void 0 ? {} : { view }
25148
24714
  });
@@ -25202,7 +24768,7 @@ var CodexLiveProjection = class {
25202
24768
  follow.streamActive = false;
25203
24769
  }
25204
24770
  pushAssistantChunk(follow, chunk) {
25205
- if (this.context.sessionGeneration !== "v3" || follow.rcOnly === true) {
24771
+ if (this.context.sessionGeneration !== "v3") {
25206
24772
  this.pushEvent(follow, "assistant/chunk", { turn: follow.turn, step: 1, chunk });
25207
24773
  return;
25208
24774
  }
@@ -25249,7 +24815,7 @@ var CodexLiveProjection = class {
25249
24815
  if (attempt === void 0) return;
25250
24816
  follow.assistantAttempt = void 0;
25251
24817
  follow.assistantStreamRevision += 1;
25252
- if (this.context.sessionGeneration === "v3" && follow.rcOnly !== true) {
24818
+ if (this.context.sessionGeneration === "v3") {
25253
24819
  follow.queue.push({
25254
24820
  type: "assistant-stream",
25255
24821
  frame: {
@@ -25310,65 +24876,6 @@ var CodexLiveProjection = class {
25310
24876
  follow.liveToolResultSeq.clear();
25311
24877
  follow.pendingToolImages = [];
25312
24878
  }
25313
- async ensureRcFollow(sessionId, seedHistory) {
25314
- if (this.followsHas(sessionId)) return;
25315
- const threadId = nativeThreadId(sessionId);
25316
- const stale = [...this.context.follows].filter((follow2) => follow2.rcOnly && follow2.sessionId !== sessionId);
25317
- for (const follow2 of stale) {
25318
- this.context.follows.delete(follow2);
25319
- follow2.queue.close();
25320
- await follow2.close?.().catch(() => void 0);
25321
- }
25322
- const history = seedHistory ?? await this.context.readHistoryPage(threadId, {}, void 0);
25323
- const controller = new AbortController();
25324
- const follow = {
25325
- sessionId,
25326
- threadId,
25327
- queue: new AsyncValueQueue2(controller.signal),
25328
- nextSeq: history.cursor + 1,
25329
- turn: history.nextTurn,
25330
- stepOpen: history.activeTurnId !== void 0,
25331
- startedItems: /* @__PURE__ */ new Set(),
25332
- completedItems: /* @__PURE__ */ new Set(),
25333
- streamedBlocks: /* @__PURE__ */ new Map(),
25334
- nextBlockIndex: 0,
25335
- streamActive: false,
25336
- assistantStreamRevision: 0,
25337
- liveItems: /* @__PURE__ */ new Map(),
25338
- liveToolOutput: /* @__PURE__ */ new Map(),
25339
- liveToolResultSeq: /* @__PURE__ */ new Map(),
25340
- pendingToolImages: [],
25341
- requestId: this.context.pendingRequestIds.get(sessionId),
25342
- rcOnly: true,
25343
- ...history.activeTurnId === void 0 ? {} : { activeTurnId: history.activeTurnId }
25344
- };
25345
- this.context.follows.add(follow);
25346
- try {
25347
- const stream = await this.context.client.subscribe(
25348
- threadId,
25349
- (frame) => this.acceptCodexFrame(follow, frame),
25350
- controller.signal,
25351
- () => this.closeFollowAfterRemoteStreamClosed(follow)
25352
- );
25353
- if (this.context.closed || !this.context.follows.has(follow)) {
25354
- await stream.close().catch(() => void 0);
25355
- throw new Error("The CodeX follow was closed before it opened.");
25356
- }
25357
- follow.close = async () => {
25358
- controller.abort();
25359
- await stream.close();
25360
- };
25361
- } catch (error) {
25362
- this.context.follows.delete(follow);
25363
- controller.abort();
25364
- follow.queue.close();
25365
- throw error;
25366
- }
25367
- }
25368
- followsHas(sessionId) {
25369
- for (const follow of this.context.follows) if (follow.sessionId === sessionId) return true;
25370
- return false;
25371
- }
25372
24879
  closeFollowAfterRemoteStreamClosed(follow) {
25373
24880
  this.context.follows.delete(follow);
25374
24881
  follow.queue.close();
@@ -25411,7 +24918,6 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
25411
24918
  publishProjection: (...args) => owner.events.publishProjection(...args),
25412
24919
  setPermissionSelection: (...args) => owner.setPermissionSelection(...args),
25413
24920
  emitRemoteEvent: (...args) => owner.events.emitRemoteEvent(...args),
25414
- broadcastRcHost: (...args) => owner.events.broadcastRcHost(...args),
25415
24921
  get selectedModels() {
25416
24922
  return owner.selectedModels;
25417
24923
  },
@@ -25420,7 +24926,6 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
25420
24926
  return owner.pendingApprovals;
25421
24927
  },
25422
24928
  emitApproval: (...args) => owner.events.emitApproval(...args),
25423
- broadcastRcMux: (...args) => owner.events.broadcastRcMux(...args),
25424
24929
  get imageAttachments() {
25425
24930
  return owner.imageAttachments;
25426
24931
  }
@@ -25448,26 +24953,15 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
25448
24953
  },
25449
24954
  get client() {
25450
24955
  return owner.client;
25451
- },
25452
- dispatch: (...args) => owner.dispatch(...args),
25453
- get rcMuxStreams() {
25454
- return owner.rcMuxStreams;
25455
- },
25456
- get rcHostStreams() {
25457
- return owner.rcHostStreams;
25458
24956
  }
25459
24957
  });
25460
- this.api = this.events.createApiProxy();
25461
24958
  }
25462
24959
  live;
25463
24960
  events;
25464
- api;
25465
24961
  catalog;
25466
24962
  workspaceStreams = /* @__PURE__ */ new Set();
25467
24963
  controlStreams = /* @__PURE__ */ new Set();
25468
24964
  eventStreams = /* @__PURE__ */ new Map();
25469
- rcMuxStreams = /* @__PURE__ */ new Set();
25470
- rcHostStreams = /* @__PURE__ */ new Set();
25471
24965
  follows = /* @__PURE__ */ new Set();
25472
24966
  pendingRequestIds = /* @__PURE__ */ new Map();
25473
24967
  pendingApprovals = /* @__PURE__ */ new Map();
@@ -25665,13 +25159,9 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
25665
25159
  for (const stream of this.workspaceStreams) stream.close();
25666
25160
  for (const stream of this.controlStreams) stream.close();
25667
25161
  for (const stream of this.eventStreams.values()) stream.close();
25668
- for (const stream of this.rcMuxStreams) stream.close();
25669
- for (const stream of this.rcHostStreams) stream.close();
25670
25162
  this.workspaceStreams.clear();
25671
25163
  this.controlStreams.clear();
25672
25164
  this.eventStreams.clear();
25673
- this.rcMuxStreams.clear();
25674
- this.rcHostStreams.clear();
25675
25165
  const follows = [...this.follows];
25676
25166
  this.follows.clear();
25677
25167
  for (const follow of follows) {
@@ -25978,7 +25468,6 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
25978
25468
  const threadId = nativeThreadId(sessionId);
25979
25469
  const selection = this.modelSelection(sessionId, await this.models(signal));
25980
25470
  const isFreshBlankThread = this.blankThreads.has(threadId) || this.pendingThreads.has(threadId);
25981
- await this.live.ensureRcFollow(sessionId);
25982
25471
  if (!isFreshBlankThread) {
25983
25472
  const resumeResult = await this.client.request("thread/resume", {
25984
25473
  threadId,
@@ -26124,7 +25613,6 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
26124
25613
  }, signal);
26125
25614
  const directory = await this.models(signal).catch(() => void 0);
26126
25615
  if (beforeSeq === void 0) {
26127
- await this.live.ensureRcFollow(sessionId, history);
26128
25616
  signal.throwIfAborted();
26129
25617
  if (this.closed) throw new Error("The CodeX virtual Harness is closed.");
26130
25618
  this.rememberOpenedSession(sessionId);
@@ -26291,7 +25779,6 @@ function writeText(res, status2, body) {
26291
25779
  import { readFile, realpath as realpathEntrypoint } from "node:fs/promises";
26292
25780
  import { createRequire } from "node:module";
26293
25781
  import { dirname, isAbsolute, join } from "node:path";
26294
- var LEGACY_PLACEHOLDER_VERSION = "0.0.1";
26295
25782
  var HARNESS_PACKAGE_NAME = "@deepseek-ai/dsh";
26296
25783
  function normalizeHarnessVersion(value) {
26297
25784
  if (typeof value !== "string") return void 0;
@@ -26299,10 +25786,6 @@ function normalizeHarnessVersion(value) {
26299
25786
  if (version.length === 0 || version.length > 64 || /[\u0000-\u001f]/u.test(version)) return void 0;
26300
25787
  return version;
26301
25788
  }
26302
- function selectHarnessVersion(reportedVersion, distributionVersion) {
26303
- if (reportedVersion !== void 0 && reportedVersion !== LEGACY_PLACEHOLDER_VERSION) return reportedVersion;
26304
- return distributionVersion;
26305
- }
26306
25789
  function harnessSessionGeneration(version) {
26307
25790
  if (version === void 0) return "legacy";
26308
25791
  const match = /^(?:dsh-)?v?(\d+)\.(\d+)\.(\d+)(?:-|$)/u.exec(version.trim());
@@ -26344,400 +25827,68 @@ async function readHarnessDistributionVersion(entrypoint = process.argv[1]) {
26344
25827
  }
26345
25828
  }
26346
25829
 
26347
- // src/remote-api-proxy.ts
26348
- var DIRECT_API_CALL_BYTES = 2 * 1024 * 1024;
26349
- var AGENT_PRESET_SETTINGS_NS = "agent-presets";
26350
- var LEGACY_AGENT_PRESET_ALIASES = {
26351
- code: "ptc"
26352
- };
26353
- var WELCOME_NOTICE_NAMESPACE = "ui-settings-general";
26354
- var WELCOME_NOTICE_FIELD = "welcomeNoticeVersion";
26355
- var WELCOME_NOTICE_VERSION = "2026-08-13.1";
26356
- var RemoteHarnessApiProxy = class {
26357
- constructor(client, harnessVersion) {
26358
- this.client = client;
26359
- this.harnessVersion = harnessVersion;
26360
- const call = (method) => (request, signal) => this.call(method, request, signal);
26361
- this.api = {
26362
- sessions: {
26363
- list: call("session.list"),
26364
- search: call("session.search"),
26365
- create: call("session.create"),
26366
- history: call("session.history"),
26367
- models: call("session.models"),
26368
- selectModel: call("session.selectModel"),
26369
- rename: call("session.rename"),
26370
- fork: call("session.fork"),
26371
- prompt: call("session.prompt"),
26372
- attachment: call("session.attachment"),
26373
- updateQueue: call("session.updateQueue"),
26374
- cancel: call("session.cancel")
26375
- },
26376
- subagents: {
26377
- list: call("subagent.list"),
26378
- history: call("subagent.history"),
26379
- prompt: call("subagent.prompt"),
26380
- interrupt: call("subagent.interrupt")
26381
- },
26382
- host: {
26383
- describe: call("host.describe"),
26384
- pickDirectory: call("host.pickDirectory"),
26385
- listDirectory: call("host.listDirectory"),
26386
- createDirectory: call("host.createDirectory"),
26387
- openPath: call("host.openPath")
26388
- },
26389
- workspace: {
26390
- list: call("workspace.list"),
26391
- create: call("workspace.create"),
26392
- rename: call("workspace.rename"),
26393
- delete: call("workspace.delete"),
26394
- insertBefore: call("workspace.insertBefore"),
26395
- insertSessionBefore: call("workspace.insertSessionBefore"),
26396
- archiveSession: call("workspace.archiveSession")
26397
- },
26398
- skills: { list: call("skill.list") },
26399
- agentPresets: {
26400
- list: call("agentPreset.list"),
26401
- select: call("agentPreset.select"),
26402
- read: call("agentPreset.read"),
26403
- copy: call("agentPreset.copy"),
26404
- openDocument: call("agentPreset.openDocument"),
26405
- remove: call("agentPreset.remove")
26406
- },
26407
- goals: {
26408
- create: call("goal.create"),
26409
- edit: call("goal.edit"),
26410
- pause: call("goal.pause"),
26411
- resume: call("goal.resume"),
26412
- complete: call("goal.complete"),
26413
- clear: call("goal.clear")
26414
- },
26415
- settings: {
26416
- describe: call("settings.describe"),
26417
- openDocument: call("settings.openDocument"),
26418
- update: call("settings.update"),
26419
- replace: call("settings.replace"),
26420
- mutate: call("settings.mutate")
26421
- },
26422
- credentials: {
26423
- describe: call("credentials.describe"),
26424
- set: call("credentials.set"),
26425
- unset: call("credentials.unset")
26426
- },
26427
- llm: {
26428
- providers: call("llm.providers"),
26429
- models: call("llm.models"),
26430
- discoverModels: call("llm.discoverModels")
26431
- },
26432
- events: {
26433
- mux: (request, signal) => this.stream("mux", request, signal),
26434
- host: (request, signal) => this.stream("host", request, signal)
26435
- },
26436
- downloads: {},
26437
- respond: (message) => this.respond(message)
26438
- };
25830
+ // src/ids.ts
25831
+ import { randomBytes as randomBytes7 } from "node:crypto";
25832
+ function uuidV7(now = Date.now()) {
25833
+ if (!Number.isSafeInteger(now) || now < 0 || now > 281474976710655) {
25834
+ throw new RangeError("UUIDv7 timestamp must be a non-negative 48-bit integer");
26439
25835
  }
26440
- api;
26441
- legacyWelcomeAcknowledged = false;
26442
- settingsDescribeValue;
26443
- async call(method, request, signal) {
26444
- const params = {
26445
- method,
26446
- rpcId: String(request.rpcId),
26447
- payload: normalizeLegacyRequest(method, request.payload)
25836
+ const bytes = randomBytes7(16);
25837
+ let timestamp = BigInt(now);
25838
+ for (let index = 5; index >= 0; index -= 1) {
25839
+ bytes[index] = Number(timestamp & 0xffn);
25840
+ timestamp >>= 8n;
25841
+ }
25842
+ bytes[6] = 112 | bytes[6] & 15;
25843
+ bytes[8] = 128 | bytes[8] & 63;
25844
+ const hex = bytes.toString("hex");
25845
+ return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
25846
+ }
25847
+
25848
+ // src/session-format-compat.ts
25849
+ function normalizeLegacySessionGatewayValue(endpoint, value) {
25850
+ if (endpoint === "session/page") return normalizePage(value);
25851
+ if (endpoint === "session/follow") return normalizeFollowFrame(value);
25852
+ return value;
25853
+ }
25854
+ function normalizeAssistantMessageStreamValue(endpoint, value) {
25855
+ if (endpoint === "session/page" && isRecord7(value)) return { ...value, records: normalizeRecords(value.records) };
25856
+ if (endpoint === "session/follow" && isRecord7(value) && value.type === "snapshot") {
25857
+ return { ...value, records: normalizeRecords(value.records) };
25858
+ }
25859
+ if (endpoint === "session/follow") return normalizeEntry(value);
25860
+ return value;
25861
+ }
25862
+ function normalizeFollowFrame(value) {
25863
+ if (!isRecord7(value)) return value;
25864
+ if (value.type === "snapshot") {
25865
+ return {
25866
+ ...value,
25867
+ header: normalizeHeader(value.header),
25868
+ records: normalizeRecords(value.records),
25869
+ ...value.assistantStream === void 0 ? { assistantStream: { revision: 0 } } : {}
26448
25870
  };
26449
- const encoded = new TextEncoder().encode(JSON.stringify(params));
26450
- const response = method === "session.attachment" || encoded.byteLength > DIRECT_API_CALL_BYTES ? await this.callTransferred(encoded, signal) : await this.client.rpc("harness.api.call", params, signal);
26451
- if (String(response.rpcId) !== String(request.rpcId) || typeof response.result !== "object" || response.result === null) {
26452
- throw new Error("The remote Host returned an invalid Harness API response.");
26453
- }
26454
- const normalized = normalizeLegacyResponse(method, response);
26455
- return this.normalizeLegacyWelcomeSettings(method, params.payload, normalized);
26456
25871
  }
26457
- normalizeLegacyWelcomeSettings(method, payload, response) {
26458
- if (!isLegacyRemoteHost(this.harnessVersion)) return response;
26459
- if (method === "settings.describe" && response.result.ok && isRecord7(response.result.value)) {
26460
- this.settingsDescribeValue = response.result.value;
26461
- return this.legacyWelcomeAcknowledged ? patchWelcomeDescribe(response) : response;
25872
+ return normalizeEntry(value);
25873
+ }
25874
+ function normalizePage(value) {
25875
+ if (!isRecord7(value)) return value;
25876
+ return { ...value, records: normalizeRecords(value.records) };
25877
+ }
25878
+ function normalizeRecords(value) {
25879
+ if (!Array.isArray(value)) return value;
25880
+ const records = [];
25881
+ let previousSeq;
25882
+ for (const record9 of value) {
25883
+ if (!isEventEntry(record9)) continue;
25884
+ const seq = entrySeq(record9);
25885
+ if (previousSeq !== void 0 && seq !== void 0 && seq > previousSeq + 1) {
25886
+ for (let fillerSeq = previousSeq + 1; fillerSeq < seq; fillerSeq += 1) {
25887
+ records.push(createLegacyGapRecord(fillerSeq, record9));
25888
+ }
26462
25889
  }
26463
- if (method !== "settings.mutate" || !isWelcomeNoticeRequest(payload)) return response;
26464
- this.legacyWelcomeAcknowledged = true;
26465
- return patchWelcomeMutate(this.settingsDescribeValue ?? { namespaces: [] }, response.rpcId);
26466
- }
26467
- async callTransferred(encoded, signal) {
26468
- if (encoded.byteLength > MAX_HARNESS_API_TRANSFER_BYTES) {
26469
- throw new Error("The Harness API request exceeds the remote image transfer limit.");
26470
- }
26471
- const transferId = uuidV7();
26472
- const totalChunks = Math.ceil(encoded.byteLength / HARNESS_API_TRANSFER_CHUNK_BYTES);
26473
- let opened = false;
26474
- try {
26475
- await this.client.rpc("harness.api.transfer.open", {
26476
- transferId,
26477
- totalBytes: encoded.byteLength,
26478
- totalChunks
26479
- }, signal);
26480
- opened = true;
26481
- for (let index = 0; index < totalChunks; index += 1) {
26482
- const start = index * HARNESS_API_TRANSFER_CHUNK_BYTES;
26483
- const chunk = encoded.subarray(start, Math.min(start + HARNESS_API_TRANSFER_CHUNK_BYTES, encoded.byteLength));
26484
- await this.client.rpc("harness.api.transfer.chunk", {
26485
- transferId,
26486
- index,
26487
- data: bytesToBase642(chunk)
26488
- }, signal);
26489
- }
26490
- const committed = await this.client.rpc(
26491
- "harness.api.transfer.commit",
26492
- { transferId },
26493
- signal
26494
- );
26495
- if (committed.kind === "inline") return committed.response;
26496
- if (committed.transferId !== transferId || committed.totalBytes <= 0 || committed.totalBytes > MAX_HARNESS_API_TRANSFER_BYTES || committed.totalChunks !== Math.ceil(committed.totalBytes / HARNESS_API_TRANSFER_CHUNK_BYTES)) {
26497
- throw new Error("The remote Host returned an invalid Harness API transfer descriptor.");
26498
- }
26499
- const responseBytes = new Uint8Array(committed.totalBytes);
26500
- let offset = 0;
26501
- for (let index = 0; index < committed.totalChunks; index += 1) {
26502
- const result = await this.client.rpc(
26503
- "harness.api.transfer.read",
26504
- { transferId, index },
26505
- signal
26506
- );
26507
- if (result.transferId !== transferId || result.index !== index) {
26508
- throw new Error("The remote Host returned an out-of-order Harness API transfer chunk.");
26509
- }
26510
- const chunk = base64ToBytes2(result.data);
26511
- const expectedBytes = Math.min(HARNESS_API_TRANSFER_CHUNK_BYTES, committed.totalBytes - offset);
26512
- if (chunk.byteLength !== expectedBytes) {
26513
- throw new Error("The remote Host returned an invalid Harness API transfer chunk.");
26514
- }
26515
- responseBytes.set(chunk, offset);
26516
- offset += chunk.byteLength;
26517
- }
26518
- return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(responseBytes));
26519
- } finally {
26520
- if (opened) {
26521
- await this.client.rpc("harness.api.transfer.close", { transferId }).catch(() => void 0);
26522
- }
26523
- }
26524
- }
26525
- async respond(message) {
26526
- return this.client.rpc("harness.api.respond", { message });
26527
- }
26528
- async *stream(stream, request, signal) {
26529
- const streamId = uuidV7();
26530
- const queue = new AsyncFrameQueue();
26531
- const unsubscribe = this.client.onEvent((event) => routeStreamEvent(event, streamId, queue));
26532
- const unsubscribeClose = this.client.onClose(() => queue.close());
26533
- const onAbort = () => queue.close();
26534
- signal.addEventListener("abort", onAbort, { once: true });
26535
- try {
26536
- try {
26537
- await this.client.rpc("harness.api.stream.open", {
26538
- streamId,
26539
- stream,
26540
- rpcId: String(request.rpcId),
26541
- payload: request.payload
26542
- }, signal);
26543
- for await (const frame of queue) yield frame;
26544
- } catch (error) {
26545
- if (!isRemoteDisconnect(error)) throw error;
26546
- }
26547
- } finally {
26548
- signal.removeEventListener("abort", onAbort);
26549
- unsubscribe();
26550
- unsubscribeClose();
26551
- queue.close();
26552
- await this.client.rpc("harness.api.stream.close", { streamId }).catch(() => void 0);
26553
- }
26554
- }
26555
- };
26556
- function normalizeLegacyResponse(method, response) {
26557
- if (method !== "host.describe" || !response.result.ok) return response;
26558
- const value = response.result.value;
26559
- if (typeof value !== "object" || value === null || Array.isArray(value)) return response;
26560
- const description = value;
26561
- if (typeof description.home === "string" || typeof description.cwd !== "string") return response;
26562
- return {
26563
- ...response,
26564
- result: {
26565
- ...response.result,
26566
- value: { ...description, home: description.cwd }
26567
- }
26568
- };
26569
- }
26570
- function normalizeLegacyRequest(method, payload) {
26571
- if (!isRecord7(payload)) return payload;
26572
- if (method === "agentPreset.read") return replaceAgentPreset(payload, "agentPreset");
26573
- if (method === "agentPreset.select") return replaceAgentPreset(payload, "agentPreset");
26574
- if (method === "agentPreset.copy") return replaceAgentPreset(payload, "from");
26575
- if (method === "settings.update" || method === "settings.replace" || method === "settings.mutate") {
26576
- return replaceAgentPresetSettings(payload);
26577
- }
26578
- return payload;
26579
- }
26580
- function replaceAgentPreset(payload, key) {
26581
- const value = payload[key];
26582
- const replacement = typeof value === "string" ? LEGACY_AGENT_PRESET_ALIASES[value] : void 0;
26583
- return replacement === void 0 ? payload : { ...payload, [key]: replacement };
26584
- }
26585
- function replaceAgentPresetSettings(payload) {
26586
- if (payload.ns !== AGENT_PRESET_SETTINGS_NS || !isRecord7(payload.patch)) return payload;
26587
- const patch = replaceAgentPreset(payload.patch, "default");
26588
- return patch === payload.patch ? payload : { ...payload, patch };
26589
- }
26590
- function isLegacyRemoteHost(version) {
26591
- if (version === void 0) return false;
26592
- const match = /^(?:dsh-)?v?(\d+)\.(\d+)\.(\d+)(?:-|$)/u.exec(version.trim());
26593
- return match !== null && Number(match[1]) === 0 && Number(match[2]) === 1 && Number(match[3]) < 7;
26594
- }
26595
- function isWelcomeNoticeRequest(payload) {
26596
- if (!isRecord7(payload) || payload.ns !== WELCOME_NOTICE_NAMESPACE || !Array.isArray(payload.ops)) return false;
26597
- return payload.ops.some((operation) => isRecord7(operation) && operation.op === "set" && Array.isArray(operation.path) && operation.path.length === 1 && operation.path[0] === WELCOME_NOTICE_FIELD && operation.value === WELCOME_NOTICE_VERSION);
26598
- }
26599
- function patchWelcomeDescribe(response) {
26600
- if (!response.result.ok || !isRecord7(response.result.value) || !Array.isArray(response.result.value.namespaces)) return response;
26601
- return {
26602
- ...response,
26603
- result: {
26604
- ...response.result,
26605
- value: {
26606
- ...response.result.value,
26607
- namespaces: response.result.value.namespaces.map((namespace) => {
26608
- if (!isRecord7(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE) return namespace;
26609
- const value = isRecord7(namespace.value) ? namespace.value : {};
26610
- return { ...namespace, value: { ...value, [WELCOME_NOTICE_FIELD]: WELCOME_NOTICE_VERSION } };
26611
- })
26612
- }
26613
- }
26614
- };
26615
- }
26616
- function patchWelcomeMutate(value, rpcId2) {
26617
- const response = {
26618
- rpcId: rpcId2,
26619
- result: { ok: true, value: { ...value, namespaces: [] } }
26620
- };
26621
- const namespaces = Array.isArray(value.namespaces) ? value.namespaces : [];
26622
- response.result.value.namespaces = namespaces.map((namespace) => {
26623
- if (!isRecord7(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE) return namespace;
26624
- const current = isRecord7(namespace.value) ? namespace.value : {};
26625
- return { ...namespace, value: { ...current, [WELCOME_NOTICE_FIELD]: WELCOME_NOTICE_VERSION } };
26626
- });
26627
- return response;
26628
- }
26629
- function isRemoteDisconnect(error) {
26630
- return error instanceof RemoteClientError && (error.code === "TRANSPORT_CLOSED" || error.code === "CLIENT_CLOSED");
26631
- }
26632
- function isRecord7(value) {
26633
- return typeof value === "object" && value !== null && !Array.isArray(value);
26634
- }
26635
- var AsyncFrameQueue = class {
26636
- values = [];
26637
- waiters = [];
26638
- closed = false;
26639
- push(value) {
26640
- if (this.closed) return;
26641
- const waiter = this.waiters.shift();
26642
- if (waiter === void 0) this.values.push(value);
26643
- else waiter({ done: false, value });
26644
- }
26645
- close() {
26646
- if (this.closed) return;
26647
- this.closed = true;
26648
- for (const waiter of this.waiters.splice(0)) waiter({ done: true, value: void 0 });
26649
- }
26650
- async *[Symbol.asyncIterator]() {
26651
- while (true) {
26652
- const value = this.values.shift();
26653
- if (value !== void 0) {
26654
- yield value;
26655
- continue;
26656
- }
26657
- if (this.closed) return;
26658
- const next = await new Promise((resolve6) => this.waiters.push(resolve6));
26659
- if (next.done) return;
26660
- yield next.value;
26661
- }
26662
- }
26663
- };
26664
- function routeStreamEvent(event, streamId, queue) {
26665
- if (event.event === "harness.api.frame") {
26666
- const data2 = event.data;
26667
- if (data2.streamId !== streamId || typeof data2.frame !== "object" || data2.frame === null || typeof data2.frame.rpcId !== "string" || !("payload" in data2.frame)) return;
26668
- queue.push(data2.frame);
26669
- }
26670
- if (event.event === "harness.api.stream.closed") {
26671
- const data2 = event.data;
26672
- if (data2.streamId === streamId) queue.close();
26673
- }
26674
- }
26675
- function bytesToBase642(bytes) {
26676
- let binary = "";
26677
- for (let offset = 0; offset < bytes.byteLength; offset += 32768) {
26678
- binary += String.fromCharCode(...bytes.subarray(offset, Math.min(offset + 32768, bytes.byteLength)));
26679
- }
26680
- return btoa(binary);
26681
- }
26682
- function base64ToBytes2(value) {
26683
- let binary;
26684
- try {
26685
- binary = atob(value);
26686
- } catch {
26687
- throw new Error("The remote Host returned a malformed Harness API transfer chunk.");
26688
- }
26689
- const bytes = new Uint8Array(binary.length);
26690
- for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
26691
- if (bytesToBase642(bytes) !== value) {
26692
- throw new Error("The remote Host returned a non-canonical Harness API transfer chunk.");
26693
- }
26694
- return bytes;
26695
- }
26696
-
26697
- // src/session-format-compat.ts
26698
- function normalizeLegacySessionGatewayValue(endpoint, value) {
26699
- if (endpoint === "session/page") return normalizePage(value);
26700
- if (endpoint === "session/follow") return normalizeFollowFrame(value);
26701
- return value;
26702
- }
26703
- function normalizeAssistantMessageStreamValue(endpoint, value) {
26704
- if (endpoint === "session/page" && isRecord8(value)) return { ...value, records: normalizeRecords(value.records) };
26705
- if (endpoint === "session/follow" && isRecord8(value) && value.type === "snapshot") {
26706
- return { ...value, records: normalizeRecords(value.records) };
26707
- }
26708
- if (endpoint === "session/follow") return normalizeEntry(value);
26709
- return value;
26710
- }
26711
- function normalizeFollowFrame(value) {
26712
- if (!isRecord8(value)) return value;
26713
- if (value.type === "snapshot") {
26714
- return {
26715
- ...value,
26716
- header: normalizeHeader(value.header),
26717
- records: normalizeRecords(value.records),
26718
- ...value.assistantStream === void 0 ? { assistantStream: { revision: 0 } } : {}
26719
- };
26720
- }
26721
- return normalizeEntry(value);
26722
- }
26723
- function normalizePage(value) {
26724
- if (!isRecord8(value)) return value;
26725
- return { ...value, records: normalizeRecords(value.records) };
26726
- }
26727
- function normalizeRecords(value) {
26728
- if (!Array.isArray(value)) return value;
26729
- const records = [];
26730
- let previousSeq;
26731
- for (const record9 of value) {
26732
- if (!isEventEntry(record9)) continue;
26733
- const seq = entrySeq(record9);
26734
- if (previousSeq !== void 0 && seq !== void 0 && seq > previousSeq + 1) {
26735
- for (let fillerSeq = previousSeq + 1; fillerSeq < seq; fillerSeq += 1) {
26736
- records.push(createLegacyGapRecord(fillerSeq, record9));
26737
- }
26738
- }
26739
- records.push(normalizeEntry(record9));
26740
- if (seq !== void 0) previousSeq = seq;
25890
+ records.push(normalizeEntry(record9));
25891
+ if (seq !== void 0) previousSeq = seq;
26741
25892
  }
26742
25893
  return records;
26743
25894
  }
@@ -26766,10 +25917,10 @@ function eventTime(value) {
26766
25917
  return typeof value.event.time === "number" && Number.isSafeInteger(value.event.time) ? value.event.time : 0;
26767
25918
  }
26768
25919
  function isEventEntry(value) {
26769
- return isRecord8(value) && value.type === "event" && isRecord8(value.event);
25920
+ return isRecord7(value) && value.type === "event" && isRecord7(value.event);
26770
25921
  }
26771
25922
  function normalizeHeader(value) {
26772
- if (!isRecord8(value)) return value;
25923
+ if (!isRecord7(value)) return value;
26773
25924
  const next = {
26774
25925
  ...value,
26775
25926
  version: 3,
@@ -26778,7 +25929,7 @@ function normalizeHeader(value) {
26778
25929
  return next.agentPreset === "code" ? { ...next, agentPreset: "ptc" } : next;
26779
25930
  }
26780
25931
  function normalizeEvent(value) {
26781
- if (!isRecord8(value)) return value;
25932
+ if (!isRecord7(value)) return value;
26782
25933
  let next = value;
26783
25934
  const type = normalizeEventType(value.type);
26784
25935
  if (type !== value.type) next = { ...next, type };
@@ -26798,7 +25949,7 @@ function normalizeEventType(value) {
26798
25949
  return value;
26799
25950
  }
26800
25951
  function normalizeEventData(type, value) {
26801
- if (!isRecord8(value)) return value;
25952
+ if (!isRecord7(value)) return value;
26802
25953
  if (type === "assistant/message" && Object.hasOwn(value, "stream") && !Array.isArray(value.stream)) {
26803
25954
  const { stream: _stream, ...rest } = value;
26804
25955
  return rest;
@@ -26815,7 +25966,7 @@ function normalizeEventData(type, value) {
26815
25966
  return value;
26816
25967
  }
26817
25968
  function normalizeRequestHeaderData(value) {
26818
- if (!isRecord8(value.header)) return value;
25969
+ if (!isRecord7(value.header)) return value;
26819
25970
  const header = normalizeRequestHeader(value.header);
26820
25971
  return header === value.header ? value : { ...value, header };
26821
25972
  }
@@ -26831,7 +25982,7 @@ function normalizeRequestHeader(value) {
26831
25982
  changed = true;
26832
25983
  continue;
26833
25984
  }
26834
- if (key === "adapterDefaults" && isRecord8(field) && Object.keys(field).length === 0) {
25985
+ if (key === "adapterDefaults" && isRecord7(field) && Object.keys(field).length === 0) {
26835
25986
  changed = true;
26836
25987
  continue;
26837
25988
  }
@@ -26840,12 +25991,12 @@ function normalizeRequestHeader(value) {
26840
25991
  return changed ? next : value;
26841
25992
  }
26842
25993
  function normalizeMessage(value) {
26843
- if (!isRecord8(value) || !isRecord8(value.source)) return value;
25994
+ if (!isRecord7(value) || !isRecord7(value.source)) return value;
26844
25995
  if (value.source.kind !== "plugin" || value.source.plugin !== "tools-code-mode") return value;
26845
25996
  return { ...value, source: { ...value.source, plugin: "tools-ptc" } };
26846
25997
  }
26847
25998
  function normalizeSurfaceOp(value) {
26848
- if (!isRecord8(value) || value.op !== "replace") return value;
25999
+ if (!isRecord7(value) || value.op !== "replace") return value;
26849
26000
  const { start, end, ...rest } = value;
26850
26001
  if (start === void 0 && end === void 0) return value;
26851
26002
  return {
@@ -26855,7 +26006,7 @@ function normalizeSurfaceOp(value) {
26855
26006
  ...end === void 0 ? {} : { endSeq: end }
26856
26007
  };
26857
26008
  }
26858
- function isRecord8(value) {
26009
+ function isRecord7(value) {
26859
26010
  return typeof value === "object" && value !== null && !Array.isArray(value);
26860
26011
  }
26861
26012
  function isEventSeq(value) {
@@ -26864,15 +26015,16 @@ function isEventSeq(value) {
26864
26015
 
26865
26016
  // src/remote-typert-gateway.ts
26866
26017
  var DIRECT_REMOTE_CALL_BYTES2 = 2 * 1024 * 1024;
26867
- var WELCOME_NOTICE_NAMESPACE2 = "ui-settings-general";
26868
- var WELCOME_NOTICE_FIELD2 = "welcomeNoticeVersion";
26869
- var WELCOME_NOTICE_VERSION2 = "2026-08-13.1";
26018
+ var WELCOME_NOTICE_NAMESPACE = "ui-settings-general";
26019
+ var WELCOME_NOTICE_FIELD = "welcomeNoticeVersion";
26020
+ var WELCOME_NOTICE_VERSION = "2026-08-13.1";
26870
26021
  var RemoteTypertGateway2 = class {
26871
26022
  constructor(client, compatibility, harnessVersion) {
26872
26023
  this.client = client;
26873
26024
  this.compatibility = compatibility;
26874
26025
  this.harnessVersion = harnessVersion;
26875
26026
  }
26027
+ frameTransfers;
26876
26028
  async invoke(request) {
26877
26029
  const result = await this.dispatch(
26878
26030
  `${request.namespace}/${request.method}`,
@@ -26909,43 +26061,83 @@ var RemoteTypertGateway2 = class {
26909
26061
  settingsDescribeValue;
26910
26062
  /** DSH <=0.1.6 cannot persist the 0.1.7 welcome acknowledgement remotely. */
26911
26063
  normalizeLegacyWelcomeSettings(endpoint, payload, result) {
26912
- if (!isLegacyRemoteHost2(this.harnessVersion)) return void 0;
26913
- if (endpoint === "settings/describe" && result.ok && isRecord9(result.value)) {
26064
+ if (!isLegacyRemoteHost(this.harnessVersion)) return void 0;
26065
+ if (endpoint === "settings/describe" && result.ok && isRecord8(result.value)) {
26914
26066
  this.settingsDescribeValue = result.value;
26915
- return this.legacyWelcomeAcknowledged ? { ...result, value: patchWelcomeDescribe2(result.value) } : void 0;
26067
+ return this.legacyWelcomeAcknowledged ? { ...result, value: patchWelcomeDescribe(result.value) } : void 0;
26916
26068
  }
26917
- if (endpoint !== "settings/mutate" || !isRecord9(payload) || !isRecord9(payload.args)) return void 0;
26069
+ if (endpoint !== "settings/mutate" || !isRecord8(payload) || !isRecord8(payload.args)) return void 0;
26918
26070
  const args = payload.args;
26919
- if (args.ns !== WELCOME_NOTICE_NAMESPACE2 || !isWelcomeNoticeOperation(args.ops)) return void 0;
26920
- const value = patchWelcomeDescribe2(this.settingsDescribeValue ?? { namespaces: [] });
26071
+ if (args.ns !== WELCOME_NOTICE_NAMESPACE || !isWelcomeNoticeOperation(args.ops)) return void 0;
26072
+ const value = patchWelcomeDescribe(this.settingsDescribeValue ?? { namespaces: [] });
26921
26073
  this.legacyWelcomeAcknowledged = true;
26922
26074
  return { ok: true, value };
26923
26075
  }
26924
26076
  async open(endpoint, payload, signal) {
26077
+ if (this.frameTransfers === void 0) {
26078
+ const description = await this.client.rpc("harness.transport.describe", {}, signal);
26079
+ this.frameTransfers = isRecord8(description) && Array.isArray(description.capabilities) && description.capabilities.includes("harness.remote.stream.transfer.v1");
26080
+ }
26081
+ signal.throwIfAborted();
26925
26082
  const streamId = uuidV7();
26926
26083
  const queue = new AsyncValueQueue4();
26927
- const unsubscribe = this.client.onEvent((event) => routeStreamEvent2(event, streamId, queue));
26084
+ const lifetime = new AbortController();
26085
+ const transferSignal = AbortSignal.any([signal, lifetime.signal]);
26086
+ const unsubscribe = this.client.onEvent((event) => routeStreamEvent(event, streamId, queue));
26928
26087
  const unsubscribeClose = this.client.onClose(() => {
26088
+ lifetime.abort();
26929
26089
  queue.fail(new RemoteClientError("TRANSPORT_CLOSED", "The remote Harness stream transport closed."));
26930
26090
  });
26931
- const onAbort = () => queue.close();
26091
+ const onAbort = () => {
26092
+ lifetime.abort();
26093
+ queue.close();
26094
+ unsubscribe();
26095
+ unsubscribeClose();
26096
+ void this.client.rpc("harness.remote.stream.close", { streamId }, void 0, { timeoutMs: 5e3 }).catch(() => void 0);
26097
+ };
26932
26098
  signal.addEventListener("abort", onAbort, { once: true });
26933
26099
  try {
26934
- await this.client.rpc("harness.remote.stream.open", { streamId, endpoint, payload }, signal);
26100
+ await this.client.rpc("harness.remote.stream.open", {
26101
+ streamId,
26102
+ endpoint,
26103
+ payload,
26104
+ ...this.frameTransfers ? { transferFrames: true } : {}
26105
+ }, signal);
26935
26106
  } catch (error) {
26936
26107
  signal.removeEventListener("abort", onAbort);
26937
26108
  unsubscribe();
26938
26109
  unsubscribeClose();
26110
+ lifetime.abort();
26111
+ void this.client.rpc("harness.remote.stream.close", { streamId }).catch(() => void 0);
26939
26112
  throw error;
26940
26113
  }
26941
- return this.iterate(streamId, endpoint, queue, unsubscribe, unsubscribeClose, signal, onAbort);
26114
+ return this.iterate(streamId, endpoint, queue, unsubscribe, unsubscribeClose, signal, onAbort, lifetime, transferSignal);
26942
26115
  }
26943
- async *iterate(streamId, endpoint, queue, unsubscribe, unsubscribeClose, signal, onAbort) {
26116
+ async *iterate(streamId, endpoint, queue, unsubscribe, unsubscribeClose, signal, onAbort, lifetime, transferSignal) {
26944
26117
  try {
26945
- for await (const value of queue) {
26118
+ for await (const item of queue) {
26119
+ let frame = item;
26120
+ if (frame.transfer !== void 0) {
26121
+ if (!this.frameTransfers || Object.hasOwn(frame, "value")) throw new Error("Unnegotiated or ambiguous Harness Remote stream transfer");
26122
+ const descriptor = frame.transfer;
26123
+ try {
26124
+ const decoded = await this.readTransferred(descriptor, transferSignal);
26125
+ if (!isRecord8(decoded) || decoded.streamId !== streamId || decoded.hasValue !== true || Object.hasOwn(decoded, "transfer")) {
26126
+ throw new Error("Invalid Harness Remote transferred stream frame");
26127
+ }
26128
+ frame = decoded;
26129
+ } finally {
26130
+ if (typeof descriptor.transferId === "string") {
26131
+ await this.client.rpc("harness.remote.transfer.close", { transferId: descriptor.transferId }, void 0, { timeoutMs: 5e3 }).catch(() => void 0);
26132
+ }
26133
+ }
26134
+ }
26135
+ transferSignal.throwIfAborted();
26136
+ const value = frame.value;
26946
26137
  yield this.compatibility === "legacy-to-v3" ? normalizeLegacySessionGatewayValue(endpoint, value) : normalizeAssistantMessageStreamValue(endpoint, value);
26947
26138
  }
26948
26139
  } finally {
26140
+ lifetime.abort();
26949
26141
  signal.removeEventListener("abort", onAbort);
26950
26142
  unsubscribe();
26951
26143
  unsubscribeClose();
@@ -26973,7 +26165,7 @@ var RemoteTypertGateway2 = class {
26973
26165
  await this.client.rpc("harness.remote.transfer.chunk", {
26974
26166
  transferId,
26975
26167
  index,
26976
- data: bytesToBase643(chunk)
26168
+ data: bytesToBase642(chunk)
26977
26169
  }, signal);
26978
26170
  }
26979
26171
  const committed = await this.client.rpc(
@@ -26982,33 +26174,41 @@ var RemoteTypertGateway2 = class {
26982
26174
  signal
26983
26175
  );
26984
26176
  if (committed.kind === "inline") return committed.response;
26985
- if (committed.transferId !== transferId || committed.totalBytes <= 0 || committed.totalBytes > MAX_HARNESS_API_TRANSFER_BYTES || committed.totalChunks !== Math.ceil(committed.totalBytes / HARNESS_API_TRANSFER_CHUNK_BYTES)) {
26177
+ if (committed.transferId !== transferId) {
26986
26178
  throw new Error("The remote Host returned an invalid Harness Remote transfer descriptor.");
26987
26179
  }
26988
- const responseBytes = new Uint8Array(committed.totalBytes);
26989
- let offset = 0;
26990
- for (let index = 0; index < committed.totalChunks; index += 1) {
26991
- const result = await this.client.rpc(
26992
- "harness.remote.transfer.read",
26993
- { transferId, index },
26994
- signal
26995
- );
26996
- if (result.transferId !== transferId || result.index !== index) {
26997
- throw new Error("The remote Host returned an out-of-order Harness Remote transfer chunk.");
26998
- }
26999
- const chunk = base64ToBytes3(result.data);
27000
- const expectedBytes = Math.min(HARNESS_API_TRANSFER_CHUNK_BYTES, committed.totalBytes - offset);
27001
- if (chunk.byteLength !== expectedBytes) {
27002
- throw new Error("The remote Host returned an invalid Harness Remote transfer chunk.");
27003
- }
27004
- responseBytes.set(chunk, offset);
27005
- offset += chunk.byteLength;
27006
- }
27007
- return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(responseBytes));
26180
+ return await this.readTransferred(committed, signal);
27008
26181
  } finally {
27009
26182
  if (opened) await this.client.rpc("harness.remote.transfer.close", { transferId }).catch(() => void 0);
27010
26183
  }
27011
26184
  }
26185
+ async readTransferred(committed, signal) {
26186
+ if (committed.kind !== "chunked" || typeof committed.transferId !== "string" || !/^[0-9a-f]{8}(?:-[0-9a-f]{4}){3}-[0-9a-f]{12}$/i.test(committed.transferId) || !Number.isSafeInteger(committed.totalBytes) || committed.totalBytes <= 0 || committed.totalBytes > MAX_HARNESS_API_TRANSFER_BYTES || committed.totalChunks !== Math.ceil(committed.totalBytes / HARNESS_API_TRANSFER_CHUNK_BYTES)) {
26187
+ throw new Error("The remote Host returned an invalid Harness Remote transfer descriptor.");
26188
+ }
26189
+ signal.throwIfAborted();
26190
+ const { transferId } = committed;
26191
+ const responseBytes = new Uint8Array(committed.totalBytes);
26192
+ let offset = 0;
26193
+ for (let index = 0; index < committed.totalChunks; index += 1) {
26194
+ const result = await this.client.rpc(
26195
+ "harness.remote.transfer.read",
26196
+ { transferId, index },
26197
+ signal
26198
+ );
26199
+ if (result.transferId !== transferId || result.index !== index) {
26200
+ throw new Error("The remote Host returned an out-of-order Harness Remote transfer chunk.");
26201
+ }
26202
+ const chunk = base64ToBytes2(result.data);
26203
+ const expectedBytes = Math.min(HARNESS_API_TRANSFER_CHUNK_BYTES, committed.totalBytes - offset);
26204
+ if (chunk.byteLength !== expectedBytes) {
26205
+ throw new Error("The remote Host returned an invalid Harness Remote transfer chunk.");
26206
+ }
26207
+ responseBytes.set(chunk, offset);
26208
+ offset += chunk.byteLength;
26209
+ }
26210
+ return JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(responseBytes));
26211
+ }
27012
26212
  };
27013
26213
  var AsyncValueQueue4 = class {
27014
26214
  values = [];
@@ -27064,10 +26264,10 @@ var AsyncValueQueue4 = class {
27064
26264
  }
27065
26265
  }
27066
26266
  };
27067
- function routeStreamEvent2(event, streamId, queue) {
26267
+ function routeStreamEvent(event, streamId, queue) {
27068
26268
  if (event.event === "harness.remote.frame") {
27069
26269
  const data3 = event.data;
27070
- if (data3.streamId === streamId && data3.hasValue === true) queue.push(data3.value);
26270
+ if (data3.streamId === streamId && data3.hasValue === true) queue.push(data3);
27071
26271
  return;
27072
26272
  }
27073
26273
  if (event.event !== "harness.remote.stream.closed") return;
@@ -27078,16 +26278,16 @@ function routeStreamEvent2(event, streamId, queue) {
27078
26278
  queue.fail(remoteFailure({
27079
26279
  code: typeof failure4?.code === "string" ? failure4.code : "internal",
27080
26280
  message: typeof failure4?.message === "string" ? failure4.message : "The remote Harness stream failed.",
27081
- details: isRecord9(failure4?.details) ? failure4.details : {}
26281
+ details: isRecord8(failure4?.details) ? failure4.details : {}
27082
26282
  }));
27083
26283
  } else {
27084
26284
  queue.close();
27085
26285
  }
27086
26286
  }
27087
26287
  function parseRpcResult(value) {
27088
- if (!isRecord9(value)) throw new Error("The remote Host returned an invalid Gateway result.");
26288
+ if (!isRecord8(value)) throw new Error("The remote Host returned an invalid Gateway result.");
27089
26289
  if (value.ok === true) return Object.hasOwn(value, "value") ? { ok: true, value: value.value } : { ok: true };
27090
- if (value.ok !== false || !isRecord9(value.error) || typeof value.error.code !== "string" || typeof value.error.message !== "string" || !isRecord9(value.error.details)) {
26290
+ if (value.ok !== false || !isRecord8(value.error) || typeof value.error.code !== "string" || typeof value.error.message !== "string" || !isRecord8(value.error.details)) {
27091
26291
  throw new Error("The remote Host returned an invalid Gateway failure.");
27092
26292
  }
27093
26293
  return {
@@ -27102,14 +26302,14 @@ function remoteFailure(failure4) {
27102
26302
  details: failure4.details
27103
26303
  });
27104
26304
  }
27105
- function bytesToBase643(bytes) {
26305
+ function bytesToBase642(bytes) {
27106
26306
  let binary = "";
27107
26307
  for (let offset = 0; offset < bytes.byteLength; offset += 32768) {
27108
26308
  binary += String.fromCharCode(...bytes.subarray(offset, Math.min(offset + 32768, bytes.byteLength)));
27109
26309
  }
27110
26310
  return btoa(binary);
27111
26311
  }
27112
- function base64ToBytes3(value) {
26312
+ function base64ToBytes2(value) {
27113
26313
  let binary;
27114
26314
  try {
27115
26315
  binary = atob(value);
@@ -27118,44 +26318,44 @@ function base64ToBytes3(value) {
27118
26318
  }
27119
26319
  const bytes = new Uint8Array(binary.length);
27120
26320
  for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
27121
- if (bytesToBase643(bytes) !== value) throw new Error("The remote Host returned non-canonical Harness Remote transfer data.");
26321
+ if (bytesToBase642(bytes) !== value) throw new Error("The remote Host returned non-canonical Harness Remote transfer data.");
27122
26322
  return bytes;
27123
26323
  }
27124
26324
  function normalizeWorkspaceBinaryResult(endpoint, value) {
27125
26325
  if (endpoint !== "workspaceFiles/readBytes" && endpoint !== "officeToPdf/render") return value;
27126
- if (!isRecord9(value) || typeof value.data !== "string") return value;
27127
- return { ...value, data: base64ToBytes3(value.data) };
26326
+ if (!isRecord8(value) || typeof value.data !== "string") return value;
26327
+ return { ...value, data: base64ToBytes2(value.data) };
27128
26328
  }
27129
- function isRecord9(value) {
26329
+ function isRecord8(value) {
27130
26330
  return typeof value === "object" && value !== null && !Array.isArray(value);
27131
26331
  }
27132
26332
  function hasErrorCode(error, code) {
27133
26333
  return error instanceof Error && "code" in error && error.code === code;
27134
26334
  }
27135
- function isLegacyRemoteHost2(version) {
26335
+ function isLegacyRemoteHost(version) {
27136
26336
  if (version === void 0) return false;
27137
26337
  const match = /^(?:dsh-)?v?(\d+)\.(\d+)\.(\d+)(?:-|$)/u.exec(version.trim());
27138
26338
  if (match === null) return false;
27139
26339
  return Number(match[1]) === 0 && Number(match[2]) === 1 && Number(match[3]) < 7;
27140
26340
  }
27141
26341
  function isWelcomeNoticeOperation(value) {
27142
- return Array.isArray(value) && value.some((operation) => isRecord9(operation) && operation.op === "set" && Array.isArray(operation.path) && operation.path.length === 1 && operation.path[0] === WELCOME_NOTICE_FIELD2 && operation.value === WELCOME_NOTICE_VERSION2);
26342
+ return Array.isArray(value) && value.some((operation) => isRecord8(operation) && operation.op === "set" && Array.isArray(operation.path) && operation.path.length === 1 && operation.path[0] === WELCOME_NOTICE_FIELD && operation.value === WELCOME_NOTICE_VERSION);
27143
26343
  }
27144
- function patchWelcomeDescribe2(value) {
26344
+ function patchWelcomeDescribe(value) {
27145
26345
  if (!Array.isArray(value.namespaces)) return value;
27146
26346
  const namespaces = value.namespaces.map((namespace) => {
27147
- if (!isRecord9(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE2) return namespace;
27148
- const current = isRecord9(namespace.value) ? namespace.value : {};
27149
- return { ...namespace, value: { ...current, [WELCOME_NOTICE_FIELD2]: WELCOME_NOTICE_VERSION2 } };
26347
+ if (!isRecord8(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE) return namespace;
26348
+ const current = isRecord8(namespace.value) ? namespace.value : {};
26349
+ return { ...namespace, value: { ...current, [WELCOME_NOTICE_FIELD]: WELCOME_NOTICE_VERSION } };
27150
26350
  });
27151
26351
  return { ...value, namespaces };
27152
26352
  }
27153
26353
  function normalizeProjectionResult(endpoint, value) {
27154
- if (endpoint !== "session/projections" || !isRecord9(value) || value.kind !== void 0) return value;
27155
- return Number.isSafeInteger(value.asOfSeq) && isRecord9(value.values) ? { ...value, kind: "sequenced" } : value;
26354
+ if (endpoint !== "session/projections" || !isRecord8(value) || value.kind !== void 0) return value;
26355
+ return Number.isSafeInteger(value.asOfSeq) && isRecord8(value.values) ? { ...value, kind: "sequenced" } : value;
27156
26356
  }
27157
26357
  function normalizeThemeSettingsResult(endpoint, result) {
27158
- if (!result.ok || !isRecord9(result.value)) return result;
26358
+ if (!result.ok || !isRecord8(result.value)) return result;
27159
26359
  const value = result.value;
27160
26360
  if (endpoint === "settings/describe" && Array.isArray(value.namespaces)) {
27161
26361
  const original = value.namespaces;
@@ -27169,7 +26369,7 @@ function normalizeThemeSettingsResult(endpoint, result) {
27169
26369
  return result;
27170
26370
  }
27171
26371
  function normalizeThemeNamespace(namespace) {
27172
- if (!isRecord9(namespace) || namespace.ns !== "ui-theme" || !isRecord9(namespace.value)) return namespace;
26372
+ if (!isRecord8(namespace) || namespace.ns !== "ui-theme" || !isRecord8(namespace.value)) return namespace;
27173
26373
  const section = namespace.value;
27174
26374
  const defaults = {
27175
26375
  codeFontSize: 11,
@@ -27431,7 +26631,7 @@ function normalizeServerUrl(value) {
27431
26631
  }
27432
26632
 
27433
26633
  // src/version.ts
27434
- var PLUGIN_VERSION = "0.5.18";
26634
+ var PLUGIN_VERSION = "0.5.19";
27435
26635
 
27436
26636
  // src/server-api.ts
27437
26637
  var TERMINAL_CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/u;
@@ -28024,13 +27224,13 @@ var TerminalCarrierCompat = class {
28024
27224
  try {
28025
27225
  for await (const value of source) {
28026
27226
  if (lifetime.aborted) break;
28027
- if (isRecord10(value) && value.type === "ack") {
27227
+ if (isRecord9(value) && value.type === "ack") {
28028
27228
  const pending = entry.pending.get(Number(value.sequence));
28029
27229
  if (!pending) throw new RpcError("INVALID_MESSAGE", "Unexpected terminal input acknowledgement.");
28030
27230
  entry.pending.delete(Number(value.sequence));
28031
27231
  if (value.refusal) pending.reject(new RpcError("PERMISSION_DENIED", "Terminal input was refused."));
28032
27232
  else pending.resolve();
28033
- } else if (isRecord10(value) && (value.type === "snapshot" || value.type === "state") && isRecord10(value.info)) {
27233
+ } else if (isRecord9(value) && (value.type === "snapshot" || value.type === "state") && isRecord9(value.info)) {
28034
27234
  entry.writable = value.writable === true;
28035
27235
  yield { ...value, info: { ...value.info, ...entry.writable ? { controllerId: args.attachmentId } : {} } };
28036
27236
  } else yield value;
@@ -28104,7 +27304,7 @@ async function openRemoteTerminal(target2, payload, signal, uplink) {
28104
27304
  try {
28105
27305
  for await (const value of source) {
28106
27306
  if (lifetime.aborted) break;
28107
- if (isRecord10(value) && (value.type === "snapshot" || value.type === "state") && isRecord10(value.info)) {
27307
+ if (isRecord9(value) && (value.type === "snapshot" || value.type === "state") && isRecord9(value.info)) {
28108
27308
  writable = value.info.controllerId === attachmentId;
28109
27309
  output.push({ ...value, writable });
28110
27310
  if (value.type === "snapshot") startInput();
@@ -28152,7 +27352,7 @@ async function openRemoteTerminal(target2, payload, signal, uplink) {
28152
27352
  }
28153
27353
  })();
28154
27354
  }
28155
- function isRecord10(value) {
27355
+ function isRecord9(value) {
28156
27356
  return typeof value === "object" && value !== null && !Array.isArray(value);
28157
27357
  }
28158
27358
 
@@ -28305,14 +27505,14 @@ var TypertGatewaySwitch = class {
28305
27505
  if (normalized !== void 0) return normalized;
28306
27506
  const source = error instanceof Error ? error : new Error("The Harness Gateway rejected the request.");
28307
27507
  const code = "code" in source && typeof source.code === "string" ? source.code : "internal";
28308
- const details2 = "details" in source && isRecord11(source.details) ? source.details : {};
27508
+ const details2 = "details" in source && isRecord10(source.details) ? source.details : {};
28309
27509
  return { code, message: source.message, details: details2 };
28310
27510
  }
28311
27511
  };
28312
27512
  function workspaceConnectionResult(endpoint, result) {
28313
27513
  if (endpoint === "terminal/environment" && result.ok) return { ...result, value: normalizeTerminalEnvironment(endpoint, result.value) };
28314
27514
  if (endpoint !== "workspaceFiles/readBytes" && endpoint !== "officeToPdf/render") return result;
28315
- if (!result.ok || !isRecord11(result.value) || !(result.value.data instanceof Uint8Array)) return result;
27515
+ if (!result.ok || !isRecord10(result.value) || !(result.value.data instanceof Uint8Array)) return result;
28316
27516
  return {
28317
27517
  ...result,
28318
27518
  value: { ...result.value, data: null },
@@ -28358,7 +27558,7 @@ function requestFromCarrier(endpoint, payload, signal) {
28358
27558
  if (segments.length !== 2 || segments.some((segment) => segment.length === 0)) {
28359
27559
  throw new Error("The Harness Gateway endpoint is invalid.");
28360
27560
  }
28361
- if (!isRecord11(payload) || !isRecord11(payload.args)) {
27561
+ if (!isRecord10(payload) || !isRecord10(payload.args)) {
28362
27562
  throw new Error("The Harness Gateway payload is invalid.");
28363
27563
  }
28364
27564
  return { namespace: segments[0], method: segments[1], args: payload.args, signal };
@@ -28373,11 +27573,11 @@ function isLocalOnlyEndpoint(endpoint) {
28373
27573
  function isRemoteCommandMethod(method) {
28374
27574
  return REMOTE_COMMAND_METHODS.includes(method);
28375
27575
  }
28376
- function isRecord11(value) {
27576
+ function isRecord10(value) {
28377
27577
  return typeof value === "object" && value !== null && !Array.isArray(value);
28378
27578
  }
28379
27579
  function normalizeTerminalEnvironment(endpoint, value) {
28380
- if (endpoint !== "terminal/environment" || !isRecord11(value) || value.maxBufferedBytes !== void 0) return value;
27580
+ if (endpoint !== "terminal/environment" || !isRecord10(value) || value.maxBufferedBytes !== void 0) return value;
28381
27581
  return { ...value, maxBufferedBytes: 256 * 1024 };
28382
27582
  }
28383
27583
 
@@ -28461,7 +27661,7 @@ function nvmNodeCandidates() {
28461
27661
  function isUsableExternalNode(candidate, requireFrom) {
28462
27662
  if (!isExecutableFile(candidate)) return false;
28463
27663
  const env = { ...process.env, DSH_REMOTE_RTC_HELPER_REQUIRE_FROM: requireFrom };
28464
- delete env.ELECTRON_RUN_AS_NODE;
27664
+ env.ELECTRON_RUN_AS_NODE = "1";
28465
27665
  const probe = spawnSync(candidate, [
28466
27666
  "--input-type=module",
28467
27667
  "--eval",
@@ -29446,7 +28646,7 @@ function isPrivate(ip) {
29446
28646
 
29447
28647
  // src/client-runtime.ts
29448
28648
  var ClientModeRuntime = class {
29449
- constructor(config, identities, server, apiProxy, typertGateway, logger, host, rtcFactoryProvider = loadNodeRtcFactory) {
28649
+ constructor(config, identities, server, typertGateway, logger, host, rtcFactoryProvider = loadNodeRtcFactory) {
29450
28650
  this.config = config;
29451
28651
  this.identities = identities;
29452
28652
  this.server = server;
@@ -29495,9 +28695,6 @@ var ClientModeRuntime = class {
29495
28695
  },
29496
28696
  closeCodexVirtual: (...args) => owner.closeCodexVirtual(...args),
29497
28697
  closeCursorVirtual: (...args) => owner.closeCursorVirtual(...args),
29498
- get proxySwitch() {
29499
- return owner.proxySwitch;
29500
- },
29501
28698
  get gatewaySwitch() {
29502
28699
  return owner.gatewaySwitch;
29503
28700
  },
@@ -29554,7 +28751,6 @@ var ClientModeRuntime = class {
29554
28751
  return owner.host;
29555
28752
  }
29556
28753
  });
29557
- this.proxySwitch = apiProxy === void 0 ? void 0 : new ApiProxySwitch(apiProxy);
29558
28754
  this.gatewaySwitch = new TypertGatewaySwitch(typertGateway);
29559
28755
  }
29560
28756
  async connect(targetDeviceId, signal) {
@@ -29584,7 +28780,6 @@ var ClientModeRuntime = class {
29584
28780
  codexOpenGeneration = 0;
29585
28781
  cursorVirtual;
29586
28782
  acpVirtualBackend = "cursor";
29587
- proxySwitch;
29588
28783
  gatewaySwitch;
29589
28784
  codexStreams = /* @__PURE__ */ new Map();
29590
28785
  connectionProgress;
@@ -29595,7 +28790,6 @@ var ClientModeRuntime = class {
29595
28790
  if (this.closed) throw new Error("client remote-mode runtime is closed");
29596
28791
  this.identity = await this.identities.loadOrCreate(this.config.deviceName);
29597
28792
  this.server.bindIdentity(this.identity);
29598
- this.proxySwitch?.install();
29599
28793
  this.gatewaySwitch.install();
29600
28794
  this.logger.info("client remote-mode identity ready", {
29601
28795
  deviceId: shortId(this.identity.deviceId),
@@ -29627,7 +28821,7 @@ var ClientModeRuntime = class {
29627
28821
  return registerControlRoute(connection, (endpoint, payload, signal) => this.control.handleControl(endpoint, payload, signal), webServer);
29628
28822
  }
29629
28823
  status() {
29630
- const targetStatus = this.gatewaySwitch.supportsCarrier() ? this.gatewaySwitch.status() : this.proxySwitch?.status() ?? this.gatewaySwitch.status();
28824
+ const targetStatus = this.gatewaySwitch.status();
29631
28825
  return {
29632
28826
  available: this.config.serverUrl !== void 0,
29633
28827
  identityReady: this.identity !== void 0,
@@ -29791,61 +28985,34 @@ var ClientModeRuntime = class {
29791
28985
  }
29792
28986
  async listRemoteDirectory(targetDeviceId, path, signal) {
29793
28987
  const remote = await this.ensureConnected(targetDeviceId, signal);
29794
- if (remote.features.remoteGateway) {
29795
- const value = await new RemoteTypertGateway2(remote.client).invoke({
29796
- namespace: "directoryPicker",
29797
- method: "list",
29798
- args: path === void 0 ? {} : { path },
29799
- ...signal === void 0 ? {} : { signal }
29800
- });
29801
- return value;
29802
- }
29803
- const api = new RemoteHarnessApiProxy(remote.client).api;
29804
- const response = await api.host.listDirectory({
29805
- rpcId: `remote-directory-${Date.now()}`,
29806
- payload: path === void 0 ? {} : { path }
29807
- }, signal ?? new AbortController().signal);
29808
- return unwrapNativeResult(response);
28988
+ const value = await new RemoteTypertGateway2(remote.client).invoke({
28989
+ namespace: "directoryPicker",
28990
+ method: "list",
28991
+ args: path === void 0 ? {} : { path },
28992
+ ...signal === void 0 ? {} : { signal }
28993
+ });
28994
+ return value;
29809
28995
  }
29810
28996
  async listRemoteWorkspaces(targetDeviceId, signal) {
29811
28997
  const remote = await this.ensureConnected(targetDeviceId, signal);
29812
- if (remote.features.remoteGateway) {
29813
- return readRemoteWorkspaceBaseline(new RemoteTypertGateway2(remote.client), signal);
29814
- }
29815
- const api = new RemoteHarnessApiProxy(remote.client).api;
29816
- const response = await api.workspace.list({
29817
- rpcId: `remote-workspaces-${Date.now()}`,
29818
- payload: {}
29819
- });
29820
- const value = unwrapNativeResult(response);
29821
- return value.items;
28998
+ return readRemoteWorkspaceBaseline(new RemoteTypertGateway2(remote.client), signal);
29822
28999
  }
29823
29000
  async openRemoteWorkspace(targetDeviceId, path, signal) {
29824
29001
  if (path.trim() === "") throw new ClientModeError("INVALID_MESSAGE", "A remote working directory is required.");
29825
29002
  const remote = await this.ensureConnected(targetDeviceId, signal);
29826
- const transport = this.selectHarnessRemoteTransport(remote);
29827
- let workspace;
29828
- if (transport === "remoteGateway") {
29829
- workspace = await new RemoteTypertGateway2(remote.client).invoke({
29830
- namespace: "workspace",
29831
- method: "create",
29832
- args: { request: { path } },
29833
- ...signal === void 0 ? {} : { signal }
29834
- });
29835
- } else {
29836
- const api = new RemoteHarnessApiProxy(remote.client).api;
29837
- const response = await api.workspace.create({
29838
- rpcId: `remote-workspace-${Date.now()}`,
29839
- payload: { path }
29840
- });
29841
- workspace = unwrapNativeResult(response);
29842
- }
29003
+ this.assertRemoteCompatible(remote);
29004
+ const workspace = await new RemoteTypertGateway2(remote.client).invoke({
29005
+ namespace: "workspace",
29006
+ method: "create",
29007
+ args: { request: { path } },
29008
+ ...signal === void 0 ? {} : { signal }
29009
+ });
29843
29010
  this.assertRemoteCurrent(remote, signal);
29844
29011
  await this.closeCodexVirtual();
29845
29012
  this.assertRemoteCurrent(remote, signal);
29846
29013
  await this.closeCursorVirtual();
29847
29014
  this.assertRemoteCurrent(remote, signal);
29848
- this.selectRemoteTarget(remote, transport);
29015
+ this.selectRemoteTarget(remote);
29849
29016
  const workspaceId = workspaceRecordId(workspace.workspace);
29850
29017
  this.pendingWorkspaceSelection = { targetDeviceId: remote.target.deviceId, workspaceId };
29851
29018
  this.logger.info("Remote workspace opened", { targetDeviceId: shortId(remote.target.deviceId) });
@@ -30036,7 +29203,6 @@ var ClientModeRuntime = class {
30036
29203
  try {
30037
29204
  await this.leaveRemote();
30038
29205
  } finally {
30039
- this.proxySwitch?.restore();
30040
29206
  this.gatewaySwitch.restore();
30041
29207
  }
30042
29208
  }
@@ -30047,7 +29213,6 @@ var ClientModeRuntime = class {
30047
29213
  this.connected = void 0;
30048
29214
  this.connectionProgress = void 0;
30049
29215
  this.pendingWorkspaceSelection = void 0;
30050
- this.proxySwitch?.selectLocal();
30051
29216
  this.gatewaySwitch.selectLocal();
30052
29217
  const results = await Promise.allSettled([
30053
29218
  this.closeCodexVirtual(),
@@ -30082,17 +29247,10 @@ var ClientModeRuntime = class {
30082
29247
  activeRemote() {
30083
29248
  return this.connected;
30084
29249
  }
30085
- selectRemoteTarget(remote, transport = this.selectHarnessRemoteTransport(remote)) {
29250
+ selectRemoteTarget(remote) {
29251
+ this.assertRemoteCompatible(remote);
30086
29252
  const target2 = { deviceId: remote.target.deviceId, name: remote.target.name };
30087
- if (transport === "remoteGateway") {
30088
- this.gatewaySwitch.selectRemote(this.remoteTypertGateway(remote), void 0, target2);
30089
- return;
30090
- }
30091
- this.proxySwitch?.selectRemote(new RemoteHarnessApiProxy(remote.client, remote.harnessVersion).api, target2);
30092
- this.gatewaySwitch.selectRemote((request) => invokeRemoteCommand(remote.client, request), {
30093
- execute: true,
30094
- list: remote.features.commandList
30095
- }, target2);
29253
+ this.gatewaySwitch.selectRemote(this.remoteTypertGateway(remote), void 0, target2);
30096
29254
  }
30097
29255
  remoteTypertGateway(remote) {
30098
29256
  const localSessionGeneration = harnessSessionGeneration(this.host?.localHarnessVersion?.());
@@ -30104,12 +29262,7 @@ var ClientModeRuntime = class {
30104
29262
  }
30105
29263
  selectCodexTarget(virtual, remote) {
30106
29264
  const target2 = { deviceId: remote.target.deviceId, name: remote.target.name };
30107
- if (this.gatewaySwitch.supportsCarrier()) {
30108
- this.gatewaySwitch.selectRemote(virtual, void 0, target2);
30109
- return;
30110
- }
30111
- this.proxySwitch.selectRemote(virtual.api, target2);
30112
- this.gatewaySwitch.selectRemote((request) => virtual.invoke(request), { execute: true, list: true }, target2);
29265
+ this.gatewaySwitch.selectRemote(virtual, void 0, target2);
30113
29266
  }
30114
29267
  async closeCodexVirtual(invalidatePending = true) {
30115
29268
  if (invalidatePending) this.codexOpenGeneration += 1;
@@ -30136,34 +29289,25 @@ var ClientModeRuntime = class {
30136
29289
  }
30137
29290
  selectCursorTarget(virtual, remote) {
30138
29291
  const target2 = { deviceId: remote.target.deviceId, name: remote.target.name };
30139
- if (this.gatewaySwitch.supportsCarrier()) {
30140
- this.gatewaySwitch.selectRemote(virtual, void 0, target2);
30141
- return;
30142
- }
30143
- this.proxySwitch.selectRemote(virtual.api, target2);
30144
- this.gatewaySwitch.selectRemote((request) => virtual.invoke(request), { execute: true, list: true }, target2);
29292
+ this.gatewaySwitch.selectRemote(virtual, void 0, target2);
30145
29293
  }
30146
29294
  assertRemoteCompatible(remote) {
30147
- this.selectHarnessRemoteTransport(remote);
30148
- }
30149
- selectHarnessRemoteTransport(remote) {
30150
29295
  const localRemoteGateway = this.gatewaySwitch.supportsCarrier();
30151
29296
  const localSessionGeneration = harnessSessionGeneration(this.host?.localHarnessVersion?.());
30152
29297
  if (localRemoteGateway && remote.features.remoteGateway) {
30153
- if (localSessionGeneration === "v3" || remote.features.sessionFormat !== 3) return "remoteGateway";
29298
+ if (localSessionGeneration === "v3" || remote.features.sessionFormat !== 3) return;
30154
29299
  throw new ClientModeError(
30155
29300
  "HARNESS_VERSION_INCOMPATIBLE",
30156
29301
  "The selected Host uses Harness Session V3, but this Client uses the legacy Typert Remote session format."
30157
29302
  );
30158
29303
  }
30159
- if (this.proxySwitch !== void 0 && remote.features.apiProxy) return "apiProxy";
30160
29304
  throw new ClientModeError(
30161
29305
  "HARNESS_VERSION_INCOMPATIBLE",
30162
- localRemoteGateway ? "The selected Host does not provide a compatible Harness Typert Remote Gateway transport." : "The selected Host does not provide the legacy Harness ApiProxy transport."
29306
+ "Both this Client and the selected Host must provide a compatible Harness Typert Remote Gateway transport."
30163
29307
  );
30164
29308
  }
30165
29309
  assertLocalHarnessCarrierAvailable() {
30166
- if (this.gatewaySwitch.supportsCarrier() || this.proxySwitch !== void 0) return;
29310
+ if (this.gatewaySwitch.supportsCarrier()) return;
30167
29311
  throw new ClientModeError(
30168
29312
  "HARNESS_VERSION_INCOMPATIBLE",
30169
29313
  "This Client does not provide a compatible Harness carrier for the selected remote workspace."
@@ -30719,7 +29863,7 @@ var CodexAppServerClient = class {
30719
29863
  this.handleProcessFailure("CODEX_INVALID_RESPONSE", new Error("Codex App Server emitted invalid JSON."));
30720
29864
  return;
30721
29865
  }
30722
- if (!isRecord12(value)) {
29866
+ if (!isRecord11(value)) {
30723
29867
  this.handleProcessFailure("CODEX_INVALID_RESPONSE", new Error("Codex App Server emitted an invalid message."));
30724
29868
  return;
30725
29869
  }
@@ -30766,7 +29910,7 @@ var CodexAppServerClient = class {
30766
29910
  var CODEX_THREAD_UNMATERIALIZED = "CODEX_THREAD_UNMATERIALIZED";
30767
29911
  var CODEX_UNMATERIALIZED_THREAD_MESSAGE = "Codex thread has no turns yet.";
30768
29912
  function safeUpstreamError(value) {
30769
- if (!isRecord12(value) || typeof value.message !== "string") {
29913
+ if (!isRecord11(value) || typeof value.message !== "string") {
30770
29914
  return new CodexAppServerError("CODEX_UPSTREAM_ERROR", "Codex App Server rejected the request.");
30771
29915
  }
30772
29916
  const message = value.message.toLowerCase();
@@ -30784,7 +29928,7 @@ function safeUpstreamError(value) {
30784
29928
  message.includes("not initialized") ? "Codex App Server is not initialized." : "Codex App Server rejected the request."
30785
29929
  );
30786
29930
  }
30787
- function isRecord12(value) {
29931
+ function isRecord11(value) {
30788
29932
  return typeof value === "object" && value !== null && !Array.isArray(value);
30789
29933
  }
30790
29934
 
@@ -31276,15 +30420,15 @@ function decodeCanonicalBase64(value) {
31276
30420
  }
31277
30421
  return decoded;
31278
30422
  }
31279
- function isRecord13(value) {
30423
+ function isRecord12(value) {
31280
30424
  return typeof value === "object" && value !== null && !Array.isArray(value);
31281
30425
  }
31282
30426
  function safeErrorCode2(error) {
31283
- if (isRecord13(error) && typeof error.code === "string") return error.code;
30427
+ if (isRecord12(error) && typeof error.code === "string") return error.code;
31284
30428
  return "UNKNOWN";
31285
30429
  }
31286
30430
  function safeMethod(input3) {
31287
- return isRecord13(input3) && typeof input3.method === "string" ? input3.method : "invalid";
30431
+ return isRecord12(input3) && typeof input3.method === "string" ? input3.method : "invalid";
31288
30432
  }
31289
30433
  function concatChunks(chunks, totalBytes) {
31290
30434
  const output = new Uint8Array(totalBytes);
@@ -31797,14 +30941,14 @@ var CodexRemoteDomain = class {
31797
30941
  if (codexPermissionPresetFromResponse(result) !== params.permissionPreset) {
31798
30942
  await this.callUpstream("thread/settings/update", { threadId, ...settings });
31799
30943
  assertCurrent();
31800
- result = { ...isRecord14(result) ? result : {}, ...settings, sandbox: settings.sandboxPolicy };
30944
+ result = { ...isRecord13(result) ? result : {}, ...settings, sandbox: settings.sandboxPolicy };
31801
30945
  }
31802
30946
  }
31803
30947
  await this.publishPermission(threadId, result);
31804
30948
  return result;
31805
30949
  }
31806
30950
  async publishPermission(threadId, value) {
31807
- const source = isRecord14(value) ? value : {};
30951
+ const source = isRecord13(value) ? value : {};
31808
30952
  const threadSettings = { approvalPolicy: source.approvalPolicy, sandboxPolicy: source.sandboxPolicy ?? source.sandbox };
31809
30953
  await this.handleInbound({ kind: "notification", method: "thread/settings/updated", params: { threadId, threadSettings } });
31810
30954
  }
@@ -31883,7 +31027,7 @@ var CodexRemoteDomain = class {
31883
31027
  if (legacyThread === void 0 || legacyThread.id !== threadId || !Array.isArray(legacyThread.turns)) {
31884
31028
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid Thread history.");
31885
31029
  }
31886
- if (legacyThread.turns.some((turn) => !isRecord14(turn) || typeof turn.id !== "string" || !Array.isArray(turn.items) || turn.items.some((item) => !isRecord14(item)))) {
31030
+ if (legacyThread.turns.some((turn) => !isRecord13(turn) || typeof turn.id !== "string" || !Array.isArray(turn.items) || turn.items.some((item) => !isRecord13(item)))) {
31887
31031
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned invalid Thread history content.");
31888
31032
  }
31889
31033
  return legacyThread;
@@ -31917,17 +31061,17 @@ var CodexRemoteDomain = class {
31917
31061
  }
31918
31062
  throw error;
31919
31063
  }
31920
- if (!isRecord14(result) || !Array.isArray(result.data)) {
31064
+ if (!isRecord13(result) || !Array.isArray(result.data)) {
31921
31065
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid Turn page.");
31922
31066
  }
31923
31067
  const pageResult = result;
31924
31068
  for (const rawTurn of result.data) {
31925
- if (!isRecord14(rawTurn) || typeof rawTurn.id !== "string" || rawTurn.id.length === 0 || rawTurn.itemsView === "full" && !Array.isArray(rawTurn.items)) {
31069
+ if (!isRecord13(rawTurn) || typeof rawTurn.id !== "string" || rawTurn.id.length === 0 || rawTurn.itemsView === "full" && !Array.isArray(rawTurn.items)) {
31926
31070
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid history Turn.");
31927
31071
  }
31928
31072
  const inlineFull = rawTurn.itemsView === "full" || rawTurn.itemsView === void 0 && itemsView === "full" && Array.isArray(rawTurn.items);
31929
31073
  const items = inlineFull ? rawTurn.items : await this.readThreadItems(threadId, rawTurn.id);
31930
- if (items.some((item) => !isRecord14(item))) {
31074
+ if (items.some((item) => !isRecord13(item))) {
31931
31075
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid history Item.");
31932
31076
  }
31933
31077
  turns.push({ ...rawTurn, items });
@@ -31948,11 +31092,11 @@ var CodexRemoteDomain = class {
31948
31092
  sortDirection: "asc",
31949
31093
  ...cursor2 === void 0 ? {} : { cursor: cursor2 }
31950
31094
  });
31951
- if (!isRecord14(result) || !Array.isArray(result.data)) {
31095
+ if (!isRecord13(result) || !Array.isArray(result.data)) {
31952
31096
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid Item page.");
31953
31097
  }
31954
31098
  for (const entry of result.data) {
31955
- if (!isRecord14(entry) || !isRecord14(entry.item)) {
31099
+ if (!isRecord13(entry) || !isRecord13(entry.item)) {
31956
31100
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid history Item.");
31957
31101
  }
31958
31102
  items.push(entry.item);
@@ -32020,7 +31164,7 @@ var CodexRemoteDomain = class {
32020
31164
  return [...this.peers.values()].some((peer) => peer.hasThreadSubscription(threadId));
32021
31165
  }
32022
31166
  resolveUpstreamApproval(params) {
32023
- if (!isRecord14(params) || typeof params.requestId !== "string" && typeof params.requestId !== "number") return;
31167
+ if (!isRecord13(params) || typeof params.requestId !== "string" && typeof params.requestId !== "number") return;
32024
31168
  for (const [handle, approval] of this.approvals) {
32025
31169
  if (approval.upstreamId === params.requestId) this.approvals.delete(handle);
32026
31170
  }
@@ -32248,8 +31392,8 @@ function findImageBlock(value, attachmentId) {
32248
31392
  }
32249
31393
  return void 0;
32250
31394
  }
32251
- if (!isRecord14(value)) return void 0;
32252
- if (value.type === "image" && isRecord14(value.attachment) && value.attachment.attachmentId === attachmentId && typeof value.data === "string") {
31395
+ if (!isRecord13(value)) return void 0;
31396
+ if (value.type === "image" && isRecord13(value.attachment) && value.attachment.attachmentId === attachmentId && typeof value.data === "string") {
32253
31397
  return { attachment: value.attachment, data: value.data };
32254
31398
  }
32255
31399
  for (const child of Object.values(value)) {
@@ -32267,7 +31411,7 @@ function codexBinaryCandidates(configured, hostPlatform = process.platform, user
32267
31411
  const codexCli = join5(chatGptApp, "Contents", "Resources", "codex-cli");
32268
31412
  try {
32269
31413
  const manifest = JSON.parse(readFileSync(join5(codexCli, "codex-package.json"), "utf8"));
32270
- if (!isRecord14(manifest) || typeof manifest.entrypoint !== "string" || manifest.entrypoint.length === 0) {
31414
+ if (!isRecord13(manifest) || typeof manifest.entrypoint !== "string" || manifest.entrypoint.length === 0) {
32271
31415
  return [];
32272
31416
  }
32273
31417
  const candidate = join5(codexCli, manifest.entrypoint);
@@ -32286,24 +31430,24 @@ function codexBinaryCandidates(configured, hostPlatform = process.platform, user
32286
31430
  ])];
32287
31431
  }
32288
31432
  function parseCallEnvelope(input3) {
32289
- if (!isRecord14(input3) || typeof input3.method !== "string" || !("params" in input3) || Object.keys(input3).some((key) => key !== "method" && key !== "params")) {
31433
+ if (!isRecord13(input3) || typeof input3.method !== "string" || !("params" in input3) || Object.keys(input3).some((key) => key !== "method" && key !== "params")) {
32290
31434
  throw new RpcError("INVALID_MESSAGE", "The Codex call envelope is invalid.");
32291
31435
  }
32292
31436
  return { method: input3.method, params: input3.params };
32293
31437
  }
32294
31438
  function parseRespond(input3) {
32295
- if (!isRecord14(input3) || typeof input3.requestHandle !== "string" || !["accept", "decline", "cancel"].includes(String(input3.decision)) || Object.keys(input3).some((key) => key !== "requestHandle" && key !== "decision")) {
31439
+ if (!isRecord13(input3) || typeof input3.requestHandle !== "string" || !["accept", "decline", "cancel"].includes(String(input3.decision)) || Object.keys(input3).some((key) => key !== "requestHandle" && key !== "decision")) {
32296
31440
  throw new RpcError("INVALID_MESSAGE", "The Codex approval response is invalid.");
32297
31441
  }
32298
31442
  return input3;
32299
31443
  }
32300
31444
  function accountCanRun(result) {
32301
- if (!isRecord14(result) || typeof result.requiresOpenaiAuth !== "boolean") return false;
32302
- return result.requiresOpenaiAuth === false || isRecord14(result.account);
31445
+ if (!isRecord13(result) || typeof result.requiresOpenaiAuth !== "boolean") return false;
31446
+ return result.requiresOpenaiAuth === false || isRecord13(result.account);
32303
31447
  }
32304
31448
  function sanitizeAccount(result) {
32305
- if (!isRecord14(result)) throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned invalid account state.");
32306
- const account = isRecord14(result.account) ? result.account : void 0;
31449
+ if (!isRecord13(result)) throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned invalid account state.");
31450
+ const account = isRecord13(result.account) ? result.account : void 0;
32307
31451
  return {
32308
31452
  authenticated: account !== void 0 || result.requiresOpenaiAuth === false,
32309
31453
  requiresOpenaiAuth: result.requiresOpenaiAuth === true,
@@ -32316,11 +31460,11 @@ function sanitizeAccount(result) {
32316
31460
  };
32317
31461
  }
32318
31462
  function sanitizeThreadList(result) {
32319
- if (!isRecord14(result) || !Array.isArray(result.data)) {
31463
+ if (!isRecord13(result) || !Array.isArray(result.data)) {
32320
31464
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid thread list.");
32321
31465
  }
32322
31466
  const data2 = result.data.flatMap((value) => {
32323
- if (!isRecord14(value) || typeof value.id !== "string") return [];
31467
+ if (!isRecord13(value) || typeof value.id !== "string") return [];
32324
31468
  return [{
32325
31469
  id: value.id,
32326
31470
  ...typeof value.sessionId === "string" ? { sessionId: value.sessionId } : {},
@@ -32332,7 +31476,7 @@ function sanitizeThreadList(result) {
32332
31476
  ...typeof value.updatedAt === "number" && Number.isFinite(value.updatedAt) ? { updatedAt: value.updatedAt } : {},
32333
31477
  ...typeof value.archived === "boolean" ? { archived: value.archived } : {},
32334
31478
  ...typeof value.isPinned === "boolean" ? { isPinned: value.isPinned } : {},
32335
- ...isRecord14(value.status) ? { status: value.status } : {}
31479
+ ...isRecord13(value.status) ? { status: value.status } : {}
32336
31480
  }];
32337
31481
  });
32338
31482
  return {
@@ -32342,18 +31486,18 @@ function sanitizeThreadList(result) {
32342
31486
  };
32343
31487
  }
32344
31488
  function filterThreadListByWorkspaceAuthority(result, authority) {
32345
- if (!isRecord14(result) || !Array.isArray(result.data)) {
31489
+ if (!isRecord13(result) || !Array.isArray(result.data)) {
32346
31490
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid thread list.");
32347
31491
  }
32348
31492
  return {
32349
31493
  ...result,
32350
- data: result.data.map((record9) => isRecord14(record9) ? record9 : void 0).filter((thread) => thread !== void 0 && isThreadAllowedByWorkspaceAuthority(thread, authority))
31494
+ data: result.data.map((record9) => isRecord13(record9) ? record9 : void 0).filter((thread) => thread !== void 0 && isThreadAllowedByWorkspaceAuthority(thread, authority))
32351
31495
  };
32352
31496
  }
32353
31497
  function sanitizeProject(value) {
32354
- if (!isRecord14(value) || typeof value.id !== "string" || typeof value.name !== "string") return void 0;
31498
+ if (!isRecord13(value) || typeof value.id !== "string" || typeof value.name !== "string") return void 0;
32355
31499
  const roots = Array.isArray(value.roots) ? value.roots.flatMap((root) => {
32356
- const path = isRecord14(root) && typeof root.path === "string" && root.path.length > 0 ? root.path : void 0;
31500
+ const path = isRecord13(root) && typeof root.path === "string" && root.path.length > 0 ? root.path : void 0;
32357
31501
  return path === void 0 || !isAbsolute2(path) ? [] : [{ path }];
32358
31502
  }) : [];
32359
31503
  if (roots.length === 0) return void 0;
@@ -32367,7 +31511,7 @@ function sanitizeProject(value) {
32367
31511
  };
32368
31512
  }
32369
31513
  function sanitizeProjectList(result) {
32370
- if (!isRecord14(result) || !Array.isArray(result.data)) {
31514
+ if (!isRecord13(result) || !Array.isArray(result.data)) {
32371
31515
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid project list.");
32372
31516
  }
32373
31517
  const data2 = result.data.flatMap((value) => sanitizeProject(value) ?? []);
@@ -32377,7 +31521,7 @@ function sanitizeProjectList(result) {
32377
31521
  };
32378
31522
  }
32379
31523
  function sanitizeProjectCreate(result) {
32380
- const project2 = isRecord14(result) ? sanitizeProject(result.project) : void 0;
31524
+ const project2 = isRecord13(result) ? sanitizeProject(result.project) : void 0;
32381
31525
  if (project2 === void 0) {
32382
31526
  throw new RpcError("CODEX_INVALID_RESPONSE", "Codex App Server returned an invalid created project.");
32383
31527
  }
@@ -32409,19 +31553,19 @@ function codexDirectoryCrumbs(root, path) {
32409
31553
  return crumbs2;
32410
31554
  }
32411
31555
  function extractThread(result) {
32412
- return isRecord14(result) && isRecord14(result.thread) ? result.thread : void 0;
31556
+ return isRecord13(result) && isRecord13(result.thread) ? result.thread : void 0;
32413
31557
  }
32414
31558
  function extractTurnId(result) {
32415
- if (!isRecord14(result)) return void 0;
31559
+ if (!isRecord13(result)) return void 0;
32416
31560
  if (typeof result.turnId === "string" && result.turnId.length > 0) return result.turnId;
32417
- if (isRecord14(result.turn) && typeof result.turn.id === "string" && result.turn.id.length > 0) return result.turn.id;
31561
+ if (isRecord13(result.turn) && typeof result.turn.id === "string" && result.turn.id.length > 0) return result.turn.id;
32418
31562
  return void 0;
32419
31563
  }
32420
31564
  function extractThreadId(params) {
32421
- if (!isRecord14(params)) return void 0;
31565
+ if (!isRecord13(params)) return void 0;
32422
31566
  if (typeof params.threadId === "string") return params.threadId;
32423
- if (isRecord14(params.thread) && typeof params.thread.id === "string") return params.thread.id;
32424
- if (isRecord14(params.turn) && typeof params.turn.threadId === "string") return params.turn.threadId;
31567
+ if (isRecord13(params.thread) && typeof params.thread.id === "string") return params.thread.id;
31568
+ if (isRecord13(params.turn) && typeof params.turn.threadId === "string") return params.turn.threadId;
32425
31569
  return void 0;
32426
31570
  }
32427
31571
  function optionalInteger3(value) {
@@ -32463,13 +31607,13 @@ function mapCodexImageInputs(params) {
32463
31607
  return {
32464
31608
  ...params,
32465
31609
  input: params.input.map((value) => {
32466
- if (!isRecord14(value) || value.type !== "image" || typeof value.mediaType !== "string" || typeof value.data !== "string") return value;
31610
+ if (!isRecord13(value) || value.type !== "image" || typeof value.mediaType !== "string" || typeof value.data !== "string") return value;
32467
31611
  return { type: "image", url: `data:${value.mediaType};base64,${value.data}` };
32468
31612
  })
32469
31613
  };
32470
31614
  }
32471
31615
  function sanitizeApprovalParams(params, requestHandle) {
32472
- if (!isRecord14(params)) return { requestHandle };
31616
+ if (!isRecord13(params)) return { requestHandle };
32473
31617
  const safe = { ...params };
32474
31618
  delete safe.proposedExecpolicyAmendment;
32475
31619
  delete safe.additionalPermissions;
@@ -32510,7 +31654,7 @@ function isProjectListFallbackError(error) {
32510
31654
  function canTryNextBinary(error) {
32511
31655
  return !(error instanceof RpcError) || !["CODEX_AUTH_REQUIRED", "CODEX_CLOSED"].includes(error.code);
32512
31656
  }
32513
- function isRecord14(value) {
31657
+ function isRecord13(value) {
32514
31658
  return typeof value === "object" && value !== null && !Array.isArray(value);
32515
31659
  }
32516
31660
  function maskId(value) {
@@ -32659,7 +31803,7 @@ var CursorAcpClient = class {
32659
31803
  async call(method, params, timeoutMs) {
32660
31804
  if (!this.ready) throw new CursorAcpError("CURSOR_UNAVAILABLE", "Cursor ACP is not ready.");
32661
31805
  const backend = this.options.modelBackend ?? (this.options.authenticationMethod === null ? void 0 : "cursor");
32662
- const id5 = isRecord15(params) && typeof params.sessionId === "string" ? params.sessionId : void 0;
31806
+ const id5 = isRecord14(params) && typeof params.sessionId === "string" ? params.sessionId : void 0;
32663
31807
  if (backend && (method === "dsh/sessionModels" || method === "dsh/selectModel")) {
32664
31808
  const state = id5 ? this.modelStates.get(id5) : void 0;
32665
31809
  if (!state || !id5) throw new CursorAcpError("ACP_SESSION_NOT_LOADED", "Load the ACP session before selecting a model.");
@@ -32700,7 +31844,7 @@ var CursorAcpClient = class {
32700
31844
  const budget = timeoutMs ?? (method === "session/prompt" ? ACP_PROMPT_TIMEOUT_MS : ACP_REQUEST_TIMEOUT_MS);
32701
31845
  const result = await this.request(method, params, budget);
32702
31846
  if (backend && (method === "session/new" || method === "session/load")) {
32703
- const returnedId = isRecord15(result) && typeof result.sessionId === "string" ? result.sessionId : void 0;
31847
+ const returnedId = isRecord14(result) && typeof result.sessionId === "string" ? result.sessionId : void 0;
32704
31848
  const sessionId = method === "session/load" ? id5 : returnedId;
32705
31849
  if (!this.ready || !sessionId || returnedId && returnedId !== sessionId) throw new CursorAcpError("ACP_INVALID_SESSION", "ACP returned an invalid session.");
32706
31850
  const state = new AcpSessionModelState(backend);
@@ -32864,7 +32008,7 @@ var CursorAcpClient = class {
32864
32008
  this.handleProcessFailure("CURSOR_INVALID_RESPONSE", new Error("Cursor ACP emitted invalid JSON."));
32865
32009
  return;
32866
32010
  }
32867
- if (!isRecord15(value)) {
32011
+ if (!isRecord14(value)) {
32868
32012
  this.handleProcessFailure("CURSOR_INVALID_RESPONSE", new Error("Cursor ACP emitted an invalid message."));
32869
32013
  return;
32870
32014
  }
@@ -32881,7 +32025,7 @@ var CursorAcpClient = class {
32881
32025
  if (typeof value.method !== "string" || value.method.length === 0 || value.method.length > 160) return;
32882
32026
  const params = value.params ?? {};
32883
32027
  const inbound = value.method !== "session/update" && (typeof value.id === "string" || typeof value.id === "number") ? { kind: "request", id: value.id, method: value.method, params } : { kind: "notification", method: value.method, params };
32884
- if (inbound.kind === "notification" && inbound.method === "session/update" && isRecord15(params) && typeof params.sessionId === "string") {
32028
+ if (inbound.kind === "notification" && inbound.method === "session/update" && isRecord14(params) && typeof params.sessionId === "string") {
32885
32029
  this.modelStates.get(params.sessionId)?.update(params.update);
32886
32030
  }
32887
32031
  for (const handler of this.inboundHandlers) handler(inbound);
@@ -32913,7 +32057,7 @@ var CursorAcpClient = class {
32913
32057
  }
32914
32058
  };
32915
32059
  function safeUpstreamError2(value) {
32916
- if (!isRecord15(value) || typeof value.message !== "string") return "Cursor ACP rejected the request.";
32060
+ if (!isRecord14(value) || typeof value.message !== "string") return "Cursor ACP rejected the request.";
32917
32061
  const message = value.message.toLowerCase();
32918
32062
  if (message.includes("auth") || message.includes("login") || message.includes("api key")) {
32919
32063
  return "Cursor ACP authentication failed.";
@@ -32921,7 +32065,7 @@ function safeUpstreamError2(value) {
32921
32065
  if (message.includes("not initialized")) return "Cursor ACP is not initialized.";
32922
32066
  return "Cursor ACP rejected the request.";
32923
32067
  }
32924
- function isRecord15(value) {
32068
+ function isRecord14(value) {
32925
32069
  return typeof value === "object" && value !== null && !Array.isArray(value);
32926
32070
  }
32927
32071
 
@@ -34118,8 +33262,8 @@ var WorkspaceBridge = class {
34118
33262
  }
34119
33263
  };
34120
33264
  function argsOf(payload) {
34121
- const value = isRecord16(payload) ? payload : {};
34122
- return isRecord16(value.args) ? value.args : value;
33265
+ const value = isRecord15(payload) ? payload : {};
33266
+ return isRecord15(value.args) ? value.args : value;
34123
33267
  }
34124
33268
  function toolScope(endpoint, args) {
34125
33269
  const session = args.agentId ?? args.sessionId;
@@ -34129,13 +33273,13 @@ function toolScope(endpoint, args) {
34129
33273
  }
34130
33274
  return session;
34131
33275
  }
34132
- function isRecord16(value) {
33276
+ function isRecord15(value) {
34133
33277
  return typeof value === "object" && value !== null && !Array.isArray(value);
34134
33278
  }
34135
33279
  function byteOrLineRange(args) {
34136
- const options = isRecord16(args.options) ? args.options : void 0;
34137
- if (options !== void 0 && isRecord16(options.range)) return options.range;
34138
- return isRecord16(args.range) ? args.range : args;
33280
+ const options = isRecord15(args.options) ? args.options : void 0;
33281
+ if (options !== void 0 && isRecord15(options.range)) return options.range;
33282
+ return isRecord15(args.range) ? args.range : args;
34139
33283
  }
34140
33284
  function readOffset(args) {
34141
33285
  const range = byteOrLineRange(args);
@@ -35662,7 +34806,7 @@ var OpencodeAcpClient = class _OpencodeAcpClient {
35662
34806
  busy = /* @__PURE__ */ new Set();
35663
34807
  async call(method, params, timeoutMs) {
35664
34808
  if (!this.ready) throw new OpencodeAcpError("OPENCODE_UNAVAILABLE", "OpenCode ACP is not ready.");
35665
- const p = isRecord17(params) ? params : {};
34809
+ const p = isRecord16(params) ? params : {};
35666
34810
  const id5 = typeof p.sessionId === "string" ? p.sessionId : void 0;
35667
34811
  if (id5 && this.archivingSessions.has(id5)) throw new OpencodeAcpError("ACP_SESSION_BUSY", "The OpenCode session is being archived.");
35668
34812
  if (id5 && this.archivedSessions.has(id5) && ["session/load", "session/prompt", "dsh/selectModel"].includes(method)) throw new OpencodeAcpError("ACP_SESSION_ARCHIVED", "This OpenCode session is archived.");
@@ -35708,7 +34852,7 @@ var OpencodeAcpClient = class _OpencodeAcpClient {
35708
34852
  }
35709
34853
  const result = await this.request(method, params, budget);
35710
34854
  const nativeApi = this.nativeApi;
35711
- if (method === "session/list" && nativeApi && isRecord17(result) && Array.isArray(result.sessions)) {
34855
+ if (method === "session/list" && nativeApi && isRecord16(result) && Array.isArray(result.sessions)) {
35712
34856
  if (result.sessions.length > 1e3) throw new OpencodeAcpError("INVALID_MESSAGE", "The OpenCode catalog page is too large.");
35713
34857
  const items = result.sessions;
35714
34858
  const archivedItems = /* @__PURE__ */ new Map();
@@ -35718,7 +34862,7 @@ var OpencodeAcpClient = class _OpencodeAcpClient {
35718
34862
  const index = next++;
35719
34863
  if (index >= items.length) return;
35720
34864
  const item = items[index];
35721
- if (!isRecord17(item) || typeof item.sessionId !== "string" || typeof item.cwd !== "string") continue;
34865
+ if (!isRecord16(item) || typeof item.sessionId !== "string" || typeof item.cwd !== "string") continue;
35722
34866
  const cwd2 = await realpath4(item.cwd).catch(() => void 0);
35723
34867
  if (!cwd2) continue;
35724
34868
  const archived = await nativeApi.isArchived(item.sessionId, cwd2);
@@ -35734,7 +34878,7 @@ var OpencodeAcpClient = class _OpencodeAcpClient {
35734
34878
  }
35735
34879
  async loadSession(method, params, budget, sessionId) {
35736
34880
  const result = await this.request(method, params, budget);
35737
- const returnedId = isRecord17(result) && typeof result.sessionId === "string" ? result.sessionId : void 0;
34881
+ const returnedId = isRecord16(result) && typeof result.sessionId === "string" ? result.sessionId : void 0;
35738
34882
  const id5 = sessionId ?? returnedId;
35739
34883
  if (!this.ready || !id5 || sessionId && returnedId && returnedId !== sessionId) {
35740
34884
  throw new OpencodeAcpError("ACP_INVALID_SESSION", "OpenCode returned an invalid session.");
@@ -35912,7 +35056,7 @@ var OpencodeAcpClient = class _OpencodeAcpClient {
35912
35056
  this.handleProcessFailure("OPENCODE_INVALID_RESPONSE", new Error("OpenCode ACP emitted invalid JSON."));
35913
35057
  return;
35914
35058
  }
35915
- if (!isRecord17(value)) {
35059
+ if (!isRecord16(value)) {
35916
35060
  this.handleProcessFailure("OPENCODE_INVALID_RESPONSE", new Error("OpenCode ACP emitted an invalid message."));
35917
35061
  return;
35918
35062
  }
@@ -35929,11 +35073,11 @@ var OpencodeAcpClient = class _OpencodeAcpClient {
35929
35073
  if (typeof value.method !== "string" || value.method.length === 0 || value.method.length > 160) return;
35930
35074
  const params = value.params ?? {};
35931
35075
  const inbound = value.method !== "session/update" && (typeof value.id === "string" || typeof value.id === "number") ? { kind: "request", id: value.id, method: value.method, params } : { kind: "notification", method: value.method, params };
35932
- if (inbound.kind === "request" && isRecord17(params) && typeof params.sessionId === "string" && this.loads.has(params.sessionId)) {
35076
+ if (inbound.kind === "request" && isRecord16(params) && typeof params.sessionId === "string" && this.loads.has(params.sessionId)) {
35933
35077
  void this.respondError(inbound.id, -32600, "OpenCode session is not loaded.").catch(() => void 0);
35934
35078
  return;
35935
35079
  }
35936
- if (inbound.kind === "notification" && inbound.method === "session/update" && isRecord17(params) && typeof params.sessionId === "string") {
35080
+ if (inbound.kind === "notification" && inbound.method === "session/update" && isRecord16(params) && typeof params.sessionId === "string") {
35937
35081
  this.models.get(params.sessionId)?.update(params.update);
35938
35082
  if (this.loads.has(params.sessionId) && !this.options.historyReader) return;
35939
35083
  }
@@ -35969,7 +35113,7 @@ var OpencodeAcpClient = class _OpencodeAcpClient {
35969
35113
  }
35970
35114
  };
35971
35115
  function safeUpstreamError3(value) {
35972
- if (!isRecord17(value) || typeof value.message !== "string") return "OpenCode ACP rejected the request.";
35116
+ if (!isRecord16(value) || typeof value.message !== "string") return "OpenCode ACP rejected the request.";
35973
35117
  const message = value.message.toLowerCase();
35974
35118
  if (message.includes("auth") || message.includes("login") || message.includes("api key")) {
35975
35119
  return "OpenCode ACP authentication failed.";
@@ -35977,7 +35121,7 @@ function safeUpstreamError3(value) {
35977
35121
  if (message.includes("not initialized")) return "OpenCode ACP is not initialized.";
35978
35122
  return "OpenCode ACP rejected the request.";
35979
35123
  }
35980
- function isRecord17(value) {
35124
+ function isRecord16(value) {
35981
35125
  return typeof value === "object" && value !== null && !Array.isArray(value);
35982
35126
  }
35983
35127
 
@@ -36714,15 +35858,15 @@ function decodeCanonicalBase642(value) {
36714
35858
  }
36715
35859
  return decoded;
36716
35860
  }
36717
- function isRecord18(value) {
35861
+ function isRecord17(value) {
36718
35862
  return typeof value === "object" && value !== null && !Array.isArray(value);
36719
35863
  }
36720
35864
  function safeErrorCode3(error) {
36721
- if (isRecord18(error) && typeof error.code === "string") return error.code;
35865
+ if (isRecord17(error) && typeof error.code === "string") return error.code;
36722
35866
  return "UNKNOWN";
36723
35867
  }
36724
35868
  function safeMethod2(input3) {
36725
- return isRecord18(input3) && typeof input3.method === "string" ? input3.method : "invalid";
35869
+ return isRecord17(input3) && typeof input3.method === "string" ? input3.method : "invalid";
36726
35870
  }
36727
35871
  function concatChunks2(chunks, totalBytes) {
36728
35872
  const output = new Uint8Array(totalBytes);
@@ -37113,7 +36257,7 @@ var AcpRemoteGateway = class {
37113
36257
  const requested = typeof call.params.backend === "string" ? call.params.backend : selected ?? this.defaultBackend();
37114
36258
  if (selected !== void 0 && selected !== requested) throw new RpcError("INVALID_MESSAGE", "The ACP session backend does not match.");
37115
36259
  this.requireAcp(requested);
37116
- if (Array.isArray(call.params.prompt) && call.params.prompt.some((part) => isRecord19(part) && part.type === "image") && requested !== "antigravity") throw new RpcError("METHOD_NOT_ALLOWED", "This ACP backend does not accept image prompts.");
36260
+ if (Array.isArray(call.params.prompt) && call.params.prompt.some((part) => isRecord18(part) && part.type === "image") && requested !== "antigravity") throw new RpcError("METHOD_NOT_ALLOWED", "This ACP backend does not accept image prompts.");
37117
36261
  this.sessionBackends.set(sessionId, requested);
37118
36262
  }
37119
36263
  if (call.method === "session/load") {
@@ -37227,7 +36371,7 @@ var AcpRemoteGateway = class {
37227
36371
  const result = await task.client.call("session/prompt", params);
37228
36372
  await this.inboundChain;
37229
36373
  if (!current()) return;
37230
- const stopReason = isRecord19(result) && typeof result.stopReason === "string" ? result.stopReason : "end_turn";
36374
+ const stopReason = isRecord18(result) && typeof result.stopReason === "string" ? result.stopReason : "end_turn";
37231
36375
  const catchUp = takeTurnCatchUp(this.turnCatchUp, sessionId);
37232
36376
  this.logger.info("ACP prompt finished", {
37233
36377
  sessionId: shortSessionId(sessionId),
@@ -37559,7 +36703,7 @@ var AcpRemoteGateway = class {
37559
36703
  await peer.publishInbound(sessionId, {
37560
36704
  method: message.method,
37561
36705
  params: {
37562
- ...isRecord19(message.params) ? message.params : {},
36706
+ ...isRecord18(message.params) ? message.params : {},
37563
36707
  requestHandle,
37564
36708
  sessionId,
37565
36709
  upstreamMethod: message.method
@@ -37594,8 +36738,8 @@ var AcpRemoteGateway = class {
37594
36738
  recordTurnCatchUp(sessionId, frame) {
37595
36739
  const list = this.turnCatchUp.get(sessionId);
37596
36740
  if (list === void 0 || frame.method !== "session/update") return;
37597
- const params = isRecord19(frame.params) ? frame.params : void 0;
37598
- const update = params !== void 0 && isRecord19(params.update) ? params.update : params;
36741
+ const params = isRecord18(frame.params) ? frame.params : void 0;
36742
+ const update = params !== void 0 && isRecord18(params.update) ? params.update : params;
37599
36743
  const kind = update !== void 0 && typeof update.sessionUpdate === "string" ? update.sessionUpdate : void 0;
37600
36744
  if (kind === void 0 || !CATCH_UP_SESSION_UPDATES.has(kind)) return;
37601
36745
  list.push({ method: frame.method, params: frame.params });
@@ -37731,11 +36875,11 @@ var AcpRemoteGateway = class {
37731
36875
  for (let page = 0; page < 100; page++) {
37732
36876
  const result = await client.call("session/list", { ...cwd2 ? { cwd: cwd2 } : {}, ...cursor2 ? { cursor: cursor2 } : {} });
37733
36877
  assertCurrent();
37734
- if (!isRecord19(result) || !Array.isArray(result.sessions) || result.nextCursor != null && (typeof result.nextCursor !== "string" || result.nextCursor.length === 0)) {
36878
+ if (!isRecord18(result) || !Array.isArray(result.sessions) || result.nextCursor != null && (typeof result.nextCursor !== "string" || result.nextCursor.length === 0)) {
37735
36879
  throw new RpcError("INVALID_MESSAGE", "The ACP session catalog response is invalid.");
37736
36880
  }
37737
36881
  for (const item of result.sessions) {
37738
- if (!isRecord19(item) || typeof item.sessionId !== "string" || typeof item.cwd !== "string") continue;
36882
+ if (!isRecord18(item) || typeof item.sessionId !== "string" || typeof item.cwd !== "string") continue;
37739
36883
  const canonical = await this.requireExistingDirectory(item.cwd).catch(() => void 0);
37740
36884
  assertCurrent();
37741
36885
  if (!canonical || cwd2 && canonical !== cwd2) continue;
@@ -37832,24 +36976,24 @@ var AcpRemoteGateway = class {
37832
36976
  }
37833
36977
  };
37834
36978
  function parseCallEnvelope2(input3) {
37835
- if (!isRecord19(input3) || typeof input3.method !== "string") {
36979
+ if (!isRecord18(input3) || typeof input3.method !== "string") {
37836
36980
  throw new RpcError("INVALID_MESSAGE", "The Cursor call envelope is invalid.");
37837
36981
  }
37838
36982
  return { method: input3.method, params: input3.params ?? {} };
37839
36983
  }
37840
36984
  function parseRespondEnvelope(input3) {
37841
- if (!isRecord19(input3) || typeof input3.requestHandle !== "string" || input3.requestHandle.length === 0 || Object.keys(input3).some((key) => !["requestHandle", "decision", "result"].includes(key)) || typeof input3.decision !== "string" || !["allow-once", "reject-once", "cancel"].includes(input3.decision)) {
36985
+ if (!isRecord18(input3) || typeof input3.requestHandle !== "string" || input3.requestHandle.length === 0 || Object.keys(input3).some((key) => !["requestHandle", "decision", "result"].includes(key)) || typeof input3.decision !== "string" || !["allow-once", "reject-once", "cancel"].includes(input3.decision)) {
37842
36986
  throw new RpcError("INVALID_MESSAGE", "The ACP respond envelope is invalid.");
37843
36987
  }
37844
36988
  return input3;
37845
36989
  }
37846
36990
  function permissionOptions(params) {
37847
- if (!isRecord19(params) || !Array.isArray(params.options) || params.options.length === 0) {
36991
+ if (!isRecord18(params) || !Array.isArray(params.options) || params.options.length === 0) {
37848
36992
  throw new Error("Missing permission options");
37849
36993
  }
37850
36994
  const ids = /* @__PURE__ */ new Set();
37851
36995
  const options = params.options.map((option) => {
37852
- if (!isRecord19(option) || typeof option.optionId !== "string" || !option.optionId || typeof option.kind !== "string" || !["allow_once", "allow_always", "reject_once", "reject_always"].includes(option.kind) || ids.has(option.optionId)) throw new Error("Invalid permission option");
36996
+ if (!isRecord18(option) || typeof option.optionId !== "string" || !option.optionId || typeof option.kind !== "string" || !["allow_once", "allow_always", "reject_once", "reject_always"].includes(option.kind) || ids.has(option.optionId)) throw new Error("Invalid permission option");
37853
36997
  ids.add(option.optionId);
37854
36998
  return { kind: option.kind, optionId: option.optionId };
37855
36999
  });
@@ -37870,21 +37014,21 @@ function mapPermissionDecision(params, pending) {
37870
37014
  }
37871
37015
  const outcome = pending.method === "cursor/create_plan" ? params.decision === "allow-once" ? "accepted" : params.decision === "cancel" ? "cancelled" : "rejected" : "cancelled";
37872
37016
  if (params.result !== void 0) {
37873
- if (!isRecord19(params.result) || Object.keys(params.result).length !== 1 || !isRecord19(params.result.outcome) || Object.keys(params.result.outcome).length !== 1 || params.result.outcome.outcome !== outcome) throw invalid();
37017
+ if (!isRecord18(params.result) || Object.keys(params.result).length !== 1 || !isRecord18(params.result.outcome) || Object.keys(params.result.outcome).length !== 1 || params.result.outcome.outcome !== outcome) throw invalid();
37874
37018
  }
37875
37019
  return { outcome: { outcome } };
37876
37020
  }
37877
37021
  function readSessionId(value) {
37878
- if (!isRecord19(value)) return void 0;
37022
+ if (!isRecord18(value)) return void 0;
37879
37023
  return typeof value.sessionId === "string" ? value.sessionId : void 0;
37880
37024
  }
37881
37025
  function readNestedSessionId(value) {
37882
- if (!isRecord19(value)) return void 0;
37883
- if (isRecord19(value.update) && typeof value.update.sessionId === "string") return value.update.sessionId;
37026
+ if (!isRecord18(value)) return void 0;
37027
+ if (isRecord18(value.update) && typeof value.update.sessionId === "string") return value.update.sessionId;
37884
37028
  return void 0;
37885
37029
  }
37886
37030
  function sanitizeSessionResult(value) {
37887
- if (!isRecord19(value)) return value;
37031
+ if (!isRecord18(value)) return value;
37888
37032
  const next = {};
37889
37033
  for (const [key, entry] of Object.entries(value)) {
37890
37034
  if (key === "sessionId" || key === "stopReason" || key === "mode") next[key] = entry;
@@ -37944,7 +37088,7 @@ function takeTurnCatchUp(turnCatchUp, sessionId) {
37944
37088
  turnCatchUp.delete(sessionId);
37945
37089
  return list;
37946
37090
  }
37947
- function isRecord19(value) {
37091
+ function isRecord18(value) {
37948
37092
  return typeof value === "object" && value !== null && !Array.isArray(value);
37949
37093
  }
37950
37094
 
@@ -38339,11 +37483,11 @@ function editableConfig(config) {
38339
37483
  ...config.acp === void 0 ? {} : { acp: { enabled: config.acp.enabled, backends: config.acp.backends } }
38340
37484
  };
38341
37485
  }
38342
- function isRecord20(value) {
37486
+ function isRecord19(value) {
38343
37487
  return typeof value === "object" && value !== null && !Array.isArray(value);
38344
37488
  }
38345
37489
  function record7(value) {
38346
- if (!isRecord20(value)) throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
37490
+ if (!isRecord19(value)) throw new ClientModeError("INVALID_MESSAGE", "The control request payload is invalid.");
38347
37491
  return value;
38348
37492
  }
38349
37493
  function ok3(value) {
@@ -38610,9 +37754,6 @@ function unavailable2() {
38610
37754
  return new RpcError("UPLOAD_WORKSPACE_UNAVAILABLE", "The session workspace is unavailable.");
38611
37755
  }
38612
37756
 
38613
- // src/service.ts
38614
- import { randomUUID as randomUUID7 } from "node:crypto";
38615
-
38616
37757
  // src/connection-controller.ts
38617
37758
  var ConnectionController = class {
38618
37759
  constructor(identities, createRouter, logger) {
@@ -38809,15 +37950,6 @@ var historyConfigureSchema = external_exports.object({ compact: external_exports
38809
37950
  var apiMethods = /* @__PURE__ */ new Set([
38810
37951
  "harness.transport.describe",
38811
37952
  "remote.history.configure",
38812
- "harness.api.call",
38813
- "harness.api.transfer.open",
38814
- "harness.api.transfer.chunk",
38815
- "harness.api.transfer.commit",
38816
- "harness.api.transfer.read",
38817
- "harness.api.transfer.close",
38818
- "harness.api.respond",
38819
- "harness.api.stream.open",
38820
- "harness.api.stream.close",
38821
37953
  "harness.remote.call",
38822
37954
  "harness.remote.transfer.open",
38823
37955
  "harness.remote.transfer.chunk",
@@ -38853,8 +37985,6 @@ var apiMethods = /* @__PURE__ */ new Set([
38853
37985
  "workspace.upload.abort"
38854
37986
  ]);
38855
37987
  var HOST_CAPABILITIES = [
38856
- "harness.api.v1",
38857
- "harness.api.transfer.v1",
38858
37988
  "harness.remote.v1",
38859
37989
  "harness.remote.transfer.v1",
38860
37990
  "fileviewer.read.v1",
@@ -38865,8 +37995,7 @@ var HOST_CAPABILITIES = [
38865
37995
  "agent.acp.transfer.v1"
38866
37996
  ];
38867
37997
  var RpcRouter = class {
38868
- constructor(harnessApi, maxPending = 128, logger, fileViewer, harnessRemote, capabilities = () => HOST_CAPABILITIES, codex, acp, loopback, workspaceTypes, pluginRoute, workspaceUpload) {
38869
- this.harnessApi = harnessApi;
37998
+ constructor(maxPending = 128, logger, fileViewer, harnessRemote, capabilities = () => HOST_CAPABILITIES, codex, acp, loopback, workspaceTypes, pluginRoute, workspaceUpload) {
38870
37999
  this.maxPending = maxPending;
38871
38000
  this.logger = logger;
38872
38001
  this.fileViewer = fileViewer;
@@ -38883,7 +38012,6 @@ var RpcRouter = class {
38883
38012
  async closePeerStreams() {
38884
38013
  this.loopback?.closeAll();
38885
38014
  await Promise.all([
38886
- this.harnessApi?.closeAll(),
38887
38015
  this.harnessRemote?.closeAll(),
38888
38016
  this.codex?.closeAll(),
38889
38017
  this.acp?.closeAll(),
@@ -38933,7 +38061,11 @@ var RpcRouter = class {
38933
38061
  switch (method) {
38934
38062
  case "harness.transport.describe": {
38935
38063
  emptyParamsSchema.parse(params);
38936
- const capabilities = [.../* @__PURE__ */ new Set([...this.capabilities(), "remote.history.compact.v1"])];
38064
+ const capabilities = [.../* @__PURE__ */ new Set([
38065
+ ...this.capabilities(),
38066
+ "remote.history.compact.v1",
38067
+ ...this.harnessRemote === void 0 ? [] : ["harness.remote.stream.transfer.v1"]
38068
+ ])];
38937
38069
  let workspaceTypes;
38938
38070
  if (this.workspaceTypes !== void 0) {
38939
38071
  try {
@@ -38949,29 +38081,11 @@ var RpcRouter = class {
38949
38081
  }
38950
38082
  case "remote.history.configure": {
38951
38083
  const { compact } = historyConfigureSchema.parse(params);
38952
- for (const bridge of [this.harnessApi, this.harnessRemote, this.codex, this.acp]) {
38084
+ for (const bridge of [this.harnessRemote, this.codex, this.acp]) {
38953
38085
  if (bridge !== void 0) bridge.compactHistoryEnabled = compact;
38954
38086
  }
38955
38087
  return { compact };
38956
38088
  }
38957
- case "harness.api.call":
38958
- return this.requireApiProxy().call(params);
38959
- case "harness.api.transfer.open":
38960
- return this.requireApiProxy().openTransfer(params);
38961
- case "harness.api.transfer.chunk":
38962
- return this.requireApiProxy().appendTransfer(params);
38963
- case "harness.api.transfer.commit":
38964
- return this.requireApiProxy().commitTransfer(params);
38965
- case "harness.api.transfer.read":
38966
- return this.requireApiProxy().readTransfer(params);
38967
- case "harness.api.transfer.close":
38968
- return this.requireApiProxy().closeTransfer(params);
38969
- case "harness.api.respond":
38970
- return this.requireApiProxy().respond(params);
38971
- case "harness.api.stream.open":
38972
- return this.requireApiProxy().openStream(params);
38973
- case "harness.api.stream.close":
38974
- return this.requireApiProxy().closeStream(params);
38975
38089
  case "harness.remote.call":
38976
38090
  return this.requireRemoteGateway().call(params);
38977
38091
  case "harness.remote.transfer.open":
@@ -39047,12 +38161,6 @@ var RpcRouter = class {
39047
38161
  throw new RpcError("METHOD_NOT_FOUND", "The requested method does not exist.");
39048
38162
  }
39049
38163
  }
39050
- requireApiProxy() {
39051
- if (this.harnessApi === void 0) {
39052
- throw new RpcError("FEATURE_NOT_SUPPORTED", "This Harness version does not provide the legacy ApiProxy transport.");
39053
- }
39054
- return this.harnessApi;
39055
- }
39056
38164
  requireRemoteGateway() {
39057
38165
  if (this.harnessRemote === void 0) {
39058
38166
  throw new RpcError("FEATURE_NOT_SUPPORTED", "This Harness version does not provide the Remote Gateway transport.");
@@ -39211,7 +38319,7 @@ function isOversizedListing(value) {
39211
38319
  // src/server-connection.ts
39212
38320
  var DEFAULT_WEBRTC_NEGOTIATE_TIMEOUT_MS = 12e3;
39213
38321
  var HostServerConnection = class {
39214
- constructor(config, identity2, identities, api, connections, logger, createWebSocket = (url) => new WebSocket(url), rtcFactoryProvider, hostCapabilities = () => ["harness.api.v1"], harnessVersion) {
38322
+ constructor(config, identity2, identities, api, connections, logger, createWebSocket = (url) => new WebSocket(url), rtcFactoryProvider, hostCapabilities = () => [], harnessVersion) {
39215
38323
  this.config = config;
39216
38324
  this.identity = identity2;
39217
38325
  this.identities = identities;
@@ -40128,6 +39236,9 @@ function closeCode(code) {
40128
39236
  return "CONNECTION_FAILED";
40129
39237
  }
40130
39238
 
39239
+ // src/harness-remote-bridge.ts
39240
+ import { randomUUID as randomUUID7 } from "node:crypto";
39241
+
40131
39242
  // src/remote-directory-browser.ts
40132
39243
  import { mkdir as mkdir3, readdir as readdir4, stat as stat7 } from "node:fs/promises";
40133
39244
  import { homedir as homedir6, platform as platform2 } from "node:os";
@@ -40179,841 +39290,16 @@ function crumbs(path) {
40179
39290
  return result;
40180
39291
  }
40181
39292
 
40182
- // src/harness-api-history.ts
40183
- var SESSION_HISTORY_PAGE_SIZES = [50, 30, 20, 12, 6, 3, 1];
40184
- function callSessionHistory(callWithTimeout, payload, rpcId2) {
40185
- const fallbackPageSizes = sessionHistoryFallbackPageSizes(payloadMaxMessages(payload));
40186
- return callHistoryWithRetry(callWithTimeout, payload, rpcId2, fallbackPageSizes);
40187
- }
40188
- async function callHistoryWithRetry(callWithTimeout, payload, rpcId2, pageSizes) {
40189
- for (const maxMessages of pageSizes) {
40190
- const requestPayload = historyRequestPayload(payload, maxMessages);
40191
- const response = await callWithTimeout(requestPayload);
40192
- const request = createRpcResponse(rpcId2, response.result);
40193
- if (encodeMessage(request).byteLength <= MAX_SECURE_MESSAGE_BYTES) return response;
40194
- if (maxMessages === pageSizes[pageSizes.length - 1]) {
40195
- throw new RpcError(
40196
- "RESPONSE_TOO_LARGE",
40197
- "The Host response is too large for the remote channel. Request a smaller page.",
40198
- { maxBytes: MAX_SECURE_MESSAGE_BYTES },
40199
- true
40200
- );
40201
- }
40202
- }
40203
- throw new RpcError("INTERNAL_ERROR", "Failed to load session history with a fallback page size.");
40204
- }
40205
- function sessionHistoryFallbackPageSizes(requestedMaxMessages) {
40206
- const requested = normalizeSessionHistoryPageSize(requestedMaxMessages);
40207
- const sizes = [];
40208
- if (requested === void 0) {
40209
- sizes.push(...SESSION_HISTORY_PAGE_SIZES);
40210
- return sizes;
40211
- }
40212
- sizes.push(requested);
40213
- for (const value of SESSION_HISTORY_PAGE_SIZES) {
40214
- if (value < requested && !sizes.includes(value)) sizes.push(value);
40215
- }
40216
- return sizes;
40217
- }
40218
- function normalizeSessionHistoryPageSize(value) {
40219
- if (value === void 0) return void 0;
40220
- if (!Number.isInteger(value)) return void 0;
40221
- if (value <= 0) return void 0;
40222
- return Math.max(1, value);
40223
- }
40224
- function payloadMaxMessages(payload) {
40225
- if (payload === null || typeof payload !== "object") return void 0;
40226
- const value = payload.maxMessages;
40227
- return typeof value === "number" && Number.isInteger(value) && value > 0 ? value : void 0;
40228
- }
40229
- function historyRequestPayload(payload, maxMessages) {
40230
- if (payload === null || typeof payload !== "object" || Array.isArray(payload)) return { maxMessages };
40231
- return { ...payload, maxMessages };
40232
- }
40233
-
40234
- // src/harness-api-bridge.ts
40235
- var callSchema3 = external_exports.object({
40236
- method: external_exports.string().min(1).max(80),
40237
- rpcId: external_exports.string().min(1).max(128),
40238
- payload: external_exports.unknown()
40239
- }).strict();
40240
- var respondSchema = external_exports.object({
40241
- message: external_exports.object({
40242
- type: external_exports.literal("client-response"),
40243
- rpcId: external_exports.string().min(1).max(128),
40244
- result: external_exports.unknown()
40245
- }).strict()
40246
- }).strict();
40247
- var streamOpenSchema3 = external_exports.object({
40248
- streamId: external_exports.string().min(1).max(128),
40249
- stream: external_exports.enum(["mux", "host"]),
40250
- rpcId: external_exports.string().min(1).max(128),
40251
- payload: external_exports.object({
40252
- // Optional focus for a mux stream: only frames belonging to this session
40253
- // are forwarded. The Remote Web selects one session at a time, so without
40254
- // this every active session's events (potentially megabytes) would be
40255
- // pushed over the tunnel and stall the WebRTC data channel.
40256
- sessionId: external_exports.string().min(1).max(128).optional()
40257
- }).strict()
40258
- }).strict();
40259
- var streamCloseSchema3 = external_exports.object({ streamId: external_exports.string().min(1).max(128) }).strict();
40260
- var transferIdSchema3 = external_exports.string().min(1).max(128);
40261
- var transferOpenSchema3 = external_exports.object({
40262
- transferId: transferIdSchema3,
40263
- totalBytes: external_exports.number().int().positive().max(MAX_HARNESS_API_TRANSFER_BYTES),
40264
- totalChunks: external_exports.number().int().positive().max(Math.ceil(MAX_HARNESS_API_TRANSFER_BYTES / HARNESS_API_TRANSFER_CHUNK_BYTES))
40265
- }).strict();
40266
- var transferChunkSchema3 = external_exports.object({
40267
- transferId: transferIdSchema3,
40268
- index: external_exports.number().int().nonnegative(),
40269
- data: external_exports.string().max(Math.ceil(HARNESS_API_TRANSFER_CHUNK_BYTES / 3) * 4)
40270
- }).strict();
40271
- var transferCommitSchema = external_exports.object({ transferId: transferIdSchema3 }).strict();
40272
- var transferReadSchema3 = external_exports.object({ transferId: transferIdSchema3, index: external_exports.number().int().nonnegative() }).strict();
40273
- var transferCloseSchema = external_exports.object({ transferId: transferIdSchema3 }).strict();
40274
- var commandExecuteSchema = external_exports.object({
40275
- agentId: external_exports.string().min(1).max(128),
40276
- line: external_exports.string().min(1).max(2048),
40277
- // dsh-commands <= 0.1.2 calls this field `images`; dsh-commands 0.1.5
40278
- // renamed it to `submittedAttachments` and expanded its element type to
40279
- // include staged file receipts. Remote command execution keeps attachments
40280
- // out of scope, so either compatibility field is restricted to an empty
40281
- // list. The dispatcher below chooses the matching Host descriptor.
40282
- images: external_exports.array(external_exports.never()).length(0).optional(),
40283
- submittedAttachments: external_exports.array(external_exports.never()).length(0).optional()
40284
- }).strict().superRefine((value, context) => {
40285
- if (value.images !== void 0 && value.submittedAttachments !== void 0) {
40286
- context.addIssue({
40287
- code: external_exports.ZodIssueCode.custom,
40288
- message: "Use either images or submittedAttachments, not both.",
40289
- path: ["submittedAttachments"]
40290
- });
40291
- }
40292
- });
40293
- var commandListSchema = external_exports.object({
40294
- agentId: external_exports.string().min(1).max(128)
40295
- }).strict();
40296
- var directoryListSchema = external_exports.object({
40297
- path: external_exports.string().min(1).max(4096).optional()
40298
- }).strict();
40299
- var credentialRefSchema = external_exports.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "Invalid credential reference name").max(128);
40300
- var CONFIG_PLANE_SETTINGS_BYTES = 64 * 1024;
40301
- var CONFIG_PLANE_MAX_OPS = 64;
40302
- var CONFIG_PLANE_MAX_PATH_SEGMENTS = 8;
40303
- var CONFIG_PLANE_MAX_PATH_SEGMENT_BYTES = 64;
40304
- var CONFIG_PLANE_MAX_CREDENTIAL_VALUE_BYTES = 8 * 1024;
40305
- var CONFIG_PLANE_MAX_BASE_URL_BYTES = 2048;
40306
- var CONFIG_PLANE_MAX_NS_BYTES = 128;
40307
- var settingsDescribeSchema = external_exports.object({}).strict();
40308
- var settingsWriteBase = {
40309
- ns: external_exports.string().min(1).max(CONFIG_PLANE_MAX_NS_BYTES),
40310
- expectedRevision: external_exports.number().int().nonnegative().optional()
40311
- };
40312
- var settingsUpdateSchema = external_exports.object({
40313
- ...settingsWriteBase,
40314
- patch: external_exports.record(external_exports.string().min(1).max(CONFIG_PLANE_MAX_PATH_SEGMENT_BYTES), external_exports.unknown())
40315
- }).strict();
40316
- var settingsReplaceSchema = external_exports.object({
40317
- ...settingsWriteBase,
40318
- section: external_exports.record(external_exports.string().min(1).max(CONFIG_PLANE_MAX_PATH_SEGMENT_BYTES), external_exports.unknown())
40319
- }).strict();
40320
- var settingsOpSchema = external_exports.union([
40321
- external_exports.object({
40322
- op: external_exports.literal("set"),
40323
- path: external_exports.array(external_exports.string().min(1).max(CONFIG_PLANE_MAX_PATH_SEGMENT_BYTES)).max(CONFIG_PLANE_MAX_PATH_SEGMENTS),
40324
- value: external_exports.unknown()
40325
- }).strict(),
40326
- external_exports.object({
40327
- op: external_exports.literal("unset"),
40328
- path: external_exports.array(external_exports.string().min(1).max(CONFIG_PLANE_MAX_PATH_SEGMENT_BYTES)).max(CONFIG_PLANE_MAX_PATH_SEGMENTS)
40329
- }).strict()
40330
- ]);
40331
- var settingsMutateSchema = external_exports.object({
40332
- ...settingsWriteBase,
40333
- ops: external_exports.array(settingsOpSchema).min(1).max(CONFIG_PLANE_MAX_OPS)
40334
- }).strict();
40335
- var credentialsDescribeSchema = external_exports.object({
40336
- refs: external_exports.array(credentialRefSchema).max(CONFIG_PLANE_MAX_OPS)
40337
- }).strict();
40338
- var credentialsSetSchema = external_exports.object({
40339
- ref: credentialRefSchema,
40340
- value: external_exports.string().min(1).max(CONFIG_PLANE_MAX_CREDENTIAL_VALUE_BYTES)
40341
- }).strict();
40342
- var credentialsUnsetSchema = external_exports.object({
40343
- ref: credentialRefSchema
40344
- }).strict();
40345
- var discoverModelsSchema = external_exports.object({
40346
- settingsNs: external_exports.string().min(1).max(CONFIG_PLANE_MAX_NS_BYTES),
40347
- provider: external_exports.string().min(1).max(CONFIG_PLANE_MAX_NS_BYTES).optional(),
40348
- baseURL: external_exports.string().max(CONFIG_PLANE_MAX_BASE_URL_BYTES).optional(),
40349
- api: external_exports.string().min(1).max(CONFIG_PLANE_MAX_NS_BYTES).optional(),
40350
- apiKey: external_exports.string().min(1).max(CONFIG_PLANE_MAX_CREDENTIAL_VALUE_BYTES).optional()
40351
- }).strict();
40352
- var HARNESS_API_ALLOWLIST = [
40353
- "session.list",
40354
- "session.search",
40355
- "session.create",
40356
- "session.history",
40357
- "session.models",
40358
- "session.selectModel",
40359
- "session.rename",
40360
- "session.fork",
40361
- "session.prompt",
40362
- "session.attachment",
40363
- "session.updateQueue",
40364
- "session.cancel",
40365
- "subagent.list",
40366
- "subagent.history",
40367
- "subagent.prompt",
40368
- "subagent.interrupt",
40369
- "host.describe",
40370
- "host.listDirectory",
40371
- "workspace.list",
40372
- "workspace.create",
40373
- "workspace.rename",
40374
- "workspace.delete",
40375
- "workspace.insertBefore",
40376
- "workspace.insertSessionBefore",
40377
- "workspace.archiveSession",
40378
- "skill.list",
40379
- "agentPreset.list",
40380
- "agentPreset.select",
40381
- "agentPreset.read",
40382
- "goal.create",
40383
- "goal.edit",
40384
- "goal.pause",
40385
- "goal.resume",
40386
- "goal.complete",
40387
- "goal.clear",
40388
- "commands.execute",
40389
- "commands.list",
40390
- "llm.providers",
40391
- "llm.models",
40392
- "llm.discoverModels",
40393
- "settings.describe",
40394
- "settings.update",
40395
- "settings.replace",
40396
- "settings.mutate",
40397
- "credentials.describe",
40398
- "credentials.set",
40399
- "credentials.unset"
40400
- ];
40401
- var NATIVE_CALL_TIMEOUT_MS = 3e4;
40402
- var MAX_ACTIVE_API_TRANSFERS = MAX_ACTIVE_TRANSFERS_PER_DIRECTION;
40403
- var API_TRANSFER_IDLE_MS = TRANSFER_IDLE_MS;
40404
- var INLINE_TRANSFER_RESPONSE_BYTES3 = 2 * 1024 * 1024;
40405
- var HarnessApiBridge = class {
40406
- constructor(api, publish, maxStreams = 8, logger, typertGateway, harnessVersion) {
40407
- this.api = api;
40408
- this.publish = publish;
40409
- this.maxStreams = maxStreams;
40410
- this.logger = logger;
40411
- this.harnessVersion = harnessVersion;
40412
- this.methods = createMethodMap(api, typertGateway, harnessVersion);
40413
- this.mux = api.events.mux.bind(api.events);
40414
- this.host = api.events.host.bind(api.events);
40415
- this.answer = api.respond.bind(api);
40416
- }
40417
- compactHistoryEnabled = false;
40418
- methods;
40419
- streams = /* @__PURE__ */ new Map();
40420
- respondable = /* @__PURE__ */ new Map();
40421
- incomingTransfers = /* @__PURE__ */ new Map();
40422
- outgoingTransfers = /* @__PURE__ */ new Map();
40423
- mux;
40424
- host;
40425
- answer;
40426
- async call(input3) {
40427
- const params = callSchema3.parse(input3);
40428
- const signal = AbortSignal.timeout(NATIVE_CALL_TIMEOUT_MS);
40429
- const method = this.methods.get(params.method);
40430
- if (method === void 0) {
40431
- if (params.method === "host.listDirectory") {
40432
- return this.callDirectoryFallback(params, signal);
40433
- }
40434
- if (params.method === "host.describe") {
40435
- return this.describeFallback(params.rpcId);
40436
- }
40437
- throw deniedMethod(params.method);
40438
- }
40439
- const startedAt = performance.now();
40440
- const request = { rpcId: params.rpcId, payload: params.payload };
40441
- try {
40442
- const callWithTimeout = (overridePayload) => withTimeout(
40443
- method({ rpcId: params.rpcId, payload: overridePayload }, signal),
40444
- NATIVE_CALL_TIMEOUT_MS,
40445
- `Harness API call ${params.method} timed out after ${NATIVE_CALL_TIMEOUT_MS}ms`
40446
- );
40447
- let response;
40448
- if (params.method === "session.history") {
40449
- response = await callSessionHistory(async (payload) => {
40450
- const result = await callWithTimeout(payload);
40451
- return this.compactHistoryEnabled ? { ...result, result: compactHistory(result.result) } : result;
40452
- }, params.payload, params.rpcId);
40453
- } else {
40454
- response = await callWithTimeout(request.payload);
40455
- }
40456
- if (params.method === "host.listDirectory" && needsRemoteDirectoryFallback(response)) {
40457
- response = await this.callDirectoryFallback(params, signal);
40458
- }
40459
- if (params.method === "host.describe") {
40460
- response = normalizeHostDescribe(response, this.harnessVersion, true);
40461
- }
40462
- this.logger?.debug("harness api call ok", {
40463
- method: params.method,
40464
- durationMs: Math.round(performance.now() - startedAt)
40465
- });
40466
- return this.compactHistoryEnabled && params.method === "subagent.history" ? { ...response, result: compactHistory(response.result) } : response;
40467
- } catch (error) {
40468
- const durationMs = Math.round(performance.now() - startedAt);
40469
- this.logger?.warn("harness api call failed", {
40470
- method: params.method,
40471
- durationMs,
40472
- timedOut: signal.aborted,
40473
- code: safeErrorCode(error)
40474
- });
40475
- throw error;
40476
- }
40477
- }
40478
- async callDirectoryFallback(params, signal) {
40479
- const payload = directoryListSchema.parse(params.payload);
40480
- const value = await listRemoteDirectory(payload.path, signal);
40481
- return { rpcId: params.rpcId, result: { ok: true, value } };
40482
- }
40483
- describeFallback(rpcId2) {
40484
- return {
40485
- rpcId: rpcId2,
40486
- result: {
40487
- ok: true,
40488
- value: {
40489
- version: this.harnessVersion ?? "0.0.1",
40490
- cwd: "",
40491
- home: "",
40492
- attachedSessions: 0,
40493
- canOpenPath: true
40494
- }
40495
- }
40496
- };
40497
- }
40498
- openTransfer(input3) {
40499
- this.pruneTransfers();
40500
- const params = transferOpenSchema3.parse(input3);
40501
- if (params.totalChunks !== Math.ceil(params.totalBytes / HARNESS_API_TRANSFER_CHUNK_BYTES)) {
40502
- throw new RpcError("INVALID_MESSAGE", "The Harness API transfer chunk count is invalid.");
40503
- }
40504
- if (this.incomingTransfers.has(params.transferId) || this.outgoingTransfers.has(params.transferId)) {
40505
- throw new RpcError("REQUEST_CONFLICT", "The Harness API transfer id is already active.");
40506
- }
40507
- if (this.incomingTransfers.size >= MAX_ACTIVE_API_TRANSFERS) {
40508
- throw new RpcError("RATE_LIMITED", "Too many Harness API transfers are active.", void 0, true);
40509
- }
40510
- this.incomingTransfers.set(params.transferId, {
40511
- totalBytes: params.totalBytes,
40512
- totalChunks: params.totalChunks,
40513
- chunks: [],
40514
- receivedBytes: 0,
40515
- touchedAt: Date.now()
40516
- });
40517
- return { opened: true, transferId: params.transferId };
40518
- }
40519
- appendTransfer(input3) {
40520
- this.pruneTransfers();
40521
- const params = transferChunkSchema3.parse(input3);
40522
- const transfer = this.incomingTransfers.get(params.transferId);
40523
- if (transfer === void 0) throw new RpcError("TRANSFER_NOT_FOUND", "The Harness API transfer is not active.");
40524
- if (params.index !== transfer.chunks.length || params.index >= transfer.totalChunks) {
40525
- this.incomingTransfers.delete(params.transferId);
40526
- throw new RpcError("INVALID_MESSAGE", "Harness API transfer chunks must arrive exactly once and in order.");
40527
- }
40528
- let chunk;
40529
- try {
40530
- chunk = decodeCanonicalBase643(params.data);
40531
- } catch (error) {
40532
- this.incomingTransfers.delete(params.transferId);
40533
- throw error;
40534
- }
40535
- const expectedBytes = Math.min(
40536
- HARNESS_API_TRANSFER_CHUNK_BYTES,
40537
- transfer.totalBytes - params.index * HARNESS_API_TRANSFER_CHUNK_BYTES
40538
- );
40539
- if (chunk.byteLength !== expectedBytes) {
40540
- this.incomingTransfers.delete(params.transferId);
40541
- throw new RpcError("INVALID_MESSAGE", "The Harness API transfer chunk size is invalid.");
40542
- }
40543
- transfer.chunks.push(chunk);
40544
- transfer.receivedBytes += chunk.byteLength;
40545
- transfer.touchedAt = Date.now();
40546
- return { accepted: true, transferId: params.transferId, index: params.index };
40547
- }
40548
- async commitTransfer(input3) {
40549
- this.pruneTransfers();
40550
- const params = transferCommitSchema.parse(input3);
40551
- const transfer = this.incomingTransfers.get(params.transferId);
40552
- if (transfer === void 0) throw new RpcError("TRANSFER_NOT_FOUND", "The Harness API transfer is not active.");
40553
- this.incomingTransfers.delete(params.transferId);
40554
- if (transfer.chunks.length !== transfer.totalChunks || transfer.receivedBytes !== transfer.totalBytes) {
40555
- throw new RpcError("INVALID_MESSAGE", "The Harness API transfer is incomplete.");
40556
- }
40557
- let request;
40558
- try {
40559
- const bytes = concatChunks3(transfer.chunks, transfer.totalBytes);
40560
- request = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
40561
- } catch {
40562
- throw new RpcError("INVALID_MESSAGE", "The Harness API transfer does not contain a valid request.");
40563
- }
40564
- const nativeRequest = callSchema3.parse(request);
40565
- const response = await this.call(nativeRequest);
40566
- const responseBytes = new TextEncoder().encode(JSON.stringify(response));
40567
- if (responseBytes.byteLength <= INLINE_TRANSFER_RESPONSE_BYTES3) {
40568
- return { kind: "inline", response };
40569
- }
40570
- if (responseBytes.byteLength > MAX_HARNESS_API_TRANSFER_BYTES) {
40571
- throw new RpcError("RESPONSE_TOO_LARGE", "The Harness API response exceeds the bounded transfer limit.");
40572
- }
40573
- this.pruneTransfers();
40574
- if (this.outgoingTransfers.size >= MAX_ACTIVE_API_TRANSFERS) {
40575
- throw new RpcError("RATE_LIMITED", "Too many Harness API response transfers are active.", void 0, true);
40576
- }
40577
- const totalChunks = Math.ceil(responseBytes.byteLength / HARNESS_API_TRANSFER_CHUNK_BYTES);
40578
- this.outgoingTransfers.set(params.transferId, {
40579
- bytes: responseBytes,
40580
- totalChunks,
40581
- nextIndex: 0,
40582
- touchedAt: Date.now()
40583
- });
40584
- return { kind: "chunked", transferId: params.transferId, totalBytes: responseBytes.byteLength, totalChunks };
40585
- }
40586
- readTransfer(input3) {
40587
- this.pruneTransfers();
40588
- const params = transferReadSchema3.parse(input3);
40589
- const transfer = this.outgoingTransfers.get(params.transferId);
40590
- if (transfer === void 0) throw new RpcError("TRANSFER_NOT_FOUND", "The Harness API response transfer is not active.");
40591
- if (params.index !== transfer.nextIndex || params.index >= transfer.totalChunks) {
40592
- this.outgoingTransfers.delete(params.transferId);
40593
- throw new RpcError("INVALID_MESSAGE", "Harness API response chunks must be read exactly once and in order.");
40594
- }
40595
- const start = params.index * HARNESS_API_TRANSFER_CHUNK_BYTES;
40596
- const end = Math.min(start + HARNESS_API_TRANSFER_CHUNK_BYTES, transfer.bytes.byteLength);
40597
- transfer.nextIndex += 1;
40598
- transfer.touchedAt = Date.now();
40599
- return {
40600
- transferId: params.transferId,
40601
- index: params.index,
40602
- data: Buffer.from(transfer.bytes.subarray(start, end)).toString("base64")
40603
- };
40604
- }
40605
- closeTransfer(input3) {
40606
- const params = transferCloseSchema.parse(input3);
40607
- const incoming = this.incomingTransfers.delete(params.transferId);
40608
- const outgoing = this.outgoingTransfers.delete(params.transferId);
40609
- return { closed: incoming || outgoing, transferId: params.transferId };
40610
- }
40611
- async respond(input3) {
40612
- const params = respondSchema.parse(input3);
40613
- this.logger?.debug("harness api respond", { rpcId: shortId4(params.message.rpcId) });
40614
- if (!this.respondable.has(params.message.rpcId)) {
40615
- throw new RpcError("PERMISSION_NOT_PENDING", "The response id was not emitted on this peer connection.");
40616
- }
40617
- const receipt = await this.answer(params.message);
40618
- if (receipt.accepted || receipt.reason === "not-pending") this.respondable.delete(params.message.rpcId);
40619
- return receipt;
40620
- }
40621
- openStream(input3) {
40622
- const params = streamOpenSchema3.parse(input3);
40623
- if (this.streams.has(params.streamId)) throw new RpcError("REQUEST_CONFLICT", "The Harness event stream is already open.");
40624
- if (this.streams.size >= this.maxStreams) throw new RpcError("RATE_LIMITED", "Too many Harness event streams are open.", void 0, true);
40625
- const controller = new AbortController();
40626
- const request = { rpcId: params.rpcId, payload: params.payload };
40627
- const stream = params.stream === "mux" ? this.mux(request, controller.signal) : this.host(request, controller.signal);
40628
- const focusSessionId = params.stream === "mux" ? params.payload.sessionId : void 0;
40629
- const task = this.pump(params.streamId, stream, controller.signal, focusSessionId);
40630
- this.streams.set(params.streamId, { controller, task, ...focusSessionId === void 0 ? {} : { focusSessionId } });
40631
- this.logger?.debug("harness api stream open", {
40632
- stream: params.stream,
40633
- streamId: shortId4(params.streamId),
40634
- ...focusSessionId === void 0 ? {} : { focusSessionId: shortId4(focusSessionId) }
40635
- });
40636
- return { opened: true, streamId: params.streamId };
40637
- }
40638
- closeStream(input3) {
40639
- const params = streamCloseSchema3.parse(input3);
40640
- const active = this.streams.get(params.streamId);
40641
- if (active !== void 0) {
40642
- this.streams.delete(params.streamId);
40643
- active.controller.abort();
40644
- }
40645
- this.logger?.debug("harness api stream close", { streamId: shortId4(params.streamId), closed: active !== void 0 });
40646
- return { closed: active !== void 0, streamId: params.streamId };
40647
- }
40648
- async closeAll(reason = "peer-disconnected") {
40649
- const streams = [...this.streams.values()];
40650
- this.streams.clear();
40651
- this.respondable.clear();
40652
- this.incomingTransfers.clear();
40653
- this.outgoingTransfers.clear();
40654
- for (const stream of streams) stream.controller.abort(reason);
40655
- }
40656
- pruneTransfers() {
40657
- const cutoff = Date.now() - API_TRANSFER_IDLE_MS;
40658
- for (const [transferId, transfer] of this.incomingTransfers) {
40659
- if (transfer.touchedAt < cutoff) this.incomingTransfers.delete(transferId);
40660
- }
40661
- for (const [transferId, transfer] of this.outgoingTransfers) {
40662
- if (transfer.touchedAt < cutoff) this.outgoingTransfers.delete(transferId);
40663
- }
40664
- }
40665
- async pump(streamId, stream, signal, focusSessionId) {
40666
- let reason = "completed";
40667
- try {
40668
- for await (const frame of stream) {
40669
- if (signal.aborted) break;
40670
- if (focusSessionId !== void 0 && frameSessionId(frame) !== void 0 && frameSessionId(frame) !== focusSessionId) {
40671
- continue;
40672
- }
40673
- this.trackRespondable(frame);
40674
- const data2 = { streamId, frame };
40675
- if (encodeMessage(createEvent("harness.api.frame", data2)).byteLength > MAX_SECURE_MESSAGE_BYTES) {
40676
- throw new Error("Oversized Harness API frame");
40677
- }
40678
- await this.publish("harness.api.frame", data2);
40679
- }
40680
- if (signal.aborted) reason = "cancelled";
40681
- } catch {
40682
- reason = signal.aborted ? "cancelled" : "failed";
40683
- } finally {
40684
- this.streams.delete(streamId);
40685
- await this.publish("harness.api.stream.closed", { streamId, reason }).catch(() => void 0);
40686
- }
40687
- }
40688
- trackRespondable(frame) {
40689
- const payload = frame.payload;
40690
- if (payload.type === "approval/requested") {
40691
- this.respondable.set(String(frame.rpcId), `approval:${String(payload.approvalId)}`);
40692
- return;
40693
- }
40694
- if (payload.type === "question/requested") {
40695
- this.respondable.set(String(frame.rpcId), `question:${String(frame.rpcId)}`);
40696
- return;
40697
- }
40698
- if (payload.type === "approval/resolved") {
40699
- this.deleteRespondable(`approval:${String(payload.approvalId)}`);
40700
- return;
40701
- }
40702
- if (payload.type === "question/resolved") {
40703
- this.respondable.delete(String(payload.questionRpcId));
40704
- }
40705
- }
40706
- deleteRespondable(value) {
40707
- for (const [rpcId2, correlation] of this.respondable) {
40708
- if (correlation === value) this.respondable.delete(rpcId2);
40709
- }
40710
- }
40711
- };
40712
- function needsRemoteDirectoryFallback(response) {
40713
- const result = response.result;
40714
- return typeof result === "object" && result !== null && "ok" in result && result.ok === false && "error" in result && typeof result.error === "object" && result.error !== null && "code" in result.error && result.error.code === "directory-picker-unavailable";
40715
- }
40716
- function normalizeHostDescribe(response, harnessVersion, canListDirectory) {
40717
- if (!response.result.ok) return response;
40718
- const value = response.result.value;
40719
- if (typeof value !== "object" || value === null || Array.isArray(value)) return response;
40720
- const description = value;
40721
- const selectedVersion = selectHarnessVersion(
40722
- normalizeHarnessVersion(description.version),
40723
- harnessVersion
40724
- );
40725
- const versionChanged = selectedVersion !== void 0 && description.version !== selectedVersion;
40726
- const canOpenPathChanged = canListDirectory && description.canOpenPath !== true;
40727
- if (!versionChanged && !canOpenPathChanged) return response;
40728
- const normalized = {
40729
- ...description,
40730
- ...versionChanged ? { version: selectedVersion } : {},
40731
- ...canOpenPathChanged ? { canOpenPath: true } : {}
40732
- };
40733
- return {
40734
- ...response,
40735
- result: {
40736
- ...response.result,
40737
- value: normalized
40738
- }
40739
- };
40740
- }
40741
- function createMethodMap(api, typertGateway, harnessVersion) {
40742
- const domains = api;
40743
- const methods = /* @__PURE__ */ new Map();
40744
- for (const method of HARNESS_API_ALLOWLIST) {
40745
- if (method === "commands.execute" || method === "commands.list") {
40746
- if (typertGateway === void 0) continue;
40747
- const [namespace, commandMethod] = method.split(".");
40748
- const implementation2 = async (request, signal) => {
40749
- if (commandMethod === "execute") {
40750
- const payload = commandExecuteSchema.parse(request.payload);
40751
- const legacyArgs = {
40752
- agentId: payload.agentId,
40753
- line: payload.line,
40754
- images: payload.images ?? []
40755
- };
40756
- const currentArgs = {
40757
- agentId: payload.agentId,
40758
- line: payload.line,
40759
- submittedAttachments: payload.submittedAttachments ?? []
40760
- };
40761
- const args2 = harnessSessionGeneration(harnessVersion) === "v3" ? currentArgs : legacyArgs;
40762
- const value2 = await typertGateway.invoke({
40763
- namespace,
40764
- method: "execute",
40765
- args: args2,
40766
- ...signal === void 0 ? {} : { signal }
40767
- });
40768
- return { rpcId: request.rpcId, result: { ok: true, value: value2 } };
40769
- }
40770
- const args = commandListSchema.parse(request.payload);
40771
- const value = await typertGateway.invoke({
40772
- namespace,
40773
- method: "list",
40774
- args,
40775
- ...signal === void 0 ? {} : { signal }
40776
- });
40777
- return { rpcId: request.rpcId, result: { ok: true, value } };
40778
- };
40779
- methods.set(method, implementation2);
40780
- continue;
40781
- }
40782
- const [wireDomain, action] = method.split(".");
40783
- const domain = domainProperty(wireDomain);
40784
- const implementation = domains[domain]?.[action];
40785
- if (typeof implementation !== "function") continue;
40786
- const scoped = CONFIG_PLANE_METHODS.includes(method) ? scopeConfigPlaneMethod(api, method, implementation) : void 0;
40787
- methods.set(method, scoped ?? implementation.bind(domains[domain]));
40788
- }
40789
- return methods;
40790
- }
40791
- function domainProperty(wireDomain) {
40792
- if (wireDomain === "session") return "sessions";
40793
- if (wireDomain === "subagent") return "subagents";
40794
- if (wireDomain === "skill") return "skills";
40795
- if (wireDomain === "agentPreset") return "agentPresets";
40796
- if (wireDomain === "goal") return "goals";
40797
- return wireDomain;
40798
- }
40799
- var CONFIG_PLANE_METHODS = [
40800
- "llm.discoverModels",
40801
- "settings.describe",
40802
- "settings.update",
40803
- "settings.replace",
40804
- "settings.mutate",
40805
- "credentials.describe",
40806
- "credentials.set",
40807
- "credentials.unset"
40808
- ];
40809
- function scopeConfigPlaneMethod(api, method, native) {
40810
- switch (method) {
40811
- case "llm.discoverModels":
40812
- return async (request, signal) => {
40813
- const payload = parseConfigPlane(discoverModelsSchema, request.payload, "llm.discoverModels");
40814
- if (payload.baseURL !== void 0) validateDiscoverBaseUrl(payload.baseURL);
40815
- try {
40816
- const response = await native({ rpcId: request.rpcId, payload }, signal);
40817
- return sanitizeModelDiscoveryResponse(response, payload.settingsNs);
40818
- } catch {
40819
- return modelDiscoveryFailure(request.rpcId, payload.settingsNs);
40820
- }
40821
- };
40822
- case "settings.describe":
40823
- return async (request, signal) => {
40824
- parseConfigPlane(settingsDescribeSchema, request.payload, "settings.describe");
40825
- const response = await native({ rpcId: request.rpcId, payload: {} }, signal);
40826
- return disableRemoteSettingsDocument(response);
40827
- };
40828
- case "settings.update":
40829
- return async (request, signal) => {
40830
- const payload = parseConfigPlane(settingsUpdateSchema, request.payload, "settings.update");
40831
- await assertRegisteredSettingsNamespace(api, payload.ns);
40832
- assertSerializedBytes(payload.patch, CONFIG_PLANE_SETTINGS_BYTES, "settings.update patch");
40833
- return native({ rpcId: request.rpcId, payload }, signal);
40834
- };
40835
- case "settings.replace":
40836
- return async (request, signal) => {
40837
- const payload = parseConfigPlane(settingsReplaceSchema, request.payload, "settings.replace");
40838
- await assertRegisteredSettingsNamespace(api, payload.ns);
40839
- assertSerializedBytes(payload.section, CONFIG_PLANE_SETTINGS_BYTES, "settings.replace section");
40840
- return native({ rpcId: request.rpcId, payload }, signal);
40841
- };
40842
- case "settings.mutate":
40843
- return async (request, signal) => {
40844
- const payload = parseConfigPlane(settingsMutateSchema, request.payload, "settings.mutate");
40845
- await assertRegisteredSettingsNamespace(api, payload.ns);
40846
- assertSerializedBytes(payload.ops, CONFIG_PLANE_SETTINGS_BYTES, "settings.mutate ops");
40847
- return native({ rpcId: request.rpcId, payload }, signal);
40848
- };
40849
- case "credentials.describe":
40850
- return async (request, signal) => {
40851
- const payload = parseConfigPlane(credentialsDescribeSchema, request.payload, "credentials.describe");
40852
- return native({ rpcId: request.rpcId, payload }, signal);
40853
- };
40854
- case "credentials.set":
40855
- return async (request, signal) => {
40856
- const payload = parseConfigPlane(credentialsSetSchema, request.payload, "credentials.set");
40857
- return native({ rpcId: request.rpcId, payload }, signal);
40858
- };
40859
- case "credentials.unset":
40860
- return async (request, signal) => {
40861
- const payload = parseConfigPlane(credentialsUnsetSchema, request.payload, "credentials.unset");
40862
- return native({ rpcId: request.rpcId, payload }, signal);
40863
- };
40864
- }
40865
- }
40866
- function parseConfigPlane(schema, payload, label) {
40867
- try {
40868
- return schema.parse(payload);
40869
- } catch (error) {
40870
- if (error instanceof external_exports.ZodError) {
40871
- throw new RpcError("INVALID_MESSAGE", `The ${label} payload is invalid for the remote channel.`);
40872
- }
40873
- throw error;
40874
- }
40875
- }
40876
- function validateDiscoverBaseUrl(value) {
40877
- let url;
40878
- try {
40879
- url = new URL(value);
40880
- } catch {
40881
- throw new RpcError("INVALID_MESSAGE", "The model discovery baseURL is invalid.");
40882
- }
40883
- const local = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1";
40884
- if (url.protocol !== "https:" && !(local && url.protocol === "http:")) {
40885
- throw new RpcError("INVALID_MESSAGE", "The model discovery baseURL must use HTTPS (HTTP is allowed only for localhost).");
40886
- }
40887
- if (url.username !== "" || url.password !== "") {
40888
- throw new RpcError("INVALID_MESSAGE", "The model discovery baseURL must not contain credentials.");
40889
- }
40890
- if (url.hash !== "") {
40891
- throw new RpcError("INVALID_MESSAGE", "The model discovery baseURL must not contain a fragment.");
40892
- }
40893
- }
40894
- function assertSerializedBytes(value, maxBytes, label) {
40895
- const bytes = new TextEncoder().encode(JSON.stringify(value)).byteLength;
40896
- if (bytes > maxBytes) {
40897
- throw new RpcError("INVALID_MESSAGE", `The ${label} exceeds the ${maxBytes}-byte remote limit.`);
40898
- }
40899
- }
40900
- function sanitizeModelDiscoveryResponse(response, settingsNs) {
40901
- const result = response.result;
40902
- if (typeof result === "object" && result !== null && "ok" in result && result.ok === true) return response;
40903
- return modelDiscoveryFailure(response.rpcId, settingsNs);
40904
- }
40905
- function modelDiscoveryFailure(rpcId2, settingsNs) {
40906
- return {
40907
- rpcId: rpcId2,
40908
- result: {
40909
- ok: false,
40910
- error: {
40911
- code: "model-discovery-failed",
40912
- message: "Model discovery failed.",
40913
- details: { settingsNs }
40914
- }
40915
- }
40916
- };
40917
- }
40918
- function disableRemoteSettingsDocument(response) {
40919
- const result = response.result;
40920
- if (typeof result !== "object" || result === null || !("ok" in result) || result.ok !== true) return response;
40921
- const value = result.value;
40922
- if (typeof value !== "object" || value === null) return response;
40923
- return { ...response, result: { ...result, value: { ...value, hasDocument: false } } };
40924
- }
40925
- var EMPTY_SETTINGS_NAMESPACES = /* @__PURE__ */ new Set();
40926
- async function assertRegisteredSettingsNamespace(api, ns) {
40927
- if (ns === "ds-harness-remote" || ns === "dsh-remote") {
40928
- throw new RpcError("PERMISSION_DENIED", "Remote access settings can only be changed locally on the Host.");
40929
- }
40930
- const allowed = await registeredSettingsNamespaces(api);
40931
- if (!allowed.has(ns)) throw deniedSettingsNamespace(ns);
40932
- }
40933
- async function registeredSettingsNamespaces(api) {
40934
- const settings = api.settings;
40935
- const describe = settings?.describe;
40936
- if (typeof describe !== "function") return EMPTY_SETTINGS_NAMESPACES;
40937
- const response = await withTimeout(
40938
- describe.call(settings, { rpcId: "bridge-settings-scope", payload: {} }, AbortSignal.timeout(NATIVE_CALL_TIMEOUT_MS)),
40939
- NATIVE_CALL_TIMEOUT_MS,
40940
- "The Host settings.describe call timed out."
40941
- );
40942
- const value = unwrapNativeValue(response, "settings.describe");
40943
- const list = typeof value === "object" && value !== null ? value.namespaces : void 0;
40944
- if (!Array.isArray(list)) return EMPTY_SETTINGS_NAMESPACES;
40945
- const namespaces = /* @__PURE__ */ new Set();
40946
- for (const item of list) {
40947
- if (typeof item !== "object" || item === null) continue;
40948
- const ns = item.ns;
40949
- if (typeof ns === "string" && ns.length > 0) namespaces.add(ns);
40950
- }
40951
- return namespaces;
40952
- }
40953
- function unwrapNativeValue(response, method) {
40954
- const result = response.result;
40955
- if (typeof result !== "object" || result === null || !("ok" in result) || result.ok !== true || !("value" in result)) {
40956
- throw new RpcError("INTERNAL_ERROR", `The Host ${method} call did not succeed.`);
40957
- }
40958
- return result.value;
40959
- }
40960
- function deniedSettingsNamespace(ns) {
40961
- return new RpcError("METHOD_NOT_ALLOWED", `Harness settings namespace ${JSON.stringify(ns)} is not registered on the Host.`);
40962
- }
40963
- function deniedMethod(method) {
40964
- return new RpcError("METHOD_NOT_ALLOWED", `Harness API method ${JSON.stringify(method)} is not available in remote mode.`);
40965
- }
40966
- function frameSessionId(frame) {
40967
- const payload = frame.payload;
40968
- return typeof payload.sessionId === "string" && payload.sessionId.length > 0 ? payload.sessionId : void 0;
40969
- }
40970
- function withTimeout(promise, ms, message) {
40971
- return new Promise((resolve6, reject) => {
40972
- const timer = setTimeout(() => {
40973
- reject(new RpcError("TIMEOUT", message, void 0, true));
40974
- }, ms);
40975
- timer.unref?.();
40976
- promise.then(
40977
- (value) => {
40978
- clearTimeout(timer);
40979
- resolve6(value);
40980
- },
40981
- (error) => {
40982
- clearTimeout(timer);
40983
- reject(error);
40984
- }
40985
- );
40986
- });
40987
- }
40988
- function shortId4(value) {
40989
- return value.length <= 12 ? value : `${value.slice(0, 8)}\u2026${value.slice(-4)}`;
40990
- }
40991
- function decodeCanonicalBase643(value) {
40992
- const bytes = Buffer.from(value, "base64");
40993
- if (bytes.toString("base64") !== value) {
40994
- throw new RpcError("INVALID_MESSAGE", "The Harness API transfer chunk is not canonical base64.");
40995
- }
40996
- return bytes;
40997
- }
40998
- function concatChunks3(chunks, totalBytes) {
40999
- const result = new Uint8Array(totalBytes);
41000
- let offset = 0;
41001
- for (const chunk of chunks) {
41002
- result.set(chunk, offset);
41003
- offset += chunk.byteLength;
41004
- }
41005
- return result;
41006
- }
41007
-
41008
39293
  // src/harness-remote-bridge.ts
41009
39294
  var endpointSchema = external_exports.string().min(1).max(128).regex(/^(?:\$events(?:\/result)?|[A-Za-z0-9_$.-]+\/[A-Za-z0-9_$.-]+)$/);
41010
- var callSchema4 = external_exports.object({ endpoint: endpointSchema, payload: external_exports.unknown() }).strict();
41011
- var streamOpenSchema4 = external_exports.object({
39295
+ var callSchema3 = external_exports.object({ endpoint: endpointSchema, payload: external_exports.unknown() }).strict();
39296
+ var streamOpenSchema3 = external_exports.object({
41012
39297
  streamId: external_exports.string().min(1).max(128),
41013
39298
  endpoint: endpointSchema,
41014
- payload: external_exports.unknown()
39299
+ payload: external_exports.unknown(),
39300
+ transferFrames: external_exports.boolean().optional()
41015
39301
  }).strict();
41016
- var streamCloseSchema4 = external_exports.object({ streamId: external_exports.string().min(1).max(128) }).strict();
39302
+ var streamCloseSchema3 = external_exports.object({ streamId: external_exports.string().min(1).max(128) }).strict();
41017
39303
  var commandExecuteArgsSchema = external_exports.object({
41018
39304
  agentId: external_exports.string().min(1).max(128),
41019
39305
  line: external_exports.string().min(1).max(2048),
@@ -41032,27 +39318,27 @@ var commandExecuteArgsSchema = external_exports.object({
41032
39318
  }
41033
39319
  });
41034
39320
  var commandExecutePayloadSchema = external_exports.object({ args: commandExecuteArgsSchema }).strict();
41035
- var transferOpenSchema4 = external_exports.object({
39321
+ var transferOpenSchema3 = external_exports.object({
41036
39322
  transferId: external_exports.string().uuid(),
41037
39323
  totalBytes: external_exports.number().int().positive().max(MAX_HARNESS_API_TRANSFER_BYTES),
41038
39324
  totalChunks: external_exports.number().int().positive()
41039
39325
  }).strict();
41040
- var transferChunkSchema4 = external_exports.object({
39326
+ var transferChunkSchema3 = external_exports.object({
41041
39327
  transferId: external_exports.string().uuid(),
41042
39328
  index: external_exports.number().int().nonnegative(),
41043
39329
  data: external_exports.string().min(1)
41044
39330
  }).strict();
41045
- var transferIdSchema4 = external_exports.object({ transferId: external_exports.string().uuid() }).strict();
41046
- var transferReadSchema4 = external_exports.object({
39331
+ var transferIdSchema3 = external_exports.object({ transferId: external_exports.string().uuid() }).strict();
39332
+ var transferReadSchema3 = external_exports.object({
41047
39333
  transferId: external_exports.string().uuid(),
41048
39334
  index: external_exports.number().int().nonnegative()
41049
39335
  }).strict();
41050
- var directoryListSchema2 = external_exports.object({
39336
+ var directoryListSchema = external_exports.object({
41051
39337
  path: external_exports.string().min(1).max(4096).optional()
41052
39338
  }).strict();
41053
39339
  var MAX_ACTIVE_STREAMS3 = MAX_ALPHA_STREAMS_PER_CONNECTION;
41054
39340
  var MAX_ACTIVE_TRANSFERS3 = MAX_ACTIVE_TRANSFERS_PER_DIRECTION;
41055
- var INLINE_TRANSFER_RESPONSE_BYTES4 = 2 * 1024 * 1024;
39341
+ var INLINE_TRANSFER_RESPONSE_BYTES3 = 2 * 1024 * 1024;
41056
39342
  var HARNESS_REMOTE_ALLOWLIST = [
41057
39343
  "$events",
41058
39344
  "$events/result",
@@ -41161,7 +39447,7 @@ var HarnessRemoteBridge = class {
41161
39447
  outgoingTransfers = /* @__PURE__ */ new Map();
41162
39448
  terminalCarrier;
41163
39449
  async call(input3) {
41164
- const params = callSchema4.parse(input3);
39450
+ const params = callSchema3.parse(input3);
41165
39451
  this.assertAllowed(params.endpoint);
41166
39452
  if (TERMINAL_STREAMS.has(params.endpoint)) throw new RpcError("METHOD_NOT_ALLOWED", "Use a stream for this terminal endpoint.");
41167
39453
  if (["settings/update", "settings/replace", "settings/mutate"].includes(params.endpoint)) {
@@ -41228,12 +39514,12 @@ var HarnessRemoteBridge = class {
41228
39514
  }
41229
39515
  async directoryList(payload, signal) {
41230
39516
  const args = requestArgs(payload);
41231
- const params = directoryListSchema2.parse(args);
39517
+ const params = directoryListSchema.parse(args);
41232
39518
  return { ok: true, value: await listRemoteDirectory(params.path, signal) };
41233
39519
  }
41234
39520
  openTransfer(input3) {
41235
39521
  this.pruneTransfers();
41236
- const params = transferOpenSchema4.parse(input3);
39522
+ const params = transferOpenSchema3.parse(input3);
41237
39523
  if (params.totalChunks !== Math.ceil(params.totalBytes / HARNESS_API_TRANSFER_CHUNK_BYTES)) {
41238
39524
  throw new RpcError("INVALID_MESSAGE", "The Harness Remote transfer chunk count is invalid.");
41239
39525
  }
@@ -41254,14 +39540,14 @@ var HarnessRemoteBridge = class {
41254
39540
  }
41255
39541
  appendTransfer(input3) {
41256
39542
  this.pruneTransfers();
41257
- const params = transferChunkSchema4.parse(input3);
39543
+ const params = transferChunkSchema3.parse(input3);
41258
39544
  const transfer = this.incomingTransfers.get(params.transferId);
41259
39545
  if (transfer === void 0) throw new RpcError("TRANSFER_NOT_FOUND", "The Harness Remote transfer is not active.");
41260
39546
  if (params.index !== transfer.chunks.length || params.index >= transfer.totalChunks) {
41261
39547
  this.incomingTransfers.delete(params.transferId);
41262
39548
  throw new RpcError("INVALID_MESSAGE", "Harness Remote transfer chunks must arrive exactly once and in order.");
41263
39549
  }
41264
- const chunk = decodeCanonicalBase644(params.data);
39550
+ const chunk = decodeCanonicalBase643(params.data);
41265
39551
  const expectedBytes = Math.min(
41266
39552
  HARNESS_API_TRANSFER_CHUNK_BYTES,
41267
39553
  transfer.totalBytes - params.index * HARNESS_API_TRANSFER_CHUNK_BYTES
@@ -41277,7 +39563,7 @@ var HarnessRemoteBridge = class {
41277
39563
  }
41278
39564
  async commitTransfer(input3) {
41279
39565
  this.pruneTransfers();
41280
- const params = transferIdSchema4.parse(input3);
39566
+ const params = transferIdSchema3.parse(input3);
41281
39567
  const transfer = this.incomingTransfers.get(params.transferId);
41282
39568
  if (transfer === void 0) throw new RpcError("TRANSFER_NOT_FOUND", "The Harness Remote transfer is not active.");
41283
39569
  this.incomingTransfers.delete(params.transferId);
@@ -41286,13 +39572,13 @@ var HarnessRemoteBridge = class {
41286
39572
  }
41287
39573
  let request;
41288
39574
  try {
41289
- request = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(concatChunks4(transfer.chunks, transfer.totalBytes)));
39575
+ request = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(concatChunks3(transfer.chunks, transfer.totalBytes)));
41290
39576
  } catch {
41291
39577
  throw new RpcError("INVALID_MESSAGE", "The Harness Remote transfer does not contain a valid request.");
41292
39578
  }
41293
- const response = await this.call(callSchema4.parse(request));
39579
+ const response = await this.call(callSchema3.parse(request));
41294
39580
  const responseBytes = new TextEncoder().encode(JSON.stringify(response));
41295
- if (responseBytes.byteLength <= INLINE_TRANSFER_RESPONSE_BYTES4) return { kind: "inline", response };
39581
+ if (responseBytes.byteLength <= INLINE_TRANSFER_RESPONSE_BYTES3) return { kind: "inline", response };
41296
39582
  if (responseBytes.byteLength > MAX_HARNESS_API_TRANSFER_BYTES) {
41297
39583
  throw new RpcError("RESPONSE_TOO_LARGE", "The Harness Remote response exceeds the bounded transfer limit.");
41298
39584
  }
@@ -41310,11 +39596,12 @@ var HarnessRemoteBridge = class {
41310
39596
  }
41311
39597
  readTransfer(input3) {
41312
39598
  this.pruneTransfers();
41313
- const params = transferReadSchema4.parse(input3);
39599
+ const params = transferReadSchema3.parse(input3);
41314
39600
  const transfer = this.outgoingTransfers.get(params.transferId);
41315
39601
  if (transfer === void 0) throw new RpcError("TRANSFER_NOT_FOUND", "The Harness Remote response transfer is not active.");
41316
39602
  if (params.index !== transfer.nextIndex || params.index >= transfer.totalChunks) {
41317
39603
  this.outgoingTransfers.delete(params.transferId);
39604
+ transfer.finish?.(new Error("Invalid Harness Remote stream transfer order"));
41318
39605
  throw new RpcError("INVALID_MESSAGE", "Harness Remote response chunks must be read exactly once and in order.");
41319
39606
  }
41320
39607
  const start = params.index * HARNESS_API_TRANSFER_CHUNK_BYTES;
@@ -41328,12 +39615,14 @@ var HarnessRemoteBridge = class {
41328
39615
  };
41329
39616
  }
41330
39617
  closeTransfer(input3) {
41331
- const params = transferIdSchema4.parse(input3);
39618
+ const params = transferIdSchema3.parse(input3);
39619
+ const transfer = this.outgoingTransfers.get(params.transferId);
39620
+ transfer?.finish?.(transfer.nextIndex === transfer.totalChunks ? void 0 : new Error("Incomplete Harness Remote stream transfer"));
41332
39621
  const closed = this.incomingTransfers.delete(params.transferId) || this.outgoingTransfers.delete(params.transferId);
41333
39622
  return { closed, transferId: params.transferId };
41334
39623
  }
41335
39624
  async openStream(input3) {
41336
- const params = streamOpenSchema4.parse(input3);
39625
+ const params = streamOpenSchema3.parse(input3);
41337
39626
  this.assertAllowed(params.endpoint);
41338
39627
  if (params.endpoint.startsWith("pluginManager/")) throw new RpcError("METHOD_NOT_ALLOWED", "Plugin management endpoints are not streams.");
41339
39628
  if (params.endpoint.startsWith("settings/")) throw new RpcError("METHOD_NOT_ALLOWED", "Settings endpoints are not streams.");
@@ -41354,11 +39643,11 @@ var HarnessRemoteBridge = class {
41354
39643
  controller.abort();
41355
39644
  throw error;
41356
39645
  }
41357
- void this.pump(params.streamId, source, controller.signal, params.endpoint === "session/follow");
39646
+ void this.pump(params.streamId, source, controller.signal, params.endpoint === "session/follow", params.transferFrames);
41358
39647
  return { opened: true, streamId: params.streamId };
41359
39648
  }
41360
39649
  closeStream(input3) {
41361
- const params = streamCloseSchema4.parse(input3);
39650
+ const params = streamCloseSchema3.parse(input3);
41362
39651
  const active = this.streams.get(params.streamId);
41363
39652
  if (active !== void 0) {
41364
39653
  this.streams.delete(params.streamId);
@@ -41386,10 +39675,10 @@ var HarnessRemoteBridge = class {
41386
39675
  const args = parsed.data.args;
41387
39676
  const result = await this.gateway.dispatch(plugin ? "pluginManager/listPlugins" : "pluginManager/listBundles", { args: {} }, AbortSignal.timeout(6e4));
41388
39677
  if (!result.ok || !Array.isArray(result.value)) throw new RpcError("PERMISSION_DENIED", "Cannot verify the Host plugin inventory.");
41389
- const row = result.value.find((value) => isRecord21(value) && value[plugin ? "entryId" : "name"] === args[key]);
41390
- if (!isRecord21(row) || row.readOnlyReason !== void 0) throw new RpcError("PERMISSION_DENIED", "The Host plugin cannot be changed remotely.");
39678
+ const row = result.value.find((value) => isRecord20(value) && value[plugin ? "entryId" : "name"] === args[key]);
39679
+ if (!isRecord20(row) || row.readOnlyReason !== void 0) throw new RpcError("PERMISSION_DENIED", "The Host plugin cannot be changed remotely.");
41391
39680
  const remoteModule = (value) => typeof value === "string" && /^(?:ds-harness-remote|dsh-remote)(?:\/|$)/.test(value);
41392
- if (remoteModule(plugin ? row.moduleName : row.name) || !plugin && (!Array.isArray(row.rows) || row.rows.some((value) => !isRecord21(value) || remoteModule(value.moduleName)) || Array.isArray(row.overrides) && row.overrides.some((value) => remoteModule(value) || value === "ds-harness-remote-tui"))) {
39681
+ if (remoteModule(plugin ? row.moduleName : row.name) || !plugin && (!Array.isArray(row.rows) || row.rows.some((value) => !isRecord20(value) || remoteModule(value.moduleName)) || Array.isArray(row.overrides) && row.overrides.some((value) => remoteModule(value) || value === "ds-harness-remote-tui"))) {
41393
39682
  throw new RpcError("PERMISSION_DENIED", "The Remote plugin can only be enabled or disabled locally on the Host.");
41394
39683
  }
41395
39684
  }
@@ -41401,7 +39690,7 @@ var HarnessRemoteBridge = class {
41401
39690
  throw new RpcError("FEATURE_NOT_SUPPORTED", "This Harness version does not support Remote event transport.");
41402
39691
  }
41403
39692
  }
41404
- async pump(streamId, source, signal, historyFollow = false) {
39693
+ async pump(streamId, source, signal, historyFollow = false, transferFrames = false) {
41405
39694
  let reason = "completed";
41406
39695
  let failure4;
41407
39696
  try {
@@ -41413,9 +39702,11 @@ var HarnessRemoteBridge = class {
41413
39702
  ...value === void 0 ? {} : { value: historyFollow && this.compactHistoryEnabled && isCompactSnapshot(value) ? compactHistory(value) : value }
41414
39703
  };
41415
39704
  if (encodeMessage(createEvent("harness.remote.frame", frame)).byteLength > MAX_SECURE_MESSAGE_BYTES) {
41416
- throw new Error("Oversized Harness Remote frame");
39705
+ if (!transferFrames) throw new Error("Oversized Harness Remote frame");
39706
+ await this.transferStreamFrame(frame, signal);
39707
+ } else {
39708
+ await this.publish("harness.remote.frame", frame);
41417
39709
  }
41418
- await this.publish("harness.remote.frame", frame);
41419
39710
  }
41420
39711
  if (signal.aborted) reason = "cancelled";
41421
39712
  } catch (error) {
@@ -41430,19 +39721,57 @@ var HarnessRemoteBridge = class {
41430
39721
  }).catch(() => void 0);
41431
39722
  }
41432
39723
  }
39724
+ /** Keep the source paused until the Client reads and releases this exact item. */
39725
+ async transferStreamFrame(frame, signal) {
39726
+ signal.throwIfAborted();
39727
+ this.pruneTransfers();
39728
+ const bytes = new TextEncoder().encode(JSON.stringify(frame));
39729
+ if (bytes.byteLength > MAX_HARNESS_API_TRANSFER_BYTES) throw new Error("Harness Remote stream item exceeds the bounded transfer limit");
39730
+ if (this.outgoingTransfers.size >= MAX_ACTIVE_TRANSFERS3) throw new Error("Too many Harness Remote response transfers are active");
39731
+ const transferId = randomUUID7();
39732
+ const totalChunks = Math.ceil(bytes.byteLength / HARNESS_API_TRANSFER_CHUNK_BYTES);
39733
+ let finish;
39734
+ const completed = new Promise((resolve6, reject) => {
39735
+ finish = (error) => error === void 0 ? resolve6() : reject(error);
39736
+ });
39737
+ void completed.catch(() => void 0);
39738
+ const transfer = { bytes, totalChunks, nextIndex: 0, touchedAt: Date.now(), finish };
39739
+ this.outgoingTransfers.set(transferId, transfer);
39740
+ const onAbort = () => finish(new Error("Harness Remote stream transfer cancelled"));
39741
+ signal.addEventListener("abort", onAbort, { once: true });
39742
+ const timer = setInterval(() => {
39743
+ if (Date.now() - transfer.touchedAt >= TRANSFER_IDLE_MS) finish(new Error("Harness Remote stream transfer timed out"));
39744
+ }, 1e3);
39745
+ timer.unref();
39746
+ try {
39747
+ await this.publish("harness.remote.frame", {
39748
+ streamId: frame.streamId,
39749
+ hasValue: true,
39750
+ transfer: { kind: "chunked", transferId, totalBytes: bytes.byteLength, totalChunks }
39751
+ });
39752
+ await completed;
39753
+ } finally {
39754
+ clearInterval(timer);
39755
+ signal.removeEventListener("abort", onAbort);
39756
+ this.outgoingTransfers.delete(transferId);
39757
+ }
39758
+ }
41433
39759
  pruneTransfers() {
41434
39760
  const cutoff = Date.now() - TRANSFER_IDLE_MS;
41435
39761
  for (const [id5, transfer] of this.incomingTransfers) if (transfer.touchedAt < cutoff) this.incomingTransfers.delete(id5);
41436
- for (const [id5, transfer] of this.outgoingTransfers) if (transfer.touchedAt < cutoff) this.outgoingTransfers.delete(id5);
39762
+ for (const [id5, transfer] of this.outgoingTransfers) if (transfer.touchedAt < cutoff) {
39763
+ this.outgoingTransfers.delete(id5);
39764
+ transfer.finish?.(new Error("Harness Remote stream transfer timed out"));
39765
+ }
41437
39766
  }
41438
39767
  };
41439
39768
  function normalizeWorkspaceChangesPayload(endpoint, payload, harnessVersion) {
41440
39769
  if (endpoint !== "workspaceFiles/changes" || !requiresWorkspaceChangePath(harnessVersion)) return payload;
41441
- if (!isRecord21(payload) || !isRecord21(payload.args) || Object.hasOwn(payload.args, "path")) return payload;
39770
+ if (!isRecord20(payload) || !isRecord20(payload.args) || Object.hasOwn(payload.args, "path")) return payload;
41442
39771
  return { ...payload, args: { ...payload.args, path: "." } };
41443
39772
  }
41444
39773
  function normalizeWorkspaceRequestPayload(endpoint, payload, harnessVersion) {
41445
- if (!isRecord21(payload) || !isRecord21(payload.args)) return payload;
39774
+ if (!isRecord20(payload) || !isRecord20(payload.args)) return payload;
41446
39775
  const args = payload.args;
41447
39776
  if (endpoint === "workspaceFiles/readBytes" && requiresWorkspaceChangePath(harnessVersion)) {
41448
39777
  if (!Object.hasOwn(args, "range") || Object.hasOwn(args, "options")) return payload;
@@ -41488,7 +39817,7 @@ async function dispatchCommandForHost(gateway, payload, signal, harnessVersion)
41488
39817
  signal
41489
39818
  );
41490
39819
  }
41491
- function decodeCanonicalBase644(value) {
39820
+ function decodeCanonicalBase643(value) {
41492
39821
  const bytes = Buffer.from(value, "base64");
41493
39822
  if (bytes.toString("base64") !== value) throw new RpcError("INVALID_MESSAGE", "The Harness Remote transfer chunk is invalid.");
41494
39823
  return bytes;
@@ -41523,7 +39852,7 @@ function isBinary(value) {
41523
39852
  function isJsonRecord(value) {
41524
39853
  return typeof value === "object" && value !== null && !Array.isArray(value);
41525
39854
  }
41526
- function concatChunks4(chunks, totalBytes) {
39855
+ function concatChunks3(chunks, totalBytes) {
41527
39856
  const result = new Uint8Array(totalBytes);
41528
39857
  let offset = 0;
41529
39858
  for (const chunk of chunks) {
@@ -41541,27 +39870,27 @@ function needsDirectoryFallback(result) {
41541
39870
  function filterRemotePluginInventory(endpoint, result) {
41542
39871
  if (!result.ok) return result;
41543
39872
  const isRemote = (value) => typeof value === "string" && /^(?:ds-harness-remote|dsh-remote)(?:\/|$)/.test(value);
41544
- const filterEntries = (entries) => entries.filter((entry) => !isRecord21(entry) || !isRemote(entry.moduleName));
39873
+ const filterEntries = (entries) => entries.filter((entry) => !isRecord20(entry) || !isRemote(entry.moduleName));
41545
39874
  if (endpoint === "pluginManager/listPlugins" && Array.isArray(result.value)) {
41546
39875
  return { ...result, value: filterEntries(result.value) };
41547
39876
  }
41548
39877
  if (endpoint === "pluginManager/listBundles" && Array.isArray(result.value)) {
41549
- return { ...result, value: result.value.filter((bundle) => !isRecord21(bundle) || !isRemote(bundle.name)).map((bundle) => isRecord21(bundle) && Array.isArray(bundle.rows) ? { ...bundle, rows: filterEntries(bundle.rows) } : bundle) };
39878
+ return { ...result, value: result.value.filter((bundle) => !isRecord20(bundle) || !isRemote(bundle.name)).map((bundle) => isRecord20(bundle) && Array.isArray(bundle.rows) ? { ...bundle, rows: filterEntries(bundle.rows) } : bundle) };
41550
39879
  }
41551
- if (endpoint === "pluginInventory/list" && isRecord21(result.value) && Array.isArray(result.value.entries)) {
39880
+ if (endpoint === "pluginInventory/list" && isRecord20(result.value) && Array.isArray(result.value.entries)) {
41552
39881
  return { ...result, value: { ...result.value, entries: filterEntries(result.value.entries) } };
41553
39882
  }
41554
39883
  return result;
41555
39884
  }
41556
39885
  function requestArgs(payload) {
41557
39886
  const root = record8(payload);
41558
- const args = isRecord21(root.args) ? root.args : root;
39887
+ const args = isRecord20(root.args) ? root.args : root;
41559
39888
  return record8(args.request ?? args._request ?? args);
41560
39889
  }
41561
39890
  function record8(value) {
41562
- return isRecord21(value) ? value : {};
39891
+ return isRecord20(value) ? value : {};
41563
39892
  }
41564
- function isRecord21(value) {
39893
+ function isRecord20(value) {
41565
39894
  return typeof value === "object" && value !== null && !Array.isArray(value);
41566
39895
  }
41567
39896
  function isCompactSnapshot(value) {
@@ -41591,10 +39920,9 @@ var CodexWorkspaceBridge = class extends WorkspaceBridge {
41591
39920
 
41592
39921
  // src/service.ts
41593
39922
  var HostPluginRuntime = class {
41594
- constructor(config, identities, apiProxy, logger, localGateway, fileViewerHost, terminalSpawner, pluginRoutes) {
39923
+ constructor(config, identities, logger, localGateway, fileViewerHost, terminalSpawner, pluginRoutes) {
41595
39924
  this.config = config;
41596
39925
  this.identities = identities;
41597
- this.apiProxy = apiProxy;
41598
39926
  this.logger = logger;
41599
39927
  this.localGateway = localGateway;
41600
39928
  this.fileViewerHost = fileViewerHost;
@@ -41606,14 +39934,6 @@ var HostPluginRuntime = class {
41606
39934
  this.acp = new AcpRemoteGateway(config.acp ?? { enabled: false, backends: [] }, logger, void 0, void 0, () => this.terminalEnabled, this.terminalSpawner);
41607
39935
  this.connections = new ConnectionController(this.identities, (context, send) => {
41608
39936
  const peerGateway = this.localGateway?.createPeer?.() ?? this.localGateway;
41609
- const harnessApi = this.apiProxy === void 0 ? void 0 : new HarnessApiBridge(
41610
- this.apiProxy,
41611
- (event, data2) => send(createEvent(event, data2)),
41612
- void 0,
41613
- this.logger,
41614
- peerGateway,
41615
- this.harnessVersion
41616
- );
41617
39937
  const harnessRemote = peerGateway?.supportsCarrier === true ? new HarnessRemoteBridge(
41618
39938
  peerGateway,
41619
39939
  (event, data2) => send(createEvent(event, data2)),
@@ -41642,7 +39962,6 @@ var HostPluginRuntime = class {
41642
39962
  const dispatcher = this.pluginRoutes?.(peerGateway?.peer);
41643
39963
  const pluginRoute = dispatcher === void 0 ? void 0 : new PluginRouteBridge(dispatcher, this.logger);
41644
39964
  return new RpcRouter(
41645
- harnessApi,
41646
39965
  void 0,
41647
39966
  this.logger,
41648
39967
  fileViewer,
@@ -41712,7 +40031,7 @@ var HostPluginRuntime = class {
41712
40031
  if (this.closed) throw new Error("remote runtime is closed");
41713
40032
  this.identity = await this.identities.loadOrCreate(this.config.deviceName);
41714
40033
  this.logger.info("host identity ready", {
41715
- deviceId: shortId5(this.identity.deviceId),
40034
+ deviceId: shortId4(this.identity.deviceId),
41716
40035
  fingerprint: this.identity.fingerprint,
41717
40036
  server: this.config.serverUrl ?? "not configured"
41718
40037
  });
@@ -41725,7 +40044,7 @@ var HostPluginRuntime = class {
41725
40044
  this.serverApi.setHarnessVersion(this.harnessVersion);
41726
40045
  this.serverApi.bindIdentity(this.identity);
41727
40046
  this.serverConnection = this.createServerConnection(this.identity);
41728
- this.serverConnection.start();
40047
+ if (this.config.hostControl?.enabled !== false) this.serverConnection.start();
41729
40048
  }
41730
40049
  }
41731
40050
  currentIdentity() {
@@ -41926,15 +40245,15 @@ var HostPluginRuntime = class {
41926
40245
  diagnostics() {
41927
40246
  return {
41928
40247
  loaded: this.identity !== void 0,
41929
- deviceId: this.identity === void 0 ? void 0 : shortId5(this.identity.deviceId),
40248
+ deviceId: this.identity === void 0 ? void 0 : shortId4(this.identity.deviceId),
41930
40249
  identityValid: this.identity !== void 0,
41931
40250
  serverConfigured: this.config.serverUrl !== void 0,
41932
40251
  serverOnline: this.serverConnection?.isOnline() ?? false,
41933
40252
  serverError: this.serverConnection?.lastError(),
41934
40253
  online: this.connections.isOnline(),
41935
40254
  activeConnections: this.connections.connectionCount(),
41936
- peerDeviceId: this.connections.peerDeviceId() === void 0 ? void 0 : shortId5(this.connections.peerDeviceId()),
41937
- peerDeviceIds: this.connections.peerDeviceIds().map(shortId5),
40255
+ peerDeviceId: this.connections.peerDeviceId() === void 0 ? void 0 : shortId4(this.connections.peerDeviceId()),
40256
+ peerDeviceIds: this.connections.peerDeviceIds().map(shortId4),
41938
40257
  trustedPeers: this.identities.listTrustedPeers().length,
41939
40258
  capabilities: this.hostCapabilities(),
41940
40259
  workspaceTypes: this.hostWorkspaceTypes(),
@@ -41957,23 +40276,9 @@ var HostPluginRuntime = class {
41957
40276
  );
41958
40277
  }
41959
40278
  async readHarnessVersion() {
41960
- let reportedVersion;
41961
- let errorCode6;
41962
- try {
41963
- const response = await this.apiProxy?.host.describe({ rpcId: randomUUID7(), payload: {} });
41964
- if (response === void 0) throw new Error("ApiProxy is unavailable");
41965
- if (!response.result.ok) {
41966
- errorCode6 = response.result.error.code;
41967
- } else {
41968
- reportedVersion = normalizeHarnessVersion(response.result.value.version);
41969
- }
41970
- } catch {
41971
- }
41972
- const distributionVersion = reportedVersion === void 0 || reportedVersion === "0.0.1" ? await readHarnessDistributionVersion() : void 0;
41973
- const version = selectHarnessVersion(reportedVersion, distributionVersion);
41974
- if (version !== void 0) return version;
41975
- this.logger.warn("Harness version is unavailable", errorCode6 === void 0 ? void 0 : { code: errorCode6 });
41976
- return void 0;
40279
+ const version = await readHarnessDistributionVersion();
40280
+ if (version === void 0) this.logger.warn("Harness version is unavailable");
40281
+ return version;
41977
40282
  }
41978
40283
  hostCapabilities() {
41979
40284
  const capabilities = ["workspace.upload.v1"];
@@ -41985,9 +40290,6 @@ var HostPluginRuntime = class {
41985
40290
  );
41986
40291
  }
41987
40292
  if (this.localGateway?.supportsCarrier && this.terminalEnabled) capabilities.push("harness.terminal.v1");
41988
- if (this.apiProxy !== void 0) {
41989
- capabilities.push("harness.api.v1", "harness.api.transfer.v1");
41990
- }
41991
40293
  if (this.fileViewerHost?.() !== void 0) capabilities.push("fileviewer.read.v1");
41992
40294
  if (this.pluginRoutes?.() !== void 0) capabilities.push("plugin.route.v1");
41993
40295
  if (this.codex.isAvailable()) capabilities.push("codex.appserver.v1", "codex.appserver.transfer.v1");
@@ -42070,7 +40372,7 @@ var HostPluginRuntime = class {
42070
40372
  return peer;
42071
40373
  }
42072
40374
  };
42073
- function shortId5(value) {
40375
+ function shortId4(value) {
42074
40376
  return value.length <= 12 ? value : `${value.slice(0, 8)}\u2026${value.slice(-4)}`;
42075
40377
  }
42076
40378
  function isPlainRecord(value) {
@@ -42586,7 +40888,7 @@ function remoteStatusLines(target2) {
42586
40888
  `Server connection: ${connection}`,
42587
40889
  ...status2.error === void 0 ? [] : [`Connection error: ${status2.error}`],
42588
40890
  ...status2.error === "CONNECTION_REPLACED" ? ["Another instance is using this Host identity. Stop it or use a separate DSH_HOME before reconnecting."] : status2.error === "SERVER_CREDENTIALS_BUSY" ? ["Credential refresh is locked. Stop all instances before removing an orphaned server-credentials.json.refresh-lock and authorizing again."] : status2.accountRequired ? ["Authorize again with /remote login [provider|list]."] : [],
42589
- `Harness Remote API: ${capabilities.has("harness.api.v1") ? "available (ApiProxy)" : capabilities.has("harness.remote.v3") ? "available (Typert Remote Session V3)" : capabilities.has("harness.remote.v1") ? "available (Typert Remote)" : "unavailable"}`,
40891
+ `Harness Remote API: ${capabilities.has("harness.remote.v3") ? "available (Typert Remote Session V3)" : capabilities.has("harness.remote.v1") ? "available (Typert Remote)" : "unavailable"}`,
42590
40892
  `Remote clients: ${diagnostics.activeConnections}`,
42591
40893
  `Codex Remote: ${codex.enabled ? codex.state : "disabled"}`,
42592
40894
  `Agent ACP: ${cursor2.enabled ? cursor2.state : "disabled"}`,
@@ -42957,11 +41259,10 @@ function apply(ctx, entry = void 0) {
42957
41259
  disposePendingControl = void 0;
42958
41260
  await activate(activeContext, readConfig, entryId, tuiBinding);
42959
41261
  };
42960
- if (tuiCommandsAvailable || runtimeContext.get("apiProxy") !== void 0 || new TypertGatewaySwitch(gateway).supportsCarrier()) {
41262
+ if (tuiCommandsAvailable || new TypertGatewaySwitch(gateway).supportsCarrier()) {
42961
41263
  return startActiveRuntime(runtimeContext);
42962
41264
  }
42963
41265
  installPendingControl();
42964
- runtimeContext.inject(["apiProxy"], (legacyContext) => startActiveRuntime(legacyContext));
42965
41266
  };
42966
41267
  if (tuiCommandsAvailable) {
42967
41268
  ctx.inject(["settings", "typertGateway"], activateWhenCarrierReady);
@@ -43002,7 +41303,6 @@ async function activate(ctx, readConfig, entryId, tuiBinding) {
43002
41303
  console.error(message);
43003
41304
  }
43004
41305
  }, config.logLevel);
43005
- const apiProxy = ctx.get("apiProxy");
43006
41306
  const nativeTypertGateway = ctx.get("typertGateway");
43007
41307
  const hostGateway = new TypertGatewaySwitch(nativeTypertGateway);
43008
41308
  const localTypertGateway = hostGateway.local();
@@ -43027,7 +41327,6 @@ async function activate(ctx, readConfig, entryId, tuiBinding) {
43027
41327
  const runtime2 = new HostPluginRuntime(
43028
41328
  config2,
43029
41329
  hostIdentities,
43030
- apiProxy,
43031
41330
  logger,
43032
41331
  localTypertGateway,
43033
41332
  () => ctx.get("fileViewerHost"),
@@ -43047,7 +41346,6 @@ async function activate(ctx, readConfig, entryId, tuiBinding) {
43047
41346
  config2,
43048
41347
  clientIdentities,
43049
41348
  new ClientServerApi(config2.serverUrl, new ServerCredentialStore(clientIdentities.directory)),
43050
- apiProxy,
43051
41349
  nativeTypertGateway,
43052
41350
  logger,
43053
41351
  runtime2
@@ -43110,7 +41408,6 @@ async function activate(ctx, readConfig, entryId, tuiBinding) {
43110
41408
  } else {
43111
41409
  logger.warn("client remote mode is unavailable", {
43112
41410
  serverConfigured: config.serverUrl !== void 0,
43113
- apiProxyAvailable: apiProxy !== void 0,
43114
41411
  remoteGatewayAvailable: localTypertGateway.supportsCarrier,
43115
41412
  connectionAvailable: connection !== void 0
43116
41413
  });
@@ -43239,7 +41536,6 @@ export {
43239
41536
  AcpGateway,
43240
41537
  AcpPeerBridge,
43241
41538
  AcpRemoteGateway,
43242
- ApiProxySwitch,
43243
41539
  CODEX_APP_ALLOWLIST,
43244
41540
  ClientModeError,
43245
41541
  ClientModeRuntime,
@@ -43254,10 +41550,8 @@ export {
43254
41550
  ConnectionRejectedError,
43255
41551
  CursorAcpClient,
43256
41552
  CursorAcpError,
43257
- HARNESS_API_ALLOWLIST,
43258
41553
  HARNESS_REMOTE_ALLOWLIST,
43259
41554
  HOST_CAPABILITIES,
43260
- HarnessApiBridge,
43261
41555
  HarnessRemoteBridge,
43262
41556
  HostPluginRuntime,
43263
41557
  HostServerApi,
@@ -43266,7 +41560,6 @@ export {
43266
41560
  IdentityStore,
43267
41561
  PluginControlRuntime,
43268
41562
  RemoteFileViewerBridge,
43269
- RemoteHarnessApiProxy,
43270
41563
  RemoteTypertGateway2 as RemoteTypertGateway,
43271
41564
  RpcError,
43272
41565
  RpcRouter,