@blue-soda/dsh-remote 0.4.30 → 0.4.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -14812,6 +14812,100 @@ async function readHarnessDistributionVersion(entrypoint = process.argv[1]) {
14812
14812
  }
14813
14813
  }
14814
14814
 
14815
+ // src/rpc-binary-attachments.ts
14816
+ function hydrateRpcAttachments(result) {
14817
+ if (!isRecord2(result)) return result;
14818
+ const envelope = result;
14819
+ if (!Array.isArray(envelope.attachments) || envelope.attachments.length === 0) return result;
14820
+ const { attachments, ...rest } = result;
14821
+ const base = Object.hasOwn(rest, "value") ? rest.value : void 0;
14822
+ for (const attachment of attachments) {
14823
+ const entry = attachment;
14824
+ const path = Array.isArray(entry.path) ? entry.path : void 0;
14825
+ if (path === void 0 || path.length === 0) {
14826
+ throw new Error("The remote Host returned a byte attachment without a path.");
14827
+ }
14828
+ assignAtPath(base, path, decodeAttachmentBytes(entry.bytes));
14829
+ }
14830
+ return rest;
14831
+ }
14832
+ function assignAtPath(base, path, bytes) {
14833
+ if (base === null || typeof base !== "object") {
14834
+ throw new Error("The remote Host returned a byte attachment that its result cannot hold.");
14835
+ }
14836
+ let cursor2 = base;
14837
+ for (let index = 0; index < path.length - 1; index += 1) {
14838
+ const key = pathKey(path[index]);
14839
+ const next = cursor2[key];
14840
+ if (next === null || typeof next !== "object") {
14841
+ throw new Error("The remote Host returned a byte attachment at an unknown result path.");
14842
+ }
14843
+ cursor2 = next;
14844
+ }
14845
+ cursor2[pathKey(path[path.length - 1])] = bytes;
14846
+ }
14847
+ function pathKey(segment) {
14848
+ if (typeof segment === "string") return segment;
14849
+ if (typeof segment === "number" && Number.isInteger(segment) && segment >= 0) return String(segment);
14850
+ throw new Error("The remote Host returned a byte attachment with an invalid path segment.");
14851
+ }
14852
+ function decodeAttachmentBytes(value) {
14853
+ if (value instanceof Uint8Array) return value;
14854
+ if (typeof value === "string") return decodeBase64(value);
14855
+ if (Array.isArray(value)) return Uint8Array.from(value);
14856
+ if (!isRecord2(value)) throw new Error("The remote Host returned invalid byte attachment data.");
14857
+ if (Array.isArray(value.data)) {
14858
+ return Uint8Array.from(value.data);
14859
+ }
14860
+ const keys = Object.keys(value);
14861
+ if (keys.every((key) => /^\d+$/u.test(key))) {
14862
+ const ordered = keys.map(Number).sort((left, right) => left - right);
14863
+ return Uint8Array.from(ordered.map((key) => value[String(key)]));
14864
+ }
14865
+ throw new Error("The remote Host returned invalid byte attachment data.");
14866
+ }
14867
+ function decodeBase64(value) {
14868
+ const binary = atob(value);
14869
+ const bytes = new Uint8Array(binary.length);
14870
+ for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
14871
+ return bytes;
14872
+ }
14873
+ function isRecord2(value) {
14874
+ return typeof value === "object" && value !== null && !Array.isArray(value);
14875
+ }
14876
+ function collectRpcAttachments(result) {
14877
+ if (!isRecord2(result) || !Object.hasOwn(result, "value")) return result;
14878
+ const attachments = [];
14879
+ const value = replaceBytes(result.value, [], attachments);
14880
+ if (attachments.length === 0) return result;
14881
+ return { ...result, value, attachments };
14882
+ }
14883
+ function replaceBytes(value, path, attachments) {
14884
+ if (value instanceof Uint8Array) {
14885
+ attachments.push({ path: [...path], bytes: encodeBase64(value) });
14886
+ return null;
14887
+ }
14888
+ if (Array.isArray(value)) return value.map((item, index) => replaceBytes(item, [...path, index], attachments));
14889
+ if (!isRecord2(value)) return value;
14890
+ const clone = {};
14891
+ for (const [key, item] of Object.entries(value)) clone[key] = replaceBytes(item, [...path, key], attachments);
14892
+ return clone;
14893
+ }
14894
+ function encodeBase64(bytes) {
14895
+ let binary = "";
14896
+ for (let offset = 0; offset < bytes.byteLength; offset += 32768) {
14897
+ binary += String.fromCharCode(...bytes.subarray(offset, offset + 32768));
14898
+ }
14899
+ return btoa(binary);
14900
+ }
14901
+ function decodeByteValue(value) {
14902
+ try {
14903
+ return decodeAttachmentBytes(value);
14904
+ } catch {
14905
+ return void 0;
14906
+ }
14907
+ }
14908
+
14815
14909
  // src/remote-api-proxy.ts
