ds-harness-remote 0.5.1 → 0.5.3

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 (38) hide show
  1. package/README.md +5 -9
  2. package/dist/acp/adapters/antigravity-process.d.ts +5 -0
  3. package/dist/acp/adapters/antigravity-process.d.ts.map +1 -1
  4. package/dist/acp/adapters/antigravity-process.js +92 -14
  5. package/dist/acp/adapters/antigravity-process.js.map +1 -1
  6. package/dist/acp/virtual-harness.d.ts +23 -2
  7. package/dist/acp/virtual-harness.d.ts.map +1 -1
  8. package/dist/acp/virtual-harness.js +36 -4
  9. package/dist/acp/virtual-harness.js.map +1 -1
  10. package/dist/client-runtime.js +2 -2
  11. package/dist/client-runtime.js.map +1 -1
  12. package/dist/codex/virtual-harness.d.ts +7 -0
  13. package/dist/codex/virtual-harness.d.ts.map +1 -1
  14. package/dist/codex/virtual-harness.js +19 -1
  15. package/dist/codex/virtual-harness.js.map +1 -1
  16. package/dist/control-runtime.d.ts.map +1 -1
  17. package/dist/control-runtime.js +5 -2
  18. package/dist/control-runtime.js.map +1 -1
  19. package/dist/harness-remote-bridge.d.ts +1 -1
  20. package/dist/harness-remote-bridge.d.ts.map +1 -1
  21. package/dist/harness-remote-bridge.js +28 -1
  22. package/dist/harness-remote-bridge.js.map +1 -1
  23. package/dist/index.js +175 -29
  24. package/dist/index.js.map +3 -3
  25. package/dist/rpc-router.d.ts.map +1 -1
  26. package/dist/rpc-router.js +4 -0
  27. package/dist/rpc-router.js.map +1 -1
  28. package/dist/server-api.d.ts +1 -1
  29. package/dist/server-api.d.ts.map +1 -1
  30. package/dist/server-api.js +17 -3
  31. package/dist/server-api.js.map +1 -1
  32. package/dist/service.d.ts.map +1 -1
  33. package/dist/service.js +9 -2
  34. package/dist/service.js.map +1 -1
  35. package/dist/version.d.ts +1 -1
  36. package/dist/version.js +1 -1
  37. package/dsh-plugin.json +1 -1
  38. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -16344,7 +16344,7 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
16344
16344
  case "commands/execute":
16345
16345
  return ok(await this.executeCommand(args, signal));
16346
16346
  default:
16347
- return fail("method-not-found", `CodeX virtual Harness does not implement ${endpoint}.`);
16347
+ return this.hostCarrier === void 0 ? fail("method-not-found", `CodeX virtual Harness does not implement ${endpoint}.`) : await this.hostCarrier.dispatch(endpoint, payload, signal);
16348
16348
  }
