@gatherthread/dsh-host 0.1.0-alpha.5 → 0.1.0-alpha.6
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 +20 -5
- package/bundle/manifest.json +1 -1
- package/client/client.js +7 -0
- package/cordis.patch.yml +18 -0
- package/dist/bundle/native-plugin.js +606 -71
- package/dist/bundle/plugin.js +445 -68
- package/package.json +1 -1
package/dist/bundle/plugin.js
CHANGED
|
@@ -432,7 +432,7 @@ var HttpCollaborationClient = class {
|
|
|
432
432
|
async registerRuntime(runtime) {
|
|
433
433
|
const body = requiredObject2(await this.#request("/runtimes", {
|
|
434
434
|
method: "POST",
|
|
435
|
-
body: JSON.stringify(
|
|
435
|
+
body: JSON.stringify(toWireRuntimeRegistration(runtime))
|
|
436
436
|
}));
|
|
437
437
|
return fromWireRuntime(body.runtime ?? body);
|
|
438
438
|
}
|
|
@@ -448,12 +448,19 @@ var HttpCollaborationClient = class {
|
|
|
448
448
|
method: "POST",
|
|
449
449
|
body: JSON.stringify({ runtime_id: runtimeId })
|
|
450
450
|
}));
|
|
451
|
-
|
|
451
|
+
if (body.status !== "claimed" && body.status !== "completed") {
|
|
452
|
+
throw new Error("Collaboration API omitted claim.status");
|
|
453
|
+
}
|
|
454
|
+
const attemptCount = body.attempt_count === void 0 ? 1 : requiredNumber(body.attempt_count, "claim.attempt_count");
|
|
455
|
+
if (attemptCount < 1)
|
|
456
|
+
throw new Error("Collaboration API omitted claim.attempt_count");
|
|
457
|
+
const status = body.status;
|
|
452
458
|
return {
|
|
453
459
|
claimed: status === "claimed",
|
|
454
460
|
status,
|
|
455
461
|
requestId: requiredString2(body.request_event_id, "claim.request_event_id"),
|
|
456
|
-
runtimeId: requiredString2(body.runtime_id, "claim.runtime_id")
|
|
462
|
+
runtimeId: requiredString2(body.runtime_id, "claim.runtime_id"),
|
|
463
|
+
attemptCount
|
|
457
464
|
};
|
|
458
465
|
}
|
|
459
466
|
async completeAgentRequest(sessionId, requestId, input) {
|
|
@@ -461,6 +468,7 @@ var HttpCollaborationClient = class {
|
|
|
461
468
|
method: "POST",
|
|
462
469
|
body: JSON.stringify({
|
|
463
470
|
runtime_id: input.runtimeId,
|
|
471
|
+
...input.claimAttempt === void 0 ? {} : { claim_attempt: input.claimAttempt },
|
|
464
472
|
idempotency_key: input.idempotencyKey,
|
|
465
473
|
payload: truncateJsonValue(input.payload, 160 * 1024),
|
|
466
474
|
...input.observedModel === void 0 ? {} : { observed_model: input.observedModel },
|
|
@@ -474,6 +482,7 @@ var HttpCollaborationClient = class {
|
|
|
474
482
|
method: "POST",
|
|
475
483
|
body: JSON.stringify({
|
|
476
484
|
runtime_id: input.runtimeId,
|
|
485
|
+
...input.claimAttempt === void 0 ? {} : { claim_attempt: input.claimAttempt },
|
|
477
486
|
idempotency_key: input.idempotencyKey,
|
|
478
487
|
payload: truncateJsonValue(input.payload, 32 * 1024),
|
|
479
488
|
...input.observedModel === void 0 ? {} : { observed_model: input.observedModel },
|
|
@@ -595,15 +604,34 @@ function toWireEvent(event) {
|
|
|
595
604
|
reply_to_event_id: event.replyTo,
|
|
596
605
|
visibility: event.visibility ?? "session",
|
|
597
606
|
runtime_id: event.runtimeId ?? event.runtime?.runtimeId,
|
|
607
|
+
claim_attempt: event.claimAttempt,
|
|
598
608
|
observed_model: event.observedModel,
|
|
599
609
|
observed_reasoning_effort: event.observedReasoningEffort
|
|
600
610
|
};
|
|
601
611
|
}
|
|
602
|
-
function
|
|
603
|
-
return
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
612
|
+
function toWireRuntimeRegistration(runtime) {
|
|
613
|
+
return {
|
|
614
|
+
...runtime.runtimeId === void 0 ? {} : { runtime_id: runtime.runtimeId },
|
|
615
|
+
session_id: runtime.sessionId,
|
|
616
|
+
device_id: runtime.deviceId,
|
|
617
|
+
harness: runtime.harness,
|
|
618
|
+
provider: runtime.provider,
|
|
619
|
+
model: runtime.model,
|
|
620
|
+
...runtime.executionProfiles === void 0 ? {} : {
|
|
621
|
+
execution_profiles: runtime.executionProfiles.map((profile) => ({
|
|
622
|
+
provider: profile.provider,
|
|
623
|
+
model: profile.model,
|
|
624
|
+
...profile.reasoningEfforts === void 0 ? {} : { reasoning_efforts: [...profile.reasoningEfforts] },
|
|
625
|
+
...profile.defaultReasoningEffort === void 0 ? {} : {
|
|
626
|
+
default_reasoning_effort: profile.defaultReasoningEffort
|
|
627
|
+
}
|
|
628
|
+
}))
|
|
629
|
+
},
|
|
630
|
+
local_session_id: runtime.localSessionId,
|
|
631
|
+
capture_fidelity: runtime.captureFidelity,
|
|
632
|
+
...runtime.capabilities === void 0 ? {} : { capabilities: [...runtime.capabilities] },
|
|
633
|
+
...runtime.purpose === void 0 ? {} : { purpose: runtime.purpose }
|
|
634
|
+
};
|
|
607
635
|
}
|
|
608
636
|
function fromWireEvent(value) {
|
|
609
637
|
const input = requiredObject2(value);
|
|
@@ -713,11 +741,61 @@ function fromWireRuntime(value) {
|
|
|
713
741
|
harness: requiredString2(input.harness, "runtime.harness"),
|
|
714
742
|
provider: requiredString2(input.provider, "runtime.provider"),
|
|
715
743
|
model: requiredString2(input.model, "runtime.model"),
|
|
744
|
+
...input.execution_profiles === void 0 || input.execution_profiles === null ? {} : { executionProfiles: fromWireExecutionProfiles(input.execution_profiles) },
|
|
716
745
|
localSessionId: requiredString2(input.local_session_id, "runtime.local_session_id"),
|
|
717
746
|
captureFidelity: requiredString2(input.capture_fidelity, "runtime.capture_fidelity"),
|
|
718
747
|
purpose
|
|
719
748
|
};
|
|
720
749
|
}
|
|
750
|
+
function fromWireExecutionProfiles(value) {
|
|
751
|
+
if (!Array.isArray(value) || value.length < 1 || value.length > 32) {
|
|
752
|
+
throw new Error("Collaboration API returned invalid runtime.execution_profiles");
|
|
753
|
+
}
|
|
754
|
+
const routes = /* @__PURE__ */ new Set();
|
|
755
|
+
return value.map((entry, index) => {
|
|
756
|
+
const profile = requiredObject2(entry);
|
|
757
|
+
const allowedKeys = /* @__PURE__ */ new Set(["provider", "model", "reasoning_efforts", "default_reasoning_effort"]);
|
|
758
|
+
if (Object.keys(profile).some((key) => !allowedKeys.has(key))) {
|
|
759
|
+
throw new Error(`Collaboration API returned invalid runtime.execution_profiles[${index}]`);
|
|
760
|
+
}
|
|
761
|
+
const provider = requiredExecutionProfileString(profile.provider, `runtime.execution_profiles[${index}].provider`, 80);
|
|
762
|
+
const model = requiredExecutionProfileString(profile.model, `runtime.execution_profiles[${index}].model`, 160);
|
|
763
|
+
const route = `${provider}\0${model}`;
|
|
764
|
+
if (routes.has(route))
|
|
765
|
+
throw new Error("Collaboration API returned duplicate runtime.execution_profiles");
|
|
766
|
+
routes.add(route);
|
|
767
|
+
const rawEfforts = profile.reasoning_efforts;
|
|
768
|
+
let reasoningEfforts;
|
|
769
|
+
if (rawEfforts !== void 0) {
|
|
770
|
+
if (!Array.isArray(rawEfforts) || rawEfforts.length < 1 || rawEfforts.length > 16) {
|
|
771
|
+
throw new Error(`Collaboration API returned invalid runtime.execution_profiles[${index}].reasoning_efforts`);
|
|
772
|
+
}
|
|
773
|
+
reasoningEfforts = rawEfforts.map((effort, effortIndex) => requiredExecutionProfileString(effort, `runtime.execution_profiles[${index}].reasoning_efforts[${effortIndex}]`, 80));
|
|
774
|
+
if (new Set(reasoningEfforts).size !== reasoningEfforts.length) {
|
|
775
|
+
throw new Error(`Collaboration API returned duplicate runtime.execution_profiles[${index}].reasoning_efforts`);
|
|
776
|
+
}
|
|
777
|
+
}
|
|
778
|
+
const defaultReasoningEffort = profile.default_reasoning_effort === void 0 ? void 0 : requiredExecutionProfileString(profile.default_reasoning_effort, `runtime.execution_profiles[${index}].default_reasoning_effort`, 80);
|
|
779
|
+
if (defaultReasoningEffort !== void 0 && !reasoningEfforts?.includes(defaultReasoningEffort)) {
|
|
780
|
+
throw new Error(`Collaboration API returned an unadvertised runtime.execution_profiles[${index}].default_reasoning_effort`);
|
|
781
|
+
}
|
|
782
|
+
return {
|
|
783
|
+
provider,
|
|
784
|
+
model,
|
|
785
|
+
...reasoningEfforts === void 0 ? {} : { reasoningEfforts },
|
|
786
|
+
...defaultReasoningEffort === void 0 ? {} : { defaultReasoningEffort }
|
|
787
|
+
};
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
function requiredExecutionProfileString(value, field, maxLength) {
|
|
791
|
+
if (typeof value !== "string")
|
|
792
|
+
throw new Error(`Collaboration API omitted ${field}`);
|
|
793
|
+
const normalized = value.trim();
|
|
794
|
+
if (!normalized || normalized.length > maxLength || /[\u0000-\u001f\u007f-\u009f]/u.test(normalized)) {
|
|
795
|
+
throw new Error(`Collaboration API returned invalid ${field}`);
|
|
796
|
+
}
|
|
797
|
+
return normalized;
|
|
798
|
+
}
|
|
721
799
|
function fromWireProvenance(value) {
|
|
722
800
|
const input = requiredObject2(value);
|
|
723
801
|
return {
|
|
@@ -976,7 +1054,7 @@ function isTerminalClaimConflict(error) {
|
|
|
976
1054
|
if (!error || typeof error !== "object")
|
|
977
1055
|
return false;
|
|
978
1056
|
const candidate = error;
|
|
979
|
-
return candidate.status === 409 && (candidate.code === "agent_request_already_claimed" || candidate.code === "agent_request_already_completed");
|
|
1057
|
+
return candidate.status === 409 && (candidate.code === "agent_request_already_claimed" || candidate.code === "agent_request_already_completed" || candidate.code === "agent_request_failed");
|
|
980
1058
|
}
|
|
981
1059
|
|
|
982
1060
|
// dist/src/connector.js
|
|
@@ -1003,11 +1081,16 @@ function requestedDshProfile(event) {
|
|
|
1003
1081
|
if (profile.provider !== void 0 && !provider) {
|
|
1004
1082
|
throw new Error("DeepSeek Harness Agent request has an invalid provider target");
|
|
1005
1083
|
}
|
|
1084
|
+
const reasoningEffort = profile.reasoning_effort === void 0 ? void 0 : safeProfileText(profile.reasoning_effort, 80);
|
|
1085
|
+
if (profile.reasoning_effort !== void 0 && !reasoningEffort) {
|
|
1086
|
+
throw new Error("DeepSeek Harness Agent request has an invalid reasoning effort target");
|
|
1087
|
+
}
|
|
1006
1088
|
const runtimeId = profile.runtime_id === void 0 ? void 0 : safeRuntimeId(profile.runtime_id);
|
|
1007
1089
|
return {
|
|
1008
1090
|
harness,
|
|
1009
1091
|
...provider === void 0 ? {} : { provider },
|
|
1010
1092
|
model,
|
|
1093
|
+
...reasoningEffort === void 0 ? {} : { reasoningEffort },
|
|
1011
1094
|
...runtimeId === void 0 ? {} : { runtimeId }
|
|
1012
1095
|
};
|
|
1013
1096
|
}
|
|
@@ -1304,6 +1387,7 @@ function asObject2(value) {
|
|
|
1304
1387
|
}
|
|
1305
1388
|
|
|
1306
1389
|
// dist/src/connector.js
|
|
1390
|
+
var LIVE_PROGRESS_MIN_INTERVAL_MS = 6e4;
|
|
1307
1391
|
var DshHostConnector = class {
|
|
1308
1392
|
#config;
|
|
1309
1393
|
#api;
|
|
@@ -1324,11 +1408,15 @@ var DshHostConnector = class {
|
|
|
1324
1408
|
#pollPromise;
|
|
1325
1409
|
#localSyncControlPromise;
|
|
1326
1410
|
#heartbeatPromise;
|
|
1411
|
+
#liveProgressPromise = Promise.resolve();
|
|
1412
|
+
#lastLiveProgressKey;
|
|
1413
|
+
#lastLiveProgressAt = 0;
|
|
1327
1414
|
#stopPromise;
|
|
1328
1415
|
#backgroundFatalError;
|
|
1329
1416
|
#lifecycleAbort = new AbortController();
|
|
1330
1417
|
#listenerDisposers = [];
|
|
1331
1418
|
#activeStatuses = [];
|
|
1419
|
+
#activeExecutionSelection;
|
|
1332
1420
|
#liveEventSequences = /* @__PURE__ */ new Set();
|
|
1333
1421
|
#session;
|
|
1334
1422
|
#visibleState = "connecting";
|
|
@@ -1407,6 +1495,14 @@ var DshHostConnector = class {
|
|
|
1407
1495
|
const active = this.#state?.activeRequest;
|
|
1408
1496
|
if (active !== void 0 && event.seq >= active.dshFromSequence) {
|
|
1409
1497
|
this.#liveEventSequences.add(event.seq);
|
|
1498
|
+
this.#queueLiveProgress(`dsh-live-${String(event.seq)}`, {
|
|
1499
|
+
content: "DeepSeek Harness produced durable work for the active request.",
|
|
1500
|
+
phase: "activity",
|
|
1501
|
+
status: "running",
|
|
1502
|
+
dsh_event_sequence: event.seq,
|
|
1503
|
+
capture_fidelity: "harness_transcript",
|
|
1504
|
+
source_harness: "deepseek-harness"
|
|
1505
|
+
});
|
|
1410
1506
|
}
|
|
1411
1507
|
if (active === void 0 && event.type === "turn/end" && turnSettlement([event]) === "completed" && this.#automaticPolling) {
|
|
1412
1508
|
queueMicrotask(() => {
|
|
@@ -1421,8 +1517,9 @@ var DshHostConnector = class {
|
|
|
1421
1517
|
this.#listenerDisposers.push(this.#host.onStatus((status) => {
|
|
1422
1518
|
if (this.#state?.activeRequest === void 0)
|
|
1423
1519
|
return;
|
|
1424
|
-
if (this.#activeStatuses.at(-1) !== status)
|
|
1520
|
+
if (this.#activeStatuses.at(-1) !== status) {
|
|
1425
1521
|
this.#activeStatuses.push(status);
|
|
1522
|
+
}
|
|
1426
1523
|
this.#notifyLifecycle(status);
|
|
1427
1524
|
}));
|
|
1428
1525
|
try {
|
|
@@ -1453,16 +1550,20 @@ var DshHostConnector = class {
|
|
|
1453
1550
|
"canonical_history_projection",
|
|
1454
1551
|
"bidirectional_local_turns"
|
|
1455
1552
|
],
|
|
1553
|
+
...this.#config.executionProfiles === void 0 ? {} : {
|
|
1554
|
+
executionProfiles: cloneExecutionProfiles(this.#config.executionProfiles)
|
|
1555
|
+
},
|
|
1456
1556
|
purpose: "execution"
|
|
1457
1557
|
});
|
|
1458
1558
|
this.#assertRuntime(this.#runtime);
|
|
1459
1559
|
this.#notifyLifecycle("idle");
|
|
1460
1560
|
if (options.schedule !== false)
|
|
1461
1561
|
this.#scheduleHeartbeat();
|
|
1462
|
-
await this.#flushOutbox(this.#requireState().automaticUpload);
|
|
1463
|
-
await this.#finalizeDeliveredRequest();
|
|
1464
1562
|
if (this.#state.activeRequest !== void 0) {
|
|
1465
1563
|
await this.#withExecutionPermit(() => this.#recoverActiveRequest());
|
|
1564
|
+
} else {
|
|
1565
|
+
await this.#flushOutbox(this.#requireState().automaticUpload);
|
|
1566
|
+
await this.#finalizeDeliveredRequest();
|
|
1466
1567
|
}
|
|
1467
1568
|
if (options.runImmediately !== false)
|
|
1468
1569
|
await this.pollOnce();
|
|
@@ -1549,12 +1650,12 @@ var DshHostConnector = class {
|
|
|
1549
1650
|
}
|
|
1550
1651
|
async #poll() {
|
|
1551
1652
|
const state = this.#requireState();
|
|
1552
|
-
await this.#flushOutbox(state.automaticUpload);
|
|
1553
|
-
await this.#finalizeDeliveredRequest();
|
|
1554
1653
|
if (state.activeRequest !== void 0) {
|
|
1555
1654
|
await this.#withExecutionPermit(() => this.#recoverActiveRequest());
|
|
1556
1655
|
return { scanned: 0, claimed: 0, completed: 1 };
|
|
1557
1656
|
}
|
|
1657
|
+
await this.#flushOutbox(state.automaticUpload);
|
|
1658
|
+
await this.#finalizeDeliveredRequest();
|
|
1558
1659
|
if (state.automaticUpload) {
|
|
1559
1660
|
await this.#captureLocalTurns();
|
|
1560
1661
|
await this.#flushOutbox(true);
|
|
@@ -1570,7 +1671,7 @@ var DshHostConnector = class {
|
|
|
1570
1671
|
scanCursor = Math.max(scanCursor, event.sequence);
|
|
1571
1672
|
scanned += 1;
|
|
1572
1673
|
const profile = requestedDshProfile(event);
|
|
1573
|
-
if (profile === void 0 || event.actorId !== this.#requireRuntime().userId ||
|
|
1674
|
+
if (profile === void 0 || event.actorId !== this.#requireRuntime().userId || !this.#profileTargetsThisRuntime(profile)) {
|
|
1574
1675
|
passive.push(event);
|
|
1575
1676
|
continue;
|
|
1576
1677
|
}
|
|
@@ -1578,13 +1679,8 @@ var DshHostConnector = class {
|
|
|
1578
1679
|
if (manualUploadRequired) {
|
|
1579
1680
|
return { scanned, claimed: 0, completed: 0 };
|
|
1580
1681
|
}
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
}
|
|
1584
|
-
if (profile.model !== this.#config.model) {
|
|
1585
|
-
throw new Error("DeepSeek Harness Agent request model does not match the configured Host binding");
|
|
1586
|
-
}
|
|
1587
|
-
const outcome = await this.#withExecutionPermit(() => this.#executeRequest(event));
|
|
1682
|
+
const selection = this.#resolveExecutionSelection(profile);
|
|
1683
|
+
const outcome = await this.#withExecutionPermit(() => this.#executeRequest(event, selection));
|
|
1588
1684
|
return {
|
|
1589
1685
|
scanned,
|
|
1590
1686
|
claimed: outcome.claimed ? 1 : 0,
|
|
@@ -1602,7 +1698,7 @@ var DshHostConnector = class {
|
|
|
1602
1698
|
}
|
|
1603
1699
|
throw new Error("DSH connector stopped during event replay");
|
|
1604
1700
|
}
|
|
1605
|
-
async #executeRequest(request) {
|
|
1701
|
+
async #executeRequest(request, selection) {
|
|
1606
1702
|
if (this.#stopped)
|
|
1607
1703
|
throw new Error("DSH connector stopped before claiming an Agent request");
|
|
1608
1704
|
const state = this.#requireState();
|
|
@@ -1626,17 +1722,20 @@ var DshHostConnector = class {
|
|
|
1626
1722
|
requestId: request.id,
|
|
1627
1723
|
requestSequence: request.sequence,
|
|
1628
1724
|
dshFromSequence: baseline,
|
|
1629
|
-
promptDigest: digest(prompt)
|
|
1725
|
+
promptDigest: digest(prompt),
|
|
1726
|
+
claimAttempt: claim.attemptCount ?? 1
|
|
1630
1727
|
};
|
|
1631
1728
|
this.#activeStatuses = [];
|
|
1729
|
+
this.#activeExecutionSelection = selection;
|
|
1632
1730
|
this.#liveEventSequences.clear();
|
|
1633
1731
|
await this.#stateStore.save(state);
|
|
1634
|
-
const result = await this.#host.prompt(prompt);
|
|
1732
|
+
const result = await this.#host.prompt(prompt, selection);
|
|
1635
1733
|
if (result.fromSequence !== baseline || result.toSequence < result.fromSequence) {
|
|
1636
1734
|
throw new Error("DSH Host prompt returned an inconsistent durable event range");
|
|
1637
1735
|
}
|
|
1736
|
+
await this.#liveProgressPromise;
|
|
1638
1737
|
this.#assertLiveEventsDurable(result);
|
|
1639
|
-
await this.#settleActiveRequest(result.events, result.toSequence);
|
|
1738
|
+
await this.#settleActiveRequest(result.events, result.toSequence, selection);
|
|
1640
1739
|
return { claimed: true, completed: true };
|
|
1641
1740
|
}
|
|
1642
1741
|
async #recoverActiveRequest() {
|
|
@@ -1646,6 +1745,46 @@ var DshHostConnector = class {
|
|
|
1646
1745
|
const active = state.activeRequest;
|
|
1647
1746
|
if (active === void 0)
|
|
1648
1747
|
return;
|
|
1748
|
+
let claim;
|
|
1749
|
+
try {
|
|
1750
|
+
claim = await this.#api.claimAgentRequest(this.#config.sessionId, active.requestId, this.#requireRuntime().id);
|
|
1751
|
+
} catch (error) {
|
|
1752
|
+
if (!isTerminalClaimConflict(error))
|
|
1753
|
+
throw error;
|
|
1754
|
+
state.outbox = state.outbox.filter((operation) => !outboxBelongsToRequest(operation, active.requestId));
|
|
1755
|
+
if (active.dshToSequence !== void 0) {
|
|
1756
|
+
state.publishedDshSequence = Math.max(state.publishedDshSequence, active.dshToSequence);
|
|
1757
|
+
}
|
|
1758
|
+
delete state.activeRequest;
|
|
1759
|
+
this.#activeStatuses = [];
|
|
1760
|
+
this.#activeExecutionSelection = void 0;
|
|
1761
|
+
this.#liveEventSequences.clear();
|
|
1762
|
+
await this.#stateStore.save(state);
|
|
1763
|
+
return;
|
|
1764
|
+
}
|
|
1765
|
+
if (claim.status === "completed" && active.dshToSequence !== void 0) {
|
|
1766
|
+
state.outbox = [];
|
|
1767
|
+
await this.#stateStore.save(state);
|
|
1768
|
+
await this.#finalizeDeliveredRequest();
|
|
1769
|
+
return;
|
|
1770
|
+
}
|
|
1771
|
+
if (!claim.claimed) {
|
|
1772
|
+
throw new Error("Active GatherThread request no longer has a recoverable claim");
|
|
1773
|
+
}
|
|
1774
|
+
const claimAttempt = claim.attemptCount ?? active.claimAttempt ?? 1;
|
|
1775
|
+
active.claimAttempt = claimAttempt;
|
|
1776
|
+
if (active.dshToSequence !== void 0) {
|
|
1777
|
+
state.outbox = state.outbox.map((operation) => {
|
|
1778
|
+
if ((operation.kind === "progress" || operation.kind === "complete") && operation.requestId === active.requestId) {
|
|
1779
|
+
return { ...operation, input: { ...operation.input, claimAttempt } };
|
|
1780
|
+
}
|
|
1781
|
+
if (operation.kind === "append" && operation.input.replyTo === active.requestId) {
|
|
1782
|
+
return { ...operation, input: { ...operation.input, claimAttempt } };
|
|
1783
|
+
}
|
|
1784
|
+
return operation;
|
|
1785
|
+
});
|
|
1786
|
+
}
|
|
1787
|
+
await this.#stateStore.save(state);
|
|
1649
1788
|
if (active.dshToSequence !== void 0) {
|
|
1650
1789
|
await this.#flushOutbox();
|
|
1651
1790
|
await this.#finalizeDeliveredRequest();
|
|
@@ -1657,6 +1796,15 @@ var DshHostConnector = class {
|
|
|
1657
1796
|
throw new Error("Active GatherThread request is unavailable during DSH resume");
|
|
1658
1797
|
}
|
|
1659
1798
|
const prompt = buildDshRequestPrompt(request);
|
|
1799
|
+
const profile = requestedDshProfile(request);
|
|
1800
|
+
if (profile === void 0) {
|
|
1801
|
+
throw new Error("Active GatherThread request lost its DeepSeek Harness execution profile");
|
|
1802
|
+
}
|
|
1803
|
+
if (!this.#profileTargetsThisRuntime(profile)) {
|
|
1804
|
+
throw new Error("Active GatherThread request no longer targets this exact DSH runtime");
|
|
1805
|
+
}
|
|
1806
|
+
const selection = this.#resolveExecutionSelection(profile);
|
|
1807
|
+
this.#activeExecutionSelection = selection;
|
|
1660
1808
|
const legacyPrompt = buildDshCanonicalPrompt(history, request, this.#requireRuntime().id);
|
|
1661
1809
|
if (digest(prompt) !== active.promptDigest && digest(legacyPrompt) !== active.promptDigest) {
|
|
1662
1810
|
throw new Error("Active GatherThread request changed during DSH resume");
|
|
@@ -1664,7 +1812,7 @@ var DshHostConnector = class {
|
|
|
1664
1812
|
const recovered = this.#host.snapshotFrom(active.dshFromSequence);
|
|
1665
1813
|
const settlement = turnSettlement(recovered);
|
|
1666
1814
|
if (settlement === "completed") {
|
|
1667
|
-
await this.#settleActiveRequest(recovered, this.#host.currentSequence());
|
|
1815
|
+
await this.#settleActiveRequest(recovered, this.#host.currentSequence(), selection);
|
|
1668
1816
|
return;
|
|
1669
1817
|
}
|
|
1670
1818
|
if (settlement !== void 0 && settlement !== "interrupted") {
|
|
@@ -1682,14 +1830,15 @@ var DshHostConnector = class {
|
|
|
1682
1830
|
this.#activeStatuses = [];
|
|
1683
1831
|
this.#liveEventSequences.clear();
|
|
1684
1832
|
await this.#stateStore.save(state);
|
|
1685
|
-
const result = await this.#host.prompt(continuation);
|
|
1833
|
+
const result = await this.#host.prompt(continuation, selection);
|
|
1686
1834
|
if (result.fromSequence !== baseline || result.toSequence < result.fromSequence) {
|
|
1687
1835
|
throw new Error("DSH Host recovery prompt returned an inconsistent durable event range");
|
|
1688
1836
|
}
|
|
1837
|
+
await this.#liveProgressPromise;
|
|
1689
1838
|
this.#assertLiveEventsDurable(result);
|
|
1690
|
-
await this.#settleActiveRequest(result.events, result.toSequence);
|
|
1839
|
+
await this.#settleActiveRequest(result.events, result.toSequence, selection);
|
|
1691
1840
|
}
|
|
1692
|
-
async #settleActiveRequest(durableEvents, toSequence) {
|
|
1841
|
+
async #settleActiveRequest(durableEvents, toSequence, selection) {
|
|
1693
1842
|
const state = this.#requireState();
|
|
1694
1843
|
const active = state.activeRequest;
|
|
1695
1844
|
if (active === void 0)
|
|
@@ -1705,11 +1854,51 @@ var DshHostConnector = class {
|
|
|
1705
1854
|
if (state.outbox.length > 0)
|
|
1706
1855
|
throw new Error("DSH connector outbox was not empty before settlement");
|
|
1707
1856
|
state.activeRequest = { ...active, dshToSequence: toSequence };
|
|
1708
|
-
state.outbox = this.#outboxFor(mapped, this.#activeStatuses, active.requestId);
|
|
1857
|
+
state.outbox = this.#outboxFor(mapped, this.#activeStatuses, active.requestId, active.claimAttempt ?? 1, selection);
|
|
1709
1858
|
await this.#stateStore.save(state);
|
|
1710
1859
|
await this.#flushOutbox();
|
|
1711
1860
|
await this.#finalizeDeliveredRequest();
|
|
1712
1861
|
}
|
|
1862
|
+
#queueLiveProgress(idSuffix, payload) {
|
|
1863
|
+
const active = this.#state?.activeRequest;
|
|
1864
|
+
const runtime = this.#runtime;
|
|
1865
|
+
if (active === void 0 || runtime === void 0)
|
|
1866
|
+
return;
|
|
1867
|
+
const requestId = active.requestId;
|
|
1868
|
+
const claimAttempt = active.claimAttempt ?? 1;
|
|
1869
|
+
const progressKey = `${requestId}:${String(claimAttempt)}`;
|
|
1870
|
+
const now = Date.now();
|
|
1871
|
+
if (this.#lastLiveProgressKey === progressKey && now - this.#lastLiveProgressAt < LIVE_PROGRESS_MIN_INTERVAL_MS) {
|
|
1872
|
+
return;
|
|
1873
|
+
}
|
|
1874
|
+
this.#lastLiveProgressKey = progressKey;
|
|
1875
|
+
this.#lastLiveProgressAt = now;
|
|
1876
|
+
const idempotencyKey = `${this.#config.deviceId}:${digest(requestId).slice(0, 24)}:${idSuffix}`;
|
|
1877
|
+
this.#liveProgressPromise = this.#liveProgressPromise.then(async () => {
|
|
1878
|
+
const current = this.#state?.activeRequest;
|
|
1879
|
+
if (current?.requestId !== requestId || (current.claimAttempt ?? 1) !== claimAttempt)
|
|
1880
|
+
return;
|
|
1881
|
+
const selection = this.#activeExecutionSelection;
|
|
1882
|
+
if (selection === void 0)
|
|
1883
|
+
return;
|
|
1884
|
+
await this.#api.appendAgentProgress(this.#config.sessionId, requestId, {
|
|
1885
|
+
runtimeId: runtime.id,
|
|
1886
|
+
claimAttempt,
|
|
1887
|
+
idempotencyKey,
|
|
1888
|
+
payload,
|
|
1889
|
+
observedModel: selection.model,
|
|
1890
|
+
...selection.reasoningEffort === void 0 ? {} : {
|
|
1891
|
+
observedReasoningEffort: selection.reasoningEffort
|
|
1892
|
+
}
|
|
1893
|
+
});
|
|
1894
|
+
}).catch((error) => {
|
|
1895
|
+
if (this.#lastLiveProgressKey === progressKey) {
|
|
1896
|
+
this.#lastLiveProgressKey = void 0;
|
|
1897
|
+
this.#lastLiveProgressAt = 0;
|
|
1898
|
+
}
|
|
1899
|
+
this.#onBackgroundError?.(publicError(error));
|
|
1900
|
+
});
|
|
1901
|
+
}
|
|
1713
1902
|
async #projectCanonicalBatch(events, throughSequence) {
|
|
1714
1903
|
const state = this.#requireState();
|
|
1715
1904
|
if (throughSequence <= state.projectionCursor)
|
|
@@ -1793,7 +1982,7 @@ var DshHostConnector = class {
|
|
|
1793
1982
|
}
|
|
1794
1983
|
await this.#stateStore.save(state);
|
|
1795
1984
|
}
|
|
1796
|
-
#outboxFor(events, statuses, requestId) {
|
|
1985
|
+
#outboxFor(events, statuses, requestId, claimAttempt, selection) {
|
|
1797
1986
|
const runtime = this.#requireRuntime();
|
|
1798
1987
|
const prefix = `${this.#config.deviceId}:${digest(requestId).slice(0, 24)}`;
|
|
1799
1988
|
const operations = [];
|
|
@@ -1805,6 +1994,7 @@ var DshHostConnector = class {
|
|
|
1805
1994
|
requestId,
|
|
1806
1995
|
input: {
|
|
1807
1996
|
runtimeId: runtime.id,
|
|
1997
|
+
claimAttempt,
|
|
1808
1998
|
idempotencyKey,
|
|
1809
1999
|
payload: {
|
|
1810
2000
|
content: status === "running" ? "DeepSeek Harness started processing the request." : "DeepSeek Harness returned to idle.",
|
|
@@ -1813,7 +2003,10 @@ var DshHostConnector = class {
|
|
|
1813
2003
|
capture_fidelity: "harness_transcript",
|
|
1814
2004
|
source_harness: "deepseek-harness"
|
|
1815
2005
|
},
|
|
1816
|
-
observedModel:
|
|
2006
|
+
observedModel: selection.model,
|
|
2007
|
+
...selection.reasoningEffort === void 0 ? {} : {
|
|
2008
|
+
observedReasoningEffort: selection.reasoningEffort
|
|
2009
|
+
}
|
|
1817
2010
|
}
|
|
1818
2011
|
});
|
|
1819
2012
|
}
|
|
@@ -1847,7 +2040,11 @@ var DshHostConnector = class {
|
|
|
1847
2040
|
payload: redactValue(payload),
|
|
1848
2041
|
replyTo: requestId,
|
|
1849
2042
|
runtimeId: runtime.id,
|
|
1850
|
-
|
|
2043
|
+
claimAttempt,
|
|
2044
|
+
observedModel: selection.model,
|
|
2045
|
+
...selection.reasoningEffort === void 0 ? {} : {
|
|
2046
|
+
observedReasoningEffort: selection.reasoningEffort
|
|
2047
|
+
}
|
|
1851
2048
|
}
|
|
1852
2049
|
});
|
|
1853
2050
|
}
|
|
@@ -1862,6 +2059,7 @@ var DshHostConnector = class {
|
|
|
1862
2059
|
requestId,
|
|
1863
2060
|
input: {
|
|
1864
2061
|
runtimeId: runtime.id,
|
|
2062
|
+
claimAttempt,
|
|
1865
2063
|
idempotencyKey: completionKey,
|
|
1866
2064
|
payload: {
|
|
1867
2065
|
text: final.content,
|
|
@@ -1870,7 +2068,10 @@ var DshHostConnector = class {
|
|
|
1870
2068
|
source_timestamp: final.timestamp,
|
|
1871
2069
|
dsh_event_sequence: final.sequence
|
|
1872
2070
|
},
|
|
1873
|
-
observedModel:
|
|
2071
|
+
observedModel: selection.model,
|
|
2072
|
+
...selection.reasoningEffort === void 0 ? {} : {
|
|
2073
|
+
observedReasoningEffort: selection.reasoningEffort
|
|
2074
|
+
}
|
|
1874
2075
|
}
|
|
1875
2076
|
});
|
|
1876
2077
|
return operations;
|
|
@@ -1914,6 +2115,7 @@ var DshHostConnector = class {
|
|
|
1914
2115
|
state.publishedDshSequence = Math.max(state.publishedDshSequence, active.dshToSequence);
|
|
1915
2116
|
delete state.activeRequest;
|
|
1916
2117
|
this.#activeStatuses = [];
|
|
2118
|
+
this.#activeExecutionSelection = void 0;
|
|
1917
2119
|
this.#liveEventSequences.clear();
|
|
1918
2120
|
await this.#stateStore.save(state);
|
|
1919
2121
|
}
|
|
@@ -1999,10 +2201,45 @@ var DshHostConnector = class {
|
|
|
1999
2201
|
return stored;
|
|
2000
2202
|
}
|
|
2001
2203
|
#assertRuntime(runtime) {
|
|
2002
|
-
if (runtime.sessionId !== this.#config.sessionId || runtime.deviceId !== this.#config.deviceId || runtime.harness !== "deepseek-harness" || runtime.provider !== this.#config.provider || runtime.model !== this.#config.model || runtime.localSessionId !== this.#config.dshSessionId || runtime.captureFidelity !== "harness_transcript" || runtime.purpose !== "execution") {
|
|
2204
|
+
if (runtime.sessionId !== this.#config.sessionId || runtime.deviceId !== this.#config.deviceId || runtime.harness !== "deepseek-harness" || runtime.provider !== this.#config.provider || runtime.model !== this.#config.model || runtime.localSessionId !== this.#config.dshSessionId || runtime.captureFidelity !== "harness_transcript" || !sameExecutionProfiles(runtime.executionProfiles, this.#config.executionProfiles) || runtime.purpose !== "execution") {
|
|
2003
2205
|
throw new Error("GatherThread returned an incompatible DSH runtime registration");
|
|
2004
2206
|
}
|
|
2005
2207
|
}
|
|
2208
|
+
#resolveExecutionSelection(profile) {
|
|
2209
|
+
const provider = profile.provider ?? this.#config.provider;
|
|
2210
|
+
const advertised = this.#config.executionProfiles;
|
|
2211
|
+
if (advertised === void 0) {
|
|
2212
|
+
if (provider !== this.#config.provider) {
|
|
2213
|
+
throw new Error("DeepSeek Harness Agent request provider does not match the configured Host binding");
|
|
2214
|
+
}
|
|
2215
|
+
if (profile.model !== this.#config.model) {
|
|
2216
|
+
throw new Error("DeepSeek Harness Agent request model does not match the configured Host binding");
|
|
2217
|
+
}
|
|
2218
|
+
if (profile.reasoningEffort !== void 0) {
|
|
2219
|
+
throw new Error("DeepSeek Harness fixed runtime did not advertise reasoning effort selection");
|
|
2220
|
+
}
|
|
2221
|
+
return { provider, model: profile.model };
|
|
2222
|
+
}
|
|
2223
|
+
const route = advertised.find((candidate) => candidate.provider === provider && candidate.model === profile.model);
|
|
2224
|
+
if (route === void 0) {
|
|
2225
|
+
throw new Error("DeepSeek Harness Agent request provider/model was not advertised by this runtime");
|
|
2226
|
+
}
|
|
2227
|
+
const reasoningEffort = profile.reasoningEffort ?? route.defaultReasoningEffort;
|
|
2228
|
+
if (reasoningEffort !== void 0 && !route.reasoningEfforts?.includes(reasoningEffort)) {
|
|
2229
|
+
throw new Error("DeepSeek Harness Agent request reasoning effort was not advertised for this model");
|
|
2230
|
+
}
|
|
2231
|
+
return {
|
|
2232
|
+
provider,
|
|
2233
|
+
model: profile.model,
|
|
2234
|
+
...reasoningEffort === void 0 ? {} : { reasoningEffort }
|
|
2235
|
+
};
|
|
2236
|
+
}
|
|
2237
|
+
#profileTargetsThisRuntime(profile) {
|
|
2238
|
+
const runtimeId = profile.runtimeId;
|
|
2239
|
+
if (runtimeId !== void 0)
|
|
2240
|
+
return runtimeId === this.#requireRuntime().id;
|
|
2241
|
+
return this.#config.executionProfiles === void 0;
|
|
2242
|
+
}
|
|
2006
2243
|
#validatePage(events, afterSequence) {
|
|
2007
2244
|
let previous = afterSequence;
|
|
2008
2245
|
for (const event of events) {
|
|
@@ -2102,6 +2339,21 @@ function turnSettlement(events) {
|
|
|
2102
2339
|
function digest(value) {
|
|
2103
2340
|
return createHash3("sha256").update(value).digest("hex");
|
|
2104
2341
|
}
|
|
2342
|
+
function cloneExecutionProfiles(profiles) {
|
|
2343
|
+
return profiles.map((profile) => ({
|
|
2344
|
+
provider: profile.provider,
|
|
2345
|
+
model: profile.model,
|
|
2346
|
+
...profile.reasoningEfforts === void 0 ? {} : {
|
|
2347
|
+
reasoningEfforts: [...profile.reasoningEfforts]
|
|
2348
|
+
},
|
|
2349
|
+
...profile.defaultReasoningEffort === void 0 ? {} : {
|
|
2350
|
+
defaultReasoningEffort: profile.defaultReasoningEffort
|
|
2351
|
+
}
|
|
2352
|
+
}));
|
|
2353
|
+
}
|
|
2354
|
+
function sameExecutionProfiles(actual, expected) {
|
|
2355
|
+
return JSON.stringify(actual ?? null) === JSON.stringify(expected ?? null);
|
|
2356
|
+
}
|
|
2105
2357
|
function publicError(error) {
|
|
2106
2358
|
if (error instanceof Error)
|
|
2107
2359
|
return error;
|
|
@@ -2201,6 +2453,12 @@ function boundedPublicText(value) {
|
|
|
2201
2453
|
}
|
|
2202
2454
|
return `${redacted.slice(0, low)}${suffix}`;
|
|
2203
2455
|
}
|
|
2456
|
+
function outboxBelongsToRequest(operation, requestId) {
|
|
2457
|
+
if (operation.kind === "progress" || operation.kind === "complete") {
|
|
2458
|
+
return operation.requestId === requestId;
|
|
2459
|
+
}
|
|
2460
|
+
return operation.kind === "append" && operation.input.replyTo === requestId;
|
|
2461
|
+
}
|
|
2204
2462
|
function sessionTimestamp(value) {
|
|
2205
2463
|
const date = new Date(value);
|
|
2206
2464
|
if (!Number.isFinite(date.getTime()))
|
|
@@ -2277,6 +2535,23 @@ function createDshHostFacade(options) {
|
|
|
2277
2535
|
for (const subscriber of statusSubscribers)
|
|
2278
2536
|
subscriber(status);
|
|
2279
2537
|
}, { global: true }));
|
|
2538
|
+
const adoptHandle = async (acquire) => {
|
|
2539
|
+
const acquired = await acquire();
|
|
2540
|
+
handle = acquired;
|
|
2541
|
+
if (disposed || lifecycleAbort.signal.aborted) {
|
|
2542
|
+
await releaseHandle();
|
|
2543
|
+
throw new Error("DSH host facade was disposed during open");
|
|
2544
|
+
}
|
|
2545
|
+
if (acquired.agent.session.id !== options.sessionId) {
|
|
2546
|
+
await releaseHandle();
|
|
2547
|
+
throw new Error("DSH Host returned an agent for an unexpected Session identity");
|
|
2548
|
+
}
|
|
2549
|
+
};
|
|
2550
|
+
const releaseHandle = async () => {
|
|
2551
|
+
const owned = handle;
|
|
2552
|
+
handle = void 0;
|
|
2553
|
+
await owned?.dispose();
|
|
2554
|
+
};
|
|
2280
2555
|
const open2 = () => {
|
|
2281
2556
|
if (disposed)
|
|
2282
2557
|
return Promise.reject(new Error("DSH host facade is disposed"));
|
|
@@ -2291,13 +2566,12 @@ function createDshHostFacade(options) {
|
|
|
2291
2566
|
const stored = liveAgent === void 0 ? await hasPersistedSession(persistence, options.sessionId, lifecycleAbort.signal) : true;
|
|
2292
2567
|
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2293
2568
|
const mode = stored ? "resumed" : "created";
|
|
2294
|
-
let openedHandle;
|
|
2295
2569
|
try {
|
|
2296
|
-
|
|
2570
|
+
await adoptHandle(() => liveAgent !== void 0 ? Promise.resolve({ agent: liveAgent, dispose: async () => void 0 }) : stored ? agents.resume({
|
|
2297
2571
|
resumeSessionId: options.sessionId,
|
|
2298
2572
|
agentOptions: { provider: options.provider, model: options.model },
|
|
2299
2573
|
signal: lifecycleAbort.signal
|
|
2300
|
-
}) :
|
|
2574
|
+
}) : agents.create({
|
|
2301
2575
|
sessionId: options.sessionId,
|
|
2302
2576
|
meta: {
|
|
2303
2577
|
cwd: options.workspacePath,
|
|
@@ -2305,42 +2579,52 @@ function createDshHostFacade(options) {
|
|
|
2305
2579
|
},
|
|
2306
2580
|
agentOptions: { provider: options.provider, model: options.model },
|
|
2307
2581
|
signal: lifecycleAbort.signal
|
|
2308
|
-
});
|
|
2582
|
+
}));
|
|
2309
2583
|
} catch (error) {
|
|
2310
2584
|
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2311
2585
|
throw error;
|
|
2312
2586
|
}
|
|
2313
|
-
if (disposed || lifecycleAbort.signal.aborted) {
|
|
2314
|
-
await openedHandle.dispose();
|
|
2315
|
-
throw new Error("DSH host facade was disposed during open");
|
|
2316
|
-
}
|
|
2317
|
-
if (openedHandle.agent.session.id !== options.sessionId) {
|
|
2318
|
-
await openedHandle.dispose();
|
|
2319
|
-
throw new Error("DSH Host returned an agent for an unexpected Session identity");
|
|
2320
|
-
}
|
|
2321
2587
|
if (sessionTitle !== void 0 && workspaceRegistry !== void 0 && options.sessionTitle !== void 0 && options.workspaceTitle !== void 0) {
|
|
2322
2588
|
try {
|
|
2323
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
2589
|
+
const session = requireAgent(handle).session;
|
|
2590
|
+
if (mode === "created") {
|
|
2591
|
+
await sessionTitle.rename(session, options.sessionTitle);
|
|
2592
|
+
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2593
|
+
}
|
|
2594
|
+
const markerWritten = liveAgent === void 0 && ensureNativeSessionListVisibility(session);
|
|
2595
|
+
await sessions.flush(session);
|
|
2596
|
+
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2597
|
+
if (markerWritten) {
|
|
2598
|
+
await releaseHandle();
|
|
2599
|
+
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2600
|
+
await adoptHandle(() => agents.resume({
|
|
2601
|
+
resumeSessionId: options.sessionId,
|
|
2602
|
+
agentOptions: { provider: options.provider, model: options.model },
|
|
2603
|
+
signal: lifecycleAbort.signal
|
|
2604
|
+
}));
|
|
2605
|
+
}
|
|
2606
|
+
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2326
2607
|
const workspace = await workspaceRegistry.create(options.workspacePath, options.workspaceTitle);
|
|
2327
2608
|
if (workspace === null || typeof workspace !== "object" || typeof workspace.attachSession !== "function") {
|
|
2328
2609
|
throw new Error("Pinned DSH workspace registry returned an incompatible Workspace");
|
|
2329
2610
|
}
|
|
2611
|
+
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2330
2612
|
await workspace.attachSession(options.sessionId);
|
|
2613
|
+
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2331
2614
|
if (options.supersededSessionId !== void 0 && options.supersededSessionId !== options.sessionId && workspace.sessionIds.includes(options.supersededSessionId)) {
|
|
2332
2615
|
if (typeof workspace.detachSession !== "function") {
|
|
2333
2616
|
throw new Error("Pinned DSH Workspace detachSession API is unavailable or incompatible");
|
|
2334
2617
|
}
|
|
2335
2618
|
await workspace.detachSession(options.supersededSessionId);
|
|
2619
|
+
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2336
2620
|
}
|
|
2337
2621
|
} catch (error) {
|
|
2338
|
-
await
|
|
2622
|
+
await releaseHandle();
|
|
2339
2623
|
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2340
2624
|
throw error;
|
|
2341
2625
|
}
|
|
2342
2626
|
}
|
|
2343
|
-
|
|
2627
|
+
throwIfDisposed(disposed, lifecycleAbort.signal, "open");
|
|
2344
2628
|
return mode;
|
|
2345
2629
|
})();
|
|
2346
2630
|
return openPromise;
|
|
@@ -2357,7 +2641,7 @@ function createDshHostFacade(options) {
|
|
|
2357
2641
|
return parsed;
|
|
2358
2642
|
});
|
|
2359
2643
|
};
|
|
2360
|
-
const prompt = async (text) => {
|
|
2644
|
+
const prompt = async (text, requestedSelection) => {
|
|
2361
2645
|
if (disposed)
|
|
2362
2646
|
throw new Error("DSH host facade is disposed");
|
|
2363
2647
|
if (!text.trim())
|
|
@@ -2370,12 +2654,24 @@ function createDshHostFacade(options) {
|
|
|
2370
2654
|
if (projectionActive)
|
|
2371
2655
|
throw new Error("DSH host facade permits only one active write");
|
|
2372
2656
|
promptActive = true;
|
|
2657
|
+
let disposeSelection;
|
|
2658
|
+
let selectionRef;
|
|
2373
2659
|
try {
|
|
2374
2660
|
await open2();
|
|
2375
2661
|
throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
|
|
2376
2662
|
const agent = requireAgent(handle);
|
|
2377
2663
|
if (agent.status !== "idle")
|
|
2378
2664
|
throw new Error("DSH Agent must be idle before a GatherThread prompt");
|
|
2665
|
+
if (requestedSelection !== void 0) {
|
|
2666
|
+
const selection = await resolveDshExecutionSelection(context, requestedSelection, lifecycleAbort.signal);
|
|
2667
|
+
throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
|
|
2668
|
+
const install = options.modelSelectionInstaller ?? await loadModelSelectionInstaller();
|
|
2669
|
+
selectionRef = { current: selection, assembled: void 0 };
|
|
2670
|
+
disposeSelection = install(agent.ctx, selectionRef);
|
|
2671
|
+
if (typeof disposeSelection !== "function") {
|
|
2672
|
+
throw new Error("Pinned DSH installModelSelection API returned an incompatible disposer");
|
|
2673
|
+
}
|
|
2674
|
+
}
|
|
2379
2675
|
const fromSequence = agent.session.seq;
|
|
2380
2676
|
const message = await createUserMessage(text, options);
|
|
2381
2677
|
throwIfDisposed(disposed, lifecycleAbort.signal, "prompt");
|
|
@@ -2391,6 +2687,11 @@ function createDshHostFacade(options) {
|
|
|
2391
2687
|
events: snapshotFrom(fromSequence)
|
|
2392
2688
|
};
|
|
2393
2689
|
} finally {
|
|
2690
|
+
if (selectionRef !== void 0) {
|
|
2691
|
+
selectionRef.current = void 0;
|
|
2692
|
+
selectionRef.assembled = void 0;
|
|
2693
|
+
}
|
|
2694
|
+
disposeSelection?.();
|
|
2394
2695
|
promptActive = false;
|
|
2395
2696
|
}
|
|
2396
2697
|
};
|
|
@@ -2447,18 +2748,32 @@ function createDshHostFacade(options) {
|
|
|
2447
2748
|
}
|
|
2448
2749
|
};
|
|
2449
2750
|
const dispose = () => {
|
|
2450
|
-
disposePromise
|
|
2451
|
-
|
|
2452
|
-
|
|
2453
|
-
|
|
2454
|
-
|
|
2455
|
-
|
|
2456
|
-
|
|
2751
|
+
if (disposePromise !== void 0)
|
|
2752
|
+
return disposePromise;
|
|
2753
|
+
disposed = true;
|
|
2754
|
+
lifecycleAbort.abort(new Error("DSH host facade disposed"));
|
|
2755
|
+
eventSubscribers.clear();
|
|
2756
|
+
statusSubscribers.clear();
|
|
2757
|
+
for (const stop of listenerDisposers.splice(0))
|
|
2758
|
+
stop();
|
|
2759
|
+
disposePromise = (async () => {
|
|
2760
|
+
let releaseError;
|
|
2457
2761
|
try {
|
|
2458
|
-
await
|
|
2459
|
-
}
|
|
2460
|
-
|
|
2762
|
+
await releaseHandle();
|
|
2763
|
+
} catch (error) {
|
|
2764
|
+
releaseError = error;
|
|
2765
|
+
}
|
|
2766
|
+
try {
|
|
2767
|
+
await openPromise;
|
|
2768
|
+
} catch {
|
|
2461
2769
|
}
|
|
2770
|
+
try {
|
|
2771
|
+
await releaseHandle();
|
|
2772
|
+
} catch (error) {
|
|
2773
|
+
releaseError ??= error;
|
|
2774
|
+
}
|
|
2775
|
+
if (releaseError !== void 0)
|
|
2776
|
+
throw releaseError;
|
|
2462
2777
|
})();
|
|
2463
2778
|
return disposePromise;
|
|
2464
2779
|
};
|
|
@@ -2490,9 +2805,10 @@ function createDshHostFacade(options) {
|
|
|
2490
2805
|
function ensureNativeSessionListVisibility(session) {
|
|
2491
2806
|
const events = session.snapshotEvents(0);
|
|
2492
2807
|
if (events.some((event) => asSessionEvent(event)?.type === "turn/start"))
|
|
2493
|
-
return;
|
|
2808
|
+
return false;
|
|
2494
2809
|
session.append("turn/start", { turn: 1 });
|
|
2495
2810
|
session.append("turn/end", { turn: 1, reason: { kind: "completed" } });
|
|
2811
|
+
return true;
|
|
2496
2812
|
}
|
|
2497
2813
|
function throwIfDisposed(disposed, signal, operation) {
|
|
2498
2814
|
if (disposed || signal.aborted) {
|
|
@@ -2572,6 +2888,49 @@ async function createUserMessage(text, options) {
|
|
|
2572
2888
|
source: { kind: "user" }
|
|
2573
2889
|
});
|
|
2574
2890
|
}
|
|
2891
|
+
async function loadModelSelectionInstaller() {
|
|
2892
|
+
const imported = asObject4(await importDshModule("@deepseek-ai/dsh-agent"));
|
|
2893
|
+
if (imported === void 0 || typeof imported.installModelSelection !== "function") {
|
|
2894
|
+
throw new Error("Pinned DSH installModelSelection API is unavailable");
|
|
2895
|
+
}
|
|
2896
|
+
return imported.installModelSelection;
|
|
2897
|
+
}
|
|
2898
|
+
async function importDshModule(specifier) {
|
|
2899
|
+
return import(specifier);
|
|
2900
|
+
}
|
|
2901
|
+
async function resolveDshExecutionSelection(context, requested, signal) {
|
|
2902
|
+
const provider = safeSelectionText(requested.provider, "provider", 80);
|
|
2903
|
+
const model = safeSelectionText(requested.model, "model", 160);
|
|
2904
|
+
const reasoningEffort = requested.reasoningEffort === void 0 ? void 0 : safeSelectionText(requested.reasoningEffort, "reasoning effort", 80);
|
|
2905
|
+
const llm = requireService(context, "llm", ["resolveModelInfo"]);
|
|
2906
|
+
const resolved = asObject4(await llm.resolveModelInfo(provider, model, signal));
|
|
2907
|
+
if (resolved === void 0 || resolved.provider !== provider || resolved.id !== model) {
|
|
2908
|
+
throw new Error("DeepSeek Harness did not resolve the requested provider/model exactly");
|
|
2909
|
+
}
|
|
2910
|
+
if (reasoningEffort !== void 0) {
|
|
2911
|
+
const reasoning = asObject4(resolved.reasoning);
|
|
2912
|
+
const efforts = Array.isArray(reasoning?.efforts) ? reasoning.efforts : [];
|
|
2913
|
+
const supported = efforts.some((value) => asObject4(value)?.id === reasoningEffort);
|
|
2914
|
+
if (!supported) {
|
|
2915
|
+
throw new Error(`DeepSeek Harness model ${provider}/${model} does not support reasoning effort ${reasoningEffort}`);
|
|
2916
|
+
}
|
|
2917
|
+
}
|
|
2918
|
+
return {
|
|
2919
|
+
provider,
|
|
2920
|
+
model,
|
|
2921
|
+
...reasoningEffort === void 0 ? {} : { reasoningEffort }
|
|
2922
|
+
};
|
|
2923
|
+
}
|
|
2924
|
+
function safeSelectionText(value, label, maximum) {
|
|
2925
|
+
if (typeof value !== "string") {
|
|
2926
|
+
throw new Error(`DeepSeek Harness ${label} selection must be a string`);
|
|
2927
|
+
}
|
|
2928
|
+
const normalized = value.trim();
|
|
2929
|
+
if (!normalized || normalized.length > maximum || /[\u0000-\u001f\u007f-\u009f]/u.test(normalized)) {
|
|
2930
|
+
throw new Error(`DeepSeek Harness ${label} selection is invalid`);
|
|
2931
|
+
}
|
|
2932
|
+
return normalized;
|
|
2933
|
+
}
|
|
2575
2934
|
function requireContext(value) {
|
|
2576
2935
|
const context = asObject4(value);
|
|
2577
2936
|
if (context === void 0 || typeof context.get !== "function" || typeof context.on !== "function" || typeof context.effect !== "function") {
|
|
@@ -2780,7 +3139,7 @@ function validateConnectorState(value) {
|
|
|
2780
3139
|
}
|
|
2781
3140
|
function parseActiveRequest(value) {
|
|
2782
3141
|
const active = requiredObject3(value, "state.activeRequest");
|
|
2783
|
-
exactKeys(active, /* @__PURE__ */ new Set(["requestId", "requestSequence", "dshFromSequence", "dshToSequence", "promptDigest"]), "state.activeRequest");
|
|
3142
|
+
exactKeys(active, /* @__PURE__ */ new Set(["requestId", "requestSequence", "dshFromSequence", "dshToSequence", "promptDigest", "claimAttempt"]), "state.activeRequest");
|
|
2784
3143
|
const parsed = {
|
|
2785
3144
|
requestId: safeString(active.requestId, "state.activeRequest.requestId", 128),
|
|
2786
3145
|
requestSequence: positiveInteger(active.requestSequence, "state.activeRequest.requestSequence"),
|
|
@@ -2788,7 +3147,10 @@ function parseActiveRequest(value) {
|
|
|
2788
3147
|
...active.dshToSequence === void 0 ? {} : {
|
|
2789
3148
|
dshToSequence: nonNegativeInteger(active.dshToSequence, "state.activeRequest.dshToSequence")
|
|
2790
3149
|
},
|
|
2791
|
-
promptDigest: hexDigest(active.promptDigest, "state.activeRequest.promptDigest")
|
|
3150
|
+
promptDigest: hexDigest(active.promptDigest, "state.activeRequest.promptDigest"),
|
|
3151
|
+
...active.claimAttempt === void 0 ? {} : {
|
|
3152
|
+
claimAttempt: positiveInteger(active.claimAttempt, "state.activeRequest.claimAttempt")
|
|
3153
|
+
}
|
|
2792
3154
|
};
|
|
2793
3155
|
if (parsed.dshToSequence !== void 0 && parsed.dshToSequence < parsed.dshFromSequence) {
|
|
2794
3156
|
throw new Error("state.activeRequest.dshToSequence cannot precede dshFromSequence");
|
|
@@ -2873,6 +3235,7 @@ function parseAppendInput(value, label) {
|
|
|
2873
3235
|
"replyTo",
|
|
2874
3236
|
"visibility",
|
|
2875
3237
|
"runtimeId",
|
|
3238
|
+
"claimAttempt",
|
|
2876
3239
|
"observedModel",
|
|
2877
3240
|
"observedReasoningEffort"
|
|
2878
3241
|
]), label);
|
|
@@ -2886,6 +3249,9 @@ function parseAppendInput(value, label) {
|
|
|
2886
3249
|
...input.replyTo === void 0 ? {} : { replyTo: safeString(input.replyTo, `${label}.replyTo`, 128) },
|
|
2887
3250
|
...input.visibility === void 0 ? {} : { visibility: safeString(input.visibility, `${label}.visibility`, 32) },
|
|
2888
3251
|
...input.runtimeId === void 0 ? {} : { runtimeId: safeString(input.runtimeId, `${label}.runtimeId`, 128) },
|
|
3252
|
+
...input.claimAttempt === void 0 ? {} : {
|
|
3253
|
+
claimAttempt: positiveInteger(input.claimAttempt, `${label}.claimAttempt`)
|
|
3254
|
+
},
|
|
2889
3255
|
...input.observedModel === void 0 ? {} : { observedModel: safeString(input.observedModel, `${label}.observedModel`, 160) },
|
|
2890
3256
|
...input.observedReasoningEffort === void 0 ? {} : {
|
|
2891
3257
|
observedReasoningEffort: safeString(input.observedReasoningEffort, `${label}.observedReasoningEffort`, 80)
|
|
@@ -2894,9 +3260,12 @@ function parseAppendInput(value, label) {
|
|
|
2894
3260
|
}
|
|
2895
3261
|
function parseCompletionInput(value, label) {
|
|
2896
3262
|
const input = requiredObject3(value, label);
|
|
2897
|
-
exactKeys(input, /* @__PURE__ */ new Set(["runtimeId", "idempotencyKey", "payload", "observedModel", "observedReasoningEffort"]), label);
|
|
3263
|
+
exactKeys(input, /* @__PURE__ */ new Set(["runtimeId", "claimAttempt", "idempotencyKey", "payload", "observedModel", "observedReasoningEffort"]), label);
|
|
2898
3264
|
return {
|
|
2899
3265
|
runtimeId: safeString(input.runtimeId, `${label}.runtimeId`, 128),
|
|
3266
|
+
...input.claimAttempt === void 0 ? {} : {
|
|
3267
|
+
claimAttempt: positiveInteger(input.claimAttempt, `${label}.claimAttempt`)
|
|
3268
|
+
},
|
|
2900
3269
|
idempotencyKey: safeString(input.idempotencyKey, `${label}.idempotencyKey`, 200),
|
|
2901
3270
|
payload: jsonValue(input.payload, `${label}.payload`),
|
|
2902
3271
|
...input.observedModel === void 0 ? {} : { observedModel: safeString(input.observedModel, `${label}.observedModel`, 160) },
|
|
@@ -3405,6 +3774,14 @@ function projectSessionConfig(config, sessionId, nativeSessionId) {
|
|
|
3405
3774
|
statePath: path4.join(config.stateRoot, `${dshSessionId}.json`),
|
|
3406
3775
|
provider: config.provider,
|
|
3407
3776
|
model: config.model,
|
|
3777
|
+
...config.executionProfiles === void 0 ? {} : {
|
|
3778
|
+
executionProfiles: config.executionProfiles.map((profile) => ({
|
|
3779
|
+
...profile,
|
|
3780
|
+
...profile.reasoningEfforts === void 0 ? {} : {
|
|
3781
|
+
reasoningEfforts: [...profile.reasoningEfforts]
|
|
3782
|
+
}
|
|
3783
|
+
}))
|
|
3784
|
+
},
|
|
3408
3785
|
pollIntervalMs: config.pollIntervalMs,
|
|
3409
3786
|
pollLimit: config.pollLimit,
|
|
3410
3787
|
shareToolEvents: config.shareToolEvents,
|