ds-harness-remote 0.3.19 → 0.3.21
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/README.md +2 -2
- package/dist/client-runtime.d.ts +2 -0
- package/dist/client-runtime.d.ts.map +1 -1
- package/dist/client-runtime.js +35 -0
- package/dist/client-runtime.js.map +1 -1
- package/dist/client.github.js +19 -2
- package/dist/client.js +19 -2
- package/dist/client.js.map +1 -1
- package/dist/harness-api-bridge.js +1 -1
- package/dist/harness-version.d.ts +9 -0
- package/dist/harness-version.d.ts.map +1 -0
- package/dist/harness-version.js +42 -0
- package/dist/harness-version.js.map +1 -0
- package/dist/index.js +198 -56
- package/dist/index.js.map +4 -4
- package/dist/remote-api-proxy.d.ts +1 -1
- package/dist/remote-api-proxy.d.ts.map +1 -1
- package/dist/remote-api-proxy.js +22 -2
- package/dist/remote-api-proxy.js.map +1 -1
- package/dist/server-api.d.ts.map +1 -1
- package/dist/server-api.js +0 -1
- package/dist/server-api.js.map +1 -1
- package/dist/server-connection.d.ts +2 -1
- package/dist/server-connection.d.ts.map +1 -1
- package/dist/server-connection.js +4 -1
- package/dist/server-connection.js.map +1 -1
- package/dist/service.d.ts +4 -1
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +33 -2
- package/dist/service.js.map +1 -1
- package/dist/version.d.ts +3 -3
- package/dist/version.js +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4111,7 +4111,8 @@ var helloPayloadSchema = external_exports.object({
|
|
|
4111
4111
|
accessToken: external_exports.string().min(1),
|
|
4112
4112
|
protocols: external_exports.array(external_exports.number().int()).min(1),
|
|
4113
4113
|
capabilities: external_exports.array(external_exports.string()),
|
|
4114
|
-
clientVersion: external_exports.string().optional()
|
|
4114
|
+
clientVersion: external_exports.string().optional(),
|
|
4115
|
+
harnessVersion: external_exports.string().optional()
|
|
4115
4116
|
});
|
|
4116
4117
|
var helloAckPayloadSchema = external_exports.object({
|
|
4117
4118
|
protocol: external_exports.literal(PROTOCOL_VERSION),
|
|
@@ -4359,6 +4360,14 @@ function cryptoRandomId() {
|
|
|
4359
4360
|
}
|
|
4360
4361
|
|
|
4361
4362
|
// ../client-core/dist/index.js
|
|
4363
|
+
var RemoteClientError = class extends Error {
|
|
4364
|
+
code;
|
|
4365
|
+
constructor(code, message, options) {
|
|
4366
|
+
super(message, options);
|
|
4367
|
+
this.code = code;
|
|
4368
|
+
this.name = "RemoteClientError";
|
|
4369
|
+
}
|
|
4370
|
+
};
|
|
4362
4371
|
var RemoteClientCore = class {
|
|
4363
4372
|
transport;
|
|
4364
4373
|
timeoutMs;
|
|
@@ -4367,6 +4376,7 @@ var RemoteClientCore = class {
|
|
|
4367
4376
|
unsubscribeTransport;
|
|
4368
4377
|
unsubscribeClose;
|
|
4369
4378
|
closeHandlers = /* @__PURE__ */ new Set();
|
|
4379
|
+
closeNotified = false;
|
|
4370
4380
|
constructor(transport, timeoutMs = 3e4) {
|
|
4371
4381
|
this.transport = transport;
|
|
4372
4382
|
this.timeoutMs = timeoutMs;
|
|
@@ -4374,6 +4384,7 @@ var RemoteClientCore = class {
|
|
|
4374
4384
|
async connect() {
|
|
4375
4385
|
if (this.unsubscribeTransport !== void 0)
|
|
4376
4386
|
return;
|
|
4387
|
+
this.closeNotified = false;
|
|
4377
4388
|
this.unsubscribeTransport = this.transport.onMessage((data) => this.handleMessage(data));
|
|
4378
4389
|
this.unsubscribeClose = this.transport.onClose?.(() => this.handleTransportClose());
|
|
4379
4390
|
try {
|
|
@@ -4387,23 +4398,24 @@ var RemoteClientCore = class {
|
|
|
4387
4398
|
}
|
|
4388
4399
|
}
|
|
4389
4400
|
async rpc(method, params, signal) {
|
|
4390
|
-
signal?.
|
|
4401
|
+
if (signal?.aborted)
|
|
4402
|
+
throw rpcAbortedError(method, signal.reason);
|
|
4391
4403
|
const request = createRpcRequest(method, params);
|
|
4392
4404
|
const result = new Promise((resolve2, reject) => {
|
|
4393
4405
|
const timer = setTimeout(() => {
|
|
4394
|
-
|
|
4395
|
-
pending2?.removeAbort?.();
|
|
4396
|
-
this.pending.delete(request.id);
|
|
4397
|
-
reject(new Error(`RPC ${method} timed out`));
|
|
4406
|
+
this.rejectPending(request.id, new RemoteClientError("RPC_TIMEOUT", `RPC ${method} timed out after ${this.timeoutMs}ms`));
|
|
4398
4407
|
}, this.timeoutMs);
|
|
4399
|
-
const pending = {
|
|
4408
|
+
const pending = {
|
|
4409
|
+
method,
|
|
4410
|
+
resolve: resolve2,
|
|
4411
|
+
reject,
|
|
4412
|
+
timer
|
|
4413
|
+
};
|
|
4400
4414
|
if (signal !== void 0) {
|
|
4401
4415
|
const onAbort = () => {
|
|
4402
4416
|
if (this.pending.get(request.id) !== pending)
|
|
4403
4417
|
return;
|
|
4404
|
-
|
|
4405
|
-
this.pending.delete(request.id);
|
|
4406
|
-
reject(signal.reason instanceof Error ? signal.reason : new Error("RPC was cancelled"));
|
|
4418
|
+
this.rejectPending(request.id, rpcAbortedError(method, signal.reason));
|
|
4407
4419
|
};
|
|
4408
4420
|
signal.addEventListener("abort", onAbort, { once: true });
|
|
4409
4421
|
pending.removeAbort = () => signal.removeEventListener("abort", onAbort);
|
|
@@ -4411,15 +4423,12 @@ var RemoteClientCore = class {
|
|
|
4411
4423
|
this.pending.set(request.id, pending);
|
|
4412
4424
|
});
|
|
4413
4425
|
try {
|
|
4414
|
-
|
|
4426
|
+
const send = this.transport.send(encodeMessage(request));
|
|
4427
|
+
void send.catch((error) => {
|
|
4428
|
+
this.rejectPending(request.id, transportSendError(error));
|
|
4429
|
+
});
|
|
4415
4430
|
} catch (error) {
|
|
4416
|
-
|
|
4417
|
-
if (pending !== void 0) {
|
|
4418
|
-
clearTimeout(pending.timer);
|
|
4419
|
-
pending.removeAbort?.();
|
|
4420
|
-
}
|
|
4421
|
-
this.pending.delete(request.id);
|
|
4422
|
-
throw error;
|
|
4431
|
+
this.rejectPending(request.id, transportSendError(error));
|
|
4423
4432
|
}
|
|
4424
4433
|
return result;
|
|
4425
4434
|
}
|
|
@@ -4439,23 +4448,13 @@ var RemoteClientCore = class {
|
|
|
4439
4448
|
this.unsubscribeTransport = void 0;
|
|
4440
4449
|
this.unsubscribeClose?.();
|
|
4441
4450
|
this.unsubscribeClose = void 0;
|
|
4451
|
+
this.rejectAllPending((pending) => new RemoteClientError("CLIENT_CLOSED", `RPC ${pending.method} terminated because the remote client closed`));
|
|
4452
|
+
this.notifyClose();
|
|
4442
4453
|
await this.transport.close();
|
|
4443
|
-
for (const pending of this.pending.values()) {
|
|
4444
|
-
clearTimeout(pending.timer);
|
|
4445
|
-
pending.removeAbort?.();
|
|
4446
|
-
pending.reject(new Error("remote client closed"));
|
|
4447
|
-
}
|
|
4448
|
-
this.pending.clear();
|
|
4449
4454
|
}
|
|
4450
4455
|
handleTransportClose() {
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
pending.removeAbort?.();
|
|
4454
|
-
pending.reject(new Error("remote transport closed"));
|
|
4455
|
-
}
|
|
4456
|
-
this.pending.clear();
|
|
4457
|
-
for (const handler of this.closeHandlers)
|
|
4458
|
-
handler();
|
|
4456
|
+
this.rejectAllPending((pending) => new RemoteClientError("TRANSPORT_CLOSED", `RPC ${pending.method} terminated because the remote transport closed`));
|
|
4457
|
+
this.notifyClose();
|
|
4459
4458
|
}
|
|
4460
4459
|
handleMessage(data) {
|
|
4461
4460
|
const message = decodeMessage(data);
|
|
@@ -4470,24 +4469,54 @@ var RemoteClientCore = class {
|
|
|
4470
4469
|
}
|
|
4471
4470
|
}
|
|
4472
4471
|
handleResponse(message) {
|
|
4473
|
-
const pending = this.
|
|
4472
|
+
const pending = this.takePending(message.payload.requestId);
|
|
4474
4473
|
if (pending === void 0)
|
|
4475
4474
|
return;
|
|
4476
|
-
this.pending.delete(message.payload.requestId);
|
|
4477
|
-
clearTimeout(pending.timer);
|
|
4478
|
-
pending.removeAbort?.();
|
|
4479
4475
|
pending.resolve(message.payload.result);
|
|
4480
4476
|
}
|
|
4481
4477
|
handleError(message) {
|
|
4482
|
-
const pending = this.
|
|
4478
|
+
const pending = this.takePending(message.payload.requestId);
|
|
4483
4479
|
if (pending === void 0)
|
|
4484
4480
|
return;
|
|
4485
|
-
|
|
4481
|
+
pending.reject(Object.assign(new Error(message.payload.message), { code: message.payload.code }));
|
|
4482
|
+
}
|
|
4483
|
+
takePending(requestId) {
|
|
4484
|
+
const pending = this.pending.get(requestId);
|
|
4485
|
+
if (pending === void 0)
|
|
4486
|
+
return void 0;
|
|
4487
|
+
this.pending.delete(requestId);
|
|
4486
4488
|
clearTimeout(pending.timer);
|
|
4487
4489
|
pending.removeAbort?.();
|
|
4488
|
-
pending
|
|
4490
|
+
return pending;
|
|
4491
|
+
}
|
|
4492
|
+
rejectPending(requestId, error) {
|
|
4493
|
+
const pending = this.takePending(requestId);
|
|
4494
|
+
if (pending === void 0)
|
|
4495
|
+
return false;
|
|
4496
|
+
pending.reject(error);
|
|
4497
|
+
return true;
|
|
4498
|
+
}
|
|
4499
|
+
rejectAllPending(createError) {
|
|
4500
|
+
for (const requestId of [...this.pending.keys()]) {
|
|
4501
|
+
const pending = this.takePending(requestId);
|
|
4502
|
+
if (pending !== void 0)
|
|
4503
|
+
pending.reject(createError(pending));
|
|
4504
|
+
}
|
|
4505
|
+
}
|
|
4506
|
+
notifyClose() {
|
|
4507
|
+
if (this.closeNotified)
|
|
4508
|
+
return;
|
|
4509
|
+
this.closeNotified = true;
|
|
4510
|
+
for (const handler of this.closeHandlers)
|
|
4511
|
+
handler();
|
|
4489
4512
|
}
|
|
4490
4513
|
};
|
|
4514
|
+
function rpcAbortedError(method, reason) {
|
|
4515
|
+
return new RemoteClientError("RPC_ABORTED", `RPC ${method} was aborted`, reason === void 0 ? void 0 : { cause: reason });
|
|
4516
|
+
}
|
|
4517
|
+
function transportSendError(error) {
|
|
4518
|
+
return error instanceof Error ? error : new Error("remote transport send failed", { cause: error });
|
|
4519
|
+
}
|
|
4491
4520
|
|
|
4492
4521
|
// ../webrtc/dist/transport.js
|
|
4493
4522
|
var BaseTransport = class {
|
|
@@ -4627,6 +4656,9 @@ function adaptDataChannel(raw) {
|
|
|
4627
4656
|
get binaryType() {
|
|
4628
4657
|
return raw.binaryType;
|
|
4629
4658
|
},
|
|
4659
|
+
set binaryType(value) {
|
|
4660
|
+
raw.binaryType = value;
|
|
4661
|
+
},
|
|
4630
4662
|
set onopen(value) {
|
|
4631
4663
|
raw.onopen = value;
|
|
4632
4664
|
},
|
|
@@ -4777,7 +4809,6 @@ function isChunk(frame) {
|
|
|
4777
4809
|
|
|
4778
4810
|
// ../webrtc/dist/rtc-data-channel.js
|
|
4779
4811
|
var DEFAULT_NEGOTIATE_TIMEOUT_MS = 8e3;
|
|
4780
|
-
var DEFAULT_SEND_TIMEOUT_MS = 5e3;
|
|
4781
4812
|
var RtcDataChannelTransport = class {
|
|
4782
4813
|
pc;
|
|
4783
4814
|
role;
|
|
@@ -4811,7 +4842,7 @@ var RtcDataChannelTransport = class {
|
|
|
4811
4842
|
this.onSignal = options.onSignal;
|
|
4812
4843
|
this.negotiateTimeoutMs = options.negotiateTimeoutMs ?? DEFAULT_NEGOTIATE_TIMEOUT_MS;
|
|
4813
4844
|
this.channelLabel = options.channelLabel ?? RTC_DATA_CHANNEL_LABEL;
|
|
4814
|
-
this.sendTimeoutMs = options.sendTimeoutMs
|
|
4845
|
+
this.sendTimeoutMs = options.sendTimeoutMs;
|
|
4815
4846
|
this.pc = options.factory.create({ iceServers: options.iceServers });
|
|
4816
4847
|
this.pc.ondatachannel = (event) => this.adoptChannel(event.channel);
|
|
4817
4848
|
this.pc.onicecandidate = (event) => {
|
|
@@ -5104,11 +5135,16 @@ var RtcDataChannelTransport = class {
|
|
|
5104
5135
|
return channel;
|
|
5105
5136
|
}
|
|
5106
5137
|
armWatchdog(channel) {
|
|
5107
|
-
if (this.
|
|
5138
|
+
if (this.closed || this.sendTimeoutMs === void 0 || this.sendTimeoutMs <= 0)
|
|
5108
5139
|
return;
|
|
5140
|
+
if (this.watchdogTimer !== void 0)
|
|
5141
|
+
clearTimeout(this.watchdogTimer);
|
|
5142
|
+
this.watchdogTimer = void 0;
|
|
5109
5143
|
const baseline = channel.bufferedAmount;
|
|
5110
|
-
if (baseline <= 0)
|
|
5144
|
+
if (baseline <= 0) {
|
|
5145
|
+
this.lastBufferedAmount = 0;
|
|
5111
5146
|
return;
|
|
5147
|
+
}
|
|
5112
5148
|
this.lastBufferedAmount = baseline;
|
|
5113
5149
|
this.watchdogTimer = setTimeout(() => {
|
|
5114
5150
|
this.watchdogTimer = void 0;
|
|
@@ -5499,7 +5535,10 @@ var AdaptiveTransport = class extends BaseTransport {
|
|
|
5499
5535
|
this.bytesReceived += data.byteLength;
|
|
5500
5536
|
this.emit(data);
|
|
5501
5537
|
});
|
|
5502
|
-
rtc.onClose(() =>
|
|
5538
|
+
rtc.onClose(() => {
|
|
5539
|
+
if (this.rtc === rtc && this.dataMode === "webrtc")
|
|
5540
|
+
this.emitClose();
|
|
5541
|
+
});
|
|
5503
5542
|
try {
|
|
5504
5543
|
await rtc.connect();
|
|
5505
5544
|
} catch (error) {
|
|
@@ -12908,7 +12947,7 @@ var RemoteHarnessApiProxy = class {
|
|
|
12908
12947
|
if (String(response.rpcId) !== String(request.rpcId) || typeof response.result !== "object" || response.result === null) {
|
|
12909
12948
|
throw new Error("The remote Host returned an invalid Harness API response.");
|
|
12910
12949
|
}
|
|
12911
|
-
return response;
|
|
12950
|
+
return normalizeLegacyResponse(method, response);
|
|
12912
12951
|
}
|
|
12913
12952
|
async respond(message) {
|
|
12914
12953
|
return this.client.rpc("harness.api.respond", { message });
|
|
@@ -12941,8 +12980,22 @@ var RemoteHarnessApiProxy = class {
|
|
|
12941
12980
|
}
|
|
12942
12981
|
}
|
|
12943
12982
|
};
|
|
12983
|
+
function normalizeLegacyResponse(method, response) {
|
|
12984
|
+
if (method !== "host.describe" || !response.result.ok) return response;
|
|
12985
|
+
const value = response.result.value;
|
|
12986
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) return response;
|
|
12987
|
+
const description = value;
|
|
12988
|
+
if (typeof description.home === "string" || typeof description.cwd !== "string") return response;
|
|
12989
|
+
return {
|
|
12990
|
+
...response,
|
|
12991
|
+
result: {
|
|
12992
|
+
...response.result,
|
|
12993
|
+
value: { ...description, home: description.cwd }
|
|
12994
|
+
}
|
|
12995
|
+
};
|
|
12996
|
+
}
|
|
12944
12997
|
function isRemoteDisconnect(error) {
|
|
12945
|
-
return error instanceof
|
|
12998
|
+
return error instanceof RemoteClientError && (error.code === "TRANSPORT_CLOSED" || error.code === "CLIENT_CLOSED");
|
|
12946
12999
|
}
|
|
12947
13000
|
var AsyncFrameQueue = class {
|
|
12948
13001
|
values = [];
|
|
@@ -13068,7 +13121,7 @@ function normalizeServerUrl(value) {
|
|
|
13068
13121
|
}
|
|
13069
13122
|
|
|
13070
13123
|
// src/version.ts
|
|
13071
|
-
var PLUGIN_VERSION = "0.3.
|
|
13124
|
+
var PLUGIN_VERSION = "0.3.21";
|
|
13072
13125
|
|
|
13073
13126
|
// src/server-api.ts
|
|
13074
13127
|
var HostServerApi = class {
|
|
@@ -13291,8 +13344,7 @@ var HostServerApi = class {
|
|
|
13291
13344
|
role: this.role,
|
|
13292
13345
|
platform: platform(),
|
|
13293
13346
|
identityKey: identity.publicKey,
|
|
13294
|
-
clientVersion: PLUGIN_VERSION
|
|
13295
|
-
...this.role === "host" ? { harnessVersion: "0.1.0-rc.6" } : {}
|
|
13347
|
+
clientVersion: PLUGIN_VERSION
|
|
13296
13348
|
};
|
|
13297
13349
|
}
|
|
13298
13350
|
saveTokens(identity, tokens, authorization) {
|
|
@@ -13711,6 +13763,7 @@ var ClientModeRuntime = class {
|
|
|
13711
13763
|
}
|
|
13712
13764
|
identity;
|
|
13713
13765
|
connected;
|
|
13766
|
+
pendingWorkspaceSelection;
|
|
13714
13767
|
proxySwitch;
|
|
13715
13768
|
gatewaySwitch;
|
|
13716
13769
|
closed = false;
|
|
@@ -13740,6 +13793,7 @@ var ClientModeRuntime = class {
|
|
|
13740
13793
|
connected: this.connected !== void 0,
|
|
13741
13794
|
transport: this.connected?.client.getStats().mode ?? "Disconnected",
|
|
13742
13795
|
remoteFeatures: this.connected?.features ?? remoteHostFeatures(),
|
|
13796
|
+
...this.pendingWorkspaceSelection === void 0 ? {} : { workspaceSelection: { ...this.pendingWorkspaceSelection } },
|
|
13743
13797
|
hostAuthorizationAvailable: this.host !== void 0,
|
|
13744
13798
|
...this.host === void 0 ? {} : { host: this.host.hostStatus() }
|
|
13745
13799
|
};
|
|
@@ -13808,6 +13862,7 @@ var ClientModeRuntime = class {
|
|
|
13808
13862
|
async clearClientAuthorization() {
|
|
13809
13863
|
const previous = this.connected;
|
|
13810
13864
|
this.connected = void 0;
|
|
13865
|
+
this.pendingWorkspaceSelection = void 0;
|
|
13811
13866
|
this.proxySwitch.selectLocal();
|
|
13812
13867
|
this.gatewaySwitch.selectLocal();
|
|
13813
13868
|
await previous?.client.close().catch(() => void 0);
|
|
@@ -13831,6 +13886,7 @@ var ClientModeRuntime = class {
|
|
|
13831
13886
|
this.gatewaySwitch.selectLocal();
|
|
13832
13887
|
const previous2 = this.connected;
|
|
13833
13888
|
this.connected = void 0;
|
|
13889
|
+
this.pendingWorkspaceSelection = void 0;
|
|
13834
13890
|
await previous2?.client.close().catch(() => void 0);
|
|
13835
13891
|
this.logger.info("Harness target switched", { mode: "local" });
|
|
13836
13892
|
return this.status();
|
|
@@ -13841,6 +13897,7 @@ var ClientModeRuntime = class {
|
|
|
13841
13897
|
const next = await this.connect(targetDeviceId, signal);
|
|
13842
13898
|
const previous = this.connected;
|
|
13843
13899
|
this.connected = next;
|
|
13900
|
+
this.pendingWorkspaceSelection = void 0;
|
|
13844
13901
|
const remoteApi = new RemoteHarnessApiProxy(next.client).api;
|
|
13845
13902
|
this.proxySwitch.selectRemote(remoteApi, { deviceId: next.target.deviceId, name: next.target.name });
|
|
13846
13903
|
this.selectRemoteCommands(next);
|
|
@@ -13878,14 +13935,24 @@ var ClientModeRuntime = class {
|
|
|
13878
13935
|
const workspace = unwrapNativeResult(response);
|
|
13879
13936
|
this.proxySwitch.selectRemote(api, { deviceId: remote.target.deviceId, name: remote.target.name });
|
|
13880
13937
|
this.selectRemoteCommands(remote);
|
|
13938
|
+
const workspaceId = workspaceRecordId(workspace.workspace);
|
|
13939
|
+
this.pendingWorkspaceSelection = { targetDeviceId: remote.target.deviceId, workspaceId };
|
|
13881
13940
|
this.logger.info("Remote workspace opened", { targetDeviceId: shortId(remote.target.deviceId) });
|
|
13882
13941
|
return { ...this.status(), workspace };
|
|
13883
13942
|
}
|
|
13943
|
+
consumeWorkspaceSelection(selection) {
|
|
13944
|
+
const pending = this.pendingWorkspaceSelection;
|
|
13945
|
+
if (pending?.targetDeviceId === selection.targetDeviceId && pending.workspaceId === selection.workspaceId) {
|
|
13946
|
+
this.pendingWorkspaceSelection = void 0;
|
|
13947
|
+
}
|
|
13948
|
+
return this.status();
|
|
13949
|
+
}
|
|
13884
13950
|
async close() {
|
|
13885
13951
|
if (this.closed) return;
|
|
13886
13952
|
this.closed = true;
|
|
13887
13953
|
this.proxySwitch.selectLocal();
|
|
13888
13954
|
this.gatewaySwitch.selectLocal();
|
|
13955
|
+
this.pendingWorkspaceSelection = void 0;
|
|
13889
13956
|
await this.connected?.client.close().catch(() => void 0);
|
|
13890
13957
|
this.connected = void 0;
|
|
13891
13958
|
this.proxySwitch.restore();
|
|
@@ -13958,6 +14025,7 @@ var ClientModeRuntime = class {
|
|
|
13958
14025
|
client.onClose(() => {
|
|
13959
14026
|
if (this.connected?.client !== client) return;
|
|
13960
14027
|
this.connected = void 0;
|
|
14028
|
+
this.pendingWorkspaceSelection = void 0;
|
|
13961
14029
|
this.proxySwitch.selectLocal();
|
|
13962
14030
|
this.gatewaySwitch.selectLocal();
|
|
13963
14031
|
void client.close().catch(() => void 0);
|
|
@@ -14023,6 +14091,16 @@ var ClientModeRuntime = class {
|
|
|
14023
14091
|
}
|
|
14024
14092
|
return ok(await this.openRemoteWorkspace(value.targetDeviceId, value.path, signal));
|
|
14025
14093
|
}
|
|
14094
|
+
if (endpoint === "workspace.selection.consume") {
|
|
14095
|
+
const value = record(payload);
|
|
14096
|
+
if (typeof value.targetDeviceId !== "string" || typeof value.workspaceId !== "string") {
|
|
14097
|
+
throw new ClientModeError("INVALID_MESSAGE", "A Host and Workspace are required.");
|
|
14098
|
+
}
|
|
14099
|
+
return ok(this.consumeWorkspaceSelection({
|
|
14100
|
+
targetDeviceId: value.targetDeviceId,
|
|
14101
|
+
workspaceId: value.workspaceId
|
|
14102
|
+
}));
|
|
14103
|
+
}
|
|
14026
14104
|
if (endpoint === "fileviewer.stat" || endpoint === "fileviewer.readRange" || endpoint === "fileviewer.list") {
|
|
14027
14105
|
const method = endpoint === "fileviewer.stat" ? "stat" : endpoint === "fileviewer.readRange" ? "readRange" : "list";
|
|
14028
14106
|
return ok(await this.callRemoteFileViewer(method, payload, signal));
|
|
@@ -14133,6 +14211,12 @@ function unwrapNativeResult(response) {
|
|
|
14133
14211
|
}
|
|
14134
14212
|
return result.value;
|
|
14135
14213
|
}
|
|
14214
|
+
function workspaceRecordId(value) {
|
|
14215
|
+
if (typeof value !== "object" || value === null || !("workspaceId" in value) || typeof value.workspaceId !== "string" || value.workspaceId.length === 0) {
|
|
14216
|
+
throw new ClientModeError("INVALID_MESSAGE", "The remote Host returned an invalid Workspace.");
|
|
14217
|
+
}
|
|
14218
|
+
return value.workspaceId;
|
|
14219
|
+
}
|
|
14136
14220
|
function fail(error) {
|
|
14137
14221
|
const source = error instanceof Error ? error : void 0;
|
|
14138
14222
|
const remoteCode = source !== void 0 && "code" in source && typeof source.code === "string" ? source.code : source instanceof ClientModeError ? source.code : void 0;
|
|
@@ -14680,6 +14764,10 @@ function redact(value, key = "") {
|
|
|
14680
14764
|
return Object.fromEntries(Object.entries(value).map(([childKey, child]) => [childKey, redact(child, childKey)]));
|
|
14681
14765
|
}
|
|
14682
14766
|
|
|
14767
|
+
// src/service.ts
|
|
14768
|
+
import { randomUUID } from "node:crypto";
|
|
14769
|
+
import { RpcId } from "@deepseek-ai/dsh-host-apiproxy/api";
|
|
14770
|
+
|
|
14683
14771
|
// src/connection-controller.ts
|
|
14684
14772
|
var ConnectionController = class {
|
|
14685
14773
|
constructor(identities, createRouter, logger) {
|
|
@@ -14848,6 +14936,36 @@ function shortId2(value) {
|
|
|
14848
14936
|
return value.length <= 12 ? value : `${value.slice(0, 8)}\u2026${value.slice(-4)}`;
|
|
14849
14937
|
}
|
|
14850
14938
|
|
|
14939
|
+
// src/harness-version.ts
|
|
14940
|
+
import { readFile as readFile3 } from "node:fs/promises";
|
|
14941
|
+
import { dirname as dirname3, isAbsolute, join as join3 } from "node:path";
|
|
14942
|
+
var LEGACY_PLACEHOLDER_VERSION = "0.0.1";
|
|
14943
|
+
function normalizeHarnessVersion(value) {
|
|
14944
|
+
if (typeof value !== "string") return void 0;
|
|
14945
|
+
const version = value.trim();
|
|
14946
|
+
if (version.length === 0 || version.length > 64 || /[\u0000-\u001f]/u.test(version)) return void 0;
|
|
14947
|
+
return version;
|
|
14948
|
+
}
|
|
14949
|
+
function selectHarnessVersion(reportedVersion, distributionVersion) {
|
|
14950
|
+
if (reportedVersion !== void 0 && reportedVersion !== LEGACY_PLACEHOLDER_VERSION) return reportedVersion;
|
|
14951
|
+
return distributionVersion;
|
|
14952
|
+
}
|
|
14953
|
+
async function readHarnessDistributionVersion(entrypoint = process.argv[1]) {
|
|
14954
|
+
if (entrypoint === void 0 || !isAbsolute(entrypoint)) return void 0;
|
|
14955
|
+
let directory = dirname3(entrypoint);
|
|
14956
|
+
for (let depth = 0; depth < 8; depth += 1) {
|
|
14957
|
+
try {
|
|
14958
|
+
const manifest = JSON.parse(await readFile3(join3(directory, "package.json"), "utf8"));
|
|
14959
|
+
if (manifest.name === "@deepseek-ai/dsh") return normalizeHarnessVersion(manifest.version);
|
|
14960
|
+
} catch {
|
|
14961
|
+
}
|
|
14962
|
+
const parent = dirname3(directory);
|
|
14963
|
+
if (parent === directory) break;
|
|
14964
|
+
directory = parent;
|
|
14965
|
+
}
|
|
14966
|
+
return void 0;
|
|
14967
|
+
}
|
|
14968
|
+
|
|
14851
14969
|
// src/rpc-router.ts
|
|
14852
14970
|
var wireRequestSchema = external_exports.object({ method: external_exports.string().min(1), params: external_exports.unknown() }).strict();
|
|
14853
14971
|
var apiMethods = /* @__PURE__ */ new Set([
|
|
@@ -15067,7 +15185,7 @@ function isOversizedListing(value) {
|
|
|
15067
15185
|
// src/server-connection.ts
|
|
15068
15186
|
var DEFAULT_WEBRTC_NEGOTIATE_TIMEOUT_MS = 8e3;
|
|
15069
15187
|
var HostServerConnection = class {
|
|
15070
|
-
constructor(config, identity, identities, api, connections, logger, createWebSocket = (url) => new WebSocket(url), rtcFactoryProvider, hostCapabilities = () => ["harness.api.v1"]) {
|
|
15188
|
+
constructor(config, identity, identities, api, connections, logger, createWebSocket = (url) => new WebSocket(url), rtcFactoryProvider, hostCapabilities = () => ["harness.api.v1"], harnessVersion) {
|
|
15071
15189
|
this.config = config;
|
|
15072
15190
|
this.identity = identity;
|
|
15073
15191
|
this.identities = identities;
|
|
@@ -15077,6 +15195,7 @@ var HostServerConnection = class {
|
|
|
15077
15195
|
this.createWebSocket = createWebSocket;
|
|
15078
15196
|
this.rtcFactoryProvider = rtcFactoryProvider;
|
|
15079
15197
|
this.hostCapabilities = hostCapabilities;
|
|
15198
|
+
this.harnessVersion = harnessVersion;
|
|
15080
15199
|
}
|
|
15081
15200
|
socket;
|
|
15082
15201
|
running;
|
|
@@ -15200,6 +15319,7 @@ var HostServerConnection = class {
|
|
|
15200
15319
|
accessToken: credentials.accessToken,
|
|
15201
15320
|
protocols: [PROTOCOL_VERSION],
|
|
15202
15321
|
clientVersion: PLUGIN_VERSION,
|
|
15322
|
+
...this.harnessVersion === void 0 ? {} : { harnessVersion: this.harnessVersion },
|
|
15203
15323
|
capabilities: this.rtcFactoryProvider === void 0 || this.config.forceRelay ? ["transport.relay", ...this.hostCapabilities()] : ["transport.p2p", "transport.turn", "transport.relay", ...this.hostCapabilities()]
|
|
15204
15324
|
});
|
|
15205
15325
|
};
|
|
@@ -15752,13 +15872,13 @@ function closeCode(code) {
|
|
|
15752
15872
|
// src/remote-directory-browser.ts
|
|
15753
15873
|
import { readdir, stat as stat3 } from "node:fs/promises";
|
|
15754
15874
|
import { homedir as homedir2, platform as platform2 } from "node:os";
|
|
15755
|
-
import { basename, dirname as
|
|
15875
|
+
import { basename, dirname as dirname4, isAbsolute as isAbsolute2, parse, resolve } from "node:path";
|
|
15756
15876
|
var MAX_ENTRIES = 500;
|
|
15757
15877
|
async function listRemoteDirectory(path, signal) {
|
|
15758
15878
|
signal?.throwIfAborted();
|
|
15759
15879
|
const home = resolve(homedir2());
|
|
15760
15880
|
const target = path === void 0 || path.trim() === "" ? home : resolve(path);
|
|
15761
|
-
if (!
|
|
15881
|
+
if (!isAbsolute2(target)) throw new Error("The remote directory path must be absolute.");
|
|
15762
15882
|
const rows = await readdir(target, { withFileTypes: true });
|
|
15763
15883
|
const directories = [];
|
|
15764
15884
|
for (const row of rows) {
|
|
@@ -15785,7 +15905,7 @@ function crumbs(path) {
|
|
|
15785
15905
|
let current = path;
|
|
15786
15906
|
while (current !== root) {
|
|
15787
15907
|
segments.unshift(basename(current));
|
|
15788
|
-
current =
|
|
15908
|
+
current = dirname4(current);
|
|
15789
15909
|
}
|
|
15790
15910
|
for (const segment of segments) {
|
|
15791
15911
|
current = resolve(current, segment);
|
|
@@ -15870,7 +15990,7 @@ var HARNESS_API_ALLOWLIST = [
|
|
|
15870
15990
|
var NATIVE_CALL_TIMEOUT_MS = 3e4;
|
|
15871
15991
|
var SESSION_HISTORY_PAGE_SIZES = [50, 30, 20, 12, 6, 3, 1];
|
|
15872
15992
|
var HarnessApiBridge = class {
|
|
15873
|
-
constructor(api, publish, maxStreams =
|
|
15993
|
+
constructor(api, publish, maxStreams = 8, logger, typertGateway) {
|
|
15874
15994
|
this.api = api;
|
|
15875
15995
|
this.publish = publish;
|
|
15876
15996
|
this.maxStreams = maxStreams;
|
|
@@ -16149,11 +16269,12 @@ var HostPluginRuntime = class {
|
|
|
16149
16269
|
constructor(config, identities, apiProxy, logger, typertGateway, fileViewerHost) {
|
|
16150
16270
|
this.config = config;
|
|
16151
16271
|
this.identities = identities;
|
|
16272
|
+
this.apiProxy = apiProxy;
|
|
16152
16273
|
this.logger = logger;
|
|
16153
16274
|
this.fileViewerHost = fileViewerHost;
|
|
16154
16275
|
this.connections = new ConnectionController(this.identities, (_context, send) => {
|
|
16155
16276
|
const harnessApi = new HarnessApiBridge(
|
|
16156
|
-
apiProxy,
|
|
16277
|
+
this.apiProxy,
|
|
16157
16278
|
(event, data) => send(createEvent(event, data)),
|
|
16158
16279
|
void 0,
|
|
16159
16280
|
this.logger,
|
|
@@ -16173,6 +16294,7 @@ var HostPluginRuntime = class {
|
|
|
16173
16294
|
identity;
|
|
16174
16295
|
serverApi;
|
|
16175
16296
|
serverConnection;
|
|
16297
|
+
harnessVersion;
|
|
16176
16298
|
closed = false;
|
|
16177
16299
|
async start() {
|
|
16178
16300
|
if (this.closed) throw new Error("remote runtime is closed");
|
|
@@ -16183,6 +16305,7 @@ var HostPluginRuntime = class {
|
|
|
16183
16305
|
server: this.config.serverUrl ?? "not configured"
|
|
16184
16306
|
});
|
|
16185
16307
|
if (this.serverApi !== void 0) {
|
|
16308
|
+
this.harnessVersion = await this.readHarnessVersion();
|
|
16186
16309
|
this.serverApi.bindIdentity(this.identity);
|
|
16187
16310
|
this.serverConnection = this.createServerConnection(this.identity);
|
|
16188
16311
|
this.serverConnection.start();
|
|
@@ -16301,9 +16424,28 @@ var HostPluginRuntime = class {
|
|
|
16301
16424
|
this.logger,
|
|
16302
16425
|
void 0,
|
|
16303
16426
|
this.config.forceRelay ? void 0 : loadWeriftFactory,
|
|
16304
|
-
() => this.fileViewerHost?.() === void 0 ? ["harness.api.v1"] : ["harness.api.v1", "fileviewer.read.v1"]
|
|
16427
|
+
() => this.fileViewerHost?.() === void 0 ? ["harness.api.v1"] : ["harness.api.v1", "fileviewer.read.v1"],
|
|
16428
|
+
this.harnessVersion
|
|
16305
16429
|
);
|
|
16306
16430
|
}
|
|
16431
|
+
async readHarnessVersion() {
|
|
16432
|
+
let reportedVersion;
|
|
16433
|
+
let errorCode2;
|
|
16434
|
+
try {
|
|
16435
|
+
const response = await this.apiProxy.host.describe({ rpcId: RpcId(randomUUID()), payload: {} });
|
|
16436
|
+
if (!response.result.ok) {
|
|
16437
|
+
errorCode2 = response.result.error.code;
|
|
16438
|
+
} else {
|
|
16439
|
+
reportedVersion = normalizeHarnessVersion(response.result.value.version);
|
|
16440
|
+
}
|
|
16441
|
+
} catch {
|
|
16442
|
+
}
|
|
16443
|
+
const distributionVersion = reportedVersion === void 0 || reportedVersion === "0.0.1" ? await readHarnessDistributionVersion() : void 0;
|
|
16444
|
+
const version = selectHarnessVersion(reportedVersion, distributionVersion);
|
|
16445
|
+
if (version !== void 0) return version;
|
|
16446
|
+
this.logger.warn("Harness version is unavailable", errorCode2 === void 0 ? void 0 : { code: errorCode2 });
|
|
16447
|
+
return void 0;
|
|
16448
|
+
}
|
|
16307
16449
|
};
|
|
16308
16450
|
function shortId5(value) {
|
|
16309
16451
|
return value.length <= 12 ? value : `${value.slice(0, 8)}\u2026${value.slice(-4)}`;
|