16349
16349
  } catch (error) {
16350
16350
  return failFrom(error);
@@ -16366,6 +16366,8 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
16366
16366
  if (endpoint === "session/control") return this.sessionControl(signal);
16367
16367
  if (endpoint === "session/follow") return this.sessionFollow(requestArg(args), signal);
16368
16368
  if (endpoint === "$events") return this.remoteEvents(signal);
16369
+ if (endpoint === "job/list" || endpoint === "job/follow") return this.emptyJobStream(endpoint, signal);
16370
+ if (this.hostCarrier !== void 0) return this.hostCarrier.open(endpoint, payload, signal);
16369
16371
  throw Object.assign(new Error(`CodeX virtual Harness does not implement stream ${endpoint}.`), {
16370
16372
  isDSHRemoteError: true,
16371
16373
  code: "method-not-found",
@@ -16592,6 +16594,17 @@ var CodexVirtualHarness = class _CodexVirtualHarness {
16592
16594
  queue.push({ type: "baseline", value: { queues: {}, jobs: {}, projections: {} } });
16593
16595
  return queue.iterate(() => this.controlStreams.delete(queue));
16594
16596
  }
16597
+ /**
16598
+ * Background jobs belong to the Host Harness session, not to a CodeX virtual
16599
+ * Workspace. The native session header mounts a job roster stream as soon as a
16600
+ * Session opens, so answer it with an authoritative empty roster instead of a
16601
+ * terminal `method-not-found` failure that tears the page down.
16602
+ */
16603
+ emptyJobStream(endpoint, signal) {
16604
+ const queue = new AsyncValueQueue2(signal);
16605
+ if (endpoint === "job/list") queue.push({ type: "rows", jobs: [] });
16606
+ return queue.iterate(() => queue.close());
16607
+ }
16595
16608
  async remoteEvents(signal) {
16596
16609
  const queue = new AsyncValueQueue2(signal);
16597
16610
  const clientId = `codex-events:${this.host.deviceId}:${Date.now().toString(36)}`;
@@ -18585,10 +18598,11 @@ async function discoverAcpVirtualWorkspaces(client, backend, signal) {
18585
18598
  return [];
18586
18599
  }
18587
18600
  var AcpVirtualHarness = class _AcpVirtualHarness {
18588
- constructor(client, host, backend = "cursor") {
18601
+ constructor(client, host, backend = "cursor", hostCarrier) {
18589
18602
  this.client = client;
18590
18603
  this.host = host;
18591
18604
  this.backend = backend;
18605
+ this.hostCarrier = hostCarrier;
18592
18606
  this.api = this.createApiProxy();
18593
18607
  }
18594
18608
  api;
@@ -18606,8 +18620,8 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
18606
18620
  lastProjectionSeq = 0;
18607
18621
  imageAttachments = /* @__PURE__ */ new Map();
18608
18622
  closed = false;
18609
- static remote(core, host, backend = "cursor", capabilities = []) {
18610
- return new _AcpVirtualHarness(new AgentAcpClient(core, capabilities), host, backend);
18623
+ static remote(core, host, backend = "cursor", capabilities = [], hostCarrier) {
18624
+ return new _AcpVirtualHarness(new AgentAcpClient(core, capabilities), host, backend, hostCarrier);
18611
18625
  }
18612
18626
  async workspaces() {
18613
18627
  return [...this.workspaceById.values()];
@@ -18762,7 +18776,7 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
18762
18776
  case "commands/execute":
18763
18777
  return business2(void 0);
18764
18778
  default:
18765
- return fail2("method-not-found", `${this.backendLabel()} virtual Harness does not implement ${endpoint}.`);
18779
+ return this.hostCarrier === void 0 ? fail2("method-not-found", `${this.backendLabel()} virtual Harness does not implement ${endpoint}.`) : await this.hostCarrier.dispatch(endpoint, payload, signal);
18766
18780
  }
18767
18781
  } catch (error) {
18768
18782
  return failFrom2(error);
@@ -18784,6 +18798,8 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
18784
18798
  if (endpoint === "session/control") return this.sessionControl(signal);
18785
18799
  if (endpoint === "session/follow") return this.sessionFollow(requestArg2(args), signal);
18786
18800
  if (endpoint === "$events") return this.remoteEvents(signal);
18801
+ if (endpoint === "job/list" || endpoint === "job/follow") return this.emptyJobStream(endpoint, signal);
18802
+ if (this.hostCarrier !== void 0) return this.hostCarrier.open(endpoint, payload, signal);
18787
18803
  throw Object.assign(new Error(`${this.backendLabel()} virtual Harness does not implement stream ${endpoint}.`), {
18788
18804
  isDSHRemoteError: true,
18789
18805
  code: "method-not-found",
@@ -18944,6 +18960,11 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
18944
18960
  if (session === void 0) return failure2("session-not-found", "The Session was not found.");
18945
18961
  await this.client.cancel(session.acpSessionId, signal);
18946
18962
  session.running = false;
18963
+ for (const follow of this.follows) {
18964
+ if (follow.sessionId === sessionId) {
18965
+ this.closeFollowAfterRemoteStreamClosed(follow);
18966
+ }
18967
+ }
18947
18968
  this.emitRemoteEvent("api-session/status", [sessionId, false]);
18948
18969
  return success2({ accepted: true });
18949
18970
  }
@@ -19101,6 +19122,17 @@ var AcpVirtualHarness = class _AcpVirtualHarness {
19101
19122
  queue.push({ type: "baseline", value: { projections: {} } });
19102
19123
  return queue.iterate(() => this.controlStreams.delete(queue));
19103
19124
  }
19125
+ /**
19126
+ * Background jobs belong to the Host Harness session, not to a backend-scoped
19127
+ * virtual Workspace. The native session header mounts a job roster stream as
19128
+ * soon as a Session opens, so answer it with an authoritative empty roster
19129
+ * instead of a terminal `method-not-found` failure that tears the page down.
19130
+ */
19131
+ emptyJobStream(endpoint, signal) {
19132
+ const queue = new AsyncValueQueue3(signal);
19133
+ if (endpoint === "job/list") queue.push({ type: "rows", jobs: [] });
19134
+ return queue.iterate(() => queue.close());
19135
+ }
19104
19136
  async remoteEvents(signal) {
19105
19137
  const id5 = `cursor-events:${Date.now()}:${Math.random()}`;
19106
19138
  const queue = new AsyncValueQueue3(signal);
@@ -20206,7 +20238,7 @@ function normalizeServerUrl(value) {
20206
20238
  }
20207
20239
 
20208
20240
  // src/version.ts
20209
- var PLUGIN_VERSION = "0.5.1";
20241
+ var PLUGIN_VERSION = "0.5.3";
20210
20242
 
20211
20243
  // src/server-api.ts
20212
20244
  var TERMINAL_CONTROL_CHARACTERS = /[\u0000-\u001f\u007f-\u009f]/u;
@@ -20257,7 +20289,7 @@ var HostServerApi = class {
20257
20289
  await this.clearAuthorization();
20258
20290
  }
20259
20291
  }
20260
- async authorizeWithAccount(identity, email, password) {
20292
+ async authorizeWithAccount(identity, email, password, recoverIdentity) {
20261
20293
  this.bindIdentity(identity);
20262
20294
  const account = email.trim();
20263
20295
  if (account.length === 0 || password.length === 0) {
@@ -20267,11 +20299,19 @@ var HostServerApi = class {
20267
20299
  method: "POST",
20268
20300
  body: JSON.stringify({ email: account, password })
20269
20301
  }));
20270
- await this.register(identity, {
20302
+ const authorization = {
20271
20303
  accountToken: login2.token,
20272
20304
  account: login2.account,
20273
20305
  authorizationMethod: "account"
20274
- });
20306
+ };
20307
+ try {
20308
+ await this.register(identity, authorization);
20309
+ } catch (error) {
20310
+ if (!(error instanceof ServerApiError) || error.code !== "DEVICE_REVOKED" || recoverIdentity === void 0) throw error;
20311
+ const nextIdentity = await recoverIdentity();
20312
+ this.bindIdentity(nextIdentity);
20313
+ await this.register(nextIdentity, authorization);
20314
+ }
20275
20315
  return {
20276
20316
  method: "account",
20277
20317
  account: login2.account,
@@ -22285,7 +22325,7 @@ var ClientModeRuntime = class {
22285
22325
  const virtual = AcpVirtualHarness.remote(remote.client, {
22286
22326
  deviceId: remote.target.deviceId,
22287
22327
  name: remote.target.name
22288
- }, backend, remote.features.acpModelLoadsSession ? ["agent.acp.antigravity.model-load.v1"] : []);
22328
+ }, backend, remote.features.acpModelLoadsSession ? ["agent.acp.antigravity.model-load.v1"] : [], new RemoteTypertGateway2(remote.client));
22289
22329
  let workspace;
22290
22330
  try {
22291
22331
  workspace = await virtual.selectWorkspace(workspaceId);
@@ -22320,7 +22360,7 @@ var ClientModeRuntime = class {
22320
22360
  const virtual = AcpVirtualHarness.remote(remote.client, {
22321
22361
  deviceId: remote.target.deviceId,
22322
22362
  name: remote.target.name
22323
- }, backend, remote.features.acpModelLoadsSession ? ["agent.acp.antigravity.model-load.v1"] : []);
22363
+ }, backend, remote.features.acpModelLoadsSession ? ["agent.acp.antigravity.model-load.v1"] : [], new RemoteTypertGateway2(remote.client));
22324
22364
  const workspace = await virtual.selectOrCreateWorkspace(trimmedPath);
22325
22365
  await this.closeCodexVirtual();
22326
22366
  await this.closeCursorVirtual();
@@ -26418,6 +26458,7 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26418
26458
  this.readModels = options.sessionWorker ? loadModels : cachedAgyModels(loadModels);
26419
26459
  this.args = options.args ?? ["--input-format", "stream-json", "--output-format", "stream-json"];
26420
26460
  this.cwd = options.cwd ?? process.cwd();
26461
+ this.brainDir = options.brainDir;
26421
26462
  this.sessionWorker = options.sessionWorker === true;
26422
26463
  this.initialConversationClaimed = options.conversationId !== void 0;
26423
26464
  this.skipPermissions = options.skipPermissions === true;
@@ -26442,6 +26483,8 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26442
26483
  args;
26443
26484
  cwd;
26444
26485
  readModels;
26486
+ brainDir;
26487
+ dispatchedThinkingSteps = /* @__PURE__ */ new Set();
26445
26488
  selections = /* @__PURE__ */ new Map();
26446
26489
  selecting = /* @__PURE__ */ new Set();
26447
26490
  currentPromptPending;
@@ -26464,6 +26507,7 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26464
26507
  skipPermissions: this.skipPermissions,
26465
26508
  sessionWorker: true,
26466
26509
  cwd: cwd2,
26510
+ brainDir: this.brainDir,
26467
26511
  ...conversationId === void 0 ? {} : { conversationId }
26468
26512
  });
26469
26513
  worker.onInbound((frame) => {
@@ -26501,6 +26545,13 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26501
26545
  this.warmNextSession(cwd2);
26502
26546
  }
26503
26547
  async call(method, params, timeoutMs) {
26548
+ if (!this.ready) {
26549
+ if (this.startPromise) {
26550
+ await this.startPromise;
26551
+ } else if (!this.closed) {
26552
+ await this.start();
26553
+ }
26554
+ }
26504
26555
  if (!this.ready) throw new AntigravityAcpError("ANTIGRAVITY_UNAVAILABLE", "Antigravity ACP is not ready.");
26505
26556
  if (method === "initialize") {
26506
26557
  return {
@@ -26597,12 +26648,7 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26597
26648
  return { sessionId };
26598
26649
  }
26599
26650
  if (method === "session/cancel") {
26600
- if (this.currentPromptPending) {
26601
- clearTimeout(this.currentPromptPending.timer);
26602
- const pending = this.currentPromptPending;
26603
- this.currentPromptPending = void 0;
26604
- pending.resolve({ stopReason: "cancelled" });
26605
- }
26651
+ await this.cancelTurn();
26606
26652
  return { cancelled: true };
26607
26653
  }
26608
26654
  if (method === "session/prompt") {
@@ -26631,6 +26677,36 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26631
26677
  this.unavailableHandlers.add(handler);
26632
26678
  return () => this.unavailableHandlers.delete(handler);
26633
26679
  }
26680
+ async cancelTurn() {
26681
+ if (this.currentPromptPending) {
26682
+ clearTimeout(this.currentPromptPending.timer);
26683
+ const pending = this.currentPromptPending;
26684
+ this.currentPromptPending = void 0;
26685
+ pending.resolve({ stopReason: "cancelled" });
26686
+ }
26687
+ if (this.watcher) {
26688
+ this.watcher.stop();
26689
+ this.watcher = void 0;
26690
+ }
26691
+ const child = this.process;
26692
+ this.process = void 0;
26693
+ this.ready = false;
26694
+ this.stdoutBuffer = Buffer5.alloc(0);
26695
+ if (child !== void 0 && child.exitCode === null && !child.killed) {
26696
+ child.stdout.removeAllListeners("data");
26697
+ child.stderr.removeAllListeners("data");
26698
+ child.kill("SIGINT");
26699
+ const timer = setTimeout(() => {
26700
+ if (child.exitCode === null && !child.killed) child.kill("SIGKILL");
26701
+ }, 1e3);
26702
+ timer.unref?.();
26703
+ }
26704
+ if (this.activeConversationId && !this.closed) {
26705
+ void this.start().catch((err) => {
26706
+ this.logger?.warn("Failed to restart Antigravity process after cancellation", { error: String(err) });
26707
+ });
26708
+ }
26709
+ }
26634
26710
  async close() {
26635
26711
  if (this.closed) return;
26636
26712
  this.closed = true;
@@ -26701,8 +26777,7 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26701
26777
  const conversationId = event.conversation_id;
26702
26778
  if (typeof conversationId === "string") {
26703
26779
  this.activeConversationId = conversationId;
26704
- this.watcher = new TranscriptWatcher(conversationId);
26705
- this.watcher.start();
26780
+ this.attachWatcher(conversationId);
26706
26781
  }
26707
26782
  resolve6();
26708
26783
  }
@@ -26781,6 +26856,32 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26781
26856
  this.process?.stdin.write(data2);
26782
26857
  });
26783
26858
  }
26859
+ attachWatcher(conversationId) {
26860
+ if (this.watcher) {
26861
+ this.watcher.stop();
26862
+ this.watcher = void 0;
26863
+ }
26864
+ const watcher = new TranscriptWatcher(conversationId, this.brainDir);
26865
+ this.watcher = watcher;
26866
+ this.dispatchedThinkingSteps.clear();
26867
+ watcher.on("thinking", ({ stepIndex, thinking }) => {
26868
+ if (this.dispatchedThinkingSteps.has(stepIndex)) return;
26869
+ this.dispatchedThinkingSteps.add(stepIndex);
26870
+ const trimmed = thinking?.trim();
26871
+ if (!trimmed) return;
26872
+ const sessionId = this.currentPromptPending?.sessionId ?? this.activeConversationId ?? "default";
26873
+ this.emitNotification("session/update", {
26874
+ sessionId,
26875
+ update: {
26876
+ sessionUpdate: "agent_thought_chunk",
26877
+ text: `${trimmed}
26878
+
26879
+ `
26880
+ }
26881
+ });
26882
+ });
26883
+ watcher.start();
26884
+ }
26784
26885
  consumeStdout(chunk, onRawEvent) {
26785
26886
  this.stdoutBuffer = Buffer5.concat([this.stdoutBuffer, chunk]);
26786
26887
  while (true) {
@@ -26795,6 +26896,7 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26795
26896
  onRawEvent(parsed);
26796
26897
  }
26797
26898
  this.handleAgyEvent(parsed);
26899
+ void this.watcher?.flush();
26798
26900
  } catch (err) {
26799
26901
  this.logger?.debug("Failed to parse agy stdout line", { code: "INVALID_AGY_STREAM_EVENT" });
26800
26902
  }
@@ -26818,6 +26920,9 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26818
26920
  } else if (stepType === "thought" || stepType === "reasoning") {
26819
26921
  const text = typeof step.text_delta === "string" ? step.text_delta : typeof step.thought === "string" ? step.thought : typeof step.reasoning === "string" ? step.reasoning : void 0;
26820
26922
  if (text) {
26923
+ if (typeof step.step_index === "number") {
26924
+ this.dispatchedThinkingSteps.add(step.step_index);
26925
+ }
26821
26926
  this.emitNotification("session/update", {
26822
26927
  sessionId,
26823
26928
  update: {
@@ -26841,11 +26946,13 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26841
26946
  }
26842
26947
  });
26843
26948
  } else if (step.state === "DONE") {
26949
+ const status2 = step.status === "ERROR" ? "failed" : "completed";
26844
26950
  this.emitNotification("session/update", {
26845
26951
  sessionId,
26846
26952
  update: {
26847
26953
  sessionUpdate: "tool_call_update",
26848
26954
  callId,
26955
+ status: status2,
26849
26956
  output: typeof toolInfo.output === "string" ? toolInfo.output : JSON.stringify(toolInfo.output ?? "")
26850
26957
  }
26851
26958
  });
@@ -26856,11 +26963,18 @@ var AntigravityAcpClient = class _AntigravityAcpClient {
26856
26963
  if (current) {
26857
26964
  clearTimeout(current.timer);
26858
26965
  this.currentPromptPending = void 0;
26859
- if (result.status === "ERROR") {
26860
- current.reject(new AntigravityAcpError("ANTIGRAVITY_TURN_FAILED", String(result.error ?? "Execution error")));
26861
- } else {
26862
- current.resolve({ stopReason: "end_turn", response: result.response });
26863
- }
26966
+ const finish = async () => {
26967
+ try {
26968
+ await this.watcher?.flush();
26969
+ } catch {
26970
+ }
26971
+ if (result.status === "ERROR") {
26972
+ current.reject(new AntigravityAcpError("ANTIGRAVITY_TURN_FAILED", String(result.error ?? "Execution error")));
26973
+ } else {
26974
+ current.resolve({ stopReason: "end_turn", response: result.response });
26975
+ }
26976
+ };
26977
+ void finish();
26864
26978
  }
26865
26979
  }
26866
26980
  }
@@ -28640,7 +28754,7 @@ var PluginControlRuntime = class {
28640
28754
  const identities = new IdentityStore({
28641
28755
  directory: serverStorageDirectory(this.identityDirectory, next.serverUrl, value.role)
28642
28756
  });
28643
- const identity = await identities.loadOrCreate(hostname2());
28757
+ let identity = await identities.loadOrCreate(hostname2());
28644
28758
  const api = value.role === "host" ? new HostServerApi(next.serverUrl, new ServerCredentialStore(identities.directory)) : new ClientServerApi(next.serverUrl, new ServerCredentialStore(identities.directory));
28645
28759
  let authorization;
28646
28760
  if (value.role === "host" && typeof value.registrationCode === "string" && value.registrationCode.trim() !== "") {
@@ -28649,7 +28763,10 @@ var PluginControlRuntime = class {
28649
28763
  if (typeof value.email !== "string" || typeof value.password !== "string") {
28650
28764
  throw new ClientModeError("INVALID_MESSAGE", "Email and password are required for account authorization.");
28651
28765
  }
28652
- authorization = await api.authorizeWithAccount(identity, value.email, value.password);
28766
+ authorization = await api.authorizeWithAccount(identity, value.email, value.password, async () => {
28767
+ identity = await identities.reset(hostname2());
28768
+ return identity;
28769
+ });
28653
28770
  }
28654
28771
  if (value.role === "client" && resolveConfig(this.settings.get()).hostControl?.enabled !== false) {
28655
28772
  await this.client?.authorizeHostByDefault();
@@ -29246,8 +29363,10 @@ var RpcRouter = class {
29246
29363
  return createRpcResponse(request.id, result);
29247
29364
  } catch (error) {
29248
29365
  const response = errorResponse2(request.id, error);
29366
+ const failedEndpoint = typeof request.payload.params?.endpoint === "string" ? String(request.payload.params.endpoint) : void 0;
29249
29367
  this.logger?.warn("host rpc failed", {
29250
29368
  method: request.payload.method,
29369
+ ...failedEndpoint ? { endpoint: failedEndpoint } : {},
29251
29370
  durationMs: Math.round(performance.now() - startedAt),
29252
29371
  code: response.payload.code,
29253
29372
  retryable: response.payload.retryable
@@ -31354,6 +31473,8 @@ var HARNESS_REMOTE_ALLOWLIST = [
31354
31473
  "goals/edit",
31355
31474
  "goals/pause",
31356
31475
  "goals/resume",
31476
+ "job/list",
31477
+ "job/follow",
31357
31478
  "llm/discoverModels",
31358
31479
  "llm/listConfigurableProviders",
31359
31480
  "llm/listProviders",
@@ -31463,7 +31584,8 @@ var HarnessRemoteBridge = class {
31463
31584
  endpoint: params.endpoint,
31464
31585
  durationMs: Math.round(performance.now() - startedAt)
31465
31586
  });
31466
- return reservation === void 0 ? result : this.terminal.result(params.endpoint, params.payload, result, reservation);
31587
+ const wireResult = normalizeWorkspaceBinaryResult(params.endpoint, result);
31588
+ return reservation === void 0 ? wireResult : this.terminal.result(params.endpoint, params.payload, wireResult, reservation);
31467
31589
  } catch (error) {
31468
31590
  if (reservation !== void 0) this.terminal.result(params.endpoint, params.payload, { ok: false, error: { code: "FAILED", message: "", details: {} } }, reservation);
31469
31591
  if (params.endpoint === "directoryPicker/list") {
@@ -31726,6 +31848,23 @@ function decodeCanonicalBase644(value) {
31726
31848
  if (bytes.toString("base64") !== value) throw new RpcError("INVALID_MESSAGE", "The Harness Remote transfer chunk is invalid.");
31727
31849
  return bytes;
31728
31850
  }
31851
+ function normalizeWorkspaceBinaryResult(endpoint, result) {
31852
+ if (result.ok !== true || endpoint !== "workspaceFiles/readBytes" && endpoint !== "officeToPdf/render") return result;
31853
+ if (!isJsonRecord(result.value) || !isBinary(result.value.data)) return result;
31854
+ return {
31855
+ ...result,
31856
+ value: {
31857
+ ...result.value,
31858
+ data: Buffer.from(result.value.data).toString("base64")
31859
+ }
31860
+ };
31861
+ }
31862
+ function isBinary(value) {
31863
+ return value instanceof Uint8Array;
31864
+ }
31865
+ function isJsonRecord(value) {
31866
+ return typeof value === "object" && value !== null && !Array.isArray(value);
31867
+ }
31729
31868
  function concatChunks4(chunks, totalBytes) {
31730
31869
  const result = new Uint8Array(totalBytes);
31731
31870
  let offset = 0;
@@ -31918,7 +32057,7 @@ var HostPluginRuntime = class {
31918
32057
  ...error === void 0 ? {} : { error },
31919
32058
  ...authorization?.account === void 0 ? {} : { account: authorization.account },
31920
32059
  authorized: authorization !== void 0,
31921
- accountRequired: error === "ACCOUNT_AUTH_REQUIRED" || error === "AUTH_INVALID" || error === "TOKEN_EXPIRED",
32060
+ accountRequired: error === "ACCOUNT_AUTH_REQUIRED" || error === "AUTH_INVALID" || error === "TOKEN_EXPIRED" || error === "DEVICE_REVOKED",
31922
32061
  connectedClients: this.listConnectedClients()
31923
32062
  };
31924
32063
  }
@@ -32007,7 +32146,14 @@ var HostPluginRuntime = class {
32007
32146
  if (this.serverApi === void 0) {
32008
32147
  throw new ServerApiError("SERVER_NOT_CONFIGURED", "Configure serverUrl before signing in.", false);
32009
32148
  }
32010
- const result = await this.serverApi.authorizeWithAccount(this.currentIdentity(), email, password);
32149
+ const result = await this.serverApi.authorizeWithAccount(this.currentIdentity(), email, password, async () => {
32150
+ await this.serverConnection?.stop();
32151
+ this.identity = await this.identities.reset(this.config.deviceName);
32152
+ this.serverApi.bindIdentity(this.identity);
32153
+ this.serverConnection = this.createServerConnection(this.identity);
32154
+ this.logger.info("Rotated revoked Host identity before account authorization");
32155
+ return this.identity;
32156
+ });
32011
32157
  this.serverConnection?.resume();
32012
32158
  this.logger.info("Host account authorized");
32013
32159
  return result;