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.
- package/README.md +6 -8
- package/dist/acp/virtual-contract.d.ts +0 -1
- package/dist/acp/virtual-contract.d.ts.map +1 -1
- package/dist/acp/virtual-contract.js +0 -5
- package/dist/acp/virtual-contract.js.map +1 -1
- package/dist/acp/virtual-event-carrier.d.ts +0 -10
- package/dist/acp/virtual-event-carrier.d.ts.map +1 -1
- package/dist/acp/virtual-event-carrier.js +1 -129
- package/dist/acp/virtual-event-carrier.js.map +1 -1
- package/dist/acp/virtual-harness.d.ts +0 -4
- package/dist/acp/virtual-harness.d.ts.map +1 -1
- package/dist/acp/virtual-harness.js +0 -14
- package/dist/acp/virtual-harness.js.map +1 -1
- package/dist/acp/virtual-live.d.ts +0 -1
- package/dist/acp/virtual-live.d.ts.map +1 -1
- package/dist/acp/virtual-live.js +0 -5
- package/dist/acp/virtual-live.js.map +1 -1
- package/dist/client/shell.js +1 -1
- package/dist/client/shell.js.map +1 -1
- package/dist/client/workspaces.d.ts.map +1 -1
- package/dist/client/workspaces.js +38 -28
- package/dist/client/workspaces.js.map +1 -1
- package/dist/client-capabilities.d.ts +1 -1
- package/dist/client-capabilities.d.ts.map +1 -1
- package/dist/client-capabilities.js +8 -28
- package/dist/client-capabilities.js.map +1 -1
- package/dist/client-connection.d.ts +0 -2
- package/dist/client-connection.d.ts.map +1 -1
- package/dist/client-connection.js +0 -1
- package/dist/client-connection.js.map +1 -1
- package/dist/client-control.d.ts +3 -3
- package/dist/client-control.d.ts.map +1 -1
- package/dist/client-runtime-contract.d.ts +4 -6
- package/dist/client-runtime-contract.d.ts.map +1 -1
- package/dist/client-runtime-contract.js.map +1 -1
- package/dist/client-runtime.d.ts +4 -6
- package/dist/client-runtime.d.ts.map +1 -1
- package/dist/client-runtime.js +25 -89
- package/dist/client-runtime.js.map +1 -1
- package/dist/client-workspace-queries.d.ts +0 -6
- package/dist/client-workspace-queries.d.ts.map +1 -1
- package/dist/client-workspace-queries.js +0 -27
- package/dist/client-workspace-queries.js.map +1 -1
- package/dist/client.github.js +4 -3
- package/dist/client.js +4 -3
- package/dist/codex/virtual-contract.d.ts +0 -2
- package/dist/codex/virtual-contract.d.ts.map +1 -1
- package/dist/codex/virtual-contract.js +0 -5
- package/dist/codex/virtual-contract.js.map +1 -1
- package/dist/codex/virtual-event-carrier.d.ts +0 -10
- package/dist/codex/virtual-event-carrier.d.ts.map +1 -1
- package/dist/codex/virtual-event-carrier.js +2 -129
- package/dist/codex/virtual-event-carrier.js.map +1 -1
- package/dist/codex/virtual-harness.d.ts +1 -5
- package/dist/codex/virtual-harness.d.ts.map +1 -1
- package/dist/codex/virtual-harness.js +1 -21
- package/dist/codex/virtual-harness.js.map +1 -1
- package/dist/codex/virtual-live.d.ts +0 -4
- package/dist/codex/virtual-live.d.ts.map +1 -1
- package/dist/codex/virtual-live.js +4 -80
- package/dist/codex/virtual-live.js.map +1 -1
- package/dist/control-result.d.ts +13 -0
- package/dist/control-result.d.ts.map +1 -0
- package/dist/control-result.js +2 -0
- package/dist/control-result.js.map +1 -0
- package/dist/control-route.d.ts +2 -2
- package/dist/control-route.d.ts.map +1 -1
- package/dist/control-runtime.js.map +1 -1
- package/dist/harness-remote-bridge.d.ts +2 -0
- package/dist/harness-remote-bridge.d.ts.map +1 -1
- package/dist/harness-remote-bridge.js +53 -5
- package/dist/harness-remote-bridge.js.map +1 -1
- package/dist/harness-target.d.ts +2 -0
- package/dist/harness-target.d.ts.map +1 -0
- package/dist/harness-target.js +2 -0
- package/dist/harness-target.js.map +1 -0
- package/dist/harness-version.d.ts +0 -1
- package/dist/harness-version.d.ts.map +1 -1
- package/dist/harness-version.js +0 -6
- package/dist/harness-version.js.map +1 -1
- package/dist/index.d.ts +0 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +419 -2126
- package/dist/index.js.map +4 -4
- package/dist/native-rtc-helper.d.ts +1 -0
- package/dist/native-rtc-helper.d.ts.map +1 -1
- package/dist/native-rtc-helper.js +5 -2
- package/dist/native-rtc-helper.js.map +1 -1
- package/dist/plugin-route-bridge.d.ts +1 -1
- package/dist/plugin-route-bridge.d.ts.map +1 -1
- package/dist/plugin-route-bridge.js +1 -1
- package/dist/plugin-route-bridge.js.map +1 -1
- package/dist/remote-typert-gateway.d.ts +2 -0
- package/dist/remote-typert-gateway.d.ts.map +1 -1
- package/dist/remote-typert-gateway.js +76 -26
- package/dist/remote-typert-gateway.js.map +1 -1
- package/dist/rpc-router.d.ts +2 -5
- package/dist/rpc-router.d.ts.map +1 -1
- package/dist/rpc-router.js +5 -32
- package/dist/rpc-router.js.map +1 -1
- package/dist/server-connection.d.ts.map +1 -1
- package/dist/server-connection.js +1 -1
- package/dist/server-connection.js.map +1 -1
- package/dist/service.d.ts +1 -3
- package/dist/service.d.ts.map +1 -1
- package/dist/service.js +9 -38
- package/dist/service.js.map +1 -1
- package/dist/tui-command.js +5 -7
- package/dist/tui-command.js.map +1 -1
- package/dist/typert-gateway-contract.d.ts +1 -1
- package/dist/typert-gateway-contract.d.ts.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/dsh-plugin.json +1 -1
- package/package.json +1 -2
- package/dist/api-proxy-switch.d.ts +0 -35
- package/dist/api-proxy-switch.d.ts.map +0 -1
- package/dist/api-proxy-switch.js +0 -118
- package/dist/api-proxy-switch.js.map +0 -1
- package/dist/harness-api-bridge.d.ts +0 -80
- package/dist/harness-api-bridge.d.ts.map +0 -1
- package/dist/harness-api-bridge.js +0 -862
- package/dist/harness-api-bridge.js.map +0 -1
- package/dist/harness-api-history.d.ts +0 -3
- package/dist/harness-api-history.d.ts.map +0 -1
- package/dist/harness-api-history.js +0 -55
- package/dist/harness-api-history.js.map +0 -1
- package/dist/remote-api-proxy.d.ts +0 -17
- package/dist/remote-api-proxy.d.ts.map +0 -1
- package/dist/remote-api-proxy.js +0 -400
- 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:
|
|
14914
|
-
fileViewer:
|
|
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")
|
|
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 (!
|
|
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
|
|
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
|
-
|
|
25137
|
-
|
|
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"
|
|
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"
|
|
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/
|
|
26348
|
-
|
|
26349
|
-
|
|
26350
|
-
|
|
26351
|
-
|
|
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
|
-
|
|
26441
|
-
|
|
26442
|
-
|
|
26443
|
-
|
|
26444
|
-
|
|
26445
|
-
|
|
26446
|
-
|
|
26447
|
-
|
|
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
|
-
|
|
26458
|
-
|
|
26459
|
-
|
|
26460
|
-
|
|
26461
|
-
|
|
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
|
-
|
|
26464
|
-
|
|
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
|
|
25920
|
+
return isRecord7(value) && value.type === "event" && isRecord7(value.event);
|
|
26770
25921
|
}
|
|
26771
25922
|
function normalizeHeader(value) {
|
|
26772
|
-
if (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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" &&
|
|
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 (!
|
|
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 (!
|
|
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
|
|
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
|
|
26868
|
-
var
|
|
26869
|
-
var
|
|
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 (!
|
|
26913
|
-
if (endpoint === "settings/describe" && result.ok &&
|
|
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:
|
|
26067
|
+
return this.legacyWelcomeAcknowledged ? { ...result, value: patchWelcomeDescribe(result.value) } : void 0;
|
|
26916
26068
|
}
|
|
26917
|
-
if (endpoint !== "settings/mutate" || !
|
|
26069
|
+
if (endpoint !== "settings/mutate" || !isRecord8(payload) || !isRecord8(payload.args)) return void 0;
|
|
26918
26070
|
const args = payload.args;
|
|
26919
|
-
if (args.ns !==
|
|
26920
|
-
const value =
|
|
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
|
|
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 = () =>
|
|
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", {
|
|
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
|
|
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:
|
|
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
|
|
26177
|
+
if (committed.transferId !== transferId) {
|
|
26986
26178
|
throw new Error("The remote Host returned an invalid Harness Remote transfer descriptor.");
|
|
26987
26179
|
}
|
|
26988
|
-
|
|
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
|
|
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
|
|
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:
|
|
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 (!
|
|
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 || !
|
|
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
|
|
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
|
|
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 (
|
|
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 (!
|
|
27127
|
-
return { ...value, data:
|
|
26326
|
+
if (!isRecord8(value) || typeof value.data !== "string") return value;
|
|
26327
|
+
return { ...value, data: base64ToBytes2(value.data) };
|
|
27128
26328
|
}
|
|
27129
|
-
function
|
|
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
|
|
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) =>
|
|
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
|
|
26344
|
+
function patchWelcomeDescribe(value) {
|
|
27145
26345
|
if (!Array.isArray(value.namespaces)) return value;
|
|
27146
26346
|
const namespaces = value.namespaces.map((namespace) => {
|
|
27147
|
-
if (!
|
|
27148
|
-
const current =
|
|
27149
|
-
return { ...namespace, value: { ...current, [
|
|
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" || !
|
|
27155
|
-
return Number.isSafeInteger(value.asOfSeq) &&
|
|
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 || !
|
|
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 (!
|
|
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.
|
|
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 (
|
|
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 (
|
|
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 (
|
|
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
|
|
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 &&
|
|
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 || !
|
|
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 (!
|
|
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
|
|
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" || !
|
|
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
|
-
|
|
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,
|
|
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.
|
|
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
|
-
|
|
29795
|
-
|
|
29796
|
-
|
|
29797
|
-
|
|
29798
|
-
|
|
29799
|
-
|
|
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
|
-
|
|
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
|
-
|
|
29827
|
-
|
|
29828
|
-
|
|
29829
|
-
|
|
29830
|
-
|
|
29831
|
-
|
|
29832
|
-
|
|
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
|
|
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
|
|
29250
|
+
selectRemoteTarget(remote) {
|
|
29251
|
+
this.assertRemoteCompatible(remote);
|
|
30086
29252
|
const target2 = { deviceId: remote.target.deviceId, name: remote.target.name };
|
|
30087
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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()
|
|
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 (!
|
|
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 (!
|
|
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
|
|
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
|
|
30423
|
+
function isRecord12(value) {
|
|
31280
30424
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
31281
30425
|
}
|
|
31282
30426
|
function safeErrorCode2(error) {
|
|
31283
|
-
if (
|
|
30427
|
+
if (isRecord12(error) && typeof error.code === "string") return error.code;
|
|
31284
30428
|
return "UNKNOWN";
|
|
31285
30429
|
}
|
|
31286
30430
|
function safeMethod(input3) {
|
|
31287
|
-
return
|
|
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 = { ...
|
|
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 =
|
|
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) => !
|
|
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 (!
|
|
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 (!
|
|
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) => !
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
32252
|
-
if (value.type === "image" &&
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
32302
|
-
return result.requiresOpenaiAuth === false ||
|
|
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 (!
|
|
32306
|
-
const account =
|
|
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 (!
|
|
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 (!
|
|
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
|
-
...
|
|
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 (!
|
|
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) =>
|
|
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 (!
|
|
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 =
|
|
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 (!
|
|
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 =
|
|
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
|
|
31556
|
+
return isRecord13(result) && isRecord13(result.thread) ? result.thread : void 0;
|
|
32413
31557
|
}
|
|
32414
31558
|
function extractTurnId(result) {
|
|
32415
|
-
if (!
|
|
31559
|
+
if (!isRecord13(result)) return void 0;
|
|
32416
31560
|
if (typeof result.turnId === "string" && result.turnId.length > 0) return result.turnId;
|
|
32417
|
-
if (
|
|
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 (!
|
|
31565
|
+
if (!isRecord13(params)) return void 0;
|
|
32422
31566
|
if (typeof params.threadId === "string") return params.threadId;
|
|
32423
|
-
if (
|
|
32424
|
-
if (
|
|
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 (!
|
|
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 (!
|
|
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
|
|
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 =
|
|
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 =
|
|
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 (!
|
|
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" &&
|
|
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 (!
|
|
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
|
|
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 =
|
|
34122
|
-
return
|
|
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
|
|
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 =
|
|
34137
|
-
if (options !== void 0 &&
|
|
34138
|
-
return
|
|
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 =
|
|
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 &&
|
|
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 (!
|
|
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 =
|
|
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 (!
|
|
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" &&
|
|
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" &&
|
|
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 (!
|
|
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
|
|
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
|
|
35861
|
+
function isRecord17(value) {
|
|
36718
35862
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
36719
35863
|
}
|
|
36720
35864
|
function safeErrorCode3(error) {
|
|
36721
|
-
if (
|
|
35865
|
+
if (isRecord17(error) && typeof error.code === "string") return error.code;
|
|
36722
35866
|
return "UNKNOWN";
|
|
36723
35867
|
}
|
|
36724
35868
|
function safeMethod2(input3) {
|
|
36725
|
-
return
|
|
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) =>
|
|
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 =
|
|
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
|
-
...
|
|
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 =
|
|
37598
|
-
const update = params !== void 0 &&
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
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 (!
|
|
37883
|
-
if (
|
|
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 (!
|
|
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
|
|
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
|
|
37486
|
+
function isRecord19(value) {
|
|
38343
37487
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
38344
37488
|
}
|
|
38345
37489
|
function record7(value) {
|
|
38346
|
-
if (!
|
|
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(
|
|
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([
|
|
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.
|
|
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 = () => [
|
|
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
|
|
41011
|
-
var
|
|
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
|
|
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
|
|
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
|
|
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
|
|
41046
|
-
var
|
|
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
|
|
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
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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(
|
|
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(
|
|
39579
|
+
const response = await this.call(callSchema3.parse(request));
|
|
41294
39580
|
const responseBytes = new TextEncoder().encode(JSON.stringify(response));
|
|
41295
|
-
if (responseBytes.byteLength <=
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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 =
|
|
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) =>
|
|
41390
|
-
if (!
|
|
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) => !
|
|
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)
|
|
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 (!
|
|
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 (!
|
|
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
|
|
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
|
|
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) => !
|
|
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) => !
|
|
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" &&
|
|
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 =
|
|
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
|
|
39891
|
+
return isRecord20(value) ? value : {};
|
|
41563
39892
|
}
|
|
41564
|
-
function
|
|
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,
|
|
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:
|
|
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 :
|
|
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 :
|
|
41937
|
-
peerDeviceIds: this.connections.peerDeviceIds().map(
|
|
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
|
-
|
|
41961
|
-
|
|
41962
|
-
|
|
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
|
|
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.
|
|
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 ||
|
|
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,
|