14816
14910
  var DIRECT_API_CALL_BYTES = 2 * 1024 * 1024;
14817
14911
  var AGENT_PRESET_SETTINGS_NS = "agent-presets";
@@ -14919,12 +15013,13 @@ var RemoteHarnessApiProxy = class {
14919
15013
  if (String(response.rpcId) !== String(request.rpcId) || typeof response.result !== "object" || response.result === null) {
14920
15014
  throw new Error("The remote Host returned an invalid Harness API response.");
14921
15015
  }
14922
- const normalized = normalizeLegacyResponse(method, response);
15016
+ const hydrated = { ...response, result: hydrateRpcAttachments(response.result) };
15017
+ const normalized = normalizeLegacyResponse(method, normalizeByteResult(method, hydrated));
14923
15018
  return this.normalizeLegacyWelcomeSettings(method, params.payload, normalized);
14924
15019
  }
14925
15020
  normalizeLegacyWelcomeSettings(method, payload, response) {
14926
15021
  if (!isLegacyRemoteHost(this.harnessVersion)) return response;
14927
- if (method === "settings.describe" && response.result.ok && isRecord2(response.result.value)) {
15022
+ if (method === "settings.describe" && response.result.ok && isRecord3(response.result.value)) {
14928
15023
  this.settingsDescribeValue = response.result.value;
14929
15024
  return this.legacyWelcomeAcknowledged ? patchWelcomeDescribe(response) : response;
14930
15025
  }
@@ -15036,7 +15131,7 @@ function normalizeLegacyResponse(method, response) {
15036
15131
  };
15037
15132
  }
15038
15133
  function normalizeLegacyRequest(method, payload) {
15039
- if (!isRecord2(payload)) return payload;
15134
+ if (!isRecord3(payload)) return payload;
15040
15135
  if (method === "agentPreset.read") return replaceAgentPreset(payload, "agentPreset");
15041
15136
  if (method === "agentPreset.select") return replaceAgentPreset(payload, "agentPreset");
15042
15137
  if (method === "agentPreset.copy") return replaceAgentPreset(payload, "from");
@@ -15051,7 +15146,7 @@ function replaceAgentPreset(payload, key) {
15051
15146
  return replacement === void 0 ? payload : { ...payload, [key]: replacement };
15052
15147
  }
15053
15148
  function replaceAgentPresetSettings(payload) {
15054
- if (payload.ns !== AGENT_PRESET_SETTINGS_NS || !isRecord2(payload.patch)) return payload;
15149
+ if (payload.ns !== AGENT_PRESET_SETTINGS_NS || !isRecord3(payload.patch)) return payload;
15055
15150
  const patch = replaceAgentPreset(payload.patch, "default");
15056
15151
  return patch === payload.patch ? payload : { ...payload, patch };
15057
15152
  }
@@ -15061,11 +15156,11 @@ function isLegacyRemoteHost(version) {
15061
15156
  return match !== null && Number(match[1]) === 0 && Number(match[2]) === 1 && Number(match[3]) < 7;
15062
15157
  }
15063
15158
  function isWelcomeNoticeRequest(payload) {
15064
- if (!isRecord2(payload) || payload.ns !== WELCOME_NOTICE_NAMESPACE || !Array.isArray(payload.ops)) return false;
15065
- return payload.ops.some((operation) => isRecord2(operation) && operation.op === "set" && Array.isArray(operation.path) && operation.path.length === 1 && operation.path[0] === WELCOME_NOTICE_FIELD && operation.value === WELCOME_NOTICE_VERSION);
15159
+ if (!isRecord3(payload) || payload.ns !== WELCOME_NOTICE_NAMESPACE || !Array.isArray(payload.ops)) return false;
15160
+ return payload.ops.some((operation) => isRecord3(operation) && operation.op === "set" && Array.isArray(operation.path) && operation.path.length === 1 && operation.path[0] === WELCOME_NOTICE_FIELD && operation.value === WELCOME_NOTICE_VERSION);
15066
15161
  }
15067
15162
  function patchWelcomeDescribe(response) {
15068
- if (!response.result.ok || !isRecord2(response.result.value) || !Array.isArray(response.result.value.namespaces)) return response;
15163
+ if (!response.result.ok || !isRecord3(response.result.value) || !Array.isArray(response.result.value.namespaces)) return response;
15069
15164
  return {
15070
15165
  ...response,
15071
15166
  result: {
@@ -15073,8 +15168,8 @@ function patchWelcomeDescribe(response) {
15073
15168
  value: {
15074
15169
  ...response.result.value,
15075
15170
  namespaces: response.result.value.namespaces.map((namespace) => {
15076
- if (!isRecord2(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE) return namespace;
15077
- const value = isRecord2(namespace.value) ? namespace.value : {};
15171
+ if (!isRecord3(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE) return namespace;
15172
+ const value = isRecord3(namespace.value) ? namespace.value : {};
15078
15173
  return { ...namespace, value: { ...value, [WELCOME_NOTICE_FIELD]: WELCOME_NOTICE_VERSION } };
15079
15174
  })
15080
15175
  }
@@ -15088,8 +15183,8 @@ function patchWelcomeMutate(value, rpcId2) {
15088
15183
  };
15089
15184
  const namespaces = Array.isArray(value.namespaces) ? value.namespaces : [];
15090
15185
  response.result.value.namespaces = namespaces.map((namespace) => {
15091
- if (!isRecord2(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE) return namespace;
15092
- const current = isRecord2(namespace.value) ? namespace.value : {};
15186
+ if (!isRecord3(namespace) || namespace.ns !== WELCOME_NOTICE_NAMESPACE) return namespace;
15187
+ const current = isRecord3(namespace.value) ? namespace.value : {};
15093
15188
  return { ...namespace, value: { ...current, [WELCOME_NOTICE_FIELD]: WELCOME_NOTICE_VERSION } };
15094
15189
  });
15095
15190
  return response;
@@ -15097,7 +15192,7 @@ function patchWelcomeMutate(value, rpcId2) {
15097
15192
  function isRemoteDisconnect(error) {
15098
15193
  return error instanceof RemoteClientError && (error.code === "TRANSPORT_CLOSED" || error.code === "CLIENT_CLOSED");
15099
15194
  }
15100
- function isRecord2(value) {
15195
+ function isRecord3(value) {
15101
15196
  return typeof value === "object" && value !== null && !Array.isArray(value);
15102
15197
  }
15103
15198
  var AsyncFrameQueue = class {
@@ -15161,67 +15256,23 @@ function base64ToBytes2(value) {
15161
15256
  }
15162
15257
  return bytes;
15163
15258
  }
15164
-
15165
- // src/rpc-binary-attachments.ts
15166
- function hydrateRpcAttachments(result) {
15167
- if (!isRecord3(result)) return result;
15168
- const envelope = result;
15169
- if (!Array.isArray(envelope.attachments) || envelope.attachments.length === 0) return result;
15170
- const { attachments, ...rest } = result;
15171
- const base = Object.hasOwn(rest, "value") ? rest.value : void 0;
15172
- for (const attachment of attachments) {
15173
- const entry = attachment;
15174
- const path = Array.isArray(entry.path) ? entry.path : void 0;
15175
- if (path === void 0 || path.length === 0) {
15176
- throw new Error("The remote Host returned a byte attachment without a path.");
15177
- }
15178
- assignAtPath(base, path, decodeAttachmentBytes(entry.bytes));
15179
- }
15180
- return rest;
15181
- }
15182
- function assignAtPath(base, path, bytes) {
15183
- if (base === null || typeof base !== "object") {
15184
- throw new Error("The remote Host returned a byte attachment that its result cannot hold.");
15185
- }
15186
- let cursor2 = base;
15187
- for (let index = 0; index < path.length - 1; index += 1) {
15188
- const key = pathKey(path[index]);
15189
- const next = cursor2[key];
15190
- if (next === null || typeof next !== "object") {
15191
- throw new Error("The remote Host returned a byte attachment at an unknown result path.");
15259
+ function normalizeByteResult(method, response) {
15260
+ if (method !== "workspaceFiles.readBytes") return response;
15261
+ const result = response.result;
15262
+ if (result === void 0 || result.ok !== true) return response;
15263
+ const value = result.value;
15264
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return response;
15265
+ const raw = value.data;
15266
+ const data2 = raw instanceof Uint8Array ? raw : decodeByteValue(raw);
15267
+ if (data2 === void 0) return response;
15268
+ return {
15269
+ ...response,
15270
+ result: {
15271
+ ...result,
15272
+ value: { ...value, data: null },
15273
+ attachments: [{ path: ["data"], bytes: data2 }]
15192
15274
  }
15193
- cursor2 = next;
15194
- }
15195
- cursor2[pathKey(path[path.length - 1])] = bytes;
15196
- }
15197
- function pathKey(segment) {
15198
- if (typeof segment === "string") return segment;
15199
- if (typeof segment === "number" && Number.isInteger(segment) && segment >= 0) return String(segment);
15200
- throw new Error("The remote Host returned a byte attachment with an invalid path segment.");
15201
- }
15202
- function decodeAttachmentBytes(value) {
15203
- if (value instanceof Uint8Array) return value;
15204
- if (typeof value === "string") return decodeBase64(value);
15205
- if (Array.isArray(value)) return Uint8Array.from(value);
15206
- if (!isRecord3(value)) throw new Error("The remote Host returned invalid byte attachment data.");
15207
- if (Array.isArray(value.data)) {
15208
- return Uint8Array.from(value.data);
15209
- }
15210
- const keys = Object.keys(value);
15211
- if (keys.every((key) => /^\d+$/u.test(key))) {
15212
- const ordered = keys.map(Number).sort((left, right) => left - right);
15213
- return Uint8Array.from(ordered.map((key) => value[String(key)]));
15214
- }
15215
- throw new Error("The remote Host returned invalid byte attachment data.");
15216
- }
15217
- function decodeBase64(value) {
15218
- const binary = atob(value);
15219
- const bytes = new Uint8Array(binary.length);
15220
- for (let index = 0; index < binary.length; index += 1) bytes[index] = binary.charCodeAt(index);
15221
- return bytes;
15222
- }
15223
- function isRecord3(value) {
15224
- return typeof value === "object" && value !== null && !Array.isArray(value);
15275
+ };
15225
15276
  }
15226
15277
 
15227
15278
  // src/session-format-compat.ts
@@ -16173,7 +16224,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
16173
16224
  try {
16174
16225
  if (isHostWorkspaceEndpoint(endpoint)) {
16175
16226
  if (this.hostCarrier === void 0) return fail("method-not-found", `CodeX virtual Harness does not implement ${endpoint}.`);
16176
- return await this.hostCarrier.dispatch(endpoint, payload, signal);
16227
+ return normalizeByteResult2(endpoint, await this.hostCarrier.dispatch(endpoint, payload, signal));
16177
16228
  }
16178
16229
  const args = carrierArgs(payload);
16179
16230
  switch (endpoint) {
@@ -18412,6 +18463,19 @@ var AsyncValueQueue2 = class {
18412
18463
  }
18413
18464
  }
18414
18465
  };
18466
+ function normalizeByteResult2(endpoint, result) {
18467
+ if (endpoint !== "workspaceFiles/readBytes" || !result.ok) return result;
18468
+ const value = result.value;
18469
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return result;
18470
+ const raw = value.data;
18471
+ const data2 = raw instanceof Uint8Array ? raw : decodeByteValue(raw);
18472
+ if (data2 === void 0) return result;
18473
+ return {
18474
+ ...result,
18475
+ value: { ...value, data: null },
18476
+ attachments: [{ path: ["data"], bytes: data2 }]
18477
+ };
18478
+ }
18415
18479
 
18416
18480
  // src/server-api.ts
18417
18481
  import { platform } from "node:os";
@@ -18692,7 +18756,7 @@ function normalizeServerUrl(value) {
18692
18756
  }
18693
18757
 
18694
18758
  // src/version.ts
18695
- var PLUGIN_VERSION = "0.4.30";
18759
+ var PLUGIN_VERSION = "0.4.31";
18696
18760
 
18697
18761
  // src/server-api.ts
18698
18762
  var ENABLED_QR_PROVIDERS = ["github"];
@@ -19239,25 +19303,39 @@ var TypertGatewaySwitch = class {
19239
19303
  install() {
19240
19304
  if (this.installed) return;
19241
19305
  this.runtime.invoke = (request) => this.selectInvoke(request);
19242
- if (this.originalStream !== void 0) {
19243
- this.runtime.stream = (request) => !this.routesToRemote(endpointOf(request)) ? this.localStream(request) : this.withLocalFallback(
19306
+ const previousStream = this.runtime.stream?.bind(this.runtime);
19307
+ const previousDispatch = this.runtime.dispatchRpc?.bind(this.runtime);
19308
+ const previousOpen = this.runtime.openWireStream;
19309
+ const forwards = (endpoint) => this.remoteTarget === void 0 && this.remoteAvailability() && !isLocalOnlyEndpoint(endpoint);
19310
+ if (previousStream !== void 0) {
19311
+ this.runtime.stream = (request) => forwards(endpointOf(request)) ? previousStream(request) : !this.routesToRemote(endpointOf(request)) ? this.localStream(request) : this.withLocalFallback(
19244
19312
  endpointOf(request),
19245
19313
  () => this.remoteTarget.open(endpointOf(request), { args: request.args }, request.signal ?? new AbortController().signal),
19246
19314
  () => this.localStream(request)
19247
19315
  );
19248
19316
  }
19249
- if (this.originalDispatch !== void 0) {
19250
- this.runtime.dispatchRpc = (endpoint, payload, signal) => !this.routesToRemote(endpoint) ? this.localDispatch(endpoint, payload, signal) : this.withLocalFallback(
19317
+ if (previousDispatch !== void 0) {
19318
+ this.runtime.dispatchRpc = (endpoint, payload, signal) => forwards(endpoint) ? Promise.resolve(previousDispatch(endpoint, payload, signal)).catch((error) => {
19319
+ console.warn("[dsh-remote] local call failed with no remote target selected", {
19320
+ endpoint,
19321
+ code: typeof error === "object" && error !== null && "code" in error ? String(error.code) : void 0,
19322
+ message: error instanceof Error ? error.message : String(error)
19323
+ });
19324
+ throw error;
19325
+ }) : !this.routesToRemote(endpoint) ? this.localDispatch(endpoint, payload, signal) : this.withLocalFallback(
19251
19326
  endpoint,
19252
19327
  () => Promise.resolve(this.remoteTarget.dispatch(endpoint, payload, signal)),
19253
19328
  () => this.localDispatch(endpoint, payload, signal)
19254
- );
19329
+ ).then((result) => normalizeByteResult3(endpoint, result));
19255
19330
  }
19256
- if (this.originalOpen !== void 0) {
19257
- const open = this.originalOpen;
19331
+ if (previousOpen !== void 0) {
19332
+ const open = previousOpen;
19258
19333
  const rc1 = usesRc1Arity(open);
19259
19334
  this.runtime.openWireStream = (...callArgs) => {
19260
19335
  const endpoint = callArgs[0];
19336
+ if (forwards(endpoint)) {
19337
+ return rc1 ? Reflect.apply(open, this.runtime, callArgs) : open.call(this.runtime, endpoint, callArgs[1], callArgs[2]);
19338
+ }
19261
19339
  if (!this.routesToRemote(endpoint)) {
19262
19340
  return rc1 ? Reflect.apply(open, this.runtime, callArgs) : open.call(this.runtime, endpoint, callArgs[1], callArgs[2]);
19263
19341
  }
@@ -19328,7 +19406,7 @@ var TypertGatewaySwitch = class {
19328
19406
  selectInvoke(request) {
19329
19407
  if (isLocalOnlyEndpoint(endpointOf(request))) return this.localInvoke(request);
19330
19408
  if (this.remoteTarget !== void 0 && this.remoteAvailability()) {
19331
- return this.remoteTarget.invoke(request).catch((error) => {
19409
+ return this.remoteTarget.invoke(request).then((result) => normalizeByteResult3(endpointOf(request), result)).catch((error) => {
19332
19410
  if (!localFallbackAllowed(endpointOf(request), error)) throw error;
19333
19411
  console.warn(`[dsh-remote] serving ${endpointOf(request)} locally: the peer did not answer it`, error);
19334
19412
  return this.localInvoke(request);
@@ -19458,6 +19536,21 @@ var UNANSWERED_BY_PEER_CODES = /* @__PURE__ */ new Set([
19458
19536
  function isRecord8(value) {
19459
19537
  return typeof value === "object" && value !== null && !Array.isArray(value);
19460
19538
  }
19539
+ function normalizeByteResult3(endpoint, result) {
19540
+ if (endpoint !== "workspaceFiles/readBytes") return result;
19541
+ if (typeof result !== "object" || result === null || Array.isArray(result)) return result;
19542
+ const envelope = result;
19543
+ const value = envelope.value;
19544
+ if (typeof value !== "object" || value === null || Array.isArray(value)) return result;
19545
+ const raw = value.data;
19546
+ const data2 = raw instanceof Uint8Array ? raw : decodeByteValue(raw);
19547
+ if (data2 === void 0) return result;
19548
+ return {
19549
+ ...envelope,
19550
+ value: { ...value, data: null },
19551
+ attachments: [{ path: ["data"], bytes: data2 }]
19552
+ };
19553
+ }
19461
19554
 
19462
19555
  // src/werift-rtc.ts
19463
19556
  import { createSocket } from "node:dgram";
@@ -26354,7 +26447,15 @@ var HarnessApiBridge = class {
26354
26447
  mux;
26355
26448
  host;
26356
26449
  answer;
26450
+ /** Answer one ApiProxy call, sending bytes in the form DSH's own connection layer expects. */
26357
26451
  async call(input2) {
26452
+ const response = await this.dispatchCall(input2);
26453
+ const result = response.result;
26454
+ if (result === void 0) return response;
26455
+ const tagged = collectRpcAttachments(result);
26456
+ return tagged === result ? response : { ...response, result: tagged };
26457
+ }
26458
+ async dispatchCall(input2) {
26358
26459
  const params = callSchema2.parse(input2);
26359
26460
  const signal = AbortSignal.timeout(NATIVE_CALL_TIMEOUT_MS);
26360
26461
  const method = this.methods.get(params.method);
@@ -27065,7 +27166,17 @@ var HarnessRemoteBridge = class {
27065
27166
  streams = /* @__PURE__ */ new Map();
27066
27167
  incomingTransfers = /* @__PURE__ */ new Map();
27067
27168
  outgoingTransfers = /* @__PURE__ */ new Map();
27169
+ /**
27170
+ * Answer one remote Gateway call.
27171
+ *
27172
+ * Bytes have to leave in DSH's own form: this result is JSON-encoded on its way to the client, and a
27173
+ * \`Uint8Array\` would arrive there as \`{"0":…}\` and fail the generated schema (the image-preview
27174
+ * failure). Tagging here, hydrating on the client, keeps one convention on both sides.
27175
+ */
27068
27176
  async call(input2) {
27177
+ return collectRpcAttachments(await this.dispatchCall(input2));
27178
+ }
27179
+ async dispatchCall(input2) {
27069
27180
  const params = callSchema3.parse(input2);
27070
27181
  this.assertAllowed(params.endpoint);
27071
27182
  if (TERMINAL_STREAMS.has(params.endpoint)) throw new RpcError("METHOD_NOT_ALLOWED", "Use a stream for this terminal endpoint.");
@@ -27285,7 +27396,7 @@ var HarnessRemoteBridge = class {
27285
27396
  await this.publish("harness.remote.frame", {
27286
27397
  streamId,
27287
27398
  hasValue: true,
27288
- ...value === void 0 ? {} : { value }
27399
+ ...value === void 0 ? {} : { value: collectRpcAttachments(value) }
27289
27400
  });
27290
27401
  }
27291
27402
  if (signal.aborted) reason = "cancelled";