@liberseek/boft-cli-win32-arm64 0.6.8 → 0.7.0
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 +1 -1
- package/THIRD_PARTY_NOTICES.txt +16 -0
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +184 -47
- package/app/host-runtime.mjs +5449 -4221
- package/app/plugins/antigravity/plugin.mjs +70 -61
- package/app/plugins/claude-code/plugin.mjs +85 -58
- package/app/plugins/codebuddy/plugin.mjs +102 -69
- package/app/plugins/cursor-cli/plugin.mjs +69 -50
- package/app/plugins/deepseek-harness/plugin.mjs +81 -53
- package/app/plugins/enabled.json +3 -1
- package/app/plugins/grok/plugin.mjs +94 -61
- package/app/plugins/hermes/plugin.mjs +308 -95
- package/app/plugins/kiro-cli/plugin.mjs +76 -49
- package/app/plugins/muse/plugin.mjs +66 -46
- package/app/plugins/omp/plugin.mjs +79 -52
- package/app/plugins/opencode/plugin.mjs +118 -92
- package/app/plugins/pi/plugin.mjs +79 -52
- package/app/plugins/qoder/assets/icon.svg +1 -0
- package/app/plugins/qoder/manifest.json +12 -0
- package/app/plugins/qoder/plugin.mjs +52290 -0
- package/app/plugins/qoder-cn/assets/icon.svg +1 -0
- package/app/plugins/qoder-cn/manifest.json +12 -0
- package/app/plugins/qoder-cn/plugin.mjs +52288 -0
- package/app/renderer-extension.js +3857 -1175
- package/bin/boft.exe +0 -0
- package/libexec/boft-node-repl.exe +0 -0
- package/libexec/boft-shim.exe +0 -0
- package/libexec/boft-updater.exe +0 -0
- package/licenses/Qoder-Agent-SDK-LICENSE.txt +7 -0
- package/licenses/QoderCN-Agent-SDK-LICENSE.txt +7 -0
- package/licenses/opencodex-LICENSE.txt +21 -0
- package/licenses/tailwindcss-LICENSE.txt +21 -0
- package/package.json +1 -1
|
@@ -5,6 +5,9 @@ var __export = (target, all) => {
|
|
|
5
5
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
+
// dist/hermes-adapter.js
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
10
|
+
|
|
8
11
|
// ../../../node_modules/zod/v4/classic/external.js
|
|
9
12
|
var external_exports = {};
|
|
10
13
|
__export(external_exports, {
|
|
@@ -14522,6 +14525,46 @@ config(en_default());
|
|
|
14522
14525
|
// ../../shared-contracts/dist/version.js
|
|
14523
14526
|
var WORKSPACE_CONTRACT_VERSION = 1;
|
|
14524
14527
|
|
|
14528
|
+
// ../../shared-contracts/dist/idle-release.js
|
|
14529
|
+
var IDLE_RELEASE_TIMEOUT_MINUTES_MIN = 5;
|
|
14530
|
+
var IDLE_RELEASE_TIMEOUT_MINUTES_MAX = 1440;
|
|
14531
|
+
var idleReleaseSettingsSchema = external_exports.strictObject({
|
|
14532
|
+
enabled: external_exports.boolean(),
|
|
14533
|
+
timeoutMinutes: external_exports.number().int().min(IDLE_RELEASE_TIMEOUT_MINUTES_MIN).max(IDLE_RELEASE_TIMEOUT_MINUTES_MAX)
|
|
14534
|
+
});
|
|
14535
|
+
var DEFAULT_IDLE_RELEASE_SETTINGS = Object.freeze({
|
|
14536
|
+
enabled: false,
|
|
14537
|
+
timeoutMinutes: 30
|
|
14538
|
+
});
|
|
14539
|
+
|
|
14540
|
+
// ../../shared-contracts/dist/loaded-sessions.js
|
|
14541
|
+
var loadedSessionStateSchema = external_exports.enum([
|
|
14542
|
+
"idle",
|
|
14543
|
+
"running",
|
|
14544
|
+
"busy",
|
|
14545
|
+
"closing",
|
|
14546
|
+
"failed",
|
|
14547
|
+
"blocked"
|
|
14548
|
+
]);
|
|
14549
|
+
var loadedSessionReasonSchema = external_exports.enum([
|
|
14550
|
+
"none",
|
|
14551
|
+
"disabled",
|
|
14552
|
+
"timeout",
|
|
14553
|
+
"operation",
|
|
14554
|
+
"background",
|
|
14555
|
+
"identity",
|
|
14556
|
+
"persistence",
|
|
14557
|
+
"closeFailed"
|
|
14558
|
+
]);
|
|
14559
|
+
var loadedSessionsSchema = external_exports.array(external_exports.strictObject({
|
|
14560
|
+
threadId: external_exports.string(),
|
|
14561
|
+
title: external_exports.string(),
|
|
14562
|
+
harnessId: external_exports.string(),
|
|
14563
|
+
state: loadedSessionStateSchema,
|
|
14564
|
+
reason: loadedSessionReasonSchema,
|
|
14565
|
+
inactiveMs: external_exports.number().nonnegative()
|
|
14566
|
+
}));
|
|
14567
|
+
|
|
14525
14568
|
// ../../shared-contracts/dist/ids.js
|
|
14526
14569
|
var opaqueIdSchema = external_exports.string().refine((value) => value.trim().length > 0, {
|
|
14527
14570
|
message: "Identifier must not be empty or whitespace"
|
|
@@ -14642,12 +14685,21 @@ var harnessAccountSnapshotSchema = external_exports.object({
|
|
|
14642
14685
|
plan: external_exports.string().trim().min(1).max(128).optional(),
|
|
14643
14686
|
credits: accountCreditsSnapshotSchema
|
|
14644
14687
|
}).strict();
|
|
14645
|
-
var
|
|
14688
|
+
var harnessAccountIdentityShape = {
|
|
14689
|
+
harnessId: harnessIdSchema,
|
|
14690
|
+
harnessName: external_exports.string().trim().min(1).max(128)
|
|
14691
|
+
};
|
|
14692
|
+
var harnessAccountSourceSchema = external_exports.object(harnessAccountIdentityShape).strict();
|
|
14693
|
+
var harnessAccountSourceListParamsSchema = external_exports.object({}).strict();
|
|
14694
|
+
var harnessAccountSourceListResultSchema = external_exports.object({ sources: external_exports.array(harnessAccountSourceSchema).max(128) }).strict();
|
|
14695
|
+
var harnessAccountInspectParamsSchema = external_exports.object({ harnessId: harnessIdSchema, refresh: external_exports.boolean().optional() }).strict();
|
|
14696
|
+
var harnessAccountInspectResultSchema = external_exports.object({
|
|
14697
|
+
...harnessAccountIdentityShape,
|
|
14698
|
+
account: harnessAccountSnapshotSchema.nullable()
|
|
14699
|
+
}).strict();
|
|
14700
|
+
var harnessAccountListParamsSchema = external_exports.object({ refresh: external_exports.boolean().optional() }).strict();
|
|
14646
14701
|
var harnessAccountListResultSchema = external_exports.object({
|
|
14647
|
-
accounts: external_exports.array(harnessAccountSnapshotSchema.extend(
|
|
14648
|
-
harnessId: harnessIdSchema,
|
|
14649
|
-
harnessName: external_exports.string().min(1)
|
|
14650
|
-
})).max(128)
|
|
14702
|
+
accounts: external_exports.array(harnessAccountSnapshotSchema.extend(harnessAccountIdentityShape)).max(128)
|
|
14651
14703
|
}).strict();
|
|
14652
14704
|
|
|
14653
14705
|
// ../../shared-contracts/dist/json-value.js
|
|
@@ -14943,7 +14995,6 @@ var threadInspectionParamsSchema = external_exports.object({
|
|
|
14943
14995
|
}).strict();
|
|
14944
14996
|
var codexThreadInspectionSchema = external_exports.object({
|
|
14945
14997
|
owner: external_exports.literal("codex"),
|
|
14946
|
-
accountId: nonBlankTextSchema2.optional(),
|
|
14947
14998
|
locked: external_exports.literal(true)
|
|
14948
14999
|
}).strict();
|
|
14949
15000
|
var externalThreadInspectionSchema = external_exports.object({
|
|
@@ -15085,53 +15136,25 @@ var codexAccountSchema = external_exports.object({
|
|
|
15085
15136
|
label: nonBlankTextSchema3.max(256),
|
|
15086
15137
|
email: external_exports.string().email().max(320).optional(),
|
|
15087
15138
|
planType: codexAccountPlanTypeSchema.optional(),
|
|
15088
|
-
codexHome: nonBlankTextSchema3.max(16384),
|
|
15089
|
-
active: external_exports.boolean(),
|
|
15090
|
-
isDefault: external_exports.boolean(),
|
|
15091
15139
|
authKind: codexAccountAuthKindSchema.optional(),
|
|
15092
15140
|
authIdentity: nonBlankTextSchema3.max(256).optional()
|
|
15093
15141
|
}).strict();
|
|
15094
|
-
var
|
|
15095
|
-
var
|
|
15096
|
-
|
|
15097
|
-
|
|
15098
|
-
|
|
15099
|
-
|
|
15100
|
-
|
|
15101
|
-
|
|
15102
|
-
accountId: accountIdSchema,
|
|
15103
|
-
loginId: nonBlankTextSchema3.max(1024),
|
|
15104
|
-
verificationUrl: external_exports.string().url().max(16384),
|
|
15105
|
-
userCode: nonBlankTextSchema3.max(1024)
|
|
15106
|
-
}).strict();
|
|
15107
|
-
var codexAccountLoginCancelParamsSchema = external_exports.object({ accountId: accountIdSchema.optional(), loginId: nonBlankTextSchema3.max(1024) }).strict();
|
|
15108
|
-
var codexAccountLoginCancelResultSchema = external_exports.object({ cancelled: external_exports.boolean() }).strict();
|
|
15109
|
-
var codexAccountLoginCompletedSchema = external_exports.object({
|
|
15110
|
-
accountId: accountIdSchema,
|
|
15111
|
-
loginId: nonBlankTextSchema3.max(1024),
|
|
15112
|
-
success: external_exports.boolean(),
|
|
15113
|
-
error: external_exports.string().max(4096).nullable()
|
|
15142
|
+
var codexAccountPhaseSchema = external_exports.enum(["ready", "unavailable"]);
|
|
15143
|
+
var codexAccountListResultSchema = external_exports.object({
|
|
15144
|
+
version: external_exports.literal(2),
|
|
15145
|
+
currentAccountId: accountIdSchema.nullable(),
|
|
15146
|
+
phase: codexAccountPhaseSchema,
|
|
15147
|
+
revision: external_exports.number().int().nonnegative(),
|
|
15148
|
+
instanceId: nonBlankTextSchema3.max(1024).optional(),
|
|
15149
|
+
accounts: external_exports.array(codexAccountSchema).max(1)
|
|
15114
15150
|
}).strict();
|
|
15115
|
-
var codexAccountUsageParamsSchema = external_exports.object({ accountId: accountIdSchema }).strict();
|
|
15151
|
+
var codexAccountUsageParamsSchema = external_exports.object({ accountId: accountIdSchema, refresh: external_exports.boolean().optional() }).strict();
|
|
15116
15152
|
var codexAccountUsageResultSchema = external_exports.object({
|
|
15117
15153
|
accountId: accountIdSchema,
|
|
15118
15154
|
usage: threadUsageSnapshotSchema.nullable(),
|
|
15119
|
-
accountCredits: accountCreditsSnapshotSchema.optional()
|
|
15120
|
-
|
|
15121
|
-
|
|
15122
|
-
accountId: accountIdSchema,
|
|
15123
|
-
idempotencyKey: external_exports.string().uuid().optional()
|
|
15124
|
-
}).strict();
|
|
15125
|
-
var codexAccountResetCreditConsumeOutcomeSchema = external_exports.enum([
|
|
15126
|
-
"reset",
|
|
15127
|
-
"nothingToReset",
|
|
15128
|
-
"noCredit",
|
|
15129
|
-
"alreadyRedeemed"
|
|
15130
|
-
]);
|
|
15131
|
-
var codexAccountResetCreditConsumeResultSchema = external_exports.object({
|
|
15132
|
-
accountId: accountIdSchema,
|
|
15133
|
-
outcome: codexAccountResetCreditConsumeOutcomeSchema,
|
|
15134
|
-
accountCredits: accountCreditsSnapshotSchema.optional()
|
|
15155
|
+
accountCredits: accountCreditsSnapshotSchema.optional(),
|
|
15156
|
+
freshness: external_exports.enum(["live", "cached"]),
|
|
15157
|
+
observedAt: external_exports.string().datetime().nullable()
|
|
15135
15158
|
}).strict();
|
|
15136
15159
|
|
|
15137
15160
|
// ../../shared-contracts/dist/harness-session-import.js
|
|
@@ -20061,6 +20084,19 @@ var HermesAcpTransport = class {
|
|
|
20061
20084
|
get stderrTail() {
|
|
20062
20085
|
return this.#stderrTail;
|
|
20063
20086
|
}
|
|
20087
|
+
/**
|
|
20088
|
+
* Point subsequent session creation at a different working directory.
|
|
20089
|
+
* The spawn cwd is process-launch state and cannot change after the fact,
|
|
20090
|
+
* but Hermes derives all session cwd behavior from the session/new
|
|
20091
|
+
* parameter (agent.session_cwd, task env overrides, turn-time session
|
|
20092
|
+
* vars), never from the process cwd — so a warm transport spawned in one
|
|
20093
|
+
* directory can safely host a Session for another.
|
|
20094
|
+
*/
|
|
20095
|
+
retarget(cwd) {
|
|
20096
|
+
if (this.#sessionId)
|
|
20097
|
+
throw new Error("Hermes ACP Transport cannot retarget an open Session");
|
|
20098
|
+
this.#options = { ...this.#options, cwd };
|
|
20099
|
+
}
|
|
20064
20100
|
async inspect() {
|
|
20065
20101
|
if (this.#sessionId)
|
|
20066
20102
|
throw new Error("Hermes ACP inspection cannot reuse an open Session");
|
|
@@ -20345,6 +20381,9 @@ function decodeHermesModelRefId(modelRefId) {
|
|
|
20345
20381
|
return null;
|
|
20346
20382
|
}
|
|
20347
20383
|
}
|
|
20384
|
+
function catalogAlignedModelLabel(name) {
|
|
20385
|
+
return name.replace(/\s+·\s+/g, " / ");
|
|
20386
|
+
}
|
|
20348
20387
|
function projectHermesModelState(models) {
|
|
20349
20388
|
if (!models || models.availableModels.length === 0) {
|
|
20350
20389
|
return { effectiveModel: null, resolvedModelLabel: null };
|
|
@@ -20354,12 +20393,13 @@ function projectHermesModelState(models) {
|
|
|
20354
20393
|
return { effectiveModel: null, resolvedModelLabel: null };
|
|
20355
20394
|
return {
|
|
20356
20395
|
effectiveModel: encodeHermesModelRef(current.modelId),
|
|
20357
|
-
resolvedModelLabel: current.name
|
|
20396
|
+
resolvedModelLabel: catalogAlignedModelLabel(current.name)
|
|
20358
20397
|
};
|
|
20359
20398
|
}
|
|
20360
20399
|
|
|
20361
20400
|
// dist/hermes-inventory.js
|
|
20362
|
-
var
|
|
20401
|
+
var POSIX_VENV_PYTHON_SHIM_PATTERN = /exec\s+"([^"]+?venv\/bin\/python)"/;
|
|
20402
|
+
var WINDOWS_VENV_HERMES_SHIM_PATTERN = /"([^"]+?[\\/]venv[\\/]Scripts[\\/]hermes\.exe)"/i;
|
|
20363
20403
|
var INVENTORY_PROBE_SCRIPT = `
|
|
20364
20404
|
import json
|
|
20365
20405
|
from hermes_cli.inventory import build_models_payload, load_picker_context
|
|
@@ -20430,11 +20470,14 @@ print(json.dumps({"models": rows, "currentModelId": current_model_id}))
|
|
|
20430
20470
|
`;
|
|
20431
20471
|
var HermesInventoryError = class extends Error {
|
|
20432
20472
|
};
|
|
20433
|
-
async function venvPythonFromShim(hermesExecutable) {
|
|
20473
|
+
async function venvPythonFromShim(hermesExecutable, platform = process.platform) {
|
|
20434
20474
|
try {
|
|
20435
20475
|
const shim = await readFile(hermesExecutable, "utf8");
|
|
20436
|
-
|
|
20437
|
-
|
|
20476
|
+
if (platform === "win32") {
|
|
20477
|
+
const target = WINDOWS_VENV_HERMES_SHIM_PATTERN.exec(shim)?.[1];
|
|
20478
|
+
return target ? path4.win32.join(path4.win32.dirname(target), "python.exe") : null;
|
|
20479
|
+
}
|
|
20480
|
+
return POSIX_VENV_PYTHON_SHIM_PATTERN.exec(shim)?.[1] ?? null;
|
|
20438
20481
|
} catch {
|
|
20439
20482
|
return null;
|
|
20440
20483
|
}
|
|
@@ -20447,15 +20490,17 @@ function inventoryPythonCandidates(hermesExecutable, platform = process.platform
|
|
|
20447
20490
|
if (environmentDirectory === "scripts") {
|
|
20448
20491
|
candidates.push(pathApi.join(executableDirectory, "python.exe"));
|
|
20449
20492
|
} else if (environmentDirectory === "bin") {
|
|
20450
|
-
candidates.push(pathApi.join(executableDirectory, "python"));
|
|
20493
|
+
candidates.push(pathApi.join(executableDirectory, platform === "win32" ? "python.exe" : "python"));
|
|
20451
20494
|
}
|
|
20452
|
-
const
|
|
20453
|
-
candidates.push(pathApi.
|
|
20495
|
+
const relativePython = platform === "win32" ? "venv/Scripts/python.exe" : "venv/bin/python";
|
|
20496
|
+
candidates.push(pathApi.resolve(executableDirectory, "../hermes-agent", relativePython));
|
|
20497
|
+
candidates.push(pathApi.resolve(executableDirectory, "../../.hermes/hermes-agent", relativePython));
|
|
20454
20498
|
return [...new Set(candidates)];
|
|
20455
20499
|
}
|
|
20456
20500
|
function runProbe(pythonExecutable, timeoutMs, environment) {
|
|
20457
20501
|
return new Promise((resolve, reject) => {
|
|
20458
|
-
const child = spawn2(pythonExecutable, ["-c", INVENTORY_PROBE_SCRIPT], {
|
|
20502
|
+
const child = spawn2(pythonExecutable, ["-I", "-c", INVENTORY_PROBE_SCRIPT], {
|
|
20503
|
+
cwd: path4.dirname(pythonExecutable),
|
|
20459
20504
|
env: { ...process.env, ...environment },
|
|
20460
20505
|
stdio: ["ignore", "pipe", "pipe"]
|
|
20461
20506
|
});
|
|
@@ -20495,11 +20540,12 @@ function runProbe(pythonExecutable, timeoutMs, environment) {
|
|
|
20495
20540
|
});
|
|
20496
20541
|
}
|
|
20497
20542
|
async function readHermesModelInventory(hermesExecutable, timeoutMs = 2e4, options = {}) {
|
|
20543
|
+
const platform = options.platform ?? process.platform;
|
|
20498
20544
|
const candidates = [
|
|
20499
|
-
|
|
20500
|
-
...inventoryPythonCandidates(hermesExecutable,
|
|
20545
|
+
await venvPythonFromShim(hermesExecutable, platform) ?? "",
|
|
20546
|
+
...inventoryPythonCandidates(hermesExecutable, platform)
|
|
20501
20547
|
].filter((candidate, index, all) => candidate.length > 0 && all.indexOf(candidate) === index);
|
|
20502
|
-
let pythonExecutable =
|
|
20548
|
+
let pythonExecutable = null;
|
|
20503
20549
|
for (const candidate of candidates) {
|
|
20504
20550
|
try {
|
|
20505
20551
|
await access(candidate);
|
|
@@ -20508,8 +20554,9 @@ async function readHermesModelInventory(hermesExecutable, timeoutMs = 2e4, optio
|
|
|
20508
20554
|
} catch {
|
|
20509
20555
|
}
|
|
20510
20556
|
}
|
|
20511
|
-
if (!pythonExecutable)
|
|
20512
|
-
throw new HermesInventoryError(
|
|
20557
|
+
if (!pythonExecutable) {
|
|
20558
|
+
throw new HermesInventoryError(`Hermes inventory interpreter not found (searched: ${candidates.join(", ")})`);
|
|
20559
|
+
}
|
|
20513
20560
|
return runProbe(pythonExecutable, timeoutMs, options.environment);
|
|
20514
20561
|
}
|
|
20515
20562
|
function catalogModelsFromInventory(inventory) {
|
|
@@ -20659,6 +20706,7 @@ var ActiveTurn = class {
|
|
|
20659
20706
|
#currentText = null;
|
|
20660
20707
|
#toolItems = /* @__PURE__ */ new Map();
|
|
20661
20708
|
#finishedItems = [];
|
|
20709
|
+
#emittedTerminalItemIds = /* @__PURE__ */ new Set();
|
|
20662
20710
|
constructor(turnId, turnKey, input) {
|
|
20663
20711
|
this.turnId = hostTurnIdSchema.parse(turnId);
|
|
20664
20712
|
this.turnKey = turnKey;
|
|
@@ -20681,23 +20729,42 @@ var ActiveTurn = class {
|
|
|
20681
20729
|
this.#currentText = { kind, item: appended };
|
|
20682
20730
|
return { startedItem: item, item: appended };
|
|
20683
20731
|
}
|
|
20732
|
+
completeCurrentText() {
|
|
20733
|
+
if (!this.#currentText)
|
|
20734
|
+
return null;
|
|
20735
|
+
const snapshot = {
|
|
20736
|
+
item: this.#currentText.item,
|
|
20737
|
+
outcome: { status: "succeeded" }
|
|
20738
|
+
};
|
|
20739
|
+
this.#currentText = null;
|
|
20740
|
+
this.#finishedItems.push(snapshot);
|
|
20741
|
+
this.#emittedTerminalItemIds.add(snapshot.item.itemId);
|
|
20742
|
+
return snapshot;
|
|
20743
|
+
}
|
|
20684
20744
|
addToolItem(toolCallId, entry) {
|
|
20685
20745
|
this.#toolItems.set(toolCallId, entry);
|
|
20686
20746
|
}
|
|
20687
20747
|
getToolItem(toolCallId) {
|
|
20688
20748
|
return this.#toolItems.get(toolCallId);
|
|
20689
20749
|
}
|
|
20750
|
+
updateToolOutput(toolCallId, output) {
|
|
20751
|
+
const entry = this.#toolItems.get(toolCallId);
|
|
20752
|
+
if (entry)
|
|
20753
|
+
entry.output = output;
|
|
20754
|
+
}
|
|
20690
20755
|
completeToolItem(toolCallId, output, failed) {
|
|
20691
20756
|
const entry = this.#toolItems.get(toolCallId);
|
|
20692
20757
|
if (!entry)
|
|
20693
20758
|
return null;
|
|
20694
20759
|
this.#toolItems.delete(toolCallId);
|
|
20695
20760
|
const outcome = failed ? { status: "failed", error: harnessError("nativeFailure", "Tool execution failed") } : { status: "succeeded" };
|
|
20761
|
+
const finalOutput = output ?? entry.output;
|
|
20696
20762
|
const snapshot = {
|
|
20697
|
-
item: { ...entry.item, ...
|
|
20763
|
+
item: { ...entry.item, ...finalOutput ? { output: finalOutput } : {} },
|
|
20698
20764
|
outcome
|
|
20699
20765
|
};
|
|
20700
20766
|
this.#finishedItems.push(snapshot);
|
|
20767
|
+
this.#emittedTerminalItemIds.add(snapshot.item.itemId);
|
|
20701
20768
|
return snapshot;
|
|
20702
20769
|
}
|
|
20703
20770
|
finish() {
|
|
@@ -20710,14 +20777,17 @@ var ActiveTurn = class {
|
|
|
20710
20777
|
}
|
|
20711
20778
|
for (const [, entry] of this.#toolItems) {
|
|
20712
20779
|
this.#finishedItems.push({
|
|
20713
|
-
item: entry.item,
|
|
20780
|
+
item: { ...entry.item, ...entry.output ? { output: entry.output } : {} },
|
|
20714
20781
|
outcome: { status: "cancelled", reason: "Turn ended" }
|
|
20715
20782
|
});
|
|
20716
20783
|
}
|
|
20717
20784
|
this.#toolItems.clear();
|
|
20718
20785
|
}
|
|
20719
20786
|
drainPendingItems() {
|
|
20720
|
-
|
|
20787
|
+
const pending = this.#finishedItems.filter((snapshot) => !this.#emittedTerminalItemIds.has(snapshot.item.itemId));
|
|
20788
|
+
this.#finishedItems = [];
|
|
20789
|
+
this.#emittedTerminalItemIds.clear();
|
|
20790
|
+
return pending;
|
|
20721
20791
|
}
|
|
20722
20792
|
toSnapshot(nativeTurnRef, outcome, includeItems) {
|
|
20723
20793
|
return {
|
|
@@ -20749,6 +20819,7 @@ function toolOutputFromUpdate(update) {
|
|
|
20749
20819
|
function historyTurnsFromReplay(replay, nativeRef, knownTurnRefs = []) {
|
|
20750
20820
|
const turns = [];
|
|
20751
20821
|
let current = null;
|
|
20822
|
+
let toolItemIndexes = /* @__PURE__ */ new Map();
|
|
20752
20823
|
const closeTurn = () => {
|
|
20753
20824
|
if (!current || current.items.length === 0) {
|
|
20754
20825
|
current = null;
|
|
@@ -20765,9 +20836,13 @@ function historyTurnsFromReplay(replay, nativeRef, knownTurnRefs = []) {
|
|
|
20765
20836
|
nativeTurnRef,
|
|
20766
20837
|
input: [{ type: "text", text: current.inputText }],
|
|
20767
20838
|
items: current.items,
|
|
20768
|
-
outcome: {
|
|
20839
|
+
outcome: {
|
|
20840
|
+
status: "unknown",
|
|
20841
|
+
reason: "Hermes replay does not include terminal Turn outcome metadata"
|
|
20842
|
+
}
|
|
20769
20843
|
});
|
|
20770
20844
|
current = null;
|
|
20845
|
+
toolItemIndexes = /* @__PURE__ */ new Map();
|
|
20771
20846
|
};
|
|
20772
20847
|
const pushText = (kind, text) => {
|
|
20773
20848
|
if (!current)
|
|
@@ -20789,8 +20864,12 @@ function historyTurnsFromReplay(replay, nativeRef, knownTurnRefs = []) {
|
|
|
20789
20864
|
for (const event of replay) {
|
|
20790
20865
|
switch (event.type) {
|
|
20791
20866
|
case "user.text": {
|
|
20792
|
-
|
|
20793
|
-
|
|
20867
|
+
if (current && current.items.length === 0) {
|
|
20868
|
+
current.inputText += event.text;
|
|
20869
|
+
} else {
|
|
20870
|
+
closeTurn();
|
|
20871
|
+
current = { inputText: event.text, items: [], turnKey: `history-${turns.length + 1}` };
|
|
20872
|
+
}
|
|
20794
20873
|
break;
|
|
20795
20874
|
}
|
|
20796
20875
|
case "agent.thought":
|
|
@@ -20803,16 +20882,42 @@ function historyTurnsFromReplay(replay, nativeRef, knownTurnRefs = []) {
|
|
|
20803
20882
|
if (!current)
|
|
20804
20883
|
current = { inputText: "(resumed)", items: [], turnKey: `history-${turns.length + 1}` };
|
|
20805
20884
|
const update = event.update;
|
|
20885
|
+
const output = toolOutputFromUpdate(update);
|
|
20806
20886
|
const toolName = typeof update.title === "string" && update.title.trim() || typeof update.name === "string" && update.name.trim() || event.toolCallId;
|
|
20807
20887
|
current.items.push({
|
|
20808
20888
|
item: {
|
|
20809
20889
|
type: "toolExecution",
|
|
20810
20890
|
itemId: hostItemIdSchema.parse(randomUUID()),
|
|
20811
20891
|
toolName,
|
|
20812
|
-
arguments: isPlainObjectOrArray(update.rawInput) ? update.rawInput : null
|
|
20892
|
+
arguments: isPlainObjectOrArray(update.rawInput) ? update.rawInput : null,
|
|
20893
|
+
...output ? { output } : {}
|
|
20813
20894
|
},
|
|
20814
|
-
outcome: { status: "succeeded" }
|
|
20895
|
+
outcome: update.status === "completed" ? { status: "succeeded" } : update.status === "failed" ? {
|
|
20896
|
+
status: "failed",
|
|
20897
|
+
error: harnessError("nativeFailure", "Tool execution failed")
|
|
20898
|
+
} : { status: "cancelled", reason: "Turn ended before terminal tool update" }
|
|
20815
20899
|
});
|
|
20900
|
+
toolItemIndexes.set(event.toolCallId, current.items.length - 1);
|
|
20901
|
+
break;
|
|
20902
|
+
}
|
|
20903
|
+
case "tool.update": {
|
|
20904
|
+
if (!current)
|
|
20905
|
+
break;
|
|
20906
|
+
const itemIndex = toolItemIndexes.get(event.toolCallId);
|
|
20907
|
+
if (itemIndex === void 0)
|
|
20908
|
+
break;
|
|
20909
|
+
const prior = current.items[itemIndex];
|
|
20910
|
+
if (!prior || prior.item.type !== "toolExecution")
|
|
20911
|
+
break;
|
|
20912
|
+
const update = event.update;
|
|
20913
|
+
const output = toolOutputFromUpdate(update);
|
|
20914
|
+
current.items[itemIndex] = {
|
|
20915
|
+
item: { ...prior.item, ...output ? { output } : {} },
|
|
20916
|
+
outcome: update.status === "completed" ? { status: "succeeded" } : update.status === "failed" ? {
|
|
20917
|
+
status: "failed",
|
|
20918
|
+
error: harnessError("nativeFailure", "Tool execution failed")
|
|
20919
|
+
} : prior.outcome
|
|
20920
|
+
};
|
|
20816
20921
|
break;
|
|
20817
20922
|
}
|
|
20818
20923
|
default:
|
|
@@ -20858,10 +20963,12 @@ var HermesSession = class {
|
|
|
20858
20963
|
#state;
|
|
20859
20964
|
#faulted = null;
|
|
20860
20965
|
#closed = false;
|
|
20966
|
+
#availableModels = [];
|
|
20861
20967
|
#activeTurn = null;
|
|
20862
20968
|
#activeTurnId = null;
|
|
20863
20969
|
#completedTurns = [];
|
|
20864
20970
|
#historyTurns;
|
|
20971
|
+
#latestUsage;
|
|
20865
20972
|
#approvalWaiters = /* @__PURE__ */ new Map();
|
|
20866
20973
|
constructor(options) {
|
|
20867
20974
|
this.#transport = options.transport;
|
|
@@ -20869,6 +20976,7 @@ var HermesSession = class {
|
|
|
20869
20976
|
this.#onSettle = options.onSettle;
|
|
20870
20977
|
const projected = projectHermesModelState(options.open.session.models);
|
|
20871
20978
|
const modes = options.open.session.modes;
|
|
20979
|
+
this.#availableModels = options.open.session.models?.availableModels ?? [];
|
|
20872
20980
|
this.#state = {
|
|
20873
20981
|
nativeRef: this.#nativeRef,
|
|
20874
20982
|
...projected.effectiveModel ? { effectiveModel: projected.effectiveModel } : {},
|
|
@@ -20878,6 +20986,7 @@ var HermesSession = class {
|
|
|
20878
20986
|
this.initialState = { ...this.#state };
|
|
20879
20987
|
this.#historyTurns = historyTurnsFromReplay(options.open.replay, this.#nativeRef, options.knownTurnRefs);
|
|
20880
20988
|
this.initialUsage = lastUsageFromReplay(options.open.replay);
|
|
20989
|
+
this.#latestUsage = this.initialUsage;
|
|
20881
20990
|
this.outputs = this.#channel.outputs;
|
|
20882
20991
|
this.#transport.onFault = (error51) => this.#fault(transportErrorToHarness(error51));
|
|
20883
20992
|
}
|
|
@@ -20924,8 +21033,14 @@ var HermesSession = class {
|
|
|
20924
21033
|
this.#onSettle(this);
|
|
20925
21034
|
}
|
|
20926
21035
|
#cancelApprovalWaiters() {
|
|
20927
|
-
for (const waiter of this.#approvalWaiters
|
|
21036
|
+
for (const [interactionId, waiter] of this.#approvalWaiters) {
|
|
20928
21037
|
waiter.resolve({ outcome: { outcome: "cancelled" } });
|
|
21038
|
+
this.#emit({
|
|
21039
|
+
type: "interaction.closed",
|
|
21040
|
+
interactionId,
|
|
21041
|
+
turnId: waiter.turnId,
|
|
21042
|
+
reason: "cancelled"
|
|
21043
|
+
});
|
|
20929
21044
|
}
|
|
20930
21045
|
this.#approvalWaiters.clear();
|
|
20931
21046
|
}
|
|
@@ -20934,8 +21049,9 @@ var HermesSession = class {
|
|
|
20934
21049
|
return;
|
|
20935
21050
|
this.#faulted = error51;
|
|
20936
21051
|
this.#cancelApprovalWaiters();
|
|
20937
|
-
this.#activeTurn
|
|
20938
|
-
|
|
21052
|
+
if (this.#activeTurn) {
|
|
21053
|
+
this.#completeActiveTurn(this.#activeTurn, { status: "failed", error: error51 });
|
|
21054
|
+
}
|
|
20939
21055
|
this.#emit({ type: "session.faulted", error: error51 });
|
|
20940
21056
|
this.#channel.end();
|
|
20941
21057
|
this.#onSettle(this);
|
|
@@ -20950,8 +21066,8 @@ var HermesSession = class {
|
|
|
20950
21066
|
if (this.#activeTurn) {
|
|
20951
21067
|
return err("sessionBusy", "Hermes Session already has an active Turn", true);
|
|
20952
21068
|
}
|
|
20953
|
-
const text = command.input.
|
|
20954
|
-
if (text.length === 0) {
|
|
21069
|
+
const text = command.input.flatMap((chunk) => chunk.type === "text" ? [chunk.text] : []).join("\n");
|
|
21070
|
+
if (text.trim().length === 0) {
|
|
20955
21071
|
return err("invalidRequest", "turn.start requires non-empty text input");
|
|
20956
21072
|
}
|
|
20957
21073
|
const turnKey = randomUUID();
|
|
@@ -20973,9 +21089,6 @@ var HermesSession = class {
|
|
|
20973
21089
|
if (this.#activeTurn !== active) {
|
|
20974
21090
|
return;
|
|
20975
21091
|
}
|
|
20976
|
-
this.#activeTurn = null;
|
|
20977
|
-
this.#activeTurnId = null;
|
|
20978
|
-
active.finish();
|
|
20979
21092
|
let outcome;
|
|
20980
21093
|
if (failure2) {
|
|
20981
21094
|
outcome = { status: "failed", error: failure2 };
|
|
@@ -20989,6 +21102,16 @@ var HermesSession = class {
|
|
|
20989
21102
|
} else {
|
|
20990
21103
|
outcome = { status: "succeeded" };
|
|
20991
21104
|
}
|
|
21105
|
+
const terminalUsage = promptResponse ? usageFromPromptResponse(promptResponse.usage) : null;
|
|
21106
|
+
const usage = terminalUsage ? this.#mergeUsage(terminalUsage) : null;
|
|
21107
|
+
this.#completeActiveTurn(active, outcome, usage);
|
|
21108
|
+
}
|
|
21109
|
+
#completeActiveTurn(active, outcome, usage = null) {
|
|
21110
|
+
if (this.#activeTurn !== active)
|
|
21111
|
+
return;
|
|
21112
|
+
this.#activeTurn = null;
|
|
21113
|
+
this.#activeTurnId = null;
|
|
21114
|
+
active.finish();
|
|
20992
21115
|
const nativeTurnRef = nativeTurnRefSchema.parse({
|
|
20993
21116
|
harnessId: this.#nativeRef.harnessId,
|
|
20994
21117
|
nativeSessionId: this.#nativeRef.nativeSessionId,
|
|
@@ -20999,7 +21122,6 @@ var HermesSession = class {
|
|
|
20999
21122
|
for (const pending of active.drainPendingItems()) {
|
|
21000
21123
|
this.#emit({ type: "item.completed", turnId: active.turnId, snapshot: pending });
|
|
21001
21124
|
}
|
|
21002
|
-
const usage = promptResponse ? usageFromPromptResponse(promptResponse.usage) : null;
|
|
21003
21125
|
if (usage) {
|
|
21004
21126
|
this.#emit({ type: "session.usage.changed", usage, observedForTurnId: active.turnId });
|
|
21005
21127
|
}
|
|
@@ -21012,9 +21134,10 @@ var HermesSession = class {
|
|
|
21012
21134
|
const usage = usageFromContext(event.used, event.size);
|
|
21013
21135
|
if (!usage)
|
|
21014
21136
|
return;
|
|
21137
|
+
const mergedUsage = this.#mergeUsage(usage);
|
|
21015
21138
|
this.#emit({
|
|
21016
21139
|
type: "session.usage.changed",
|
|
21017
|
-
usage,
|
|
21140
|
+
usage: mergedUsage,
|
|
21018
21141
|
observedForTurnId: active.turnId
|
|
21019
21142
|
});
|
|
21020
21143
|
return;
|
|
@@ -21028,6 +21151,7 @@ var HermesSession = class {
|
|
|
21028
21151
|
case "tool.call": {
|
|
21029
21152
|
const update = event.update;
|
|
21030
21153
|
this.#startToolItem(active, event.toolCallId, typeof update.title === "string" ? update.title : null, typeof update.name === "string" ? update.name : null, update.rawInput);
|
|
21154
|
+
this.#updateToolItem(active, update);
|
|
21031
21155
|
return;
|
|
21032
21156
|
}
|
|
21033
21157
|
case "tool.update":
|
|
@@ -21052,6 +21176,10 @@ var HermesSession = class {
|
|
|
21052
21176
|
});
|
|
21053
21177
|
}
|
|
21054
21178
|
#startToolItem(active, toolCallId, title, name, rawInput) {
|
|
21179
|
+
const completedText = active.completeCurrentText();
|
|
21180
|
+
if (completedText) {
|
|
21181
|
+
this.#emit({ type: "item.completed", turnId: active.turnId, snapshot: completedText });
|
|
21182
|
+
}
|
|
21055
21183
|
const item = {
|
|
21056
21184
|
type: "toolExecution",
|
|
21057
21185
|
itemId: hostItemIdSchema.parse(randomUUID()),
|
|
@@ -21061,12 +21189,18 @@ var HermesSession = class {
|
|
|
21061
21189
|
active.addToolItem(toolCallId, { item, startedAt: Date.now() });
|
|
21062
21190
|
this.#emit({ type: "item.started", turnId: active.turnId, item });
|
|
21063
21191
|
}
|
|
21192
|
+
#mergeUsage(usage) {
|
|
21193
|
+
const merged = { ...this.#latestUsage ?? {}, ...usage };
|
|
21194
|
+
this.#latestUsage = merged;
|
|
21195
|
+
return merged;
|
|
21196
|
+
}
|
|
21064
21197
|
#updateToolItem(active, update) {
|
|
21065
21198
|
const entry = active.getToolItem(update.toolCallId);
|
|
21066
21199
|
if (!entry)
|
|
21067
21200
|
return;
|
|
21068
21201
|
const output = toolOutputFromUpdate(update);
|
|
21069
21202
|
if (output && output.content.length > 0) {
|
|
21203
|
+
active.updateToolOutput(update.toolCallId, output);
|
|
21070
21204
|
this.#emit({
|
|
21071
21205
|
type: "item.updated",
|
|
21072
21206
|
turnId: active.turnId,
|
|
@@ -21163,9 +21297,6 @@ var HermesSession = class {
|
|
|
21163
21297
|
}
|
|
21164
21298
|
}
|
|
21165
21299
|
async #selectModel(command) {
|
|
21166
|
-
if (this.#activeTurn) {
|
|
21167
|
-
return err("sessionBusy", "Model selection conflicts with an active Turn", true);
|
|
21168
|
-
}
|
|
21169
21300
|
const native = decodeHermesModelRefId(command.model.id);
|
|
21170
21301
|
if (!native) {
|
|
21171
21302
|
return err("invalidRequest", "Model Ref does not belong to Hermes");
|
|
@@ -21178,10 +21309,14 @@ var HermesSession = class {
|
|
|
21178
21309
|
}
|
|
21179
21310
|
return err("nativeFailure", error51 instanceof Error ? error51.message : "Hermes rejected Model selection");
|
|
21180
21311
|
}
|
|
21312
|
+
const projectedAfterSelect = projectHermesModelState({
|
|
21313
|
+
availableModels: this.#availableModels,
|
|
21314
|
+
currentModelId: native
|
|
21315
|
+
});
|
|
21181
21316
|
this.#state = {
|
|
21182
21317
|
...this.#state,
|
|
21183
21318
|
effectiveModel: command.model,
|
|
21184
|
-
resolvedModelLabel: native
|
|
21319
|
+
resolvedModelLabel: projectedAfterSelect.resolvedModelLabel ?? catalogAlignedModelLabel(native)
|
|
21185
21320
|
};
|
|
21186
21321
|
this.#emit({ type: "session.state.changed", state: { ...this.#state } });
|
|
21187
21322
|
return ok({ completed: true });
|
|
@@ -21213,6 +21348,7 @@ var HermesSession = class {
|
|
|
21213
21348
|
// dist/hermes-adapter.js
|
|
21214
21349
|
var hermesHarnessId = harnessIdSchema.parse("hermes");
|
|
21215
21350
|
var IMPORT_TIMEOUT_MS = 2e4;
|
|
21351
|
+
var HERMES_THREAD_ID_ENV = "CODEXHOST_THREAD_ID";
|
|
21216
21352
|
var HermesAdapter = class {
|
|
21217
21353
|
harnessId = hermesHarnessId;
|
|
21218
21354
|
sessionImport = {
|
|
@@ -21223,6 +21359,7 @@ var HermesAdapter = class {
|
|
|
21223
21359
|
#inspectionCache = null;
|
|
21224
21360
|
#inspectionCacheScope = null;
|
|
21225
21361
|
#sessions = /* @__PURE__ */ new Set();
|
|
21362
|
+
#warmTransports = /* @__PURE__ */ new Map();
|
|
21226
21363
|
#transports = /* @__PURE__ */ new Set();
|
|
21227
21364
|
#closed = false;
|
|
21228
21365
|
constructor(options = {}) {
|
|
@@ -21233,7 +21370,9 @@ var HermesAdapter = class {
|
|
|
21233
21370
|
if (!input.refresh && this.#inspectionCache && this.#inspectionCacheScope === cwd) {
|
|
21234
21371
|
return this.#inspectionCache;
|
|
21235
21372
|
}
|
|
21236
|
-
const
|
|
21373
|
+
const environment = this.#effectiveEnvironment();
|
|
21374
|
+
const transport = await this.#takeTransport(cwd, environment);
|
|
21375
|
+
let retainedForOpen = false;
|
|
21237
21376
|
try {
|
|
21238
21377
|
await transport.inspect();
|
|
21239
21378
|
const inventory = await this.#readInventory();
|
|
@@ -21265,11 +21404,14 @@ var HermesAdapter = class {
|
|
|
21265
21404
|
};
|
|
21266
21405
|
this.#inspectionCache = inspection;
|
|
21267
21406
|
this.#inspectionCacheScope = cwd;
|
|
21407
|
+
this.#keepWarmTransport(cwd, environment, transport);
|
|
21408
|
+
retainedForOpen = true;
|
|
21268
21409
|
return inspection;
|
|
21269
21410
|
} catch (error51) {
|
|
21270
21411
|
return inspectionFromTransportError(error51);
|
|
21271
21412
|
} finally {
|
|
21272
|
-
|
|
21413
|
+
if (!retainedForOpen)
|
|
21414
|
+
await this.#releaseTransport(transport);
|
|
21273
21415
|
}
|
|
21274
21416
|
}
|
|
21275
21417
|
async #readInventory() {
|
|
@@ -21290,9 +21432,18 @@ var HermesAdapter = class {
|
|
|
21290
21432
|
return failure("invalidRequest", "open requires a cwd");
|
|
21291
21433
|
}
|
|
21292
21434
|
let transportOpen;
|
|
21435
|
+
let permissionModeId;
|
|
21293
21436
|
if (input.kind === "create") {
|
|
21294
21437
|
transportOpen = { kind: "create" };
|
|
21438
|
+
permissionModeId = input.permissionModeId;
|
|
21439
|
+
if (input.executionPolicy === "unattended-full-access") {
|
|
21440
|
+
if (permissionModeId && permissionModeId !== HERMES_MODE_DONT_ASK) {
|
|
21441
|
+
return failure("invalidRequest", "unattended-full-access requires the Hermes dont_ask Permission Mode");
|
|
21442
|
+
}
|
|
21443
|
+
permissionModeId = harnessPermissionModeIdSchema.parse(HERMES_MODE_DONT_ASK);
|
|
21444
|
+
}
|
|
21295
21445
|
} else if (input.kind === "resume") {
|
|
21446
|
+
permissionModeId = input.permissionModeId;
|
|
21296
21447
|
if (!input.nativeRef || input.nativeRef.harnessId !== this.harnessId) {
|
|
21297
21448
|
return failure("invalidRequest", "Native Ref does not belong to Hermes");
|
|
21298
21449
|
}
|
|
@@ -21300,7 +21451,11 @@ var HermesAdapter = class {
|
|
|
21300
21451
|
} else {
|
|
21301
21452
|
return failure("unsupported", `Hermes does not support ${input.kind}`);
|
|
21302
21453
|
}
|
|
21303
|
-
|
|
21454
|
+
if (permissionModeId && !isHermesModeId(permissionModeId)) {
|
|
21455
|
+
return failure("invalidRequest", "Permission Mode does not belong to Hermes");
|
|
21456
|
+
}
|
|
21457
|
+
const environment = this.#effectiveEnvironment(input.environment);
|
|
21458
|
+
const transport = await this.#takeTransport(cwd, environment);
|
|
21304
21459
|
if (this.#closed) {
|
|
21305
21460
|
await this.#releaseTransport(transport);
|
|
21306
21461
|
return failure("invalidState", "Hermes Adapter is closed");
|
|
@@ -21330,16 +21485,12 @@ var HermesAdapter = class {
|
|
|
21330
21485
|
currentModelId: nativeModelId
|
|
21331
21486
|
};
|
|
21332
21487
|
}
|
|
21333
|
-
if (
|
|
21334
|
-
if (
|
|
21335
|
-
await
|
|
21336
|
-
return failure("invalidRequest", "Permission Mode does not belong to Hermes");
|
|
21337
|
-
}
|
|
21338
|
-
if (open.session.modes?.currentModeId !== input.permissionModeId) {
|
|
21339
|
-
await transport.setPermissionMode(input.permissionModeId);
|
|
21488
|
+
if (permissionModeId) {
|
|
21489
|
+
if (open.session.modes?.currentModeId !== permissionModeId) {
|
|
21490
|
+
await transport.setPermissionMode(permissionModeId);
|
|
21340
21491
|
}
|
|
21341
21492
|
open.session.modes = {
|
|
21342
|
-
currentModeId:
|
|
21493
|
+
currentModeId: permissionModeId,
|
|
21343
21494
|
availableModes: open.session.modes?.availableModes ?? []
|
|
21344
21495
|
};
|
|
21345
21496
|
}
|
|
@@ -21358,6 +21509,10 @@ var HermesAdapter = class {
|
|
|
21358
21509
|
}
|
|
21359
21510
|
});
|
|
21360
21511
|
this.#sessions.add(session);
|
|
21512
|
+
const threadSpecificKeys = Object.keys(input.environment ?? {}).filter((key) => key !== HERMES_THREAD_ID_ENV);
|
|
21513
|
+
if (threadSpecificKeys.length === 0) {
|
|
21514
|
+
this.#primeTransport(cwd, environment);
|
|
21515
|
+
}
|
|
21361
21516
|
return { ok: true, value: session };
|
|
21362
21517
|
} catch (error51) {
|
|
21363
21518
|
await this.#releaseTransport(transport);
|
|
@@ -21382,11 +21537,69 @@ var HermesAdapter = class {
|
|
|
21382
21537
|
this.#inspectionCache = null;
|
|
21383
21538
|
const sessions = [...this.#sessions];
|
|
21384
21539
|
this.#sessions.clear();
|
|
21540
|
+
this.#warmTransports.clear();
|
|
21385
21541
|
await Promise.all(sessions.map((session) => session.close().catch(() => void 0)));
|
|
21386
21542
|
await Promise.all([...this.#transports].map((transport) => this.#releaseTransport(transport)));
|
|
21387
21543
|
}
|
|
21388
|
-
#
|
|
21389
|
-
const {
|
|
21544
|
+
#effectiveEnvironment(environment) {
|
|
21545
|
+
const merged = { ...this.#options.environment ?? process.env, ...environment ?? {} };
|
|
21546
|
+
return Object.fromEntries(Object.entries(merged).filter(([key]) => key !== HERMES_THREAD_ID_ENV));
|
|
21547
|
+
}
|
|
21548
|
+
#transportScope(_cwd, environment) {
|
|
21549
|
+
const serialized = JSON.stringify(Object.entries(environment).sort(([left], [right]) => left.localeCompare(right)));
|
|
21550
|
+
return createHash("sha256").update(serialized).digest("hex");
|
|
21551
|
+
}
|
|
21552
|
+
async #takeTransport(cwd, environment) {
|
|
21553
|
+
const scope = this.#transportScope(cwd, environment);
|
|
21554
|
+
const pending = this.#warmTransports.get(scope);
|
|
21555
|
+
if (!pending)
|
|
21556
|
+
return this.#createTransport(cwd, environment);
|
|
21557
|
+
this.#warmTransports.delete(scope);
|
|
21558
|
+
const warmed = await pending;
|
|
21559
|
+
if (!warmed)
|
|
21560
|
+
return this.#createTransport(cwd, environment);
|
|
21561
|
+
warmed.retarget(cwd);
|
|
21562
|
+
return warmed;
|
|
21563
|
+
}
|
|
21564
|
+
#keepWarmTransport(cwd, environment, transport) {
|
|
21565
|
+
if (this.#closed) {
|
|
21566
|
+
void this.#releaseTransport(transport);
|
|
21567
|
+
return;
|
|
21568
|
+
}
|
|
21569
|
+
const scope = this.#transportScope(cwd, environment);
|
|
21570
|
+
const previous = this.#warmTransports.get(scope);
|
|
21571
|
+
const entry = Promise.resolve(transport);
|
|
21572
|
+
this.#watchWarmTransport(scope, entry, transport);
|
|
21573
|
+
this.#warmTransports.set(scope, entry);
|
|
21574
|
+
if (previous) {
|
|
21575
|
+
void previous.then((losing) => {
|
|
21576
|
+
if (losing && losing !== transport)
|
|
21577
|
+
return this.#releaseTransport(losing);
|
|
21578
|
+
});
|
|
21579
|
+
}
|
|
21580
|
+
}
|
|
21581
|
+
#primeTransport(cwd, environment) {
|
|
21582
|
+
const scope = this.#transportScope(cwd, environment);
|
|
21583
|
+
if (this.#closed || this.#warmTransports.has(scope))
|
|
21584
|
+
return;
|
|
21585
|
+
const transport = this.#createTransport(cwd, environment);
|
|
21586
|
+
const pending = transport.inspect().then(() => transport).catch(async () => {
|
|
21587
|
+
await this.#releaseTransport(transport);
|
|
21588
|
+
return null;
|
|
21589
|
+
});
|
|
21590
|
+
this.#watchWarmTransport(scope, pending, transport);
|
|
21591
|
+
this.#warmTransports.set(scope, pending);
|
|
21592
|
+
}
|
|
21593
|
+
#watchWarmTransport(scope, entry, transport) {
|
|
21594
|
+
transport.onFault = () => {
|
|
21595
|
+
if (this.#warmTransports.get(scope) !== entry)
|
|
21596
|
+
return;
|
|
21597
|
+
this.#warmTransports.delete(scope);
|
|
21598
|
+
void this.#releaseTransport(transport);
|
|
21599
|
+
};
|
|
21600
|
+
}
|
|
21601
|
+
#createTransport(cwd, environment = this.#effectiveEnvironment()) {
|
|
21602
|
+
const { command, commandTimeoutMs, closeTimeoutMs } = this.#options;
|
|
21390
21603
|
const transport = new HermesAcpTransport({
|
|
21391
21604
|
cwd,
|
|
21392
21605
|
...command !== void 0 && command.length > 0 ? { command } : {},
|