@liberseek/boft-cli-win32-arm64 0.6.9 → 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 +12 -0
- package/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +67 -27
- package/app/host-runtime.mjs +1963 -880
- package/app/plugins/antigravity/plugin.mjs +44 -15
- package/app/plugins/claude-code/plugin.mjs +59 -12
- package/app/plugins/codebuddy/plugin.mjs +76 -23
- package/app/plugins/cursor-cli/plugin.mjs +43 -4
- package/app/plugins/deepseek-harness/plugin.mjs +55 -7
- package/app/plugins/enabled.json +3 -1
- package/app/plugins/grok/plugin.mjs +68 -15
- package/app/plugins/hermes/plugin.mjs +40 -3
- package/app/plugins/kiro-cli/plugin.mjs +50 -3
- package/app/plugins/muse/plugin.mjs +40 -0
- package/app/plugins/omp/plugin.mjs +53 -6
- package/app/plugins/opencode/plugin.mjs +92 -46
- package/app/plugins/pi/plugin.mjs +53 -6
- 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 +3297 -162
- 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/tailwindcss-LICENSE.txt +21 -0
- package/package.json +1 -1
package/app/host-runtime.mjs
CHANGED
|
@@ -4283,7 +4283,7 @@ async function runDelegationCli(input) {
|
|
|
4283
4283
|
|
|
4284
4284
|
// packages/host-runtime/src/run-host-runtime.ts
|
|
4285
4285
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
4286
|
-
import
|
|
4286
|
+
import path21 from "node:path";
|
|
4287
4287
|
import { homedir as homedir2 } from "node:os";
|
|
4288
4288
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
4289
4289
|
|
|
@@ -5978,10 +5978,10 @@ function mergeDefs(...defs) {
|
|
|
5978
5978
|
function cloneDef(schema) {
|
|
5979
5979
|
return mergeDefs(schema._zod.def);
|
|
5980
5980
|
}
|
|
5981
|
-
function getElementAtPath(obj,
|
|
5982
|
-
if (!
|
|
5981
|
+
function getElementAtPath(obj, path26) {
|
|
5982
|
+
if (!path26)
|
|
5983
5983
|
return obj;
|
|
5984
|
-
return
|
|
5984
|
+
return path26.reduce((acc, key) => acc?.[key], obj);
|
|
5985
5985
|
}
|
|
5986
5986
|
function promiseAllObject(promisesObj) {
|
|
5987
5987
|
const keys = Object.keys(promisesObj);
|
|
@@ -6390,11 +6390,11 @@ function explicitlyAborted(x, startIndex = 0) {
|
|
|
6390
6390
|
}
|
|
6391
6391
|
return false;
|
|
6392
6392
|
}
|
|
6393
|
-
function prefixIssues(
|
|
6393
|
+
function prefixIssues(path26, issues) {
|
|
6394
6394
|
return issues.map((iss) => {
|
|
6395
6395
|
var _a3;
|
|
6396
6396
|
(_a3 = iss).path ?? (_a3.path = []);
|
|
6397
|
-
iss.path.unshift(
|
|
6397
|
+
iss.path.unshift(path26);
|
|
6398
6398
|
return iss;
|
|
6399
6399
|
});
|
|
6400
6400
|
}
|
|
@@ -6541,16 +6541,16 @@ function flattenError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6541
6541
|
}
|
|
6542
6542
|
function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
6543
6543
|
const fieldErrors = { _errors: [] };
|
|
6544
|
-
const processError = (error52,
|
|
6544
|
+
const processError = (error52, path26 = []) => {
|
|
6545
6545
|
for (const issue2 of error52.issues) {
|
|
6546
6546
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
6547
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
6547
|
+
issue2.errors.map((issues) => processError({ issues }, [...path26, ...issue2.path]));
|
|
6548
6548
|
} else if (issue2.code === "invalid_key") {
|
|
6549
|
-
processError({ issues: issue2.issues }, [...
|
|
6549
|
+
processError({ issues: issue2.issues }, [...path26, ...issue2.path]);
|
|
6550
6550
|
} else if (issue2.code === "invalid_element") {
|
|
6551
|
-
processError({ issues: issue2.issues }, [...
|
|
6551
|
+
processError({ issues: issue2.issues }, [...path26, ...issue2.path]);
|
|
6552
6552
|
} else {
|
|
6553
|
-
const fullpath = [...
|
|
6553
|
+
const fullpath = [...path26, ...issue2.path];
|
|
6554
6554
|
if (fullpath.length === 0) {
|
|
6555
6555
|
fieldErrors._errors.push(mapper(issue2));
|
|
6556
6556
|
} else {
|
|
@@ -6577,17 +6577,17 @@ function formatError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6577
6577
|
}
|
|
6578
6578
|
function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
6579
6579
|
const result = { errors: [] };
|
|
6580
|
-
const processError = (error52,
|
|
6580
|
+
const processError = (error52, path26 = []) => {
|
|
6581
6581
|
var _a3, _b;
|
|
6582
6582
|
for (const issue2 of error52.issues) {
|
|
6583
6583
|
if (issue2.code === "invalid_union" && issue2.errors.length) {
|
|
6584
|
-
issue2.errors.map((issues) => processError({ issues }, [...
|
|
6584
|
+
issue2.errors.map((issues) => processError({ issues }, [...path26, ...issue2.path]));
|
|
6585
6585
|
} else if (issue2.code === "invalid_key") {
|
|
6586
|
-
processError({ issues: issue2.issues }, [...
|
|
6586
|
+
processError({ issues: issue2.issues }, [...path26, ...issue2.path]);
|
|
6587
6587
|
} else if (issue2.code === "invalid_element") {
|
|
6588
|
-
processError({ issues: issue2.issues }, [...
|
|
6588
|
+
processError({ issues: issue2.issues }, [...path26, ...issue2.path]);
|
|
6589
6589
|
} else {
|
|
6590
|
-
const fullpath = [...
|
|
6590
|
+
const fullpath = [...path26, ...issue2.path];
|
|
6591
6591
|
if (fullpath.length === 0) {
|
|
6592
6592
|
result.errors.push(mapper(issue2));
|
|
6593
6593
|
continue;
|
|
@@ -6619,8 +6619,8 @@ function treeifyError(error51, mapper = (issue2) => issue2.message) {
|
|
|
6619
6619
|
}
|
|
6620
6620
|
function toDotPath(_path) {
|
|
6621
6621
|
const segs = [];
|
|
6622
|
-
const
|
|
6623
|
-
for (const seg of
|
|
6622
|
+
const path26 = _path.map((seg) => typeof seg === "object" ? seg.key : seg);
|
|
6623
|
+
for (const seg of path26) {
|
|
6624
6624
|
if (typeof seg === "number")
|
|
6625
6625
|
segs.push(`[${seg}]`);
|
|
6626
6626
|
else if (typeof seg === "symbol")
|
|
@@ -19312,13 +19312,13 @@ function resolveRef(ref, ctx) {
|
|
|
19312
19312
|
if (!ref.startsWith("#")) {
|
|
19313
19313
|
throw new Error("External $ref is not supported, only local refs (#/...) are allowed");
|
|
19314
19314
|
}
|
|
19315
|
-
const
|
|
19316
|
-
if (
|
|
19315
|
+
const path26 = ref.slice(1).split("/").filter(Boolean);
|
|
19316
|
+
if (path26.length === 0) {
|
|
19317
19317
|
return ctx.rootSchema;
|
|
19318
19318
|
}
|
|
19319
19319
|
const defsKey = ctx.version === "draft-2020-12" ? "$defs" : "definitions";
|
|
19320
|
-
if (
|
|
19321
|
-
const key =
|
|
19320
|
+
if (path26[0] === defsKey) {
|
|
19321
|
+
const key = path26[1];
|
|
19322
19322
|
if (!key || !ctx.defs[key]) {
|
|
19323
19323
|
throw new Error(`Reference not found: ${ref}`);
|
|
19324
19324
|
}
|
|
@@ -19729,6 +19729,48 @@ config(en_default());
|
|
|
19729
19729
|
// packages/shared-contracts/dist/version.js
|
|
19730
19730
|
var WORKSPACE_CONTRACT_VERSION = 1;
|
|
19731
19731
|
|
|
19732
|
+
// packages/shared-contracts/dist/idle-release.js
|
|
19733
|
+
var IDLE_RELEASE_SETTINGS_METHOD = "codexhost/settings/idle-release/set";
|
|
19734
|
+
var IDLE_RELEASE_TIMEOUT_MINUTES_MIN = 5;
|
|
19735
|
+
var IDLE_RELEASE_TIMEOUT_MINUTES_MAX = 1440;
|
|
19736
|
+
var idleReleaseSettingsSchema = external_exports.strictObject({
|
|
19737
|
+
enabled: external_exports.boolean(),
|
|
19738
|
+
timeoutMinutes: external_exports.number().int().min(IDLE_RELEASE_TIMEOUT_MINUTES_MIN).max(IDLE_RELEASE_TIMEOUT_MINUTES_MAX)
|
|
19739
|
+
});
|
|
19740
|
+
var DEFAULT_IDLE_RELEASE_SETTINGS = Object.freeze({
|
|
19741
|
+
enabled: false,
|
|
19742
|
+
timeoutMinutes: 30
|
|
19743
|
+
});
|
|
19744
|
+
|
|
19745
|
+
// packages/shared-contracts/dist/loaded-sessions.js
|
|
19746
|
+
var LOADED_SESSIONS_METHOD = "codexhost/sessions/loaded/list";
|
|
19747
|
+
var loadedSessionStateSchema = external_exports.enum([
|
|
19748
|
+
"idle",
|
|
19749
|
+
"running",
|
|
19750
|
+
"busy",
|
|
19751
|
+
"closing",
|
|
19752
|
+
"failed",
|
|
19753
|
+
"blocked"
|
|
19754
|
+
]);
|
|
19755
|
+
var loadedSessionReasonSchema = external_exports.enum([
|
|
19756
|
+
"none",
|
|
19757
|
+
"disabled",
|
|
19758
|
+
"timeout",
|
|
19759
|
+
"operation",
|
|
19760
|
+
"background",
|
|
19761
|
+
"identity",
|
|
19762
|
+
"persistence",
|
|
19763
|
+
"closeFailed"
|
|
19764
|
+
]);
|
|
19765
|
+
var loadedSessionsSchema = external_exports.array(external_exports.strictObject({
|
|
19766
|
+
threadId: external_exports.string(),
|
|
19767
|
+
title: external_exports.string(),
|
|
19768
|
+
harnessId: external_exports.string(),
|
|
19769
|
+
state: loadedSessionStateSchema,
|
|
19770
|
+
reason: loadedSessionReasonSchema,
|
|
19771
|
+
inactiveMs: external_exports.number().nonnegative()
|
|
19772
|
+
}));
|
|
19773
|
+
|
|
19732
19774
|
// packages/shared-contracts/dist/ids.js
|
|
19733
19775
|
var opaqueIdSchema = external_exports.string().refine((value2) => value2.trim().length > 0, {
|
|
19734
19776
|
message: "Identifier must not be empty or whitespace"
|
|
@@ -20919,10 +20961,20 @@ function processIdentity(pid) {
|
|
|
20919
20961
|
if (systemErrorCode2(error51) !== "EPERM")
|
|
20920
20962
|
return null;
|
|
20921
20963
|
}
|
|
20922
|
-
if (process.platform !== "win32") {
|
|
20964
|
+
if (process.platform !== "win32" && process.platform !== "darwin") {
|
|
20923
20965
|
return { executablePath: null, startedAt: null };
|
|
20924
20966
|
}
|
|
20925
20967
|
try {
|
|
20968
|
+
if (process.platform === "darwin") {
|
|
20969
|
+
const result2 = execFileSync("/bin/ps", ["-p", String(pid), "-o", "lstart="], {
|
|
20970
|
+
encoding: "utf8",
|
|
20971
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
20972
|
+
env: { ...process.env, LC_ALL: "C" },
|
|
20973
|
+
timeout: 1e3
|
|
20974
|
+
}).trim();
|
|
20975
|
+
const startedAt2 = Date.parse(result2);
|
|
20976
|
+
return { executablePath: null, startedAt: Number.isFinite(startedAt2) ? startedAt2 : null };
|
|
20977
|
+
}
|
|
20926
20978
|
const query = [
|
|
20927
20979
|
"$ErrorActionPreference = 'Stop'",
|
|
20928
20980
|
`$process = Get-Process -Id ${pid}`,
|
|
@@ -20964,7 +21016,7 @@ function lockOwnerIsLive(lock) {
|
|
|
20964
21016
|
const identity = processIdentity(lock.pid);
|
|
20965
21017
|
if (!identity)
|
|
20966
21018
|
return false;
|
|
20967
|
-
if (process.platform !== "win32")
|
|
21019
|
+
if (process.platform !== "win32" && process.platform !== "darwin")
|
|
20968
21020
|
return true;
|
|
20969
21021
|
if (identity.executablePath && lock.executablePath) {
|
|
20970
21022
|
if (normalizeExecutablePath(identity.executablePath) !== normalizeExecutablePath(lock.executablePath)) {
|
|
@@ -21920,6 +21972,8 @@ function projectCodexQuestionRequest(input) {
|
|
|
21920
21972
|
const mapped = labels.get(value2);
|
|
21921
21973
|
if (mapped !== void 0)
|
|
21922
21974
|
return mapped;
|
|
21975
|
+
if (question.options.some((option) => option.value === value2))
|
|
21976
|
+
return value2;
|
|
21923
21977
|
if (question.allowOther)
|
|
21924
21978
|
return value2;
|
|
21925
21979
|
throw responseError2("contains an undeclared choice");
|
|
@@ -22194,6 +22248,681 @@ function projectCodexRateLimitsToCredits(usage, resetCredits) {
|
|
|
22194
22248
|
};
|
|
22195
22249
|
}
|
|
22196
22250
|
|
|
22251
|
+
// node_modules/diff/libesm/diff/base.js
|
|
22252
|
+
var Diff = class {
|
|
22253
|
+
diff(oldStr, newStr, options2 = {}) {
|
|
22254
|
+
let callback;
|
|
22255
|
+
if (typeof options2 === "function") {
|
|
22256
|
+
callback = options2;
|
|
22257
|
+
options2 = {};
|
|
22258
|
+
} else if ("callback" in options2) {
|
|
22259
|
+
callback = options2.callback;
|
|
22260
|
+
}
|
|
22261
|
+
const oldString = this.castInput(oldStr, options2);
|
|
22262
|
+
const newString = this.castInput(newStr, options2);
|
|
22263
|
+
const oldTokens = this.removeEmpty(this.tokenize(oldString, options2));
|
|
22264
|
+
const newTokens = this.removeEmpty(this.tokenize(newString, options2));
|
|
22265
|
+
return this.diffWithOptionsObj(oldTokens, newTokens, options2, callback);
|
|
22266
|
+
}
|
|
22267
|
+
diffWithOptionsObj(oldTokens, newTokens, options2, callback) {
|
|
22268
|
+
var _a3;
|
|
22269
|
+
const done = (value2) => {
|
|
22270
|
+
value2 = this.postProcess(value2, options2);
|
|
22271
|
+
if (callback) {
|
|
22272
|
+
setTimeout(function() {
|
|
22273
|
+
callback(value2);
|
|
22274
|
+
}, 0);
|
|
22275
|
+
return void 0;
|
|
22276
|
+
} else {
|
|
22277
|
+
return value2;
|
|
22278
|
+
}
|
|
22279
|
+
};
|
|
22280
|
+
const newLen = newTokens.length, oldLen = oldTokens.length;
|
|
22281
|
+
let editLength = 1;
|
|
22282
|
+
let maxEditLength = newLen + oldLen;
|
|
22283
|
+
if (options2.maxEditLength != null) {
|
|
22284
|
+
maxEditLength = Math.min(maxEditLength, options2.maxEditLength);
|
|
22285
|
+
}
|
|
22286
|
+
const maxExecutionTime = (_a3 = options2.timeout) !== null && _a3 !== void 0 ? _a3 : Infinity;
|
|
22287
|
+
const abortAfterTimestamp = Date.now() + maxExecutionTime;
|
|
22288
|
+
const bestPath = [{ oldPos: -1, lastComponent: void 0 }];
|
|
22289
|
+
let newPos = this.extractCommon(bestPath[0], newTokens, oldTokens, 0, options2);
|
|
22290
|
+
if (bestPath[0].oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
22291
|
+
return done(this.buildValues(bestPath[0].lastComponent, newTokens, oldTokens));
|
|
22292
|
+
}
|
|
22293
|
+
let minDiagonalToConsider = -Infinity, maxDiagonalToConsider = Infinity;
|
|
22294
|
+
const execEditLength = () => {
|
|
22295
|
+
for (let diagonalPath = Math.max(minDiagonalToConsider, -editLength); diagonalPath <= Math.min(maxDiagonalToConsider, editLength); diagonalPath += 2) {
|
|
22296
|
+
let basePath;
|
|
22297
|
+
const removePath = bestPath[diagonalPath - 1], addPath = bestPath[diagonalPath + 1];
|
|
22298
|
+
if (removePath) {
|
|
22299
|
+
bestPath[diagonalPath - 1] = void 0;
|
|
22300
|
+
}
|
|
22301
|
+
let canAdd = false;
|
|
22302
|
+
if (addPath) {
|
|
22303
|
+
const addPathNewPos = addPath.oldPos - diagonalPath;
|
|
22304
|
+
canAdd = addPath && 0 <= addPathNewPos && addPathNewPos < newLen;
|
|
22305
|
+
}
|
|
22306
|
+
const canRemove = removePath && removePath.oldPos + 1 < oldLen;
|
|
22307
|
+
if (!canAdd && !canRemove) {
|
|
22308
|
+
bestPath[diagonalPath] = void 0;
|
|
22309
|
+
continue;
|
|
22310
|
+
}
|
|
22311
|
+
if (!canRemove || canAdd && removePath.oldPos < addPath.oldPos) {
|
|
22312
|
+
basePath = this.addToPath(addPath, true, false, 0, options2);
|
|
22313
|
+
} else {
|
|
22314
|
+
basePath = this.addToPath(removePath, false, true, 1, options2);
|
|
22315
|
+
}
|
|
22316
|
+
newPos = this.extractCommon(basePath, newTokens, oldTokens, diagonalPath, options2);
|
|
22317
|
+
if (basePath.oldPos + 1 >= oldLen && newPos + 1 >= newLen) {
|
|
22318
|
+
return done(this.buildValues(basePath.lastComponent, newTokens, oldTokens)) || true;
|
|
22319
|
+
} else {
|
|
22320
|
+
bestPath[diagonalPath] = basePath;
|
|
22321
|
+
if (basePath.oldPos + 1 >= oldLen) {
|
|
22322
|
+
maxDiagonalToConsider = Math.min(maxDiagonalToConsider, diagonalPath - 1);
|
|
22323
|
+
}
|
|
22324
|
+
if (newPos + 1 >= newLen) {
|
|
22325
|
+
minDiagonalToConsider = Math.max(minDiagonalToConsider, diagonalPath + 1);
|
|
22326
|
+
}
|
|
22327
|
+
}
|
|
22328
|
+
}
|
|
22329
|
+
editLength++;
|
|
22330
|
+
};
|
|
22331
|
+
if (callback) {
|
|
22332
|
+
(function exec() {
|
|
22333
|
+
setTimeout(function() {
|
|
22334
|
+
if (editLength > maxEditLength || Date.now() > abortAfterTimestamp) {
|
|
22335
|
+
return callback(void 0);
|
|
22336
|
+
}
|
|
22337
|
+
if (!execEditLength()) {
|
|
22338
|
+
exec();
|
|
22339
|
+
}
|
|
22340
|
+
}, 0);
|
|
22341
|
+
})();
|
|
22342
|
+
} else {
|
|
22343
|
+
while (editLength <= maxEditLength && Date.now() <= abortAfterTimestamp) {
|
|
22344
|
+
const ret = execEditLength();
|
|
22345
|
+
if (ret) {
|
|
22346
|
+
return ret;
|
|
22347
|
+
}
|
|
22348
|
+
}
|
|
22349
|
+
}
|
|
22350
|
+
}
|
|
22351
|
+
addToPath(path26, added, removed, oldPosInc, options2) {
|
|
22352
|
+
const last = path26.lastComponent;
|
|
22353
|
+
if (last && !options2.oneChangePerToken && last.added === added && last.removed === removed) {
|
|
22354
|
+
return {
|
|
22355
|
+
oldPos: path26.oldPos + oldPosInc,
|
|
22356
|
+
lastComponent: { count: last.count + 1, added, removed, previousComponent: last.previousComponent }
|
|
22357
|
+
};
|
|
22358
|
+
} else {
|
|
22359
|
+
return {
|
|
22360
|
+
oldPos: path26.oldPos + oldPosInc,
|
|
22361
|
+
lastComponent: { count: 1, added, removed, previousComponent: last }
|
|
22362
|
+
};
|
|
22363
|
+
}
|
|
22364
|
+
}
|
|
22365
|
+
extractCommon(basePath, newTokens, oldTokens, diagonalPath, options2) {
|
|
22366
|
+
const newLen = newTokens.length, oldLen = oldTokens.length;
|
|
22367
|
+
let oldPos = basePath.oldPos, newPos = oldPos - diagonalPath, commonCount = 0;
|
|
22368
|
+
while (newPos + 1 < newLen && oldPos + 1 < oldLen && this.equals(oldTokens[oldPos + 1], newTokens[newPos + 1], options2)) {
|
|
22369
|
+
newPos++;
|
|
22370
|
+
oldPos++;
|
|
22371
|
+
commonCount++;
|
|
22372
|
+
if (options2.oneChangePerToken) {
|
|
22373
|
+
basePath.lastComponent = { count: 1, previousComponent: basePath.lastComponent, added: false, removed: false };
|
|
22374
|
+
}
|
|
22375
|
+
}
|
|
22376
|
+
if (commonCount && !options2.oneChangePerToken) {
|
|
22377
|
+
basePath.lastComponent = { count: commonCount, previousComponent: basePath.lastComponent, added: false, removed: false };
|
|
22378
|
+
}
|
|
22379
|
+
basePath.oldPos = oldPos;
|
|
22380
|
+
return newPos;
|
|
22381
|
+
}
|
|
22382
|
+
equals(left, right, options2) {
|
|
22383
|
+
if (options2.comparator) {
|
|
22384
|
+
return options2.comparator(left, right);
|
|
22385
|
+
} else {
|
|
22386
|
+
return left === right || !!options2.ignoreCase && left.toLowerCase() === right.toLowerCase();
|
|
22387
|
+
}
|
|
22388
|
+
}
|
|
22389
|
+
removeEmpty(array2) {
|
|
22390
|
+
const ret = [];
|
|
22391
|
+
for (let i = 0; i < array2.length; i++) {
|
|
22392
|
+
if (array2[i]) {
|
|
22393
|
+
ret.push(array2[i]);
|
|
22394
|
+
}
|
|
22395
|
+
}
|
|
22396
|
+
return ret;
|
|
22397
|
+
}
|
|
22398
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
22399
|
+
castInput(value2, options2) {
|
|
22400
|
+
return value2;
|
|
22401
|
+
}
|
|
22402
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
22403
|
+
tokenize(value2, options2) {
|
|
22404
|
+
return Array.from(value2);
|
|
22405
|
+
}
|
|
22406
|
+
join(chars) {
|
|
22407
|
+
return chars.join("");
|
|
22408
|
+
}
|
|
22409
|
+
postProcess(changeObjects, options2) {
|
|
22410
|
+
return changeObjects;
|
|
22411
|
+
}
|
|
22412
|
+
get useLongestToken() {
|
|
22413
|
+
return false;
|
|
22414
|
+
}
|
|
22415
|
+
buildValues(lastComponent, newTokens, oldTokens) {
|
|
22416
|
+
const components = [];
|
|
22417
|
+
let nextComponent;
|
|
22418
|
+
while (lastComponent) {
|
|
22419
|
+
components.push(lastComponent);
|
|
22420
|
+
nextComponent = lastComponent.previousComponent;
|
|
22421
|
+
delete lastComponent.previousComponent;
|
|
22422
|
+
lastComponent = nextComponent;
|
|
22423
|
+
}
|
|
22424
|
+
components.reverse();
|
|
22425
|
+
const componentLen = components.length;
|
|
22426
|
+
let componentPos = 0, newPos = 0, oldPos = 0;
|
|
22427
|
+
for (; componentPos < componentLen; componentPos++) {
|
|
22428
|
+
const component = components[componentPos];
|
|
22429
|
+
if (!component.removed) {
|
|
22430
|
+
if (!component.added && this.useLongestToken) {
|
|
22431
|
+
let value2 = newTokens.slice(newPos, newPos + component.count);
|
|
22432
|
+
value2 = value2.map(function(value3, i) {
|
|
22433
|
+
const oldValue = oldTokens[oldPos + i];
|
|
22434
|
+
return oldValue.length > value3.length ? oldValue : value3;
|
|
22435
|
+
});
|
|
22436
|
+
component.value = this.join(value2);
|
|
22437
|
+
} else {
|
|
22438
|
+
component.value = this.join(newTokens.slice(newPos, newPos + component.count));
|
|
22439
|
+
}
|
|
22440
|
+
newPos += component.count;
|
|
22441
|
+
if (!component.added) {
|
|
22442
|
+
oldPos += component.count;
|
|
22443
|
+
}
|
|
22444
|
+
} else {
|
|
22445
|
+
component.value = this.join(oldTokens.slice(oldPos, oldPos + component.count));
|
|
22446
|
+
oldPos += component.count;
|
|
22447
|
+
}
|
|
22448
|
+
}
|
|
22449
|
+
return components;
|
|
22450
|
+
}
|
|
22451
|
+
};
|
|
22452
|
+
|
|
22453
|
+
// node_modules/diff/libesm/diff/line.js
|
|
22454
|
+
var LineDiff = class extends Diff {
|
|
22455
|
+
constructor() {
|
|
22456
|
+
super(...arguments);
|
|
22457
|
+
this.tokenize = tokenize;
|
|
22458
|
+
}
|
|
22459
|
+
equals(left, right, options2) {
|
|
22460
|
+
if (options2.ignoreWhitespace) {
|
|
22461
|
+
if (!options2.newlineIsToken || !left.includes("\n")) {
|
|
22462
|
+
left = left.trim();
|
|
22463
|
+
}
|
|
22464
|
+
if (!options2.newlineIsToken || !right.includes("\n")) {
|
|
22465
|
+
right = right.trim();
|
|
22466
|
+
}
|
|
22467
|
+
} else if (options2.ignoreNewlineAtEof && !options2.newlineIsToken) {
|
|
22468
|
+
if (left.endsWith("\n")) {
|
|
22469
|
+
left = left.slice(0, -1);
|
|
22470
|
+
}
|
|
22471
|
+
if (right.endsWith("\n")) {
|
|
22472
|
+
right = right.slice(0, -1);
|
|
22473
|
+
}
|
|
22474
|
+
}
|
|
22475
|
+
return super.equals(left, right, options2);
|
|
22476
|
+
}
|
|
22477
|
+
};
|
|
22478
|
+
var lineDiff = new LineDiff();
|
|
22479
|
+
function diffLines(oldStr, newStr, options2) {
|
|
22480
|
+
return lineDiff.diff(oldStr, newStr, options2);
|
|
22481
|
+
}
|
|
22482
|
+
function tokenize(value2, options2) {
|
|
22483
|
+
if (options2.stripTrailingCr) {
|
|
22484
|
+
value2 = value2.replace(/\r\n/g, "\n");
|
|
22485
|
+
}
|
|
22486
|
+
const retLines = [], linesAndNewlines = value2.split(/(\n|\r\n)/);
|
|
22487
|
+
if (!linesAndNewlines[linesAndNewlines.length - 1]) {
|
|
22488
|
+
linesAndNewlines.pop();
|
|
22489
|
+
}
|
|
22490
|
+
for (let i = 0; i < linesAndNewlines.length; i++) {
|
|
22491
|
+
const line = linesAndNewlines[i];
|
|
22492
|
+
if (i % 2 && !options2.newlineIsToken) {
|
|
22493
|
+
retLines[retLines.length - 1] += line;
|
|
22494
|
+
} else {
|
|
22495
|
+
retLines.push(line);
|
|
22496
|
+
}
|
|
22497
|
+
}
|
|
22498
|
+
return retLines;
|
|
22499
|
+
}
|
|
22500
|
+
|
|
22501
|
+
// node_modules/diff/libesm/diff/array.js
|
|
22502
|
+
var ArrayDiff = class extends Diff {
|
|
22503
|
+
tokenize(value2) {
|
|
22504
|
+
return value2.slice();
|
|
22505
|
+
}
|
|
22506
|
+
join(value2) {
|
|
22507
|
+
return value2;
|
|
22508
|
+
}
|
|
22509
|
+
removeEmpty(value2) {
|
|
22510
|
+
return value2;
|
|
22511
|
+
}
|
|
22512
|
+
};
|
|
22513
|
+
var arrayDiff = new ArrayDiff();
|
|
22514
|
+
function diffArrays(oldArr, newArr, options2) {
|
|
22515
|
+
return arrayDiff.diff(oldArr, newArr, options2);
|
|
22516
|
+
}
|
|
22517
|
+
|
|
22518
|
+
// node_modules/diff/libesm/patch/parse.js
|
|
22519
|
+
function parsePatch(uniDiff) {
|
|
22520
|
+
const diffstr = uniDiff.split(/\n/), list = [];
|
|
22521
|
+
let i = 0;
|
|
22522
|
+
function parseIndex() {
|
|
22523
|
+
const index = {};
|
|
22524
|
+
list.push(index);
|
|
22525
|
+
while (i < diffstr.length) {
|
|
22526
|
+
const line = diffstr[i];
|
|
22527
|
+
if (/^(---|\+\+\+|@@)\s/.test(line)) {
|
|
22528
|
+
break;
|
|
22529
|
+
}
|
|
22530
|
+
const header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line);
|
|
22531
|
+
if (header) {
|
|
22532
|
+
index.index = header[1];
|
|
22533
|
+
}
|
|
22534
|
+
i++;
|
|
22535
|
+
}
|
|
22536
|
+
parseFileHeader(index);
|
|
22537
|
+
parseFileHeader(index);
|
|
22538
|
+
index.hunks = [];
|
|
22539
|
+
while (i < diffstr.length) {
|
|
22540
|
+
const line = diffstr[i];
|
|
22541
|
+
if (/^(Index:\s|diff\s|---\s|\+\+\+\s|===================================================================)/.test(line)) {
|
|
22542
|
+
break;
|
|
22543
|
+
} else if (/^@@/.test(line)) {
|
|
22544
|
+
index.hunks.push(parseHunk());
|
|
22545
|
+
} else if (line) {
|
|
22546
|
+
throw new Error("Unknown line " + (i + 1) + " " + JSON.stringify(line));
|
|
22547
|
+
} else {
|
|
22548
|
+
i++;
|
|
22549
|
+
}
|
|
22550
|
+
}
|
|
22551
|
+
}
|
|
22552
|
+
function parseFileHeader(index) {
|
|
22553
|
+
const fileHeader = /^(---|\+\+\+)\s+(.*)\r?$/.exec(diffstr[i]);
|
|
22554
|
+
if (fileHeader) {
|
|
22555
|
+
const data = fileHeader[2].split(" ", 2), header = (data[1] || "").trim();
|
|
22556
|
+
let fileName = data[0].replace(/\\\\/g, "\\");
|
|
22557
|
+
if (/^".*"$/.test(fileName)) {
|
|
22558
|
+
fileName = fileName.substr(1, fileName.length - 2);
|
|
22559
|
+
}
|
|
22560
|
+
if (fileHeader[1] === "---") {
|
|
22561
|
+
index.oldFileName = fileName;
|
|
22562
|
+
index.oldHeader = header;
|
|
22563
|
+
} else {
|
|
22564
|
+
index.newFileName = fileName;
|
|
22565
|
+
index.newHeader = header;
|
|
22566
|
+
}
|
|
22567
|
+
i++;
|
|
22568
|
+
}
|
|
22569
|
+
}
|
|
22570
|
+
function parseHunk() {
|
|
22571
|
+
var _a3;
|
|
22572
|
+
const chunkHeaderIndex = i, chunkHeaderLine = diffstr[i++], chunkHeader = chunkHeaderLine.split(/@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/);
|
|
22573
|
+
const hunk = {
|
|
22574
|
+
oldStart: +chunkHeader[1],
|
|
22575
|
+
oldLines: typeof chunkHeader[2] === "undefined" ? 1 : +chunkHeader[2],
|
|
22576
|
+
newStart: +chunkHeader[3],
|
|
22577
|
+
newLines: typeof chunkHeader[4] === "undefined" ? 1 : +chunkHeader[4],
|
|
22578
|
+
lines: []
|
|
22579
|
+
};
|
|
22580
|
+
if (hunk.oldLines === 0) {
|
|
22581
|
+
hunk.oldStart += 1;
|
|
22582
|
+
}
|
|
22583
|
+
if (hunk.newLines === 0) {
|
|
22584
|
+
hunk.newStart += 1;
|
|
22585
|
+
}
|
|
22586
|
+
let addCount = 0, removeCount = 0;
|
|
22587
|
+
for (; i < diffstr.length && (removeCount < hunk.oldLines || addCount < hunk.newLines || ((_a3 = diffstr[i]) === null || _a3 === void 0 ? void 0 : _a3.startsWith("\\"))); i++) {
|
|
22588
|
+
const operation = diffstr[i].length == 0 && i != diffstr.length - 1 ? " " : diffstr[i][0];
|
|
22589
|
+
if (operation === "+" || operation === "-" || operation === " " || operation === "\\") {
|
|
22590
|
+
hunk.lines.push(diffstr[i]);
|
|
22591
|
+
if (operation === "+") {
|
|
22592
|
+
addCount++;
|
|
22593
|
+
} else if (operation === "-") {
|
|
22594
|
+
removeCount++;
|
|
22595
|
+
} else if (operation === " ") {
|
|
22596
|
+
addCount++;
|
|
22597
|
+
removeCount++;
|
|
22598
|
+
}
|
|
22599
|
+
} else {
|
|
22600
|
+
throw new Error(`Hunk at line ${chunkHeaderIndex + 1} contained invalid line ${diffstr[i]}`);
|
|
22601
|
+
}
|
|
22602
|
+
}
|
|
22603
|
+
if (!addCount && hunk.newLines === 1) {
|
|
22604
|
+
hunk.newLines = 0;
|
|
22605
|
+
}
|
|
22606
|
+
if (!removeCount && hunk.oldLines === 1) {
|
|
22607
|
+
hunk.oldLines = 0;
|
|
22608
|
+
}
|
|
22609
|
+
if (addCount !== hunk.newLines) {
|
|
22610
|
+
throw new Error("Added line count did not match for hunk at line " + (chunkHeaderIndex + 1));
|
|
22611
|
+
}
|
|
22612
|
+
if (removeCount !== hunk.oldLines) {
|
|
22613
|
+
throw new Error("Removed line count did not match for hunk at line " + (chunkHeaderIndex + 1));
|
|
22614
|
+
}
|
|
22615
|
+
return hunk;
|
|
22616
|
+
}
|
|
22617
|
+
while (i < diffstr.length) {
|
|
22618
|
+
parseIndex();
|
|
22619
|
+
}
|
|
22620
|
+
return list;
|
|
22621
|
+
}
|
|
22622
|
+
|
|
22623
|
+
// node_modules/diff/libesm/patch/create.js
|
|
22624
|
+
function structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options2) {
|
|
22625
|
+
let optionsObj;
|
|
22626
|
+
if (!options2) {
|
|
22627
|
+
optionsObj = {};
|
|
22628
|
+
} else if (typeof options2 === "function") {
|
|
22629
|
+
optionsObj = { callback: options2 };
|
|
22630
|
+
} else {
|
|
22631
|
+
optionsObj = options2;
|
|
22632
|
+
}
|
|
22633
|
+
if (typeof optionsObj.context === "undefined") {
|
|
22634
|
+
optionsObj.context = 4;
|
|
22635
|
+
}
|
|
22636
|
+
const context = optionsObj.context;
|
|
22637
|
+
if (optionsObj.newlineIsToken) {
|
|
22638
|
+
throw new Error("newlineIsToken may not be used with patch-generation functions, only with diffing functions");
|
|
22639
|
+
}
|
|
22640
|
+
if (!optionsObj.callback) {
|
|
22641
|
+
return diffLinesResultToPatch(diffLines(oldStr, newStr, optionsObj));
|
|
22642
|
+
} else {
|
|
22643
|
+
const { callback } = optionsObj;
|
|
22644
|
+
diffLines(oldStr, newStr, Object.assign(Object.assign({}, optionsObj), { callback: (diff) => {
|
|
22645
|
+
const patch = diffLinesResultToPatch(diff);
|
|
22646
|
+
callback(patch);
|
|
22647
|
+
} }));
|
|
22648
|
+
}
|
|
22649
|
+
function diffLinesResultToPatch(diff) {
|
|
22650
|
+
if (!diff) {
|
|
22651
|
+
return;
|
|
22652
|
+
}
|
|
22653
|
+
diff.push({ value: "", lines: [] });
|
|
22654
|
+
function contextLines(lines) {
|
|
22655
|
+
return lines.map(function(entry) {
|
|
22656
|
+
return " " + entry;
|
|
22657
|
+
});
|
|
22658
|
+
}
|
|
22659
|
+
const hunks = [];
|
|
22660
|
+
let oldRangeStart = 0, newRangeStart = 0, curRange = [], oldLine = 1, newLine = 1;
|
|
22661
|
+
for (let i = 0; i < diff.length; i++) {
|
|
22662
|
+
const current = diff[i], lines = current.lines || splitLines(current.value);
|
|
22663
|
+
current.lines = lines;
|
|
22664
|
+
if (current.added || current.removed) {
|
|
22665
|
+
if (!oldRangeStart) {
|
|
22666
|
+
const prev = diff[i - 1];
|
|
22667
|
+
oldRangeStart = oldLine;
|
|
22668
|
+
newRangeStart = newLine;
|
|
22669
|
+
if (prev) {
|
|
22670
|
+
curRange = context > 0 ? contextLines(prev.lines.slice(-context)) : [];
|
|
22671
|
+
oldRangeStart -= curRange.length;
|
|
22672
|
+
newRangeStart -= curRange.length;
|
|
22673
|
+
}
|
|
22674
|
+
}
|
|
22675
|
+
for (const line of lines) {
|
|
22676
|
+
curRange.push((current.added ? "+" : "-") + line);
|
|
22677
|
+
}
|
|
22678
|
+
if (current.added) {
|
|
22679
|
+
newLine += lines.length;
|
|
22680
|
+
} else {
|
|
22681
|
+
oldLine += lines.length;
|
|
22682
|
+
}
|
|
22683
|
+
} else {
|
|
22684
|
+
if (oldRangeStart) {
|
|
22685
|
+
if (lines.length <= context * 2 && i < diff.length - 2) {
|
|
22686
|
+
for (const line of contextLines(lines)) {
|
|
22687
|
+
curRange.push(line);
|
|
22688
|
+
}
|
|
22689
|
+
} else {
|
|
22690
|
+
const contextSize = Math.min(lines.length, context);
|
|
22691
|
+
for (const line of contextLines(lines.slice(0, contextSize))) {
|
|
22692
|
+
curRange.push(line);
|
|
22693
|
+
}
|
|
22694
|
+
const hunk = {
|
|
22695
|
+
oldStart: oldRangeStart,
|
|
22696
|
+
oldLines: oldLine - oldRangeStart + contextSize,
|
|
22697
|
+
newStart: newRangeStart,
|
|
22698
|
+
newLines: newLine - newRangeStart + contextSize,
|
|
22699
|
+
lines: curRange
|
|
22700
|
+
};
|
|
22701
|
+
hunks.push(hunk);
|
|
22702
|
+
oldRangeStart = 0;
|
|
22703
|
+
newRangeStart = 0;
|
|
22704
|
+
curRange = [];
|
|
22705
|
+
}
|
|
22706
|
+
}
|
|
22707
|
+
oldLine += lines.length;
|
|
22708
|
+
newLine += lines.length;
|
|
22709
|
+
}
|
|
22710
|
+
}
|
|
22711
|
+
for (const hunk of hunks) {
|
|
22712
|
+
for (let i = 0; i < hunk.lines.length; i++) {
|
|
22713
|
+
if (hunk.lines[i].endsWith("\n")) {
|
|
22714
|
+
hunk.lines[i] = hunk.lines[i].slice(0, -1);
|
|
22715
|
+
} else {
|
|
22716
|
+
hunk.lines.splice(i + 1, 0, "\");
|
|
22717
|
+
i++;
|
|
22718
|
+
}
|
|
22719
|
+
}
|
|
22720
|
+
}
|
|
22721
|
+
return {
|
|
22722
|
+
oldFileName,
|
|
22723
|
+
newFileName,
|
|
22724
|
+
oldHeader,
|
|
22725
|
+
newHeader,
|
|
22726
|
+
hunks
|
|
22727
|
+
};
|
|
22728
|
+
}
|
|
22729
|
+
}
|
|
22730
|
+
function formatPatch(patch) {
|
|
22731
|
+
if (Array.isArray(patch)) {
|
|
22732
|
+
return patch.map(formatPatch).join("\n");
|
|
22733
|
+
}
|
|
22734
|
+
const ret = [];
|
|
22735
|
+
if (patch.oldFileName == patch.newFileName) {
|
|
22736
|
+
ret.push("Index: " + patch.oldFileName);
|
|
22737
|
+
}
|
|
22738
|
+
ret.push("===================================================================");
|
|
22739
|
+
ret.push("--- " + patch.oldFileName + (typeof patch.oldHeader === "undefined" ? "" : " " + patch.oldHeader));
|
|
22740
|
+
ret.push("+++ " + patch.newFileName + (typeof patch.newHeader === "undefined" ? "" : " " + patch.newHeader));
|
|
22741
|
+
for (let i = 0; i < patch.hunks.length; i++) {
|
|
22742
|
+
const hunk = patch.hunks[i];
|
|
22743
|
+
if (hunk.oldLines === 0) {
|
|
22744
|
+
hunk.oldStart -= 1;
|
|
22745
|
+
}
|
|
22746
|
+
if (hunk.newLines === 0) {
|
|
22747
|
+
hunk.newStart -= 1;
|
|
22748
|
+
}
|
|
22749
|
+
ret.push("@@ -" + hunk.oldStart + "," + hunk.oldLines + " +" + hunk.newStart + "," + hunk.newLines + " @@");
|
|
22750
|
+
for (const line of hunk.lines) {
|
|
22751
|
+
ret.push(line);
|
|
22752
|
+
}
|
|
22753
|
+
}
|
|
22754
|
+
return ret.join("\n") + "\n";
|
|
22755
|
+
}
|
|
22756
|
+
function createTwoFilesPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options2) {
|
|
22757
|
+
if (typeof options2 === "function") {
|
|
22758
|
+
options2 = { callback: options2 };
|
|
22759
|
+
}
|
|
22760
|
+
if (!(options2 === null || options2 === void 0 ? void 0 : options2.callback)) {
|
|
22761
|
+
const patchObj = structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, options2);
|
|
22762
|
+
if (!patchObj) {
|
|
22763
|
+
return;
|
|
22764
|
+
}
|
|
22765
|
+
return formatPatch(patchObj);
|
|
22766
|
+
} else {
|
|
22767
|
+
const { callback } = options2;
|
|
22768
|
+
structuredPatch(oldFileName, newFileName, oldStr, newStr, oldHeader, newHeader, Object.assign(Object.assign({}, options2), { callback: (patchObj) => {
|
|
22769
|
+
if (!patchObj) {
|
|
22770
|
+
callback(void 0);
|
|
22771
|
+
} else {
|
|
22772
|
+
callback(formatPatch(patchObj));
|
|
22773
|
+
}
|
|
22774
|
+
} }));
|
|
22775
|
+
}
|
|
22776
|
+
}
|
|
22777
|
+
function splitLines(text2) {
|
|
22778
|
+
const hasTrailingNl = text2.endsWith("\n");
|
|
22779
|
+
const result = text2.split("\n").map((line) => line + "\n");
|
|
22780
|
+
if (hasTrailingNl) {
|
|
22781
|
+
result.pop();
|
|
22782
|
+
} else {
|
|
22783
|
+
result.push(result.pop().slice(0, -1));
|
|
22784
|
+
}
|
|
22785
|
+
return result;
|
|
22786
|
+
}
|
|
22787
|
+
|
|
22788
|
+
// packages/protocol-core/dist/file-change-summary.js
|
|
22789
|
+
import path6 from "node:path";
|
|
22790
|
+
function filePathKey(file2, cwd) {
|
|
22791
|
+
const windows = /^[a-z]:[/\\]/i.test(cwd) || /^[a-z]:[/\\]/i.test(file2);
|
|
22792
|
+
const paths = windows ? path6.win32 : path6.posix;
|
|
22793
|
+
const resolved = paths.resolve(cwd, file2).replaceAll("\\", "/");
|
|
22794
|
+
return windows ? resolved.toLowerCase() : resolved;
|
|
22795
|
+
}
|
|
22796
|
+
function composePatches(changes) {
|
|
22797
|
+
if (changes.some((change) => change.diffScope === "fragment"))
|
|
22798
|
+
return null;
|
|
22799
|
+
const original = [];
|
|
22800
|
+
const current = [];
|
|
22801
|
+
for (const change of changes) {
|
|
22802
|
+
let patches;
|
|
22803
|
+
try {
|
|
22804
|
+
patches = parsePatch(change.unifiedDiff);
|
|
22805
|
+
} catch {
|
|
22806
|
+
return null;
|
|
22807
|
+
}
|
|
22808
|
+
const [patch] = patches;
|
|
22809
|
+
if (!patch || patches.length !== 1)
|
|
22810
|
+
return null;
|
|
22811
|
+
const hunks2 = patch.hunks;
|
|
22812
|
+
for (const hunk2 of [...hunks2].reverse()) {
|
|
22813
|
+
const start = hunk2.oldStart - 1;
|
|
22814
|
+
while (current.length < start + hunk2.oldLines) {
|
|
22815
|
+
const line = {};
|
|
22816
|
+
original.push(line);
|
|
22817
|
+
current.push(line);
|
|
22818
|
+
}
|
|
22819
|
+
const replacement = [];
|
|
22820
|
+
let offset = start;
|
|
22821
|
+
for (const [i, entry] of hunk2.lines.entries()) {
|
|
22822
|
+
const operation = entry[0];
|
|
22823
|
+
if (operation === "\\")
|
|
22824
|
+
continue;
|
|
22825
|
+
const text2 = entry.slice(1) + (hunk2.lines[i + 1]?.startsWith("\\") ? "" : "\n");
|
|
22826
|
+
if (operation === "+")
|
|
22827
|
+
replacement.push({ text: text2 });
|
|
22828
|
+
else {
|
|
22829
|
+
const line = current[offset++];
|
|
22830
|
+
if (!line || line.text !== void 0 && line.text !== text2)
|
|
22831
|
+
return null;
|
|
22832
|
+
line.text = text2;
|
|
22833
|
+
if (operation === " ")
|
|
22834
|
+
replacement.push(line);
|
|
22835
|
+
}
|
|
22836
|
+
}
|
|
22837
|
+
current.splice(start, hunk2.oldLines, ...replacement);
|
|
22838
|
+
}
|
|
22839
|
+
}
|
|
22840
|
+
const hunks = [];
|
|
22841
|
+
let oldStart = 1;
|
|
22842
|
+
let newStart = 1;
|
|
22843
|
+
let hunk;
|
|
22844
|
+
for (const part of diffArrays(original, current, {
|
|
22845
|
+
comparator: (a, b) => a === b || a.text !== void 0 && a.text === b.text
|
|
22846
|
+
})) {
|
|
22847
|
+
if (!part.added && !part.removed) {
|
|
22848
|
+
hunk = void 0;
|
|
22849
|
+
oldStart += part.count;
|
|
22850
|
+
newStart += part.count;
|
|
22851
|
+
continue;
|
|
22852
|
+
}
|
|
22853
|
+
if (!hunk) {
|
|
22854
|
+
hunk = { oldStart, newStart, oldLines: 0, newLines: 0, lines: [] };
|
|
22855
|
+
hunks.push(hunk);
|
|
22856
|
+
}
|
|
22857
|
+
for (const line of part.value) {
|
|
22858
|
+
const text2 = line.text;
|
|
22859
|
+
if (text2 === void 0)
|
|
22860
|
+
return null;
|
|
22861
|
+
hunk.lines.push((part.added ? "+" : "-") + text2.replace(/\n$/, ""));
|
|
22862
|
+
if (!text2.endsWith("\n"))
|
|
22863
|
+
hunk.lines.push("\");
|
|
22864
|
+
}
|
|
22865
|
+
if (part.added) {
|
|
22866
|
+
hunk.newLines += part.count;
|
|
22867
|
+
newStart += part.count;
|
|
22868
|
+
} else {
|
|
22869
|
+
hunk.oldLines += part.count;
|
|
22870
|
+
oldStart += part.count;
|
|
22871
|
+
}
|
|
22872
|
+
}
|
|
22873
|
+
return hunks;
|
|
22874
|
+
}
|
|
22875
|
+
function summarizeFileChanges(changes, cwd) {
|
|
22876
|
+
const groups = /* @__PURE__ */ new Map();
|
|
22877
|
+
for (const change of changes) {
|
|
22878
|
+
const key = filePathKey(change.path, cwd);
|
|
22879
|
+
const group = groups.get(key);
|
|
22880
|
+
if (group)
|
|
22881
|
+
group.push(change);
|
|
22882
|
+
else
|
|
22883
|
+
groups.set(key, [change]);
|
|
22884
|
+
}
|
|
22885
|
+
return [...groups.values()].flatMap((group) => {
|
|
22886
|
+
const first = group[0];
|
|
22887
|
+
if (group.length === 1)
|
|
22888
|
+
return [first];
|
|
22889
|
+
const last = group.at(-1) ?? first;
|
|
22890
|
+
const hunks = composePatches(group);
|
|
22891
|
+
const kind = last.kind === "delete" ? "delete" : first.kind === "add" ? "add" : "update";
|
|
22892
|
+
if (hunks) {
|
|
22893
|
+
if (hunks.length === 0 && first.kind !== "add" === (last.kind !== "delete"))
|
|
22894
|
+
return [];
|
|
22895
|
+
return [
|
|
22896
|
+
{
|
|
22897
|
+
path: first.path,
|
|
22898
|
+
kind,
|
|
22899
|
+
unifiedDiff: formatPatch({
|
|
22900
|
+
oldFileName: first.kind === "add" ? "/dev/null" : `a/${first.path}`,
|
|
22901
|
+
newFileName: last.kind === "delete" ? "/dev/null" : `b/${first.path}`,
|
|
22902
|
+
oldHeader: "",
|
|
22903
|
+
newHeader: "",
|
|
22904
|
+
hunks
|
|
22905
|
+
})
|
|
22906
|
+
}
|
|
22907
|
+
];
|
|
22908
|
+
}
|
|
22909
|
+
const bodies = group.map(({ unifiedDiff }) => {
|
|
22910
|
+
const start = unifiedDiff.indexOf("@@");
|
|
22911
|
+
return start < 0 ? unifiedDiff : unifiedDiff.slice(start);
|
|
22912
|
+
});
|
|
22913
|
+
const headerEnd = first.unifiedDiff.indexOf("@@");
|
|
22914
|
+
const header = headerEnd < 0 ? "" : first.unifiedDiff.slice(0, headerEnd);
|
|
22915
|
+
return [
|
|
22916
|
+
{
|
|
22917
|
+
path: first.path,
|
|
22918
|
+
kind,
|
|
22919
|
+
unifiedDiff: header + bodies.join("\n"),
|
|
22920
|
+
diffScope: "fragment"
|
|
22921
|
+
}
|
|
22922
|
+
];
|
|
22923
|
+
});
|
|
22924
|
+
}
|
|
22925
|
+
|
|
22197
22926
|
// packages/protocol-core/dist/codex-ui-projector.js
|
|
22198
22927
|
function resolvedItemDurationMs(item, startedAtMs, completedAtMs) {
|
|
22199
22928
|
if ((item.type === "commandExecution" || item.type === "toolExecution" || item.type === "reasoning" || item.type === "agentMessage") && item.durationMs !== void 0) {
|
|
@@ -22215,17 +22944,17 @@ function itemStatus(outcome) {
|
|
|
22215
22944
|
function isRecord5(value2) {
|
|
22216
22945
|
return typeof value2 === "object" && value2 !== null && !Array.isArray(value2);
|
|
22217
22946
|
}
|
|
22218
|
-
function nestedString(value2, keys) {
|
|
22947
|
+
function nestedString(value2, keys, preserveText = false) {
|
|
22219
22948
|
if (!isRecord5(value2))
|
|
22220
22949
|
return void 0;
|
|
22221
22950
|
for (const key of keys) {
|
|
22222
22951
|
const field = value2[key];
|
|
22223
|
-
if (typeof field === "string" && field.trim().length > 0)
|
|
22224
|
-
return field.trim();
|
|
22952
|
+
if (typeof field === "string" && (preserveText || field.trim().length > 0))
|
|
22953
|
+
return preserveText ? field : field.trim();
|
|
22225
22954
|
}
|
|
22226
22955
|
for (const wrapper of ["input", "arguments", "params"]) {
|
|
22227
|
-
const nested = nestedString(value2[wrapper], keys);
|
|
22228
|
-
if (nested)
|
|
22956
|
+
const nested = nestedString(value2[wrapper], keys, preserveText);
|
|
22957
|
+
if (nested !== void 0)
|
|
22229
22958
|
return nested;
|
|
22230
22959
|
}
|
|
22231
22960
|
return void 0;
|
|
@@ -22290,24 +23019,7 @@ function isWriteTool(toolName) {
|
|
|
22290
23019
|
return ["write", "writefile", "filewrite", "create", "createfile"].includes(compactToolName(toolName));
|
|
22291
23020
|
}
|
|
22292
23021
|
function simpleUnifiedDiff(displayedPath, oldText, newText, kind) {
|
|
22293
|
-
|
|
22294
|
-
const newLines = newText === "" ? [] : newText.split("\n");
|
|
22295
|
-
if (oldLines.at(-1) === "")
|
|
22296
|
-
oldLines.pop();
|
|
22297
|
-
if (newLines.at(-1) === "")
|
|
22298
|
-
newLines.pop();
|
|
22299
|
-
const oldHeader = kind === "add" ? "/dev/null" : `a/${displayedPath}`;
|
|
22300
|
-
const newHeader = `b/${displayedPath}`;
|
|
22301
|
-
const oldRange = kind === "add" ? "0,0" : `1,${oldLines.length}`;
|
|
22302
|
-
const newRange = newLines.length === 0 ? "0,0" : `1,${newLines.length}`;
|
|
22303
|
-
return [
|
|
22304
|
-
`--- ${oldHeader}`,
|
|
22305
|
-
`+++ ${newHeader}`,
|
|
22306
|
-
`@@ -${oldRange} +${newRange} @@`,
|
|
22307
|
-
...oldLines.map((line) => `-${line}`),
|
|
22308
|
-
...newLines.map((line) => `+${line}`),
|
|
22309
|
-
""
|
|
22310
|
-
].join("\n");
|
|
23022
|
+
return createTwoFilesPatch(kind === "add" ? "/dev/null" : `a/${displayedPath}`, `b/${displayedPath}`, oldText, newText);
|
|
22311
23023
|
}
|
|
22312
23024
|
function fileChangeFromTool(toolName, args) {
|
|
22313
23025
|
if (!isFileMutatingTool(toolName))
|
|
@@ -22316,40 +23028,27 @@ function fileChangeFromTool(toolName, args) {
|
|
|
22316
23028
|
if (!displayedPath)
|
|
22317
23029
|
return null;
|
|
22318
23030
|
if (isWriteTool(toolName)) {
|
|
22319
|
-
const content = nestedString(args, [
|
|
22320
|
-
"content",
|
|
22321
|
-
"new_string",
|
|
22322
|
-
"newString",
|
|
22323
|
-
"newText",
|
|
22324
|
-
"file_text",
|
|
22325
|
-
"text",
|
|
22326
|
-
"new"
|
|
22327
|
-
]);
|
|
23031
|
+
const content = nestedString(args, ["content", "new_string", "newString", "newText", "file_text", "text", "new"], true);
|
|
22328
23032
|
if (content === void 0)
|
|
22329
23033
|
return null;
|
|
22330
23034
|
return [
|
|
22331
23035
|
{
|
|
22332
23036
|
path: displayedPath,
|
|
22333
23037
|
kind: "add",
|
|
23038
|
+
diffScope: "fragment",
|
|
22334
23039
|
unifiedDiff: simpleUnifiedDiff(displayedPath, "", content, "add")
|
|
22335
23040
|
}
|
|
22336
23041
|
];
|
|
22337
23042
|
}
|
|
22338
|
-
const oldText = nestedString(args, ["old_string", "oldString", "oldText", "old_text", "old"]);
|
|
22339
|
-
const newText = nestedString(args, [
|
|
22340
|
-
"new_string",
|
|
22341
|
-
"newString",
|
|
22342
|
-
"newText",
|
|
22343
|
-
"new_text",
|
|
22344
|
-
"content",
|
|
22345
|
-
"new"
|
|
22346
|
-
]);
|
|
23043
|
+
const oldText = nestedString(args, ["old_string", "oldString", "oldText", "old_text", "old"], true);
|
|
23044
|
+
const newText = nestedString(args, ["new_string", "newString", "newText", "new_text", "content", "new"], true);
|
|
22347
23045
|
if (oldText === void 0 || newText === void 0)
|
|
22348
23046
|
return null;
|
|
22349
23047
|
return [
|
|
22350
23048
|
{
|
|
22351
23049
|
path: displayedPath,
|
|
22352
23050
|
kind: "update",
|
|
23051
|
+
diffScope: "fragment",
|
|
22353
23052
|
unifiedDiff: simpleUnifiedDiff(displayedPath, oldText, newText, "update")
|
|
22354
23053
|
}
|
|
22355
23054
|
];
|
|
@@ -22360,21 +23059,25 @@ function projectFileChangeKind(kind) {
|
|
|
22360
23059
|
return { type: kind };
|
|
22361
23060
|
}
|
|
22362
23061
|
function projectFileChanges(changes) {
|
|
22363
|
-
return changes.map(({ path:
|
|
22364
|
-
path:
|
|
23062
|
+
return changes.map(({ path: path26, kind, unifiedDiff }) => ({
|
|
23063
|
+
path: path26,
|
|
22365
23064
|
kind: projectFileChangeKind(kind),
|
|
22366
23065
|
diff: unifiedDiff
|
|
22367
23066
|
}));
|
|
22368
23067
|
}
|
|
22369
|
-
function
|
|
22370
|
-
|
|
22371
|
-
|
|
22372
|
-
|
|
23068
|
+
function itemFileChanges(item) {
|
|
23069
|
+
return item.type === "fileChange" ? item.changes : item.type === "toolExecution" ? fileChangeFromTool(item.toolName, item.arguments) : null;
|
|
23070
|
+
}
|
|
23071
|
+
function summarizeHostFiles(items, cwd) {
|
|
23072
|
+
const first = items.find(({ item }) => itemFileChanges(item) !== null);
|
|
23073
|
+
if (!first)
|
|
22373
23074
|
return null;
|
|
23075
|
+
const nativeSources = new Set(items.flatMap(({ item }) => item.type === "fileChange" ? item.sourceItemIds ?? [] : []));
|
|
23076
|
+
const changes = items.flatMap(({ item, outcome }) => outcome && outcome.status !== "succeeded" || nativeSources.has(item.itemId) ? [] : itemFileChanges(item) ?? []);
|
|
22374
23077
|
return {
|
|
22375
23078
|
type: "fileChange",
|
|
22376
|
-
itemId:
|
|
22377
|
-
changes:
|
|
23079
|
+
itemId: first.item.itemId,
|
|
23080
|
+
changes: summarizeFileChanges(changes, cwd)
|
|
22378
23081
|
};
|
|
22379
23082
|
}
|
|
22380
23083
|
function isTodoTool(toolName) {
|
|
@@ -22652,6 +23355,7 @@ function historicalStatus(outcome) {
|
|
|
22652
23355
|
}
|
|
22653
23356
|
function projectHistoricalTurn(input) {
|
|
22654
23357
|
const { turnId, cwd, snapshot } = input;
|
|
23358
|
+
const files = summarizeHostFiles(snapshot.items, cwd);
|
|
22655
23359
|
const error51 = snapshot.outcome.status === "failed" ? {
|
|
22656
23360
|
message: snapshot.outcome.error.message,
|
|
22657
23361
|
codexErrorInfo: "other",
|
|
@@ -22671,15 +23375,12 @@ function projectHistoricalTurn(input) {
|
|
|
22671
23375
|
content: userInputContent(snapshot.input)
|
|
22672
23376
|
},
|
|
22673
23377
|
...snapshot.items.flatMap(({ item, outcome }) => {
|
|
23378
|
+
if (itemFileChanges(item) !== null) {
|
|
23379
|
+
return files?.itemId === item.itemId ? [projectItem(files, { status: "succeeded" }, cwd)] : [];
|
|
23380
|
+
}
|
|
22674
23381
|
if (item.type === "toolExecution") {
|
|
22675
23382
|
if (isTodoTool(item.toolName) || todoPlanFromTool(item.toolName, item.arguments))
|
|
22676
23383
|
return [];
|
|
22677
|
-
const changes = fileChangeFromTool(item.toolName, item.arguments);
|
|
22678
|
-
if (changes) {
|
|
22679
|
-
return [
|
|
22680
|
-
projectItem({ type: "fileChange", itemId: item.itemId, changes }, outcome, cwd, true, "")
|
|
22681
|
-
];
|
|
22682
|
-
}
|
|
22683
23384
|
if (isFileMutatingTool(item.toolName))
|
|
22684
23385
|
return [];
|
|
22685
23386
|
}
|
|
@@ -22722,7 +23423,6 @@ var CodexTurnProjector = class {
|
|
|
22722
23423
|
#input;
|
|
22723
23424
|
#interactions = /* @__PURE__ */ new Map();
|
|
22724
23425
|
#items = /* @__PURE__ */ new Map();
|
|
22725
|
-
#itemOrder = [];
|
|
22726
23426
|
#wireItemOrder = [];
|
|
22727
23427
|
#startedAt;
|
|
22728
23428
|
#startedAtMs;
|
|
@@ -22730,6 +23430,7 @@ var CodexTurnProjector = class {
|
|
|
22730
23430
|
#turnId;
|
|
22731
23431
|
#completed = false;
|
|
22732
23432
|
#started = false;
|
|
23433
|
+
#fileItemId = null;
|
|
22733
23434
|
constructor(input) {
|
|
22734
23435
|
this.#threadId = input.threadId;
|
|
22735
23436
|
this.#turnId = input.turnId;
|
|
@@ -22751,8 +23452,7 @@ var CodexTurnProjector = class {
|
|
|
22751
23452
|
if (projected.item.type === "agentMessage") {
|
|
22752
23453
|
return [projectItem(projected.item, projected.outcome, this.#cwd)];
|
|
22753
23454
|
}
|
|
22754
|
-
|
|
22755
|
-
return fileItem ? [projectItem(fileItem, projected.outcome, this.#cwd)] : [];
|
|
23455
|
+
return itemId === this.#fileItemId ? [projectItem(this.#fileSummary(), null, this.#cwd)] : [];
|
|
22756
23456
|
})
|
|
22757
23457
|
],
|
|
22758
23458
|
error: null,
|
|
@@ -22870,11 +23570,9 @@ var CodexTurnProjector = class {
|
|
|
22870
23570
|
reasoningPartStarted: false,
|
|
22871
23571
|
streamedCommandOutput: false,
|
|
22872
23572
|
wireStarted: false,
|
|
22873
|
-
wireFileChanges: null,
|
|
22874
23573
|
startedAtMs
|
|
22875
23574
|
};
|
|
22876
23575
|
this.#items.set(event.item.itemId, projected);
|
|
22877
|
-
this.#itemOrder.push(event.item.itemId);
|
|
22878
23576
|
if ((event.item.type === "agentMessage" || event.item.type === "reasoning") && event.item.text.length === 0) {
|
|
22879
23577
|
return { messages: [] };
|
|
22880
23578
|
}
|
|
@@ -22885,30 +23583,18 @@ var CodexTurnProjector = class {
|
|
|
22885
23583
|
}
|
|
22886
23584
|
const changes = fileChangeFromTool(event.item.toolName, event.item.arguments);
|
|
22887
23585
|
if (changes) {
|
|
22888
|
-
|
|
22889
|
-
const fileItem = {
|
|
22890
|
-
type: "fileChange",
|
|
22891
|
-
itemId: event.item.itemId,
|
|
22892
|
-
changes
|
|
22893
|
-
};
|
|
22894
|
-
return {
|
|
22895
|
-
messages: [
|
|
22896
|
-
this.#startWireItem(projected, fileItem, startedAtMs),
|
|
22897
|
-
...this.#fileChangeUpdates(event.item.itemId, changes)
|
|
22898
|
-
]
|
|
22899
|
-
};
|
|
23586
|
+
return { messages: this.#fileChangeUpdates(startedAtMs) };
|
|
22900
23587
|
}
|
|
22901
23588
|
if (isFileMutatingTool(event.item.toolName))
|
|
22902
23589
|
return { messages: [] };
|
|
22903
23590
|
}
|
|
23591
|
+
if (event.item.type === "fileChange")
|
|
23592
|
+
return { messages: this.#fileChangeUpdates(startedAtMs) };
|
|
22904
23593
|
const startedItem = event.item.type === "reasoning" ? { ...event.item, text: "" } : event.item;
|
|
22905
23594
|
const messages = [this.#startWireItem(projected, startedItem, startedAtMs)];
|
|
22906
23595
|
if (event.item.type === "reasoning") {
|
|
22907
23596
|
messages.push(this.#startReasoningTranscript(event.item, startedAtMs), this.#reasoningOutputDelta(event.item.itemId, event.item.text, startedAtMs), ...this.#reasoningDelta(projected, event.item.text, startedAtMs));
|
|
22908
23597
|
}
|
|
22909
|
-
if (event.item.type === "fileChange") {
|
|
22910
|
-
messages.push(...this.#fileChangeUpdates(event.item.itemId, event.item.changes));
|
|
22911
|
-
}
|
|
22912
23598
|
return { messages };
|
|
22913
23599
|
}
|
|
22914
23600
|
#updateItem(event, emittedAtMs) {
|
|
@@ -22974,7 +23660,7 @@ var CodexTurnProjector = class {
|
|
|
22974
23660
|
}
|
|
22975
23661
|
}
|
|
22976
23662
|
} else if (event.update.type === "fileChanges.replace") {
|
|
22977
|
-
messages.push(...this.#fileChangeUpdates(
|
|
23663
|
+
messages.push(...this.#fileChangeUpdates(emittedAtMs));
|
|
22978
23664
|
} else if (event.update.type === "subagents.replace") {
|
|
22979
23665
|
messages.push({
|
|
22980
23666
|
method: "item/started",
|
|
@@ -23011,6 +23697,9 @@ var CodexTurnProjector = class {
|
|
|
23011
23697
|
const durationMs = resolvedItemDurationMs(projected.item, startedAtMs, emittedAtMs);
|
|
23012
23698
|
projected.item = withResolvedDuration(projected.item, durationMs);
|
|
23013
23699
|
projected.durationMs = durationMs;
|
|
23700
|
+
if (itemFileChanges(projected.item) !== null) {
|
|
23701
|
+
return { messages: this.#fileChangeUpdates(emittedAtMs) };
|
|
23702
|
+
}
|
|
23014
23703
|
const completedItem = (item) => ({
|
|
23015
23704
|
method: "item/completed",
|
|
23016
23705
|
emittedAtMs,
|
|
@@ -23028,28 +23717,11 @@ var CodexTurnProjector = class {
|
|
|
23028
23717
|
const plan = planFromTodoValue(projected.item.arguments) ?? planFromTodoValue(projected.item.output);
|
|
23029
23718
|
return { messages: plan ? [this.#planUpdated(plan, emittedAtMs)] : [] };
|
|
23030
23719
|
}
|
|
23031
|
-
const changes = fileChangeFromTool(projected.item.toolName, projected.item.arguments);
|
|
23032
|
-
if (changes) {
|
|
23033
|
-
projected.wireFileChanges = changes;
|
|
23034
|
-
const fileItem2 = {
|
|
23035
|
-
type: "fileChange",
|
|
23036
|
-
itemId: projected.item.itemId,
|
|
23037
|
-
changes
|
|
23038
|
-
};
|
|
23039
|
-
return {
|
|
23040
|
-
messages: [
|
|
23041
|
-
this.#startWireItem(projected, fileItem2, startedAtMs),
|
|
23042
|
-
...this.#fileChangeUpdates(projected.item.itemId, changes),
|
|
23043
|
-
completedItem(projectItem(fileItem2, projected.outcome, this.#cwd, true, this.#threadId))
|
|
23044
|
-
]
|
|
23045
|
-
};
|
|
23046
|
-
}
|
|
23047
23720
|
}
|
|
23048
23721
|
return { messages: [] };
|
|
23049
23722
|
}
|
|
23050
|
-
const fileItem = wireFileChangeItem(projected);
|
|
23051
23723
|
const messages = [
|
|
23052
|
-
completedItem(projectItem(
|
|
23724
|
+
completedItem(projectItem(projected.item, projected.outcome, this.#cwd, !projected.streamedCommandOutput, this.#threadId))
|
|
23053
23725
|
];
|
|
23054
23726
|
if (projected.item.type === "reasoning") {
|
|
23055
23727
|
const reasoning = projected.item;
|
|
@@ -23108,8 +23780,7 @@ var CodexTurnProjector = class {
|
|
|
23108
23780
|
if (projected.item.type === "agentMessage") {
|
|
23109
23781
|
return [projectItem(projected.item, projected.outcome, this.#cwd)];
|
|
23110
23782
|
}
|
|
23111
|
-
|
|
23112
|
-
return fileItem ? [projectItem(fileItem, projected.outcome, this.#cwd)] : [];
|
|
23783
|
+
return itemId === this.#fileItemId ? [projectItem(this.#fileSummary(), { status: "succeeded" }, this.#cwd)] : [];
|
|
23113
23784
|
})
|
|
23114
23785
|
],
|
|
23115
23786
|
error: error51,
|
|
@@ -23121,6 +23792,17 @@ var CodexTurnProjector = class {
|
|
|
23121
23792
|
return {
|
|
23122
23793
|
completedTurn: turn,
|
|
23123
23794
|
messages: [
|
|
23795
|
+
...this.#fileItemId ? [
|
|
23796
|
+
{
|
|
23797
|
+
method: "item/completed",
|
|
23798
|
+
emittedAtMs: completedAtMs,
|
|
23799
|
+
params: {
|
|
23800
|
+
threadId: this.#threadId,
|
|
23801
|
+
turnId: this.#turnId,
|
|
23802
|
+
item: projectItem(this.#fileSummary(), { status: "succeeded" }, this.#cwd)
|
|
23803
|
+
}
|
|
23804
|
+
}
|
|
23805
|
+
] : [],
|
|
23124
23806
|
...error51 ? [
|
|
23125
23807
|
{
|
|
23126
23808
|
method: "error",
|
|
@@ -23234,15 +23916,31 @@ var CodexTurnProjector = class {
|
|
|
23234
23916
|
}
|
|
23235
23917
|
};
|
|
23236
23918
|
}
|
|
23237
|
-
#
|
|
23238
|
-
const
|
|
23919
|
+
#fileSummary() {
|
|
23920
|
+
const summary = summarizeHostFiles([...this.#items.values()], this.#cwd);
|
|
23921
|
+
if (!summary)
|
|
23922
|
+
throw new Error("File summary requested without a file Item");
|
|
23923
|
+
return this.#fileItemId ? { ...summary, itemId: this.#fileItemId } : summary;
|
|
23924
|
+
}
|
|
23925
|
+
#fileChangeUpdates(emittedAtMs) {
|
|
23926
|
+
const summary = this.#fileSummary();
|
|
23927
|
+
const messages = [];
|
|
23928
|
+
if (!this.#fileItemId) {
|
|
23929
|
+
this.#fileItemId = summary.itemId;
|
|
23930
|
+
const source = this.#items.get(summary.itemId);
|
|
23931
|
+
if (!source)
|
|
23932
|
+
throw new Error("File summary references an unknown Item");
|
|
23933
|
+
messages.push(this.#startWireItem(source, summary, emittedAtMs));
|
|
23934
|
+
}
|
|
23935
|
+
const projectedChanges = projectFileChanges(summary.changes);
|
|
23239
23936
|
return [
|
|
23937
|
+
...messages,
|
|
23240
23938
|
{
|
|
23241
23939
|
method: "item/fileChange/patchUpdated",
|
|
23242
23940
|
params: {
|
|
23243
23941
|
threadId: this.#threadId,
|
|
23244
23942
|
turnId: this.#turnId,
|
|
23245
|
-
itemId,
|
|
23943
|
+
itemId: this.#fileItemId,
|
|
23246
23944
|
changes: projectedChanges
|
|
23247
23945
|
}
|
|
23248
23946
|
},
|
|
@@ -23251,21 +23949,11 @@ var CodexTurnProjector = class {
|
|
|
23251
23949
|
params: {
|
|
23252
23950
|
threadId: this.#threadId,
|
|
23253
23951
|
turnId: this.#turnId,
|
|
23254
|
-
diff: diffText(
|
|
23952
|
+
diff: diffText(summary.changes)
|
|
23255
23953
|
}
|
|
23256
23954
|
}
|
|
23257
23955
|
];
|
|
23258
23956
|
}
|
|
23259
|
-
#allFileChanges() {
|
|
23260
|
-
return this.#itemOrder.flatMap((itemId) => {
|
|
23261
|
-
const projected = this.#items.get(itemId);
|
|
23262
|
-
if (!projected)
|
|
23263
|
-
return [];
|
|
23264
|
-
if (projected.item.type === "fileChange")
|
|
23265
|
-
return projected.item.changes;
|
|
23266
|
-
return projected.wireFileChanges ?? [];
|
|
23267
|
-
});
|
|
23268
|
-
}
|
|
23269
23957
|
#activeItem(itemId) {
|
|
23270
23958
|
const projected = this.#items.get(itemId);
|
|
23271
23959
|
if (!projected)
|
|
@@ -23319,13 +24007,13 @@ function decodeThreadForkRequest(request) {
|
|
|
23319
24007
|
if (runtimeWorkspaceRoots !== void 0 && runtimeWorkspaceRoots !== null && (!Array.isArray(runtimeWorkspaceRoots) || runtimeWorkspaceRoots.some((root) => typeof root !== "string" || root.length === 0))) {
|
|
23320
24008
|
throw new Error("thread/fork params.runtimeWorkspaceRoots must be text paths or null");
|
|
23321
24009
|
}
|
|
23322
|
-
const
|
|
24010
|
+
const path26 = optionalText(params, "path", { allowEmpty: true });
|
|
23323
24011
|
const ephemeral = optionalBoolean(params, "ephemeral");
|
|
23324
24012
|
return {
|
|
23325
24013
|
threadId: threadId2,
|
|
23326
24014
|
...lastTurnText ? { lastTurnId: hostTurnIdSchema.parse(lastTurnText) } : {},
|
|
23327
24015
|
...beforeTurnText ? { beforeTurnId: hostTurnIdSchema.parse(beforeTurnText) } : {},
|
|
23328
|
-
...
|
|
24016
|
+
...path26 ? { path: path26 } : {},
|
|
23329
24017
|
...optionalField(params, "model"),
|
|
23330
24018
|
...optionalField(params, "modelProvider"),
|
|
23331
24019
|
...optionalField(params, "cwd"),
|
|
@@ -24484,7 +25172,7 @@ var HarnessAccountInspectionCache = class {
|
|
|
24484
25172
|
// packages/host-runtime/src/app-server-host.ts
|
|
24485
25173
|
import { createHash as createHash6, randomUUID as randomUUID8 } from "node:crypto";
|
|
24486
25174
|
import os2 from "node:os";
|
|
24487
|
-
import
|
|
25175
|
+
import path12 from "node:path";
|
|
24488
25176
|
|
|
24489
25177
|
// packages/host-runtime/src/external-thread-fork.ts
|
|
24490
25178
|
import nodePath from "node:path";
|
|
@@ -24492,7 +25180,7 @@ import nodePath from "node:path";
|
|
|
24492
25180
|
// packages/host-runtime/src/external-thread-repository.ts
|
|
24493
25181
|
import { randomUUID as randomUUID4 } from "node:crypto";
|
|
24494
25182
|
import os from "node:os";
|
|
24495
|
-
import
|
|
25183
|
+
import path7 from "node:path";
|
|
24496
25184
|
|
|
24497
25185
|
// packages/host-runtime/src/external-subagent-threads.ts
|
|
24498
25186
|
import { createHash as createHash3, randomUUID as randomUUID3 } from "node:crypto";
|
|
@@ -24632,8 +25320,8 @@ function sameMapping(left, right) {
|
|
|
24632
25320
|
}
|
|
24633
25321
|
function defaultMappingStoreDirectory(environment) {
|
|
24634
25322
|
const dataDirectory = environment.CODEXHOST_DATA_DIR;
|
|
24635
|
-
return
|
|
24636
|
-
dataDirectory ?
|
|
25323
|
+
return path7.join(
|
|
25324
|
+
dataDirectory ? path7.resolve(dataDirectory) : path7.join(os.homedir(), ".codexhost"),
|
|
24637
25325
|
"mapping-store"
|
|
24638
25326
|
);
|
|
24639
25327
|
}
|
|
@@ -25866,16 +26554,236 @@ var SessionStateObserver = class {
|
|
|
25866
26554
|
}
|
|
25867
26555
|
};
|
|
25868
26556
|
|
|
25869
|
-
// packages/host-runtime/src/
|
|
25870
|
-
|
|
25871
|
-
|
|
25872
|
-
|
|
25873
|
-
|
|
25874
|
-
|
|
25875
|
-
|
|
25876
|
-
|
|
25877
|
-
|
|
25878
|
-
|
|
26557
|
+
// packages/host-runtime/src/desktop-request-queue.ts
|
|
26558
|
+
var DesktopRequestQueue = class {
|
|
26559
|
+
#threads = /* @__PURE__ */ new Map();
|
|
26560
|
+
#pending = /* @__PURE__ */ new Set();
|
|
26561
|
+
run(threadId2, operation) {
|
|
26562
|
+
const previous = threadId2 === void 0 ? void 0 : this.#threads.get(threadId2);
|
|
26563
|
+
const task = (previous ?? Promise.resolve()).then(operation);
|
|
26564
|
+
const settled = task.then(
|
|
26565
|
+
() => void 0,
|
|
26566
|
+
() => void 0
|
|
26567
|
+
);
|
|
26568
|
+
this.#pending.add(settled);
|
|
26569
|
+
if (threadId2 !== void 0) this.#threads.set(threadId2, settled);
|
|
26570
|
+
void settled.then(() => {
|
|
26571
|
+
this.#pending.delete(settled);
|
|
26572
|
+
if (threadId2 !== void 0 && this.#threads.get(threadId2) === settled) {
|
|
26573
|
+
this.#threads.delete(threadId2);
|
|
26574
|
+
}
|
|
26575
|
+
});
|
|
26576
|
+
return task;
|
|
26577
|
+
}
|
|
26578
|
+
/** Call after admission stops, before taking the Session snapshot for shutdown. */
|
|
26579
|
+
async drain() {
|
|
26580
|
+
await Promise.all(this.#pending);
|
|
26581
|
+
}
|
|
26582
|
+
};
|
|
26583
|
+
|
|
26584
|
+
// packages/host-runtime/src/external-thread-idle-release.ts
|
|
26585
|
+
var CHECK_INTERVAL_MS = 6e4;
|
|
26586
|
+
var CLOSE_TIMEOUT_MS = 6e4;
|
|
26587
|
+
var CLOSE_FAILURE = "External Session resource release failed. Further use is blocked to avoid duplicate writers. Restart Codex Desktop to retry recovery; residual processes may require manual cleanup.";
|
|
26588
|
+
var ExternalThreadIdleRelease = class {
|
|
26589
|
+
constructor(options2) {
|
|
26590
|
+
this.options = options2;
|
|
26591
|
+
}
|
|
26592
|
+
options;
|
|
26593
|
+
#activity = /* @__PURE__ */ new WeakMap();
|
|
26594
|
+
#operations = /* @__PURE__ */ new Map();
|
|
26595
|
+
#closing = /* @__PURE__ */ new Map();
|
|
26596
|
+
#pending = /* @__PURE__ */ new Set();
|
|
26597
|
+
#scheduled = /* @__PURE__ */ new Set();
|
|
26598
|
+
#settings = { ...DEFAULT_IDLE_RELEASE_SETTINGS };
|
|
26599
|
+
#timer;
|
|
26600
|
+
#stopped = false;
|
|
26601
|
+
configure(value2) {
|
|
26602
|
+
const settings = idleReleaseSettingsSchema.parse(value2);
|
|
26603
|
+
if (this.#stopped) throw new Error("Host is shutting down");
|
|
26604
|
+
this.#settings = settings;
|
|
26605
|
+
if (settings.enabled && !this.#timer) {
|
|
26606
|
+
this.#timer = setInterval(() => this.check(), CHECK_INTERVAL_MS);
|
|
26607
|
+
this.#timer.unref();
|
|
26608
|
+
} else if (!settings.enabled && this.#timer) {
|
|
26609
|
+
clearInterval(this.#timer);
|
|
26610
|
+
this.#timer = void 0;
|
|
26611
|
+
}
|
|
26612
|
+
return { ...settings };
|
|
26613
|
+
}
|
|
26614
|
+
touch(thread) {
|
|
26615
|
+
const state = this.#activity.get(thread);
|
|
26616
|
+
if (state) state.lastActivity = Date.now();
|
|
26617
|
+
else
|
|
26618
|
+
this.#activity.set(thread, {
|
|
26619
|
+
lastActivity: Date.now(),
|
|
26620
|
+
outputFailed: false,
|
|
26621
|
+
closeFailed: false
|
|
26622
|
+
});
|
|
26623
|
+
}
|
|
26624
|
+
outputFailed(thread) {
|
|
26625
|
+
this.touch(thread);
|
|
26626
|
+
const state = this.#activity.get(thread);
|
|
26627
|
+
if (state) state.outputFailed = true;
|
|
26628
|
+
}
|
|
26629
|
+
failure(thread) {
|
|
26630
|
+
return this.#activity.get(thread)?.closeFailed ? CLOSE_FAILURE : void 0;
|
|
26631
|
+
}
|
|
26632
|
+
async waitForClose(id2) {
|
|
26633
|
+
await this.#closing.get(id2);
|
|
26634
|
+
}
|
|
26635
|
+
/** Acquire before resolving a Session, not after an await has exposed its reference. */
|
|
26636
|
+
async runOperation(id2, operation) {
|
|
26637
|
+
if (this.#stopped) throw new Error("Host is shutting down");
|
|
26638
|
+
if (id2) {
|
|
26639
|
+
while (this.#closing.has(id2)) await this.#closing.get(id2);
|
|
26640
|
+
}
|
|
26641
|
+
if (this.#stopped) throw new Error("Host is shutting down");
|
|
26642
|
+
return this.#track(id2, operation);
|
|
26643
|
+
}
|
|
26644
|
+
/** Closing may emit outputs: consume them without waiting on the close being drained. */
|
|
26645
|
+
consumeOutput(thread, operation) {
|
|
26646
|
+
this.touch(thread);
|
|
26647
|
+
return this.#track(thread.id, operation, false);
|
|
26648
|
+
}
|
|
26649
|
+
#track(id2, operation, drain = true) {
|
|
26650
|
+
if (id2) this.#operations.set(id2, (this.#operations.get(id2) ?? 0) + 1);
|
|
26651
|
+
const task = Promise.resolve().then(operation).finally(() => {
|
|
26652
|
+
if (id2) {
|
|
26653
|
+
const remaining = (this.#operations.get(id2) ?? 1) - 1;
|
|
26654
|
+
if (remaining) this.#operations.set(id2, remaining);
|
|
26655
|
+
else {
|
|
26656
|
+
this.#operations.delete(id2);
|
|
26657
|
+
const thread = this.options.get(id2);
|
|
26658
|
+
if (thread) this.touch(thread);
|
|
26659
|
+
}
|
|
26660
|
+
}
|
|
26661
|
+
this.#pending.delete(task);
|
|
26662
|
+
});
|
|
26663
|
+
if (drain) this.#pending.add(task);
|
|
26664
|
+
return task;
|
|
26665
|
+
}
|
|
26666
|
+
/** Read only: never resolve a Session or touch its activity clock. */
|
|
26667
|
+
list() {
|
|
26668
|
+
const now = Date.now();
|
|
26669
|
+
return this.options.threads().map((thread) => {
|
|
26670
|
+
const activity = this.#activity.get(thread);
|
|
26671
|
+
const inactiveMs = Math.max(0, now - (activity?.lastActivity ?? now));
|
|
26672
|
+
let state = "idle";
|
|
26673
|
+
let reason = "none";
|
|
26674
|
+
if (activity?.closeFailed) {
|
|
26675
|
+
state = "failed";
|
|
26676
|
+
reason = "closeFailed";
|
|
26677
|
+
} else if (this.#closing.has(thread.id)) {
|
|
26678
|
+
state = "closing";
|
|
26679
|
+
} else if (thread.running || thread.activeTurnId) {
|
|
26680
|
+
state = "running";
|
|
26681
|
+
reason = "operation";
|
|
26682
|
+
} else if (thread.persistenceError || activity?.outputFailed) {
|
|
26683
|
+
state = "blocked";
|
|
26684
|
+
reason = "persistence";
|
|
26685
|
+
} else if (thread.record.subagent || thread.record.state !== "ready" || !thread.record.nativeSessionRef) {
|
|
26686
|
+
state = "blocked";
|
|
26687
|
+
reason = "identity";
|
|
26688
|
+
} else if (this.#operations.has(thread.id)) {
|
|
26689
|
+
state = "busy";
|
|
26690
|
+
reason = "operation";
|
|
26691
|
+
} else if (!this.options.canRelease(thread)) {
|
|
26692
|
+
state = "busy";
|
|
26693
|
+
reason = "background";
|
|
26694
|
+
} else if (!this.#settings.enabled) {
|
|
26695
|
+
reason = "disabled";
|
|
26696
|
+
} else if (inactiveMs < this.#settings.timeoutMinutes * 6e4) {
|
|
26697
|
+
reason = "timeout";
|
|
26698
|
+
}
|
|
26699
|
+
return {
|
|
26700
|
+
threadId: thread.id,
|
|
26701
|
+
title: thread.record.title ?? thread.id,
|
|
26702
|
+
harnessId: thread.harnessId,
|
|
26703
|
+
state,
|
|
26704
|
+
reason,
|
|
26705
|
+
inactiveMs
|
|
26706
|
+
};
|
|
26707
|
+
});
|
|
26708
|
+
}
|
|
26709
|
+
#eligible(thread) {
|
|
26710
|
+
const state = this.#activity.get(thread);
|
|
26711
|
+
return !this.#stopped && this.#settings.enabled && !!state && !state.outputFailed && !state.closeFailed && this.options.get(thread.id) === thread && !this.#closing.has(thread.id) && !this.#operations.has(thread.id) && !thread.record.subagent && thread.record.state === "ready" && !!thread.record.nativeSessionRef && !thread.persistenceError && !thread.running && !thread.activeTurnId && this.options.canRelease(thread) && Date.now() - state.lastActivity >= this.#settings.timeoutMinutes * 6e4;
|
|
26712
|
+
}
|
|
26713
|
+
check() {
|
|
26714
|
+
for (const thread of this.options.threads()) {
|
|
26715
|
+
if (this.#scheduled.has(thread.id) || !this.#eligible(thread)) continue;
|
|
26716
|
+
this.#scheduled.add(thread.id);
|
|
26717
|
+
const task = this.options.queue.run(thread.id, async () => {
|
|
26718
|
+
if (!this.#eligible(thread)) return;
|
|
26719
|
+
const closing = this.#close(thread);
|
|
26720
|
+
this.#closing.set(thread.id, closing);
|
|
26721
|
+
try {
|
|
26722
|
+
await closing;
|
|
26723
|
+
} finally {
|
|
26724
|
+
this.#closing.delete(thread.id);
|
|
26725
|
+
}
|
|
26726
|
+
}).catch(this.options.diagnose).finally(() => this.#scheduled.delete(thread.id));
|
|
26727
|
+
this.#pending.add(task);
|
|
26728
|
+
void task.finally(() => this.#pending.delete(task));
|
|
26729
|
+
}
|
|
26730
|
+
}
|
|
26731
|
+
async #close(thread) {
|
|
26732
|
+
const state = this.#activity.get(thread);
|
|
26733
|
+
if (!state) return;
|
|
26734
|
+
let timeout;
|
|
26735
|
+
const closed = Promise.resolve().then(async () => {
|
|
26736
|
+
await thread.session.close();
|
|
26737
|
+
await thread.outputTask;
|
|
26738
|
+
await this.options.onClosed?.(thread);
|
|
26739
|
+
});
|
|
26740
|
+
try {
|
|
26741
|
+
await Promise.race([
|
|
26742
|
+
closed,
|
|
26743
|
+
new Promise((_, reject) => {
|
|
26744
|
+
timeout = setTimeout(
|
|
26745
|
+
() => reject(new Error("Session release timed out")),
|
|
26746
|
+
CLOSE_TIMEOUT_MS
|
|
26747
|
+
);
|
|
26748
|
+
timeout.unref();
|
|
26749
|
+
})
|
|
26750
|
+
]);
|
|
26751
|
+
if (state.outputFailed || thread.persistenceError || thread.record.state !== "ready" || !thread.record.nativeSessionRef) {
|
|
26752
|
+
throw new Error("Session release could not confirm persisted history and identity");
|
|
26753
|
+
}
|
|
26754
|
+
if (this.options.get(thread.id) !== thread) throw new Error("Session changed during release");
|
|
26755
|
+
this.options.remove(thread.id);
|
|
26756
|
+
} catch (error51) {
|
|
26757
|
+
state.closeFailed = true;
|
|
26758
|
+
this.options.diagnose(error51);
|
|
26759
|
+
} finally {
|
|
26760
|
+
if (timeout) clearTimeout(timeout);
|
|
26761
|
+
}
|
|
26762
|
+
}
|
|
26763
|
+
disable() {
|
|
26764
|
+
this.#settings = { ...this.#settings, enabled: false };
|
|
26765
|
+
if (this.#timer) clearInterval(this.#timer);
|
|
26766
|
+
this.#timer = void 0;
|
|
26767
|
+
}
|
|
26768
|
+
stop() {
|
|
26769
|
+
this.#stopped = true;
|
|
26770
|
+
this.disable();
|
|
26771
|
+
}
|
|
26772
|
+
async drain() {
|
|
26773
|
+
while (this.#pending.size) await Promise.allSettled([...this.#pending]);
|
|
26774
|
+
}
|
|
26775
|
+
};
|
|
26776
|
+
|
|
26777
|
+
// packages/host-runtime/src/external-thread-runtime.ts
|
|
26778
|
+
function nativeTurnKey3(turn) {
|
|
26779
|
+
const ref = turn.nativeTurnRef;
|
|
26780
|
+
return `${ref.harnessId}\0${ref.nativeSessionId}\0${ref.nativeTurnKey}\0${ref.formatVersion}`;
|
|
26781
|
+
}
|
|
26782
|
+
function mergeReadonlySnapshot(previous, next) {
|
|
26783
|
+
const nextByTurn = new Map(next.turns.map((turn) => [nativeTurnKey3(turn), turn]));
|
|
26784
|
+
const retainedKeys = /* @__PURE__ */ new Set();
|
|
26785
|
+
const turns = previous.turns.map((turn) => {
|
|
26786
|
+
const key = nativeTurnKey3(turn);
|
|
25879
26787
|
retainedKeys.add(key);
|
|
25880
26788
|
const update = nextByTurn.get(key);
|
|
25881
26789
|
if (!update) return turn;
|
|
@@ -25955,12 +26863,14 @@ function errorMessage2(error51) {
|
|
|
25955
26863
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
25956
26864
|
}
|
|
25957
26865
|
var ExternalThreadRuntime = class {
|
|
26866
|
+
idleRelease;
|
|
25958
26867
|
#adapters;
|
|
25959
26868
|
#consumeOutputs;
|
|
25960
26869
|
#diagnose;
|
|
25961
26870
|
#environment;
|
|
25962
26871
|
#repository;
|
|
25963
26872
|
#restores = /* @__PURE__ */ new Map();
|
|
26873
|
+
#subagentRunning;
|
|
25964
26874
|
#threads = /* @__PURE__ */ new Map();
|
|
25965
26875
|
constructor(input) {
|
|
25966
26876
|
this.#adapters = input.adapters;
|
|
@@ -25968,6 +26878,16 @@ var ExternalThreadRuntime = class {
|
|
|
25968
26878
|
this.#repository = input.repository;
|
|
25969
26879
|
this.#consumeOutputs = input.consumeOutputs;
|
|
25970
26880
|
this.#diagnose = input.diagnose;
|
|
26881
|
+
this.#subagentRunning = input.subagentRunning ?? (() => false);
|
|
26882
|
+
this.idleRelease = new ExternalThreadIdleRelease({
|
|
26883
|
+
threads: () => this.values(),
|
|
26884
|
+
get: (id2) => this.get(id2),
|
|
26885
|
+
remove: (id2) => this.remove(id2),
|
|
26886
|
+
queue: input.idleRelease?.queue ?? new DesktopRequestQueue(),
|
|
26887
|
+
canRelease: input.idleRelease?.canRelease ?? (() => false),
|
|
26888
|
+
...input.idleRelease?.onClosed ? { onClosed: input.idleRelease.onClosed } : {},
|
|
26889
|
+
diagnose: input.diagnose
|
|
26890
|
+
});
|
|
25971
26891
|
}
|
|
25972
26892
|
get(threadId2) {
|
|
25973
26893
|
return this.#threads.get(threadId2);
|
|
@@ -25997,6 +26917,7 @@ var ExternalThreadRuntime = class {
|
|
|
25997
26917
|
...effectiveThinkingOptionId ? { effectiveThinkingOptionId } : {},
|
|
25998
26918
|
...effectivePermissionModeId ? { effectivePermissionModeId } : {}
|
|
25999
26919
|
};
|
|
26920
|
+
const running = this.#subagentRunning(input.record.hostThreadId);
|
|
26000
26921
|
const externalThread = {
|
|
26001
26922
|
id: input.record.hostThreadId,
|
|
26002
26923
|
cwd: input.record.cwd,
|
|
@@ -26009,11 +26930,11 @@ var ExternalThreadRuntime = class {
|
|
|
26009
26930
|
record: input.record,
|
|
26010
26931
|
sessionId: input.sessionId,
|
|
26011
26932
|
stateObserver: new SessionStateObserver(observerState),
|
|
26012
|
-
thread: input.thread,
|
|
26933
|
+
thread: running ? { ...input.thread, status: { type: "active", activeFlags: [] } } : input.thread,
|
|
26013
26934
|
transportModelId: input.transportModelId ?? input.record.transportModelId,
|
|
26014
26935
|
turns: input.turns,
|
|
26015
26936
|
historyHydrated: true,
|
|
26016
|
-
running
|
|
26937
|
+
running,
|
|
26017
26938
|
activeTurnId: null,
|
|
26018
26939
|
latestUsage: input.session.initialUsage,
|
|
26019
26940
|
usageTurnId: null,
|
|
@@ -26023,6 +26944,7 @@ var ExternalThreadRuntime = class {
|
|
|
26023
26944
|
persistenceError: null,
|
|
26024
26945
|
ignoredInteractionIds: /* @__PURE__ */ new Set()
|
|
26025
26946
|
};
|
|
26947
|
+
this.idleRelease.touch(externalThread);
|
|
26026
26948
|
externalThread.outputTask = this.#consumeOutputs(externalThread);
|
|
26027
26949
|
this.#threads.set(externalThread.id, externalThread);
|
|
26028
26950
|
return externalThread;
|
|
@@ -26075,8 +26997,13 @@ var ExternalThreadRuntime = class {
|
|
|
26075
26997
|
}
|
|
26076
26998
|
}
|
|
26077
26999
|
async locate(threadId2) {
|
|
27000
|
+
await this.idleRelease.waitForClose(threadId2);
|
|
26078
27001
|
const loaded = this.#threads.get(threadId2);
|
|
26079
|
-
if (loaded)
|
|
27002
|
+
if (loaded) {
|
|
27003
|
+
const failure = this.idleRelease.failure(loaded);
|
|
27004
|
+
if (failure) return { kind: "error", error: { code: -32075, message: failure } };
|
|
27005
|
+
return { kind: "external", record: loaded.record, thread: loaded };
|
|
27006
|
+
}
|
|
26080
27007
|
let record3;
|
|
26081
27008
|
try {
|
|
26082
27009
|
record3 = await this.#repository.find(threadId2);
|
|
@@ -26099,13 +27026,17 @@ var ExternalThreadRuntime = class {
|
|
|
26099
27026
|
const location = await this.locate(threadId2);
|
|
26100
27027
|
if (location.kind !== "external") return location;
|
|
26101
27028
|
if (location.thread) {
|
|
27029
|
+
this.idleRelease.touch(location.thread);
|
|
26102
27030
|
return { kind: "external", thread: location.thread, historyFresh: false };
|
|
26103
27031
|
}
|
|
26104
27032
|
const { record: record3 } = location;
|
|
26105
27033
|
let restoring = this.#restores.get(threadId2);
|
|
26106
27034
|
if (!restoring) {
|
|
26107
27035
|
const restored = this.#threads.get(threadId2);
|
|
26108
|
-
if (restored)
|
|
27036
|
+
if (restored) {
|
|
27037
|
+
this.idleRelease.touch(restored);
|
|
27038
|
+
return { kind: "external", thread: restored, historyFresh: false };
|
|
27039
|
+
}
|
|
26109
27040
|
restoring = this.#restore(record3).finally(() => {
|
|
26110
27041
|
this.#restores.delete(threadId2);
|
|
26111
27042
|
});
|
|
@@ -26465,7 +27396,7 @@ var ExternalTurnSteering = class {
|
|
|
26465
27396
|
|
|
26466
27397
|
// packages/host-runtime/src/harness-delegation-coordinator.ts
|
|
26467
27398
|
import { createHash as createHash5, randomUUID as randomUUID5 } from "node:crypto";
|
|
26468
|
-
import
|
|
27399
|
+
import path8 from "node:path";
|
|
26469
27400
|
|
|
26470
27401
|
// packages/host-runtime/src/delegation-snapshot.ts
|
|
26471
27402
|
import { createHash as createHash4 } from "node:crypto";
|
|
@@ -26636,7 +27567,7 @@ function taskDigest(input) {
|
|
|
26636
27567
|
return createHash5("sha256").update(
|
|
26637
27568
|
JSON.stringify({
|
|
26638
27569
|
task: input.task,
|
|
26639
|
-
cwd:
|
|
27570
|
+
cwd: path8.resolve(input.cwd),
|
|
26640
27571
|
modelId: input.model?.id ?? null,
|
|
26641
27572
|
thinkingOptionId: input.thinkingOptionId ?? null
|
|
26642
27573
|
})
|
|
@@ -26707,7 +27638,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
26707
27638
|
return {
|
|
26708
27639
|
harnessId: input.harnessId,
|
|
26709
27640
|
inspection: await adapter.inspect({
|
|
26710
|
-
...input.cwd ? { cwd:
|
|
27641
|
+
...input.cwd ? { cwd: path8.resolve(input.cwd) } : {},
|
|
26711
27642
|
...input.refresh !== void 0 ? { refresh: input.refresh } : {}
|
|
26712
27643
|
})
|
|
26713
27644
|
};
|
|
@@ -26721,7 +27652,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
26721
27652
|
const result = await this.#startOfficial({ ...input, parentThreadId, cwd: selectedCwd });
|
|
26722
27653
|
return { ...result, parentThreadId, cwd: result.cwd ?? selectedCwd };
|
|
26723
27654
|
}
|
|
26724
|
-
const startInput = { ...input, parentThreadId, cwd:
|
|
27655
|
+
const startInput = { ...input, parentThreadId, cwd: path8.resolve(selectedCwd) };
|
|
26725
27656
|
if (!this.#adapters.has(input.harnessId)) {
|
|
26726
27657
|
throw new DelegationControlError(
|
|
26727
27658
|
"HARNESS_NOT_FOUND",
|
|
@@ -26782,94 +27713,101 @@ var HarnessDelegationCoordinator = class {
|
|
|
26782
27713
|
);
|
|
26783
27714
|
let delegation = null;
|
|
26784
27715
|
let session = null;
|
|
26785
|
-
|
|
26786
|
-
|
|
26787
|
-
|
|
26788
|
-
|
|
26789
|
-
|
|
26790
|
-
|
|
26791
|
-
|
|
26792
|
-
|
|
26793
|
-
|
|
26794
|
-
|
|
26795
|
-
|
|
26796
|
-
|
|
26797
|
-
|
|
26798
|
-
|
|
26799
|
-
|
|
26800
|
-
|
|
26801
|
-
|
|
26802
|
-
|
|
26803
|
-
|
|
26804
|
-
|
|
26805
|
-
|
|
26806
|
-
|
|
26807
|
-
|
|
26808
|
-
record3.
|
|
26809
|
-
|
|
26810
|
-
|
|
26811
|
-
|
|
26812
|
-
|
|
26813
|
-
|
|
26814
|
-
|
|
26815
|
-
|
|
26816
|
-
|
|
26817
|
-
|
|
26818
|
-
|
|
26819
|
-
|
|
26820
|
-
|
|
26821
|
-
|
|
26822
|
-
|
|
26823
|
-
|
|
26824
|
-
|
|
26825
|
-
|
|
26826
|
-
|
|
26827
|
-
|
|
26828
|
-
|
|
26829
|
-
|
|
26830
|
-
|
|
26831
|
-
|
|
26832
|
-
|
|
26833
|
-
|
|
26834
|
-
|
|
26835
|
-
|
|
26836
|
-
|
|
27716
|
+
return this.#externalRuntime.idleRelease.runOperation(childThreadId, async () => {
|
|
27717
|
+
try {
|
|
27718
|
+
delegation = await this.#repository.createDelegation({
|
|
27719
|
+
delegationId,
|
|
27720
|
+
parentHostThreadId: hostThreadIdSchema.parse(parentThreadId),
|
|
27721
|
+
childHostThreadId: childThreadId,
|
|
27722
|
+
sourceHarnessId: harnessIdSchema.parse(parent.harnessId),
|
|
27723
|
+
targetHarnessId: harnessIdSchema.parse(targetHarnessId),
|
|
27724
|
+
status: "creating",
|
|
27725
|
+
...input.requestId ? { requestId: input.requestId } : {},
|
|
27726
|
+
taskDigest: digest2
|
|
27727
|
+
});
|
|
27728
|
+
const opened = await adapter.open({
|
|
27729
|
+
kind: "create",
|
|
27730
|
+
cwd: record3.cwd,
|
|
27731
|
+
environment: { ...this.#environment, [DELEGATION_THREAD_ID_ENV]: childThreadId },
|
|
27732
|
+
executionPolicy: "unattended-full-access",
|
|
27733
|
+
...input.model ? { model: input.model } : {},
|
|
27734
|
+
...input.thinkingOptionId ? { thinkingOptionId: input.thinkingOptionId } : {}
|
|
27735
|
+
});
|
|
27736
|
+
if (!opened.ok) throw new DelegationControlError("DELEGATION_FAILED", opened.error.message);
|
|
27737
|
+
session = opened.value;
|
|
27738
|
+
if (session.initialState.nativeRef) {
|
|
27739
|
+
record3 = await this.#repository.commitNative(
|
|
27740
|
+
record3.hostThreadId,
|
|
27741
|
+
session.initialState.nativeRef
|
|
27742
|
+
);
|
|
27743
|
+
}
|
|
27744
|
+
const threadValue = externalThreadValue({
|
|
27745
|
+
record: record3,
|
|
27746
|
+
turns: [],
|
|
27747
|
+
sessionId: record3.hostThreadId,
|
|
27748
|
+
running: true
|
|
27749
|
+
});
|
|
27750
|
+
const thread = this.#registerExternalThread({
|
|
27751
|
+
record: record3,
|
|
27752
|
+
session,
|
|
27753
|
+
sessionId: record3.hostThreadId,
|
|
27754
|
+
thread: threadValue,
|
|
27755
|
+
turns: [],
|
|
27756
|
+
...input.model ? { requestedModel: input.model } : {},
|
|
27757
|
+
...input.thinkingOptionId ? { requestedThinkingOptionId: input.thinkingOptionId } : {},
|
|
27758
|
+
...session.initialState.nativeRef ? {} : { restoredState: session.initialState }
|
|
27759
|
+
});
|
|
27760
|
+
const beforeRevision = thread.stateObserver.revision;
|
|
27761
|
+
await this.#startExternalTurn(thread, input.task, turnId);
|
|
27762
|
+
if (!thread.record.nativeSessionRef) {
|
|
27763
|
+
const deadline = Date.now() + NATIVE_REF_TIMEOUT_MS;
|
|
27764
|
+
let revision = beforeRevision;
|
|
27765
|
+
while (!thread.record.nativeSessionRef) {
|
|
27766
|
+
const remaining = deadline - Date.now();
|
|
27767
|
+
if (remaining <= 0) {
|
|
27768
|
+
throw new Error("Target Harness Native Session identity was not persisted");
|
|
27769
|
+
}
|
|
27770
|
+
await thread.stateObserver.waitForChange(revision, remaining);
|
|
27771
|
+
revision = thread.stateObserver.revision;
|
|
26837
27772
|
}
|
|
26838
|
-
await thread.stateObserver.waitForChange(revision, remaining);
|
|
26839
|
-
revision = thread.stateObserver.revision;
|
|
26840
27773
|
}
|
|
27774
|
+
await this.#repository.setDelegationStatus(delegationId, "running");
|
|
27775
|
+
await this.#notifyThreadStarted(thread.thread);
|
|
27776
|
+
return {
|
|
27777
|
+
...this.#result(delegationId, childThreadId, turnId, targetHarnessId, "running", {
|
|
27778
|
+
requested: {
|
|
27779
|
+
...input.model ? { model: input.model } : {},
|
|
27780
|
+
...input.thinkingOptionId ? { thinkingOptionId: input.thinkingOptionId } : {}
|
|
27781
|
+
},
|
|
27782
|
+
effective: {
|
|
27783
|
+
...thread.stateObserver.state.effectiveModel ? { effectiveModel: thread.stateObserver.state.effectiveModel } : {},
|
|
27784
|
+
...thread.stateObserver.state.resolvedModelLabel ? { resolvedModelLabel: thread.stateObserver.state.resolvedModelLabel } : {},
|
|
27785
|
+
...thread.stateObserver.state.effectiveThinkingOptionId ? {
|
|
27786
|
+
effectiveThinkingOptionId: thread.stateObserver.state.effectiveThinkingOptionId
|
|
27787
|
+
} : {}
|
|
27788
|
+
}
|
|
27789
|
+
}),
|
|
27790
|
+
cwd: record3.cwd,
|
|
27791
|
+
parentThreadId
|
|
27792
|
+
};
|
|
27793
|
+
} catch (error51) {
|
|
27794
|
+
if (session) await session.close().catch(() => void 0);
|
|
27795
|
+
this.#externalRuntime.remove(childThreadId);
|
|
27796
|
+
if (delegation)
|
|
27797
|
+
await this.#repository.removeDelegation(delegation.delegationId).catch(() => void 0);
|
|
27798
|
+
await this.#repository.removeThread(childThreadId).catch(() => void 0);
|
|
27799
|
+
if (error51 instanceof DelegationControlError) throw error51;
|
|
27800
|
+
throw new DelegationControlError(
|
|
27801
|
+
"DELEGATION_FAILED",
|
|
27802
|
+
error51 instanceof Error ? error51.message : String(error51)
|
|
27803
|
+
);
|
|
26841
27804
|
}
|
|
26842
|
-
|
|
26843
|
-
await this.#notifyThreadStarted(thread.thread);
|
|
26844
|
-
return {
|
|
26845
|
-
...this.#result(delegationId, childThreadId, turnId, targetHarnessId, "running", {
|
|
26846
|
-
requested: {
|
|
26847
|
-
...input.model ? { model: input.model } : {},
|
|
26848
|
-
...input.thinkingOptionId ? { thinkingOptionId: input.thinkingOptionId } : {}
|
|
26849
|
-
},
|
|
26850
|
-
effective: {
|
|
26851
|
-
...thread.stateObserver.state.effectiveModel ? { effectiveModel: thread.stateObserver.state.effectiveModel } : {},
|
|
26852
|
-
...thread.stateObserver.state.resolvedModelLabel ? { resolvedModelLabel: thread.stateObserver.state.resolvedModelLabel } : {},
|
|
26853
|
-
...thread.stateObserver.state.effectiveThinkingOptionId ? { effectiveThinkingOptionId: thread.stateObserver.state.effectiveThinkingOptionId } : {}
|
|
26854
|
-
}
|
|
26855
|
-
}),
|
|
26856
|
-
cwd: record3.cwd,
|
|
26857
|
-
parentThreadId
|
|
26858
|
-
};
|
|
26859
|
-
} catch (error51) {
|
|
26860
|
-
if (session) await session.close().catch(() => void 0);
|
|
26861
|
-
this.#externalRuntime.remove(childThreadId);
|
|
26862
|
-
if (delegation)
|
|
26863
|
-
await this.#repository.removeDelegation(delegation.delegationId).catch(() => void 0);
|
|
26864
|
-
await this.#repository.removeThread(childThreadId).catch(() => void 0);
|
|
26865
|
-
if (error51 instanceof DelegationControlError) throw error51;
|
|
26866
|
-
throw new DelegationControlError(
|
|
26867
|
-
"DELEGATION_FAILED",
|
|
26868
|
-
error51 instanceof Error ? error51.message : String(error51)
|
|
26869
|
-
);
|
|
26870
|
-
}
|
|
27805
|
+
});
|
|
26871
27806
|
}
|
|
26872
27807
|
async send(input) {
|
|
27808
|
+
return this.#externalRuntime.idleRelease.runOperation(input.threadId, () => this.#send(input));
|
|
27809
|
+
}
|
|
27810
|
+
async #send(input) {
|
|
26873
27811
|
if (!input.message?.trim()) {
|
|
26874
27812
|
throw new DelegationControlError("INVALID_ARGUMENT", "Message must not be empty");
|
|
26875
27813
|
}
|
|
@@ -26901,6 +27839,12 @@ var HarnessDelegationCoordinator = class {
|
|
|
26901
27839
|
return this.#turnResult(thread.id, turnId, thread.harnessId);
|
|
26902
27840
|
}
|
|
26903
27841
|
async cancel(input) {
|
|
27842
|
+
return this.#externalRuntime.idleRelease.runOperation(
|
|
27843
|
+
input.threadId,
|
|
27844
|
+
() => this.#cancel(input)
|
|
27845
|
+
);
|
|
27846
|
+
}
|
|
27847
|
+
async #cancel(input) {
|
|
26904
27848
|
const location = await this.#externalRuntime.locate(input.threadId);
|
|
26905
27849
|
if (location.kind === "official") return this.#cancelOfficial(input);
|
|
26906
27850
|
if (location.kind === "error") {
|
|
@@ -26925,6 +27869,9 @@ var HarnessDelegationCoordinator = class {
|
|
|
26925
27869
|
return { threadId: thread.id, turnId, harnessId: thread.harnessId, cancelled: true };
|
|
26926
27870
|
}
|
|
26927
27871
|
async read(input) {
|
|
27872
|
+
return this.#externalRuntime.idleRelease.runOperation(input.threadId, () => this.#read(input));
|
|
27873
|
+
}
|
|
27874
|
+
async #read(input) {
|
|
26928
27875
|
validateReadOptions(input);
|
|
26929
27876
|
const location = await this.#externalRuntime.locate(input.threadId);
|
|
26930
27877
|
if (location.kind === "official") return this.#readOfficial(input);
|
|
@@ -27134,7 +28081,7 @@ var HarnessDelegationCoordinator = class {
|
|
|
27134
28081
|
|
|
27135
28082
|
// packages/host-runtime/src/harness-plugin-loader.ts
|
|
27136
28083
|
import { readdir as readdir3, realpath as realpath2 } from "node:fs/promises";
|
|
27137
|
-
import
|
|
28084
|
+
import path10 from "node:path";
|
|
27138
28085
|
import { pathToFileURL } from "node:url";
|
|
27139
28086
|
|
|
27140
28087
|
// packages/host-runtime/src/harness-plugin-registry.ts
|
|
@@ -27172,16 +28119,16 @@ var HarnessPluginRegistry = class {
|
|
|
27172
28119
|
|
|
27173
28120
|
// packages/host-runtime/src/plugin-files.ts
|
|
27174
28121
|
import { open as open4, realpath, stat as stat2 } from "node:fs/promises";
|
|
27175
|
-
import
|
|
28122
|
+
import path9 from "node:path";
|
|
27176
28123
|
function inside(root, candidate) {
|
|
27177
|
-
const relative =
|
|
27178
|
-
return relative !== "" && !
|
|
28124
|
+
const relative = path9.relative(root, candidate);
|
|
28125
|
+
return relative !== "" && !path9.isAbsolute(relative) && relative !== ".." && !relative.startsWith(`..${path9.sep}`);
|
|
27179
28126
|
}
|
|
27180
28127
|
async function pluginResourcePath(root, relative) {
|
|
27181
|
-
if (
|
|
28128
|
+
if (path9.isAbsolute(relative) || !inside(root, path9.resolve(root, relative))) {
|
|
27182
28129
|
throw new Error("Plugin resource escapes its root");
|
|
27183
28130
|
}
|
|
27184
|
-
const resolved = await realpath(
|
|
28131
|
+
const resolved = await realpath(path9.resolve(root, relative));
|
|
27185
28132
|
if (!inside(root, resolved) || !(await stat2(resolved)).isFile()) {
|
|
27186
28133
|
throw new Error("Plugin resource must be a regular file inside its root");
|
|
27187
28134
|
}
|
|
@@ -27263,10 +28210,11 @@ function unavailableAdapter(descriptor, code) {
|
|
|
27263
28210
|
close: async () => void 0
|
|
27264
28211
|
};
|
|
27265
28212
|
}
|
|
27266
|
-
async function loadAdapter(candidate, context, timeoutMs, diagnose, warmup) {
|
|
28213
|
+
async function loadAdapter(candidate, context, timeoutMs, diagnose, warmup, signal) {
|
|
27267
28214
|
const { manifest } = candidate;
|
|
27268
28215
|
let expired = false;
|
|
27269
28216
|
let timer;
|
|
28217
|
+
let onAbort;
|
|
27270
28218
|
const operation = (async () => {
|
|
27271
28219
|
const entry = await pluginResourcePath(candidate.root, manifest.entry);
|
|
27272
28220
|
if (!/\.(?:mjs|js)$/u.test(entry))
|
|
@@ -27292,7 +28240,7 @@ async function loadAdapter(candidate, context, timeoutMs, diagnose, warmup) {
|
|
|
27292
28240
|
return value2;
|
|
27293
28241
|
})();
|
|
27294
28242
|
try {
|
|
27295
|
-
const
|
|
28243
|
+
const races = [
|
|
27296
28244
|
operation,
|
|
27297
28245
|
new Promise((_, reject) => {
|
|
27298
28246
|
timer = setTimeout(() => {
|
|
@@ -27300,15 +28248,31 @@ async function loadAdapter(candidate, context, timeoutMs, diagnose, warmup) {
|
|
|
27300
28248
|
reject(new PluginLoadTimeout());
|
|
27301
28249
|
}, timeoutMs);
|
|
27302
28250
|
})
|
|
27303
|
-
]
|
|
28251
|
+
];
|
|
28252
|
+
if (signal) {
|
|
28253
|
+
races.push(
|
|
28254
|
+
new Promise((_, reject) => {
|
|
28255
|
+
onAbort = () => {
|
|
28256
|
+
expired = true;
|
|
28257
|
+
reject(new PluginLoadCancelled());
|
|
28258
|
+
};
|
|
28259
|
+
if (signal.aborted) onAbort();
|
|
28260
|
+
else signal.addEventListener("abort", onAbort, { once: true });
|
|
28261
|
+
})
|
|
28262
|
+
);
|
|
28263
|
+
}
|
|
28264
|
+
const adapter = await Promise.race(races);
|
|
27304
28265
|
if (!adapter) throw new PluginLoadTimeout();
|
|
27305
28266
|
return adapter;
|
|
27306
28267
|
} finally {
|
|
27307
28268
|
if (timer) clearTimeout(timer);
|
|
28269
|
+
if (signal && onAbort) signal.removeEventListener("abort", onAbort);
|
|
27308
28270
|
}
|
|
27309
28271
|
}
|
|
27310
28272
|
var PluginLoadTimeout = class extends Error {
|
|
27311
28273
|
};
|
|
28274
|
+
var PluginLoadCancelled = class extends Error {
|
|
28275
|
+
};
|
|
27312
28276
|
async function loadHarnessPlugins(options2) {
|
|
27313
28277
|
const timeoutMs = options2.loadTimeoutMs ?? 1e4;
|
|
27314
28278
|
if (!Number.isSafeInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 6e4) {
|
|
@@ -27326,7 +28290,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
27326
28290
|
const enabledIds = /* @__PURE__ */ new Set();
|
|
27327
28291
|
const roots = /* @__PURE__ */ new Set();
|
|
27328
28292
|
for (const configuredRoot of options2.roots) {
|
|
27329
|
-
if (!
|
|
28293
|
+
if (!path10.isAbsolute(configuredRoot)) {
|
|
27330
28294
|
diagnose({ code: "invalidRoot" });
|
|
27331
28295
|
continue;
|
|
27332
28296
|
}
|
|
@@ -27356,7 +28320,7 @@ async function loadHarnessPlugins(options2) {
|
|
|
27356
28320
|
for (const directory of directories) {
|
|
27357
28321
|
try {
|
|
27358
28322
|
const file2 = await pluginResourcePath(root, `${directory.name}/manifest.json`);
|
|
27359
|
-
const pluginRoot = await realpath2(
|
|
28323
|
+
const pluginRoot = await realpath2(path10.join(root, directory.name));
|
|
27360
28324
|
await pluginResourcePath(pluginRoot, "manifest.json");
|
|
27361
28325
|
const manifest = harnessPluginManifestSchema.parse(
|
|
27362
28326
|
JSON.parse(
|
|
@@ -27394,13 +28358,15 @@ async function loadHarnessPlugins(options2) {
|
|
|
27394
28358
|
}
|
|
27395
28359
|
pending.push(candidate);
|
|
27396
28360
|
}
|
|
27397
|
-
|
|
28361
|
+
if (options2.signal?.aborted) return registry2;
|
|
27398
28362
|
let next = 0;
|
|
27399
28363
|
const loaded = /* @__PURE__ */ new Map();
|
|
27400
28364
|
const worker = async () => {
|
|
27401
28365
|
for (; ; ) {
|
|
28366
|
+
if (options2.signal?.aborted) return;
|
|
27402
28367
|
const candidate = pending[next++];
|
|
27403
28368
|
if (!candidate) return;
|
|
28369
|
+
if (options2.signal?.aborted) return;
|
|
27404
28370
|
const { manifest } = candidate;
|
|
27405
28371
|
const descriptor = harnessPluginDescriptorSchema.parse({
|
|
27406
28372
|
id: manifest.id,
|
|
@@ -27416,16 +28382,20 @@ async function loadHarnessPlugins(options2) {
|
|
|
27416
28382
|
} else {
|
|
27417
28383
|
try {
|
|
27418
28384
|
if (manifest.icon) descriptor.icon = await readPluginIcon(candidate.root, manifest.icon);
|
|
27419
|
-
const remaining = deadline - Date.now();
|
|
27420
|
-
if (remaining <= 0) throw new PluginLoadTimeout();
|
|
27421
28385
|
adapter = await loadAdapter(
|
|
27422
28386
|
candidate,
|
|
27423
28387
|
options2.context,
|
|
27424
|
-
|
|
28388
|
+
timeoutMs,
|
|
27425
28389
|
diagnose,
|
|
27426
|
-
options2.warmup !== false
|
|
28390
|
+
options2.warmup !== false,
|
|
28391
|
+
options2.signal
|
|
27427
28392
|
);
|
|
28393
|
+
if (options2.signal?.aborted) {
|
|
28394
|
+
await adapter.close().catch(() => diagnose({ id: manifest.id, code: "cleanupFailed" }));
|
|
28395
|
+
return;
|
|
28396
|
+
}
|
|
27428
28397
|
} catch (error51) {
|
|
28398
|
+
if (error51 instanceof PluginLoadCancelled) return;
|
|
27429
28399
|
failure = error51 instanceof PluginLoadTimeout ? "loadTimeout" : "loadFailed";
|
|
27430
28400
|
adapter = unavailableAdapter(descriptor, failure);
|
|
27431
28401
|
}
|
|
@@ -27633,7 +28603,7 @@ var SingleNativeCodexAccount = class {
|
|
|
27633
28603
|
|
|
27634
28604
|
// packages/host-runtime/src/account/codex-home-auth.ts
|
|
27635
28605
|
import { readFile as readFile5 } from "node:fs/promises";
|
|
27636
|
-
import
|
|
28606
|
+
import path11 from "node:path";
|
|
27637
28607
|
var CODEX_API_AUTH_IDENTITY_FALLBACK = "BANK OF TOKEN";
|
|
27638
28608
|
function tomlUnquote(value2) {
|
|
27639
28609
|
const trimmed = value2.trim();
|
|
@@ -27779,10 +28749,10 @@ function inspectCodexApiUsageSource(input) {
|
|
|
27779
28749
|
return { baseUrl, apiKey };
|
|
27780
28750
|
}
|
|
27781
28751
|
async function inspectCodexHomeAuth(codexHome) {
|
|
27782
|
-
const root =
|
|
28752
|
+
const root = path11.resolve(codexHome);
|
|
27783
28753
|
const [configToml, authJson] = await Promise.all([
|
|
27784
|
-
readOptionalUtf8(
|
|
27785
|
-
readOptionalUtf8(
|
|
28754
|
+
readOptionalUtf8(path11.join(root, "config.toml")),
|
|
28755
|
+
readOptionalUtf8(path11.join(root, "auth.json"))
|
|
27786
28756
|
]);
|
|
27787
28757
|
return inspectCodexAuthDocuments({
|
|
27788
28758
|
...configToml ? { configToml } : {},
|
|
@@ -27790,10 +28760,10 @@ async function inspectCodexHomeAuth(codexHome) {
|
|
|
27790
28760
|
});
|
|
27791
28761
|
}
|
|
27792
28762
|
async function inspectCodexHomeApiUsageSource(codexHome, env = process.env) {
|
|
27793
|
-
const root =
|
|
28763
|
+
const root = path11.resolve(codexHome);
|
|
27794
28764
|
const [configToml, authJson] = await Promise.all([
|
|
27795
|
-
readOptionalUtf8(
|
|
27796
|
-
readOptionalUtf8(
|
|
28765
|
+
readOptionalUtf8(path11.join(root, "config.toml")),
|
|
28766
|
+
readOptionalUtf8(path11.join(root, "auth.json"))
|
|
27797
28767
|
]);
|
|
27798
28768
|
return inspectCodexApiUsageSource({
|
|
27799
28769
|
...configToml ? { configToml } : {},
|
|
@@ -28835,25 +29805,25 @@ function resolveExternalSessionTreeIds(records) {
|
|
|
28835
29805
|
const resolve = (start) => {
|
|
28836
29806
|
const cached2 = resolved.get(start.hostThreadId);
|
|
28837
29807
|
if (cached2) return cached2;
|
|
28838
|
-
const
|
|
29808
|
+
const path26 = [];
|
|
28839
29809
|
const visited = /* @__PURE__ */ new Set();
|
|
28840
29810
|
let current = start;
|
|
28841
29811
|
while (true) {
|
|
28842
29812
|
const known = resolved.get(current.hostThreadId);
|
|
28843
29813
|
if (known) {
|
|
28844
|
-
for (const record3 of
|
|
29814
|
+
for (const record3 of path26) resolved.set(record3.hostThreadId, known);
|
|
28845
29815
|
return known;
|
|
28846
29816
|
}
|
|
28847
29817
|
if (visited.has(current.hostThreadId)) {
|
|
28848
29818
|
throw new Error("External Thread Fork tree contains a cycle");
|
|
28849
29819
|
}
|
|
28850
29820
|
visited.add(current.hostThreadId);
|
|
28851
|
-
|
|
29821
|
+
path26.push(current);
|
|
28852
29822
|
const sourceId = current.subagent?.parentHostThreadId ?? current.forkSource?.hostThreadId;
|
|
28853
29823
|
const source = sourceId ? byId.get(sourceId) : void 0;
|
|
28854
29824
|
if (!source) {
|
|
28855
29825
|
const root = current.hostThreadId;
|
|
28856
|
-
for (const record3 of
|
|
29826
|
+
for (const record3 of path26) resolved.set(record3.hostThreadId, root);
|
|
28857
29827
|
return root;
|
|
28858
29828
|
}
|
|
28859
29829
|
current = source;
|
|
@@ -29189,6 +30159,9 @@ function isHostApprovalRequestId(value2) {
|
|
|
29189
30159
|
function isHostQuestionRequestId(value2) {
|
|
29190
30160
|
return typeof value2 === "number" && Number.isSafeInteger(value2) && value2 >= HOST_QUESTION_REQUEST_ID_MIN && value2 <= HOST_QUESTION_REQUEST_ID_MAX;
|
|
29191
30161
|
}
|
|
30162
|
+
function jsonRpcResponseFailed(value2) {
|
|
30163
|
+
return value2.error != null;
|
|
30164
|
+
}
|
|
29192
30165
|
function classifyCreateRequestRoute(request, defaultAgent) {
|
|
29193
30166
|
const route = decodeCreateRoute(request);
|
|
29194
30167
|
if (!route) return null;
|
|
@@ -29291,6 +30264,9 @@ var AppServerHost = class {
|
|
|
29291
30264
|
#runningSubagentsByParent = /* @__PURE__ */ new Map();
|
|
29292
30265
|
#pendingExternalCommandRequests = /* @__PURE__ */ new Set();
|
|
29293
30266
|
#closeRequested = false;
|
|
30267
|
+
#pluginLoadAbort = new AbortController();
|
|
30268
|
+
#pluginLoading;
|
|
30269
|
+
#desktopRequests = new DesktopRequestQueue();
|
|
29294
30270
|
#drainActiveWorkOnInputEnd = false;
|
|
29295
30271
|
#desktopInputEnded = false;
|
|
29296
30272
|
constructor(options2) {
|
|
@@ -29302,7 +30278,7 @@ var AppServerHost = class {
|
|
|
29302
30278
|
};
|
|
29303
30279
|
this.#writer = new OrderedWriter(this.#options.desktopOutput);
|
|
29304
30280
|
const environment = this.#options.environment ?? process.env;
|
|
29305
|
-
const permanentHome =
|
|
30281
|
+
const permanentHome = path12.resolve(environment.CODEX_HOME ?? path12.join(os2.homedir(), ".codex"));
|
|
29306
30282
|
this.#ownsOfficialRuntimeScope = options2.officialRuntimeScope === void 0;
|
|
29307
30283
|
this.#officialRuntimeScope = options2.officialRuntimeScope ?? new OfficialRuntimeScope({
|
|
29308
30284
|
diagnosticOutput: this.#options.diagnosticOutput,
|
|
@@ -29373,7 +30349,24 @@ var AppServerHost = class {
|
|
|
29373
30349
|
environment: this.#options.environment ?? process.env,
|
|
29374
30350
|
repository: this.#repository,
|
|
29375
30351
|
consumeOutputs: (thread) => this.#consumeHarnessOutputs(thread),
|
|
29376
|
-
diagnose: (error51) => this.#diagnose(error51)
|
|
30352
|
+
diagnose: (error51) => this.#diagnose(error51),
|
|
30353
|
+
subagentRunning: (threadId2) => this.#subagentThreadStatuses.get(threadId2) === "active",
|
|
30354
|
+
idleRelease: {
|
|
30355
|
+
queue: this.#desktopRequests,
|
|
30356
|
+
onClosed: async (thread) => {
|
|
30357
|
+
for (const pending of [...this.#pendingDesktopApprovals.values()]) {
|
|
30358
|
+
if (pending.thread === thread)
|
|
30359
|
+
await this.#resolveDesktopApproval(pending.interaction.interactionId);
|
|
30360
|
+
}
|
|
30361
|
+
for (const pending of [...this.#pendingDesktopQuestions.values()]) {
|
|
30362
|
+
if (pending.thread === thread)
|
|
30363
|
+
await this.#resolveDesktopQuestion(pending.interaction.interactionId);
|
|
30364
|
+
}
|
|
30365
|
+
},
|
|
30366
|
+
canRelease: (thread) => !this.#hasRunningSubagents(thread.id) && !this.#externalSteering.hasPending(thread.id) && !this.#pendingExternalCommandRequests.has(thread.id) && ![...this.#pendingDesktopApprovals.values()].some(
|
|
30367
|
+
(pending) => pending.thread === thread
|
|
30368
|
+
) && ![...this.#pendingDesktopQuestions.values()].some((pending) => pending.thread === thread)
|
|
30369
|
+
}
|
|
29377
30370
|
});
|
|
29378
30371
|
this.#delegationCoordinator = new HarnessDelegationCoordinator({
|
|
29379
30372
|
adapters: this.#externalAdapters,
|
|
@@ -29393,14 +30386,14 @@ var AppServerHost = class {
|
|
|
29393
30386
|
activeOfficialParents: () => [...this.#activeOfficialTurns.keys()]
|
|
29394
30387
|
});
|
|
29395
30388
|
const unregisterDelegationApi = options2.onDelegationApi?.({
|
|
29396
|
-
listHarnesses: () => this.#delegationCoordinator.listHarnesses(),
|
|
29397
|
-
inspect: (input) => this.#delegationCoordinator.inspect(input),
|
|
29398
|
-
start: (input) => this.#delegationCoordinator.start(input),
|
|
29399
|
-
send: (input) => this.#delegationCoordinator.send(input),
|
|
29400
|
-
cancel: (input) => this.#delegationCoordinator.cancel(input),
|
|
29401
|
-
read: (input) => this.#delegationCoordinator.read(input),
|
|
29402
|
-
wait: (input) => this.#delegationCoordinator.wait(input),
|
|
29403
|
-
list: (input) => this.#delegationCoordinator.list(input),
|
|
30389
|
+
listHarnesses: () => this.#waitForPlugins().then(() => this.#delegationCoordinator.listHarnesses()),
|
|
30390
|
+
inspect: (input) => this.#waitForPlugins().then(() => this.#delegationCoordinator.inspect(input)),
|
|
30391
|
+
start: (input) => this.#waitForPlugins().then(() => this.#delegationCoordinator.start(input)),
|
|
30392
|
+
send: (input) => this.#waitForPlugins().then(() => this.#delegationCoordinator.send(input)),
|
|
30393
|
+
cancel: (input) => this.#waitForPlugins().then(() => this.#delegationCoordinator.cancel(input)),
|
|
30394
|
+
read: (input) => this.#waitForPlugins().then(() => this.#delegationCoordinator.read(input)),
|
|
30395
|
+
wait: (input) => this.#waitForPlugins().then(() => this.#delegationCoordinator.wait(input)),
|
|
30396
|
+
list: (input) => this.#waitForPlugins().then(() => this.#delegationCoordinator.list(input)),
|
|
29404
30397
|
canHandleStart: (input) => this.#canHandleDelegationStart(input),
|
|
29405
30398
|
ownsThread: (threadId2) => this.#ownsDelegationThread(threadId2)
|
|
29406
30399
|
});
|
|
@@ -29409,6 +30402,8 @@ var AppServerHost = class {
|
|
|
29409
30402
|
close() {
|
|
29410
30403
|
if (this.#closeRequested) return;
|
|
29411
30404
|
this.#closeRequested = true;
|
|
30405
|
+
this.#externalRuntime.idleRelease.disable();
|
|
30406
|
+
this.#pluginLoadAbort.abort();
|
|
29412
30407
|
this.#externalSteering.close();
|
|
29413
30408
|
this.#signalActiveWorkChanged();
|
|
29414
30409
|
this.#options.desktopInput.destroy();
|
|
@@ -29427,25 +30422,38 @@ var AppServerHost = class {
|
|
|
29427
30422
|
if (typeof desktopInput.end === "function") desktopInput.end();
|
|
29428
30423
|
else desktopInput.destroy();
|
|
29429
30424
|
}
|
|
30425
|
+
#waitForPlugins() {
|
|
30426
|
+
return this.#pluginLoading ??= this.#loadInstalledPlugins().catch((error51) => {
|
|
30427
|
+
this.#diagnose(`Harness plugin load failed: ${errorMessage3(error51)}`);
|
|
30428
|
+
});
|
|
30429
|
+
}
|
|
30430
|
+
async #loadInstalledPlugins() {
|
|
30431
|
+
if (!this.#options.pluginRoots || this.#pluginLoadAbort.signal.aborted) return;
|
|
30432
|
+
const plugins = await loadHarnessPlugins({
|
|
30433
|
+
roots: this.#options.pluginRoots,
|
|
30434
|
+
context: this.#options.pluginContext ?? {
|
|
30435
|
+
environment: this.#options.environment ?? process.env,
|
|
30436
|
+
platform: process.platform,
|
|
30437
|
+
managedRemoteHost: false
|
|
30438
|
+
},
|
|
30439
|
+
reservedIds: new Set(this.#externalAdapters.keys()),
|
|
30440
|
+
signal: this.#pluginLoadAbort.signal,
|
|
30441
|
+
diagnose: (diagnostic) => this.#diagnose(`Harness plugin: ${JSON.stringify(diagnostic)}`)
|
|
30442
|
+
});
|
|
30443
|
+
if (this.#pluginLoadAbort.signal.aborted) {
|
|
30444
|
+
await plugins.close().catch((error51) => this.#diagnose(error51));
|
|
30445
|
+
return;
|
|
30446
|
+
}
|
|
30447
|
+
this.#pluginDescriptors = plugins.list();
|
|
30448
|
+
for (const [id2, adapter] of plugins.adapters) this.#externalAdapters.set(id2, adapter);
|
|
30449
|
+
}
|
|
29430
30450
|
async run() {
|
|
29431
30451
|
try {
|
|
29432
|
-
if (this.#options.pluginRoots) {
|
|
29433
|
-
const plugins = await loadHarnessPlugins({
|
|
29434
|
-
roots: this.#options.pluginRoots,
|
|
29435
|
-
context: this.#options.pluginContext ?? {
|
|
29436
|
-
environment: this.#options.environment ?? process.env,
|
|
29437
|
-
platform: process.platform,
|
|
29438
|
-
managedRemoteHost: false
|
|
29439
|
-
},
|
|
29440
|
-
reservedIds: new Set(this.#externalAdapters.keys()),
|
|
29441
|
-
diagnose: (diagnostic) => this.#diagnose(`Harness plugin: ${JSON.stringify(diagnostic)}`)
|
|
29442
|
-
});
|
|
29443
|
-
this.#pluginDescriptors = plugins.list();
|
|
29444
|
-
for (const [id2, adapter] of plugins.adapters) this.#externalAdapters.set(id2, adapter);
|
|
29445
|
-
}
|
|
29446
30452
|
await this.#repository.initialize();
|
|
29447
30453
|
} catch (error51) {
|
|
29448
30454
|
this.#diagnose(`Host initialization failed: ${errorMessage3(error51)}`);
|
|
30455
|
+
this.#pluginLoadAbort.abort();
|
|
30456
|
+
await this.#pluginLoading;
|
|
29449
30457
|
await Promise.allSettled(
|
|
29450
30458
|
[...new Set(this.#externalAdapters.values())].map(
|
|
29451
30459
|
(adapter) => Promise.resolve().then(() => adapter.close())
|
|
@@ -29469,6 +30477,7 @@ var AppServerHost = class {
|
|
|
29469
30477
|
await this.#officialRuntimeScope.owner.stop().catch((closeError) => this.#diagnose(closeError));
|
|
29470
30478
|
}
|
|
29471
30479
|
}
|
|
30480
|
+
void this.#waitForPlugins();
|
|
29472
30481
|
if (this.#closeRequested) await this.#closeOfficialRuntime();
|
|
29473
30482
|
try {
|
|
29474
30483
|
void this.#officialRuntime.failure().then(async () => {
|
|
@@ -29483,7 +30492,12 @@ var AppServerHost = class {
|
|
|
29483
30492
|
await this.#closeOfficialRuntime();
|
|
29484
30493
|
return this.#closeRequested ? 0 : 1;
|
|
29485
30494
|
} finally {
|
|
30495
|
+
this.#pluginLoadAbort.abort();
|
|
29486
30496
|
this.#externalSteering.close();
|
|
30497
|
+
await this.#desktopRequests.drain();
|
|
30498
|
+
this.#externalRuntime.idleRelease.stop();
|
|
30499
|
+
await this.#externalRuntime.idleRelease.drain();
|
|
30500
|
+
await this.#pluginLoading;
|
|
29487
30501
|
const threads = this.#externalRuntime.values();
|
|
29488
30502
|
await Promise.allSettled(threads.map(({ session }) => session.close()));
|
|
29489
30503
|
await Promise.allSettled(threads.map(({ outputTask }) => outputTask));
|
|
@@ -29573,454 +30587,486 @@ var AppServerHost = class {
|
|
|
29573
30587
|
}
|
|
29574
30588
|
continue;
|
|
29575
30589
|
}
|
|
29576
|
-
|
|
29577
|
-
|
|
29578
|
-
|
|
29579
|
-
|
|
29580
|
-
|
|
29581
|
-
|
|
29582
|
-
|
|
30590
|
+
const threadId2 = isRecord14(request.params) && typeof request.params.threadId === "string" ? request.params.threadId : void 0;
|
|
30591
|
+
this.#dispatchDesktopRequest(
|
|
30592
|
+
() => this.#desktopRequests.run(
|
|
30593
|
+
threadId2,
|
|
30594
|
+
() => this.#externalRuntime.idleRelease.runOperation(
|
|
30595
|
+
threadId2,
|
|
30596
|
+
() => this.#handleDesktopRequest(request, frame)
|
|
30597
|
+
)
|
|
30598
|
+
)
|
|
30599
|
+
);
|
|
30600
|
+
}
|
|
30601
|
+
this.#desktopInputEnded = true;
|
|
30602
|
+
this.#externalRuntime.idleRelease.disable();
|
|
30603
|
+
this.#pluginLoadAbort.abort();
|
|
30604
|
+
await this.#desktopRequests.drain();
|
|
30605
|
+
this.#externalSteering.close();
|
|
30606
|
+
if (this.#drainActiveWorkOnInputEnd) await this.#waitForActiveWorkToDrain();
|
|
30607
|
+
await this.#closeOfficialRuntime();
|
|
30608
|
+
}
|
|
30609
|
+
async #handleDesktopRequest(request, frame) {
|
|
30610
|
+
if (this.#closeRequested) return;
|
|
30611
|
+
if (request.method === LOADED_SESSIONS_METHOD) {
|
|
30612
|
+
await this.#writer.json(
|
|
30613
|
+
rpcEnvelope(request, { result: this.#externalRuntime.idleRelease.list() })
|
|
30614
|
+
);
|
|
30615
|
+
return;
|
|
30616
|
+
}
|
|
30617
|
+
if (request.method === IDLE_RELEASE_SETTINGS_METHOD) {
|
|
30618
|
+
const parsed = idleReleaseSettingsSchema.safeParse(request.params);
|
|
30619
|
+
if (!parsed.success) {
|
|
30620
|
+
await this.#writer.json(rpcError(request, -32602, "Invalid idle release settings"));
|
|
30621
|
+
} else {
|
|
30622
|
+
const settings = this.#externalRuntime.idleRelease.configure(parsed.data);
|
|
30623
|
+
await this.#writer.json(rpcEnvelope(request, { result: settings }));
|
|
29583
30624
|
}
|
|
29584
|
-
|
|
29585
|
-
|
|
29586
|
-
|
|
29587
|
-
|
|
29588
|
-
|
|
29589
|
-
|
|
29590
|
-
|
|
29591
|
-
|
|
29592
|
-
|
|
29593
|
-
|
|
29594
|
-
|
|
30625
|
+
return;
|
|
30626
|
+
}
|
|
30627
|
+
if (request.method === "codexhost/update/check" || request.method === "codexhost/update/start" || request.method === "codexhost/update/status") {
|
|
30628
|
+
this.#dispatchDesktopRequest(() => this.#handleUpdateRequest(request));
|
|
30629
|
+
return;
|
|
30630
|
+
}
|
|
30631
|
+
if (request.method === "codexhost/account/usage/inspect" || request.method === "codexhost/account/list" || request.method === "codexhost/account/refresh") {
|
|
30632
|
+
this.#dispatchDesktopRequest(() => this.#handleCodexAccountRequest(request));
|
|
30633
|
+
return;
|
|
30634
|
+
}
|
|
30635
|
+
if (request.method === "codexhost/harness/accounts/sources") {
|
|
30636
|
+
this.#dispatchDesktopRequest(async () => {
|
|
30637
|
+
if (!harnessAccountSourceListParamsSchema.safeParse(request.params).success) {
|
|
30638
|
+
await this.#writer.json(
|
|
30639
|
+
rpcError(request, -32602, "Invalid Harness account source list params")
|
|
29595
30640
|
);
|
|
29596
|
-
|
|
29597
|
-
}
|
|
29598
|
-
|
|
29599
|
-
|
|
29600
|
-
|
|
29601
|
-
|
|
29602
|
-
|
|
29603
|
-
|
|
29604
|
-
|
|
29605
|
-
|
|
29606
|
-
|
|
29607
|
-
|
|
29608
|
-
|
|
29609
|
-
|
|
29610
|
-
|
|
29611
|
-
|
|
29612
|
-
|
|
29613
|
-
);
|
|
29614
|
-
return;
|
|
29615
|
-
}
|
|
29616
|
-
const result = harnessAccountInspectResultSchema.parse(
|
|
29617
|
-
await this.#inspectHarnessAccount(adapter, params.data.refresh === true)
|
|
30641
|
+
return;
|
|
30642
|
+
}
|
|
30643
|
+
await this.#waitForPlugins();
|
|
30644
|
+
const result = listHarnessAccountSources(
|
|
30645
|
+
this.#externalAdapters.values(),
|
|
30646
|
+
this.#pluginDescriptors
|
|
30647
|
+
);
|
|
30648
|
+
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
30649
|
+
});
|
|
30650
|
+
return;
|
|
30651
|
+
}
|
|
30652
|
+
if (request.method === "codexhost/harness/accounts/inspect") {
|
|
30653
|
+
this.#dispatchDesktopRequest(async () => {
|
|
30654
|
+
const params = harnessAccountInspectParamsSchema.safeParse(request.params);
|
|
30655
|
+
if (!params.success) {
|
|
30656
|
+
await this.#writer.json(
|
|
30657
|
+
rpcError(request, -32602, "Invalid Harness account inspection params")
|
|
29618
30658
|
);
|
|
29619
|
-
|
|
29620
|
-
}
|
|
29621
|
-
|
|
29622
|
-
|
|
29623
|
-
|
|
29624
|
-
|
|
29625
|
-
|
|
29626
|
-
if (!params.success) {
|
|
29627
|
-
await this.#writer.json(
|
|
29628
|
-
rpcError(request, -32602, "Invalid Harness account list params")
|
|
29629
|
-
);
|
|
29630
|
-
return;
|
|
29631
|
-
}
|
|
29632
|
-
const inspections = await Promise.all(
|
|
29633
|
-
[...this.#externalAdapters.values()].map(
|
|
29634
|
-
(adapter) => this.#inspectHarnessAccount(adapter, params.data.refresh === true)
|
|
29635
|
-
)
|
|
30659
|
+
return;
|
|
30660
|
+
}
|
|
30661
|
+
await this.#waitForPlugins();
|
|
30662
|
+
const adapter = this.#externalAdapters.get(params.data.harnessId);
|
|
30663
|
+
if (!adapter) {
|
|
30664
|
+
await this.#writer.json(
|
|
30665
|
+
rpcError(request, -32077, `Harness '${params.data.harnessId}' is unavailable`)
|
|
29636
30666
|
);
|
|
29637
|
-
|
|
29638
|
-
|
|
29639
|
-
|
|
29640
|
-
|
|
29641
|
-
|
|
29642
|
-
|
|
29643
|
-
|
|
29644
|
-
|
|
29645
|
-
|
|
29646
|
-
|
|
29647
|
-
|
|
29648
|
-
|
|
29649
|
-
|
|
29650
|
-
|
|
29651
|
-
|
|
29652
|
-
|
|
29653
|
-
|
|
29654
|
-
|
|
29655
|
-
|
|
29656
|
-
|
|
29657
|
-
|
|
29658
|
-
|
|
29659
|
-
|
|
29660
|
-
|
|
29661
|
-
|
|
29662
|
-
|
|
29663
|
-
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
30667
|
+
return;
|
|
30668
|
+
}
|
|
30669
|
+
const result = harnessAccountInspectResultSchema.parse(
|
|
30670
|
+
await this.#inspectHarnessAccount(adapter, params.data.refresh === true)
|
|
30671
|
+
);
|
|
30672
|
+
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
30673
|
+
});
|
|
30674
|
+
return;
|
|
30675
|
+
}
|
|
30676
|
+
if (request.method === "codexhost/harness/accounts/list") {
|
|
30677
|
+
this.#dispatchDesktopRequest(async () => {
|
|
30678
|
+
const params = harnessAccountListParamsSchema.safeParse(request.params);
|
|
30679
|
+
if (!params.success) {
|
|
30680
|
+
await this.#writer.json(rpcError(request, -32602, "Invalid Harness account list params"));
|
|
30681
|
+
return;
|
|
30682
|
+
}
|
|
30683
|
+
await this.#waitForPlugins();
|
|
30684
|
+
const inspections = await Promise.all(
|
|
30685
|
+
[...this.#externalAdapters.values()].map(
|
|
30686
|
+
(adapter) => this.#inspectHarnessAccount(adapter, params.data.refresh === true)
|
|
30687
|
+
)
|
|
30688
|
+
);
|
|
30689
|
+
const result = harnessAccountListResultSchema.parse({
|
|
30690
|
+
accounts: inspections.flatMap(
|
|
30691
|
+
({ harnessId, harnessName: harnessName2, account }) => account ? [{ ...account, harnessId, harnessName: harnessName2 }] : []
|
|
30692
|
+
)
|
|
29664
30693
|
});
|
|
29665
|
-
|
|
29666
|
-
}
|
|
29667
|
-
|
|
29668
|
-
|
|
29669
|
-
|
|
29670
|
-
|
|
29671
|
-
|
|
29672
|
-
|
|
29673
|
-
|
|
30694
|
+
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
30695
|
+
});
|
|
30696
|
+
return;
|
|
30697
|
+
}
|
|
30698
|
+
if (request.method === "codexhost/harness/inspect") {
|
|
30699
|
+
this.#dispatchDesktopRequest(() => this.#inspectHarness(request));
|
|
30700
|
+
return;
|
|
30701
|
+
}
|
|
30702
|
+
if (request.method === "codexhost/harness/web-ui/open") {
|
|
30703
|
+
this.#dispatchDesktopRequest(() => this.#openHarnessWebUi(request));
|
|
30704
|
+
return;
|
|
30705
|
+
}
|
|
30706
|
+
if (request.method === "codexhost/harness/plugins/list") {
|
|
30707
|
+
this.#dispatchDesktopRequest(async () => {
|
|
30708
|
+
if (!harnessPluginListParamsSchema.safeParse(request.params).success) {
|
|
30709
|
+
await this.#writer.json(rpcError(request, -32602, "Invalid Harness plugin list params"));
|
|
30710
|
+
return;
|
|
30711
|
+
}
|
|
30712
|
+
await this.#waitForPlugins();
|
|
30713
|
+
const result = harnessPluginListResultSchema.parse({ plugins: this.#pluginDescriptors });
|
|
30714
|
+
await this.#writer.json(rpcEnvelope(request, { result: jsonValueSchema.parse(result) }));
|
|
30715
|
+
});
|
|
30716
|
+
return;
|
|
30717
|
+
}
|
|
30718
|
+
if (isSessionImportRequest(request.method)) {
|
|
30719
|
+
this.#dispatchDesktopRequest(() => this.#handleSessionImport(request));
|
|
30720
|
+
return;
|
|
30721
|
+
}
|
|
30722
|
+
if (request.method === "codexhost/thread/fork") {
|
|
30723
|
+
await this.#forkExternalThreadFromRenderer(request);
|
|
30724
|
+
return;
|
|
30725
|
+
}
|
|
30726
|
+
if (request.method === "codexhost/thread/inspect") {
|
|
30727
|
+
await this.#inspectThread(request);
|
|
30728
|
+
return;
|
|
30729
|
+
}
|
|
30730
|
+
if (request.method === "codexhost/thread/usage/inspect") {
|
|
30731
|
+
await this.#inspectThreadUsage(request);
|
|
30732
|
+
return;
|
|
30733
|
+
}
|
|
30734
|
+
if (request.method === "codexhost/thread/ownership/list") {
|
|
30735
|
+
await this.#listThreadOwnership(request);
|
|
30736
|
+
return;
|
|
30737
|
+
}
|
|
30738
|
+
if (request.method === "codexhost/thread/model/select") {
|
|
30739
|
+
await this.#selectThreadModel(request);
|
|
30740
|
+
return;
|
|
30741
|
+
}
|
|
30742
|
+
if (request.method === "codexhost/thread/thinking/select") {
|
|
30743
|
+
await this.#selectThreadThinking(request);
|
|
30744
|
+
return;
|
|
30745
|
+
}
|
|
30746
|
+
if (request.method === "codexhost/thread/permission-mode/select") {
|
|
30747
|
+
await this.#selectThreadPermissionMode(request);
|
|
30748
|
+
return;
|
|
30749
|
+
}
|
|
30750
|
+
if (request.method === "codexhost/harness/commands/inspect") {
|
|
30751
|
+
const params = harnessCommandsInspectParamsSchema.safeParse(request.params);
|
|
30752
|
+
if (!params.success) {
|
|
30753
|
+
await this.#writer.json(
|
|
30754
|
+
rpcError(request, -32602, "Invalid Harness command inspection params")
|
|
30755
|
+
);
|
|
30756
|
+
} else {
|
|
30757
|
+
await this.#writeHarnessCommandCatalog(request, params.data.harnessId);
|
|
29674
30758
|
}
|
|
29675
|
-
|
|
29676
|
-
|
|
29677
|
-
|
|
30759
|
+
return;
|
|
30760
|
+
}
|
|
30761
|
+
if (request.method === "codexhost/thread/commands/inspect") {
|
|
30762
|
+
await this.#inspectThreadCommands(request);
|
|
30763
|
+
return;
|
|
30764
|
+
}
|
|
30765
|
+
if (request.method === "codexhost/thread/command/execute") {
|
|
30766
|
+
await this.#executeThreadCommand(request);
|
|
30767
|
+
return;
|
|
30768
|
+
}
|
|
30769
|
+
if (request.method === "thread/list") {
|
|
30770
|
+
let listRequest;
|
|
30771
|
+
try {
|
|
30772
|
+
const decoded = decodeThreadListRequest(request);
|
|
30773
|
+
if (!decoded) throw new Error("Expected thread/list request");
|
|
30774
|
+
listRequest = decoded;
|
|
30775
|
+
} catch (error51) {
|
|
30776
|
+
await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
|
|
30777
|
+
return;
|
|
29678
30778
|
}
|
|
29679
|
-
if (
|
|
29680
|
-
await this.#
|
|
29681
|
-
|
|
30779
|
+
if (!listRequest.supportsExternal) {
|
|
30780
|
+
await this.#forwardOfficialRequest(request, frame);
|
|
30781
|
+
return;
|
|
29682
30782
|
}
|
|
29683
|
-
|
|
29684
|
-
|
|
29685
|
-
|
|
30783
|
+
this.#dispatchDesktopRequest(() => this.#listThreads(request, listRequest));
|
|
30784
|
+
return;
|
|
30785
|
+
}
|
|
30786
|
+
if (request.method === "thread/archive" || request.method === "thread/unarchive") {
|
|
30787
|
+
let threadId2;
|
|
30788
|
+
try {
|
|
30789
|
+
const decoded = decodeThreadArchiveRequest(request);
|
|
30790
|
+
if (!decoded) throw new Error(`Expected ${request.method} request`);
|
|
30791
|
+
threadId2 = decoded.threadId;
|
|
30792
|
+
} catch (error51) {
|
|
30793
|
+
await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
|
|
30794
|
+
return;
|
|
29686
30795
|
}
|
|
29687
|
-
|
|
29688
|
-
|
|
29689
|
-
|
|
30796
|
+
const location = await this.#locateExternalThread(threadId2);
|
|
30797
|
+
if (await this.#writeResolutionError(request, location)) return;
|
|
30798
|
+
if (location.kind === "official") {
|
|
30799
|
+
await this.#forwardOfficialRequest(request, frame);
|
|
30800
|
+
return;
|
|
29690
30801
|
}
|
|
29691
|
-
if (
|
|
29692
|
-
await this.#
|
|
29693
|
-
|
|
30802
|
+
if (location.kind === "external") {
|
|
30803
|
+
await this.#setExternalThreadArchived(
|
|
30804
|
+
request,
|
|
30805
|
+
location,
|
|
30806
|
+
request.method === "thread/archive"
|
|
30807
|
+
);
|
|
29694
30808
|
}
|
|
29695
|
-
|
|
29696
|
-
|
|
29697
|
-
|
|
30809
|
+
return;
|
|
30810
|
+
}
|
|
30811
|
+
if (request.method === "thread/metadata/update") {
|
|
30812
|
+
let threadId2;
|
|
30813
|
+
let decoded;
|
|
30814
|
+
try {
|
|
30815
|
+
const parsed = decodeThreadMetadataUpdateRequest(request);
|
|
30816
|
+
if (!parsed) throw new Error("Expected thread/metadata/update request");
|
|
30817
|
+
decoded = parsed;
|
|
30818
|
+
threadId2 = decoded.threadId;
|
|
30819
|
+
} catch (error51) {
|
|
30820
|
+
await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
|
|
30821
|
+
return;
|
|
29698
30822
|
}
|
|
29699
|
-
|
|
29700
|
-
|
|
29701
|
-
|
|
29702
|
-
|
|
29703
|
-
|
|
29704
|
-
);
|
|
29705
|
-
} else {
|
|
29706
|
-
await this.#writeHarnessCommandCatalog(request, params.data.harnessId);
|
|
29707
|
-
}
|
|
29708
|
-
continue;
|
|
30823
|
+
const location = await this.#locateExternalThread(threadId2);
|
|
30824
|
+
if (await this.#writeResolutionError(request, location)) return;
|
|
30825
|
+
if (location.kind === "official") {
|
|
30826
|
+
await this.#forwardOfficialRequest(request, frame);
|
|
30827
|
+
return;
|
|
29709
30828
|
}
|
|
29710
|
-
if (
|
|
29711
|
-
|
|
29712
|
-
|
|
30829
|
+
if (location.kind !== "external") return;
|
|
30830
|
+
if (decoded.isPinned === void 0 || decoded.gitInfo !== void 0) {
|
|
30831
|
+
await this.#writer.json(
|
|
30832
|
+
rpcError(request, -32078, "External Thread metadata updates are unsupported")
|
|
30833
|
+
);
|
|
30834
|
+
return;
|
|
29713
30835
|
}
|
|
29714
|
-
|
|
29715
|
-
|
|
29716
|
-
|
|
30836
|
+
await this.#setExternalThreadPinned(request, location, decoded.isPinned ?? false);
|
|
30837
|
+
return;
|
|
30838
|
+
}
|
|
30839
|
+
let createRoute;
|
|
30840
|
+
try {
|
|
30841
|
+
createRoute = classifyCreateRequestRoute(request, this.#options.defaultAgent);
|
|
30842
|
+
} catch (error51) {
|
|
30843
|
+
await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
|
|
30844
|
+
return;
|
|
30845
|
+
}
|
|
30846
|
+
if (createRoute) {
|
|
30847
|
+
this.#options.onCreateRequestRoute?.(createRoute);
|
|
30848
|
+
this.#options.onRequestRoute?.(
|
|
30849
|
+
this.#routeObservationTracker.registerCreate(
|
|
30850
|
+
request.id,
|
|
30851
|
+
createRoute,
|
|
30852
|
+
classifyThreadPurpose(request)
|
|
30853
|
+
)
|
|
30854
|
+
);
|
|
30855
|
+
}
|
|
30856
|
+
if (createRoute && createRoute.selectedHarness !== "codex") {
|
|
30857
|
+
await this.#startExternalThread(request, createRoute.selectedHarness);
|
|
30858
|
+
return;
|
|
30859
|
+
}
|
|
30860
|
+
if (request.method === "thread/fork") {
|
|
30861
|
+
const params = isRecord14(request.params) ? request.params : {};
|
|
30862
|
+
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
30863
|
+
if (resolution.kind === "error") {
|
|
30864
|
+
await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
|
|
30865
|
+
return;
|
|
29717
30866
|
}
|
|
29718
|
-
if (
|
|
29719
|
-
let
|
|
30867
|
+
if (resolution.kind === "external") {
|
|
30868
|
+
let fork;
|
|
29720
30869
|
try {
|
|
29721
|
-
const decoded =
|
|
29722
|
-
if (!decoded) throw new Error("Expected thread/
|
|
29723
|
-
|
|
30870
|
+
const decoded = decodeThreadForkRequest(request);
|
|
30871
|
+
if (!decoded) throw new Error("Expected thread/fork request");
|
|
30872
|
+
fork = decoded;
|
|
29724
30873
|
} catch (error51) {
|
|
29725
30874
|
await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
|
|
29726
|
-
|
|
29727
|
-
}
|
|
29728
|
-
if (!listRequest.supportsExternal) {
|
|
29729
|
-
await this.#forwardOfficialRequest(request, frame);
|
|
29730
|
-
continue;
|
|
30875
|
+
return;
|
|
29731
30876
|
}
|
|
29732
|
-
|
|
29733
|
-
|
|
30877
|
+
await this.#forkExternalThread(request, resolution.thread, fork);
|
|
30878
|
+
return;
|
|
29734
30879
|
}
|
|
29735
|
-
|
|
29736
|
-
|
|
30880
|
+
}
|
|
30881
|
+
if (request.method === "thread/revert") {
|
|
30882
|
+
const params = isRecord14(request.params) ? request.params : {};
|
|
30883
|
+
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
30884
|
+
if (resolution.kind === "error") {
|
|
30885
|
+
await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
|
|
30886
|
+
return;
|
|
30887
|
+
}
|
|
30888
|
+
if (resolution.kind === "external") {
|
|
30889
|
+
let revert;
|
|
29737
30890
|
try {
|
|
29738
|
-
const decoded =
|
|
29739
|
-
if (!decoded) throw new Error(
|
|
29740
|
-
|
|
30891
|
+
const decoded = decodeThreadRevertRequest(request);
|
|
30892
|
+
if (!decoded) throw new Error("Expected thread/revert request");
|
|
30893
|
+
revert = decoded;
|
|
29741
30894
|
} catch (error51) {
|
|
29742
30895
|
await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
|
|
29743
|
-
|
|
29744
|
-
}
|
|
29745
|
-
const location = await this.#locateExternalThread(threadId2);
|
|
29746
|
-
if (await this.#writeResolutionError(request, location)) continue;
|
|
29747
|
-
if (location.kind === "official") {
|
|
29748
|
-
await this.#forwardOfficialRequest(request, frame);
|
|
29749
|
-
continue;
|
|
29750
|
-
}
|
|
29751
|
-
if (location.kind === "external") {
|
|
29752
|
-
await this.#setExternalThreadArchived(
|
|
29753
|
-
request,
|
|
29754
|
-
location,
|
|
29755
|
-
request.method === "thread/archive"
|
|
29756
|
-
);
|
|
30896
|
+
return;
|
|
29757
30897
|
}
|
|
29758
|
-
|
|
30898
|
+
await this.#revertExternalThread(request, resolution.thread, revert);
|
|
30899
|
+
return;
|
|
30900
|
+
}
|
|
30901
|
+
}
|
|
30902
|
+
if (request.method === "thread/rollback") {
|
|
30903
|
+
const params = isRecord14(request.params) ? request.params : {};
|
|
30904
|
+
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
30905
|
+
if (resolution.kind === "error") {
|
|
30906
|
+
await this.#writer.json(rpcError(request, resolution.error.code, resolution.error.message));
|
|
30907
|
+
return;
|
|
29759
30908
|
}
|
|
29760
|
-
if (
|
|
29761
|
-
let
|
|
29762
|
-
let decoded;
|
|
30909
|
+
if (resolution.kind === "external") {
|
|
30910
|
+
let rollback;
|
|
29763
30911
|
try {
|
|
29764
|
-
const
|
|
29765
|
-
if (!
|
|
29766
|
-
|
|
29767
|
-
threadId2 = decoded.threadId;
|
|
30912
|
+
const decoded = decodeThreadRollbackRequest(request);
|
|
30913
|
+
if (!decoded) throw new Error("Expected thread/rollback request");
|
|
30914
|
+
rollback = decoded;
|
|
29768
30915
|
} catch (error51) {
|
|
29769
30916
|
await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
|
|
29770
|
-
|
|
29771
|
-
}
|
|
29772
|
-
const location = await this.#locateExternalThread(threadId2);
|
|
29773
|
-
if (await this.#writeResolutionError(request, location)) continue;
|
|
29774
|
-
if (location.kind === "official") {
|
|
29775
|
-
await this.#forwardOfficialRequest(request, frame);
|
|
29776
|
-
continue;
|
|
29777
|
-
}
|
|
29778
|
-
if (location.kind !== "external") continue;
|
|
29779
|
-
if (decoded.isPinned === void 0 || decoded.gitInfo !== void 0) {
|
|
29780
|
-
await this.#writer.json(
|
|
29781
|
-
rpcError(request, -32078, "External Thread metadata updates are unsupported")
|
|
29782
|
-
);
|
|
29783
|
-
continue;
|
|
30917
|
+
return;
|
|
29784
30918
|
}
|
|
29785
|
-
await this.#
|
|
29786
|
-
|
|
30919
|
+
await this.#rollbackExternalThread(request, resolution.thread, rollback);
|
|
30920
|
+
return;
|
|
29787
30921
|
}
|
|
29788
|
-
|
|
29789
|
-
|
|
29790
|
-
|
|
29791
|
-
|
|
29792
|
-
|
|
29793
|
-
|
|
30922
|
+
}
|
|
30923
|
+
if (request.method === "thread/turns/list" || request.method === "thread/items/list") {
|
|
30924
|
+
const params = requestObject(request);
|
|
30925
|
+
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
30926
|
+
if (await this.#writeResolutionError(request, resolution)) return;
|
|
30927
|
+
if (resolution.kind === "external") {
|
|
30928
|
+
await this.#listExternalHistory(
|
|
30929
|
+
request,
|
|
30930
|
+
resolution.thread,
|
|
30931
|
+
params,
|
|
30932
|
+
resolution.historyFresh
|
|
30933
|
+
);
|
|
30934
|
+
return;
|
|
29794
30935
|
}
|
|
29795
|
-
|
|
29796
|
-
|
|
30936
|
+
}
|
|
30937
|
+
if (request.method === "turn/start") {
|
|
30938
|
+
const params = requestObject(request);
|
|
30939
|
+
const threadId2 = params.threadId;
|
|
30940
|
+
const resolution = typeof threadId2 === "string" ? await this.#resolveExternalThread(threadId2) : { kind: "official" };
|
|
30941
|
+
if (typeof threadId2 === "string") {
|
|
29797
30942
|
this.#options.onRequestRoute?.(
|
|
29798
|
-
this.#routeObservationTracker.
|
|
29799
|
-
|
|
29800
|
-
|
|
29801
|
-
classifyThreadPurpose(request)
|
|
30943
|
+
this.#routeObservationTracker.observeTurn(
|
|
30944
|
+
threadId2,
|
|
30945
|
+
resolution.kind === "external" ? resolution.thread.harnessId : "codex"
|
|
29802
30946
|
)
|
|
29803
30947
|
);
|
|
29804
30948
|
}
|
|
29805
|
-
if (
|
|
29806
|
-
|
|
29807
|
-
|
|
30949
|
+
if (await this.#writeResolutionError(request, resolution)) return;
|
|
30950
|
+
if (resolution.kind === "external") {
|
|
30951
|
+
this.#dispatchDesktopRequest(
|
|
30952
|
+
() => this.#startExternalTurn(request, resolution.thread),
|
|
30953
|
+
resolution.thread.id
|
|
30954
|
+
);
|
|
30955
|
+
return;
|
|
29808
30956
|
}
|
|
29809
|
-
if (
|
|
29810
|
-
|
|
29811
|
-
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
29812
|
-
if (resolution.kind === "error") {
|
|
29813
|
-
await this.#writer.json(
|
|
29814
|
-
rpcError(request, resolution.error.code, resolution.error.message)
|
|
29815
|
-
);
|
|
29816
|
-
continue;
|
|
29817
|
-
}
|
|
29818
|
-
if (resolution.kind === "external") {
|
|
29819
|
-
let fork;
|
|
29820
|
-
try {
|
|
29821
|
-
const decoded = decodeThreadForkRequest(request);
|
|
29822
|
-
if (!decoded) throw new Error("Expected thread/fork request");
|
|
29823
|
-
fork = decoded;
|
|
29824
|
-
} catch (error51) {
|
|
29825
|
-
await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
|
|
29826
|
-
continue;
|
|
29827
|
-
}
|
|
29828
|
-
await this.#forkExternalThread(request, resolution.thread, fork);
|
|
29829
|
-
continue;
|
|
29830
|
-
}
|
|
30957
|
+
if (typeof threadId2 === "string") {
|
|
30958
|
+
this.#pendingOfficialTurnStarts.set(request.id, threadId2);
|
|
29831
30959
|
}
|
|
29832
|
-
|
|
29833
|
-
|
|
29834
|
-
|
|
29835
|
-
|
|
29836
|
-
|
|
29837
|
-
|
|
29838
|
-
|
|
29839
|
-
|
|
29840
|
-
|
|
29841
|
-
|
|
29842
|
-
|
|
29843
|
-
try {
|
|
29844
|
-
const decoded = decodeThreadRevertRequest(request);
|
|
29845
|
-
if (!decoded) throw new Error("Expected thread/revert request");
|
|
29846
|
-
revert = decoded;
|
|
29847
|
-
} catch (error51) {
|
|
29848
|
-
await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
|
|
29849
|
-
continue;
|
|
29850
|
-
}
|
|
29851
|
-
await this.#revertExternalThread(request, resolution.thread, revert);
|
|
29852
|
-
continue;
|
|
29853
|
-
}
|
|
30960
|
+
}
|
|
30961
|
+
if (request.method === "turn/steer") {
|
|
30962
|
+
const params = requestObject(request);
|
|
30963
|
+
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
30964
|
+
if (await this.#writeResolutionError(request, resolution)) return;
|
|
30965
|
+
if (resolution.kind === "external") {
|
|
30966
|
+
this.#dispatchDesktopRequest(
|
|
30967
|
+
() => this.#steerExternalTurn(request, resolution.thread),
|
|
30968
|
+
resolution.thread.id
|
|
30969
|
+
);
|
|
30970
|
+
return;
|
|
29854
30971
|
}
|
|
29855
|
-
|
|
29856
|
-
|
|
29857
|
-
|
|
29858
|
-
|
|
29859
|
-
|
|
29860
|
-
|
|
29861
|
-
|
|
29862
|
-
|
|
29863
|
-
|
|
29864
|
-
|
|
29865
|
-
|
|
29866
|
-
|
|
29867
|
-
|
|
29868
|
-
|
|
29869
|
-
|
|
29870
|
-
|
|
29871
|
-
await this.#writer.json(rpcError(request, -32602, errorMessage3(error51)));
|
|
29872
|
-
continue;
|
|
29873
|
-
}
|
|
29874
|
-
await this.#rollbackExternalThread(request, resolution.thread, rollback);
|
|
29875
|
-
continue;
|
|
29876
|
-
}
|
|
30972
|
+
}
|
|
30973
|
+
if (request.method === "turn/interrupt") {
|
|
30974
|
+
const params = requestObject(request);
|
|
30975
|
+
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
30976
|
+
if (await this.#writeResolutionError(request, resolution)) return;
|
|
30977
|
+
if (resolution.kind === "external") {
|
|
30978
|
+
await this.#interruptExternalTurn(request, resolution.thread, params.turnId);
|
|
30979
|
+
return;
|
|
30980
|
+
}
|
|
30981
|
+
}
|
|
30982
|
+
if (request.method === "thread/read") {
|
|
30983
|
+
const params = requestObject(request);
|
|
30984
|
+
const location = typeof params.threadId === "string" ? await this.#locateExternalThread(params.threadId) : { kind: "official" };
|
|
30985
|
+
if (location.kind === "error") {
|
|
30986
|
+
await this.#writer.json(rpcError(request, location.error.code, location.error.message));
|
|
30987
|
+
return;
|
|
29877
30988
|
}
|
|
29878
|
-
if (
|
|
29879
|
-
|
|
29880
|
-
|
|
29881
|
-
|
|
29882
|
-
|
|
29883
|
-
|
|
30989
|
+
if (location.kind === "official") {
|
|
30990
|
+
await this.#forwardOfficialRequest(request, frame);
|
|
30991
|
+
return;
|
|
30992
|
+
}
|
|
30993
|
+
if (params.includeTurns !== true) {
|
|
30994
|
+
await this.#readExternalThreadMetadata(request, location);
|
|
30995
|
+
return;
|
|
30996
|
+
}
|
|
30997
|
+
if (location.record.historyMode === "paginated") {
|
|
30998
|
+
await this.#writer.json(
|
|
30999
|
+
rpcError(request, -32602, "Paginated External Threads require thread/turns/list")
|
|
31000
|
+
);
|
|
31001
|
+
return;
|
|
31002
|
+
}
|
|
31003
|
+
}
|
|
31004
|
+
if (request.method === "thread/read" || request.method === "thread/resume") {
|
|
31005
|
+
const params = requestObject(request);
|
|
31006
|
+
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
31007
|
+
if (await this.#writeResolutionError(request, resolution)) return;
|
|
31008
|
+
if (resolution.kind === "external") {
|
|
31009
|
+
if (request.method === "thread/read") {
|
|
31010
|
+
await this.#readExternalThread(
|
|
29884
31011
|
request,
|
|
29885
31012
|
resolution.thread,
|
|
29886
|
-
params,
|
|
31013
|
+
params.includeTurns === true,
|
|
29887
31014
|
resolution.historyFresh
|
|
29888
31015
|
);
|
|
29889
|
-
|
|
29890
|
-
|
|
29891
|
-
|
|
29892
|
-
|
|
29893
|
-
|
|
29894
|
-
|
|
29895
|
-
const resolution = typeof threadId2 === "string" ? await this.#resolveExternalThread(threadId2) : { kind: "official" };
|
|
29896
|
-
if (typeof threadId2 === "string") {
|
|
29897
|
-
this.#options.onRequestRoute?.(
|
|
29898
|
-
this.#routeObservationTracker.observeTurn(
|
|
29899
|
-
threadId2,
|
|
29900
|
-
resolution.kind === "external" ? resolution.thread.harnessId : "codex"
|
|
29901
|
-
)
|
|
31016
|
+
} else {
|
|
31017
|
+
await this.#resumeExternalThread(
|
|
31018
|
+
request,
|
|
31019
|
+
resolution.thread,
|
|
31020
|
+
params,
|
|
31021
|
+
resolution.historyFresh
|
|
29902
31022
|
);
|
|
29903
31023
|
}
|
|
29904
|
-
|
|
29905
|
-
if (resolution.kind === "external") {
|
|
29906
|
-
this.#dispatchDesktopRequest(() => this.#startExternalTurn(request, resolution.thread));
|
|
29907
|
-
continue;
|
|
29908
|
-
}
|
|
29909
|
-
if (typeof threadId2 === "string") {
|
|
29910
|
-
this.#pendingOfficialTurnStarts.set(request.id, threadId2);
|
|
29911
|
-
}
|
|
29912
|
-
}
|
|
29913
|
-
if (request.method === "turn/steer") {
|
|
29914
|
-
const params = requestObject(request);
|
|
29915
|
-
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
29916
|
-
if (await this.#writeResolutionError(request, resolution)) continue;
|
|
29917
|
-
if (resolution.kind === "external") {
|
|
29918
|
-
this.#dispatchDesktopRequest(() => this.#steerExternalTurn(request, resolution.thread));
|
|
29919
|
-
continue;
|
|
29920
|
-
}
|
|
29921
|
-
}
|
|
29922
|
-
if (request.method === "turn/interrupt") {
|
|
29923
|
-
const params = requestObject(request);
|
|
29924
|
-
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
29925
|
-
if (await this.#writeResolutionError(request, resolution)) continue;
|
|
29926
|
-
if (resolution.kind === "external") {
|
|
29927
|
-
await this.#interruptExternalTurn(request, resolution.thread, params.turnId);
|
|
29928
|
-
continue;
|
|
29929
|
-
}
|
|
31024
|
+
return;
|
|
29930
31025
|
}
|
|
29931
|
-
|
|
29932
|
-
|
|
29933
|
-
|
|
29934
|
-
|
|
29935
|
-
|
|
29936
|
-
|
|
29937
|
-
}
|
|
31026
|
+
}
|
|
31027
|
+
if (request.method === "thread/unsubscribe") {
|
|
31028
|
+
const params = requestObject(request);
|
|
31029
|
+
if (typeof params.threadId === "string") {
|
|
31030
|
+
const location = await this.#locateExternalThread(params.threadId);
|
|
31031
|
+
if (await this.#writeResolutionError(request, location)) return;
|
|
29938
31032
|
if (location.kind === "official") {
|
|
29939
31033
|
await this.#forwardOfficialRequest(request, frame);
|
|
29940
|
-
|
|
29941
|
-
}
|
|
29942
|
-
if (params.includeTurns !== true) {
|
|
29943
|
-
await this.#readExternalThreadMetadata(request, location);
|
|
29944
|
-
continue;
|
|
31034
|
+
return;
|
|
29945
31035
|
}
|
|
29946
|
-
if (location.
|
|
31036
|
+
if (location.kind === "external") {
|
|
29947
31037
|
await this.#writer.json(
|
|
29948
|
-
|
|
31038
|
+
rpcEnvelope(request, {
|
|
31039
|
+
result: { status: location.thread ? "notSubscribed" : "notLoaded" }
|
|
31040
|
+
})
|
|
29949
31041
|
);
|
|
29950
|
-
|
|
29951
|
-
}
|
|
29952
|
-
}
|
|
29953
|
-
if (request.method === "thread/read" || request.method === "thread/resume") {
|
|
29954
|
-
const params = requestObject(request);
|
|
29955
|
-
const resolution = typeof params.threadId === "string" ? await this.#resolveExternalThread(params.threadId) : { kind: "official" };
|
|
29956
|
-
if (await this.#writeResolutionError(request, resolution)) continue;
|
|
29957
|
-
if (resolution.kind === "external") {
|
|
29958
|
-
if (request.method === "thread/read") {
|
|
29959
|
-
await this.#readExternalThread(
|
|
29960
|
-
request,
|
|
29961
|
-
resolution.thread,
|
|
29962
|
-
params.includeTurns === true,
|
|
29963
|
-
resolution.historyFresh
|
|
29964
|
-
);
|
|
29965
|
-
} else {
|
|
29966
|
-
await this.#resumeExternalThread(
|
|
29967
|
-
request,
|
|
29968
|
-
resolution.thread,
|
|
29969
|
-
params,
|
|
29970
|
-
resolution.historyFresh
|
|
29971
|
-
);
|
|
29972
|
-
}
|
|
29973
|
-
continue;
|
|
29974
|
-
}
|
|
29975
|
-
}
|
|
29976
|
-
if (request.method === "thread/unsubscribe") {
|
|
29977
|
-
const params = requestObject(request);
|
|
29978
|
-
if (typeof params.threadId === "string") {
|
|
29979
|
-
const location = await this.#locateExternalThread(params.threadId);
|
|
29980
|
-
if (await this.#writeResolutionError(request, location)) continue;
|
|
29981
|
-
if (location.kind === "official") {
|
|
29982
|
-
await this.#forwardOfficialRequest(request, frame);
|
|
29983
|
-
continue;
|
|
29984
|
-
}
|
|
29985
|
-
if (location.kind === "external") {
|
|
29986
|
-
await this.#writer.json(
|
|
29987
|
-
rpcEnvelope(request, {
|
|
29988
|
-
result: { status: location.thread ? "notSubscribed" : "notLoaded" }
|
|
29989
|
-
})
|
|
29990
|
-
);
|
|
29991
|
-
continue;
|
|
29992
|
-
}
|
|
31042
|
+
return;
|
|
29993
31043
|
}
|
|
29994
31044
|
}
|
|
29995
|
-
|
|
29996
|
-
|
|
29997
|
-
|
|
29998
|
-
|
|
29999
|
-
|
|
30000
|
-
|
|
30001
|
-
|
|
30002
|
-
|
|
30003
|
-
|
|
30004
|
-
|
|
30005
|
-
continue;
|
|
31045
|
+
}
|
|
31046
|
+
if (request.method === "thread/name/set" || request.method === "thread/delete") {
|
|
31047
|
+
const params = requestObject(request);
|
|
31048
|
+
const location = typeof params.threadId === "string" ? await this.#locateExternalThread(params.threadId) : { kind: "official" };
|
|
31049
|
+
if (await this.#writeResolutionError(request, location)) return;
|
|
31050
|
+
if (location.kind === "external") {
|
|
31051
|
+
if (request.method === "thread/name/set") {
|
|
31052
|
+
await this.#setExternalThreadName(request, location, params.name);
|
|
31053
|
+
} else {
|
|
31054
|
+
await this.#deleteExternalThread(request, location);
|
|
30006
31055
|
}
|
|
31056
|
+
return;
|
|
30007
31057
|
}
|
|
30008
|
-
|
|
30009
|
-
|
|
30010
|
-
|
|
30011
|
-
|
|
30012
|
-
|
|
30013
|
-
|
|
30014
|
-
)
|
|
30015
|
-
|
|
30016
|
-
|
|
31058
|
+
}
|
|
31059
|
+
if (request.method.startsWith("thread/") && !EXPLICIT_EXTERNAL_THREAD_METHODS.has(request.method) && isRecord14(request.params) && typeof request.params.threadId === "string") {
|
|
31060
|
+
const location = await this.#locateExternalThread(request.params.threadId);
|
|
31061
|
+
if (await this.#writeResolutionError(request, location)) return;
|
|
31062
|
+
if (location.kind === "external") {
|
|
31063
|
+
await this.#writer.json(
|
|
31064
|
+
rpcError(request, -32076, `External Thread does not support ${request.method}`)
|
|
31065
|
+
);
|
|
31066
|
+
return;
|
|
30017
31067
|
}
|
|
30018
|
-
await this.#forwardOfficialRequest(request, frame);
|
|
30019
31068
|
}
|
|
30020
|
-
this.#
|
|
30021
|
-
this.#externalSteering.close();
|
|
30022
|
-
if (this.#drainActiveWorkOnInputEnd) await this.#waitForActiveWorkToDrain();
|
|
30023
|
-
await this.#closeOfficialRuntime();
|
|
31069
|
+
await this.#forwardOfficialRequest(request, frame);
|
|
30024
31070
|
}
|
|
30025
31071
|
async #forwardOfficialNonRequest(value2, frame) {
|
|
30026
31072
|
const response = isRecord14(value2) ? value2 : null;
|
|
@@ -30731,6 +31777,7 @@ var AppServerHost = class {
|
|
|
30731
31777
|
await this.#writer.json(rpcError(request, -32602, "Invalid Harness inspection params"));
|
|
30732
31778
|
return;
|
|
30733
31779
|
}
|
|
31780
|
+
await this.#waitForPlugins();
|
|
30734
31781
|
const registered = [...this.#externalAdapters].find(
|
|
30735
31782
|
([harnessId]) => harnessId === params.data.harnessId
|
|
30736
31783
|
);
|
|
@@ -30770,6 +31817,7 @@ var AppServerHost = class {
|
|
|
30770
31817
|
await this.#writer.json(rpcError(request, -32602, "Invalid Harness Web UI params"));
|
|
30771
31818
|
return;
|
|
30772
31819
|
}
|
|
31820
|
+
await this.#waitForPlugins();
|
|
30773
31821
|
const adapter = [...this.#externalAdapters].find(
|
|
30774
31822
|
([harnessId]) => harnessId === params.data.harnessId
|
|
30775
31823
|
)?.[1];
|
|
@@ -30792,6 +31840,7 @@ var AppServerHost = class {
|
|
|
30792
31840
|
}
|
|
30793
31841
|
}
|
|
30794
31842
|
async #handleSessionImport(request) {
|
|
31843
|
+
await this.#waitForPlugins();
|
|
30795
31844
|
this.#sessionImportRequests ??= new SessionImportRequests({
|
|
30796
31845
|
adapters: this.#externalAdapters,
|
|
30797
31846
|
descriptors: () => this.#pluginDescriptors,
|
|
@@ -30931,6 +31980,7 @@ var AppServerHost = class {
|
|
|
30931
31980
|
await this.#writeHarnessCommandCatalog(request, location.record.harnessId);
|
|
30932
31981
|
}
|
|
30933
31982
|
async #writeHarnessCommandCatalog(request, harnessId) {
|
|
31983
|
+
await this.#waitForPlugins();
|
|
30934
31984
|
const adapter = this.#externalAdapters.get(harnessId);
|
|
30935
31985
|
if (!adapter) {
|
|
30936
31986
|
await this.#writer.json(rpcError(request, -32077, `Harness '${harnessId}' is unavailable`));
|
|
@@ -30955,7 +32005,12 @@ var AppServerHost = class {
|
|
|
30955
32005
|
await this.#writer.json(rpcError(request, -32078, "Thread is not externally owned"));
|
|
30956
32006
|
return;
|
|
30957
32007
|
}
|
|
30958
|
-
|
|
32008
|
+
this.#dispatchDesktopRequest(
|
|
32009
|
+
() => this.#executeResolvedThreadCommand(request, resolution.thread, params.data),
|
|
32010
|
+
resolution.thread.id
|
|
32011
|
+
);
|
|
32012
|
+
}
|
|
32013
|
+
async #executeResolvedThreadCommand(request, thread, params) {
|
|
30959
32014
|
if (thread.running || this.#externalSteering.hasPending(thread.id) || this.#pendingExternalCommandRequests.has(thread.id)) {
|
|
30960
32015
|
await this.#writer.json(
|
|
30961
32016
|
rpcError(request, -32072, "External Thread already has an active operation")
|
|
@@ -30976,13 +32031,13 @@ var AppServerHost = class {
|
|
|
30976
32031
|
await this.#writer.json(rpcError(request, -32078, catalog.error.message));
|
|
30977
32032
|
return;
|
|
30978
32033
|
}
|
|
30979
|
-
const descriptor = catalog.value.commands.find(({ id: id2 }) => id2 === params.
|
|
32034
|
+
const descriptor = catalog.value.commands.find(({ id: id2 }) => id2 === params.commandId);
|
|
30980
32035
|
if (!descriptor) {
|
|
30981
32036
|
await this.#writer.json(
|
|
30982
32037
|
rpcError(
|
|
30983
32038
|
request,
|
|
30984
32039
|
-32078,
|
|
30985
|
-
`External Harness does not expose command '${params.
|
|
32040
|
+
`External Harness does not expose command '${params.commandId}'`
|
|
30986
32041
|
)
|
|
30987
32042
|
);
|
|
30988
32043
|
return;
|
|
@@ -30991,9 +32046,9 @@ var AppServerHost = class {
|
|
|
30991
32046
|
await this.#startExternalCommand(
|
|
30992
32047
|
request,
|
|
30993
32048
|
thread,
|
|
30994
|
-
params.
|
|
30995
|
-
params.
|
|
30996
|
-
params.
|
|
32049
|
+
params.commandId,
|
|
32050
|
+
params.arguments,
|
|
32051
|
+
params.turnId,
|
|
30997
32052
|
"command"
|
|
30998
32053
|
);
|
|
30999
32054
|
} catch (error51) {
|
|
@@ -31308,6 +32363,7 @@ var AppServerHost = class {
|
|
|
31308
32363
|
}
|
|
31309
32364
|
}
|
|
31310
32365
|
async #startExternalThread(request, harnessId) {
|
|
32366
|
+
await this.#waitForPlugins();
|
|
31311
32367
|
const adapter = this.#externalAdapters.get(harnessId);
|
|
31312
32368
|
if (!adapter) {
|
|
31313
32369
|
this.#routeObservationTracker.rejectCreate(request.id);
|
|
@@ -31364,60 +32420,64 @@ var AppServerHost = class {
|
|
|
31364
32420
|
return;
|
|
31365
32421
|
}
|
|
31366
32422
|
const session = sessionResult.value;
|
|
31367
|
-
|
|
31368
|
-
|
|
31369
|
-
|
|
31370
|
-
record3.
|
|
31371
|
-
|
|
32423
|
+
await this.#externalRuntime.idleRelease.runOperation(record3.hostThreadId, async () => {
|
|
32424
|
+
try {
|
|
32425
|
+
if (session.initialState.nativeRef) {
|
|
32426
|
+
record3 = await this.#repository.commitNative(
|
|
32427
|
+
record3.hostThreadId,
|
|
32428
|
+
session.initialState.nativeRef
|
|
32429
|
+
);
|
|
32430
|
+
}
|
|
32431
|
+
const thread = externalThreadValue({
|
|
32432
|
+
record: record3,
|
|
32433
|
+
turns: [],
|
|
32434
|
+
sessionId: record3.hostThreadId
|
|
32435
|
+
});
|
|
32436
|
+
const externalThread = this.#registerExternalThread({
|
|
32437
|
+
record: record3,
|
|
32438
|
+
session,
|
|
32439
|
+
sessionId: record3.hostThreadId,
|
|
32440
|
+
thread,
|
|
32441
|
+
turns: [],
|
|
32442
|
+
...requestedModel ? { requestedModel } : {},
|
|
32443
|
+
...requestedThinkingOptionId ? { requestedThinkingOptionId } : {},
|
|
32444
|
+
...requestedPermissionModeId ? { requestedPermissionModeId } : {}
|
|
32445
|
+
});
|
|
32446
|
+
this.#routeObservationTracker.bindCreatedThread(request.id, externalThread.id);
|
|
32447
|
+
await this.#writer.json(
|
|
32448
|
+
rpcEnvelope(request, {
|
|
32449
|
+
result: {
|
|
32450
|
+
thread,
|
|
32451
|
+
model: transportModelId,
|
|
32452
|
+
modelProvider: "codexhost",
|
|
32453
|
+
cwd,
|
|
32454
|
+
approvalPolicy: typeof params.approvalPolicy === "string" ? params.approvalPolicy : "never",
|
|
32455
|
+
approvalsReviewer: "user",
|
|
32456
|
+
sandbox: sandboxResult(params),
|
|
32457
|
+
reasoningEffort: "medium",
|
|
32458
|
+
serviceTier: "flex",
|
|
32459
|
+
multiAgentMode: "explicitRequestOnly",
|
|
32460
|
+
activePermissionProfile: null,
|
|
32461
|
+
runtimeWorkspaceRoots: Array.isArray(params.runtimeWorkspaceRoots) ? params.runtimeWorkspaceRoots : [],
|
|
32462
|
+
instructionSources: []
|
|
32463
|
+
}
|
|
32464
|
+
})
|
|
32465
|
+
);
|
|
32466
|
+
await this.#writer.json({
|
|
32467
|
+
method: "thread/started",
|
|
32468
|
+
emittedAtMs: Date.now(),
|
|
32469
|
+
params: { thread }
|
|
32470
|
+
});
|
|
32471
|
+
} catch {
|
|
32472
|
+
this.#externalRuntime.remove(record3.hostThreadId);
|
|
32473
|
+
this.#routeObservationTracker.forgetThread(record3.hostThreadId);
|
|
32474
|
+
await session.close().catch(() => void 0);
|
|
32475
|
+
await this.#repository.removeProvisional(record3.hostThreadId).catch(() => void 0);
|
|
32476
|
+
await this.#writer.json(
|
|
32477
|
+
rpcError(request, -32081, "External Thread could not be persisted")
|
|
31372
32478
|
);
|
|
31373
32479
|
}
|
|
31374
|
-
|
|
31375
|
-
record: record3,
|
|
31376
|
-
turns: [],
|
|
31377
|
-
sessionId: record3.hostThreadId
|
|
31378
|
-
});
|
|
31379
|
-
const externalThread = this.#registerExternalThread({
|
|
31380
|
-
record: record3,
|
|
31381
|
-
session,
|
|
31382
|
-
sessionId: record3.hostThreadId,
|
|
31383
|
-
thread,
|
|
31384
|
-
turns: [],
|
|
31385
|
-
...requestedModel ? { requestedModel } : {},
|
|
31386
|
-
...requestedThinkingOptionId ? { requestedThinkingOptionId } : {},
|
|
31387
|
-
...requestedPermissionModeId ? { requestedPermissionModeId } : {}
|
|
31388
|
-
});
|
|
31389
|
-
this.#routeObservationTracker.bindCreatedThread(request.id, externalThread.id);
|
|
31390
|
-
await this.#writer.json(
|
|
31391
|
-
rpcEnvelope(request, {
|
|
31392
|
-
result: {
|
|
31393
|
-
thread,
|
|
31394
|
-
model: transportModelId,
|
|
31395
|
-
modelProvider: "codexhost",
|
|
31396
|
-
cwd,
|
|
31397
|
-
approvalPolicy: typeof params.approvalPolicy === "string" ? params.approvalPolicy : "never",
|
|
31398
|
-
approvalsReviewer: "user",
|
|
31399
|
-
sandbox: sandboxResult(params),
|
|
31400
|
-
reasoningEffort: "medium",
|
|
31401
|
-
serviceTier: "flex",
|
|
31402
|
-
multiAgentMode: "explicitRequestOnly",
|
|
31403
|
-
activePermissionProfile: null,
|
|
31404
|
-
runtimeWorkspaceRoots: Array.isArray(params.runtimeWorkspaceRoots) ? params.runtimeWorkspaceRoots : [],
|
|
31405
|
-
instructionSources: []
|
|
31406
|
-
}
|
|
31407
|
-
})
|
|
31408
|
-
);
|
|
31409
|
-
await this.#writer.json({
|
|
31410
|
-
method: "thread/started",
|
|
31411
|
-
emittedAtMs: Date.now(),
|
|
31412
|
-
params: { thread }
|
|
31413
|
-
});
|
|
31414
|
-
} catch {
|
|
31415
|
-
this.#externalRuntime.remove(record3.hostThreadId);
|
|
31416
|
-
this.#routeObservationTracker.forgetThread(record3.hostThreadId);
|
|
31417
|
-
await session.close().catch(() => void 0);
|
|
31418
|
-
await this.#repository.removeProvisional(record3.hostThreadId).catch(() => void 0);
|
|
31419
|
-
await this.#writer.json(rpcError(request, -32081, "External Thread could not be persisted"));
|
|
31420
|
-
}
|
|
32480
|
+
});
|
|
31421
32481
|
}
|
|
31422
32482
|
#registerExternalThread(input) {
|
|
31423
32483
|
return this.#externalRuntime.register(input);
|
|
@@ -31425,7 +32485,10 @@ var AppServerHost = class {
|
|
|
31425
32485
|
#locateExternalThread(threadId2) {
|
|
31426
32486
|
return this.#externalRuntime.locate(threadId2);
|
|
31427
32487
|
}
|
|
31428
|
-
#resolveExternalThread(threadId2) {
|
|
32488
|
+
async #resolveExternalThread(threadId2) {
|
|
32489
|
+
const location = await this.#locateExternalThread(threadId2);
|
|
32490
|
+
if (location.kind !== "external") return location;
|
|
32491
|
+
await this.#waitForPlugins();
|
|
31429
32492
|
return this.#externalRuntime.resolve(threadId2);
|
|
31430
32493
|
}
|
|
31431
32494
|
async #writeResolutionError(request, resolution) {
|
|
@@ -31950,12 +33013,16 @@ var AppServerHost = class {
|
|
|
31950
33013
|
try {
|
|
31951
33014
|
for await (const output of thread.session.outputs) {
|
|
31952
33015
|
try {
|
|
31953
|
-
await this.#
|
|
33016
|
+
await this.#externalRuntime.idleRelease.consumeOutput(
|
|
33017
|
+
thread,
|
|
33018
|
+
() => this.#projectHarnessOutput(thread, output)
|
|
33019
|
+
);
|
|
31954
33020
|
} catch (error51) {
|
|
31955
33021
|
await this.#recoverFailedProjection(thread, error51);
|
|
31956
33022
|
}
|
|
31957
33023
|
}
|
|
31958
33024
|
} catch (error51) {
|
|
33025
|
+
this.#externalRuntime.idleRelease.outputFailed(thread);
|
|
31959
33026
|
this.#diagnose(error51);
|
|
31960
33027
|
} finally {
|
|
31961
33028
|
this.#externalSteering.fault(
|
|
@@ -32195,6 +33262,7 @@ var AppServerHost = class {
|
|
|
32195
33262
|
if (event.type === "turn.completed" && !ephemeralTurn) {
|
|
32196
33263
|
const persistenceError = await this.#persistTerminalIdentity(thread, event);
|
|
32197
33264
|
if (persistenceError) {
|
|
33265
|
+
this.#externalRuntime.idleRelease.outputFailed(thread);
|
|
32198
33266
|
event = {
|
|
32199
33267
|
type: "turn.completed",
|
|
32200
33268
|
turnId: event.turnId,
|
|
@@ -32421,32 +33489,37 @@ var AppServerHost = class {
|
|
|
32421
33489
|
}
|
|
32422
33490
|
async #handleDesktopApprovalResponse(value2) {
|
|
32423
33491
|
if (!isRecord14(value2) || !isHostApprovalRequestId(value2.id)) return false;
|
|
32424
|
-
const
|
|
33492
|
+
const requestId = value2.id;
|
|
33493
|
+
const pending = this.#pendingDesktopApprovals.get(requestId);
|
|
32425
33494
|
if (!pending) return true;
|
|
32426
|
-
this.#
|
|
32427
|
-
|
|
32428
|
-
|
|
32429
|
-
|
|
32430
|
-
|
|
32431
|
-
|
|
32432
|
-
|
|
32433
|
-
|
|
32434
|
-
|
|
32435
|
-
|
|
32436
|
-
|
|
32437
|
-
|
|
32438
|
-
|
|
32439
|
-
|
|
32440
|
-
|
|
32441
|
-
const cancelled = await pending.thread.session.execute({
|
|
32442
|
-
type: "turn.cancel",
|
|
32443
|
-
turnId: pending.interaction.turnId
|
|
33495
|
+
return this.#externalRuntime.idleRelease.runOperation(pending.thread.id, async () => {
|
|
33496
|
+
if (this.#externalRuntime.get(pending.thread.id) !== pending.thread || this.#externalRuntime.idleRelease.failure(pending.thread))
|
|
33497
|
+
return true;
|
|
33498
|
+
this.#pendingDesktopApprovals.delete(requestId);
|
|
33499
|
+
let response;
|
|
33500
|
+
try {
|
|
33501
|
+
response = jsonRpcResponseFailed(value2) ? pending.projection.denyResponse : pending.projection.parseResponse(value2.result);
|
|
33502
|
+
} catch (error51) {
|
|
33503
|
+
this.#diagnose(error51);
|
|
33504
|
+
response = pending.projection.denyResponse;
|
|
33505
|
+
}
|
|
33506
|
+
const result = await pending.thread.session.execute({
|
|
33507
|
+
type: "interaction.respond",
|
|
33508
|
+
interactionId: pending.interaction.interactionId,
|
|
33509
|
+
response
|
|
32444
33510
|
});
|
|
32445
|
-
if (!
|
|
32446
|
-
this.#diagnose(`Approval
|
|
33511
|
+
if (!result.ok && result.error.code !== "invalidState") {
|
|
33512
|
+
this.#diagnose(`Approval response failed: ${result.error.message}`);
|
|
33513
|
+
const cancelled = await pending.thread.session.execute({
|
|
33514
|
+
type: "turn.cancel",
|
|
33515
|
+
turnId: pending.interaction.turnId
|
|
33516
|
+
});
|
|
33517
|
+
if (!cancelled.ok && cancelled.error.code !== "invalidState") {
|
|
33518
|
+
this.#diagnose(`Approval fail-closed cancellation failed: ${cancelled.error.message}`);
|
|
33519
|
+
}
|
|
32447
33520
|
}
|
|
32448
|
-
|
|
32449
|
-
|
|
33521
|
+
return true;
|
|
33522
|
+
});
|
|
32450
33523
|
}
|
|
32451
33524
|
async #denyApproval(thread, interaction) {
|
|
32452
33525
|
const denyActions = interaction.actions.filter(({ effect }) => effect === "deny");
|
|
@@ -32525,7 +33598,7 @@ var AppServerHost = class {
|
|
|
32525
33598
|
};
|
|
32526
33599
|
if (timeoutMs !== null) {
|
|
32527
33600
|
pending.timeout = setTimeout(() => {
|
|
32528
|
-
void this.#cancelExpiredQuestion(requestId);
|
|
33601
|
+
void this.#cancelExpiredQuestion(requestId).catch((error51) => this.#diagnose(error51));
|
|
32529
33602
|
}, timeoutMs);
|
|
32530
33603
|
}
|
|
32531
33604
|
this.#pendingDesktopQuestions.set(requestId, pending);
|
|
@@ -32543,39 +33616,48 @@ var AppServerHost = class {
|
|
|
32543
33616
|
}
|
|
32544
33617
|
async #handleDesktopQuestionResponse(value2) {
|
|
32545
33618
|
if (!isRecord14(value2) || !isHostQuestionRequestId(value2.id)) return false;
|
|
32546
|
-
const
|
|
33619
|
+
const requestId = value2.id;
|
|
33620
|
+
const pending = this.#pendingDesktopQuestions.get(requestId);
|
|
32547
33621
|
if (!pending) return true;
|
|
32548
|
-
this.#
|
|
32549
|
-
|
|
32550
|
-
|
|
32551
|
-
|
|
32552
|
-
|
|
32553
|
-
|
|
32554
|
-
|
|
32555
|
-
|
|
32556
|
-
|
|
32557
|
-
|
|
32558
|
-
|
|
32559
|
-
|
|
32560
|
-
|
|
33622
|
+
return this.#externalRuntime.idleRelease.runOperation(pending.thread.id, async () => {
|
|
33623
|
+
if (this.#externalRuntime.get(pending.thread.id) !== pending.thread || this.#externalRuntime.idleRelease.failure(pending.thread))
|
|
33624
|
+
return true;
|
|
33625
|
+
this.#pendingDesktopQuestions.delete(requestId);
|
|
33626
|
+
if (pending.timeout) clearTimeout(pending.timeout);
|
|
33627
|
+
let response;
|
|
33628
|
+
try {
|
|
33629
|
+
response = jsonRpcResponseFailed(value2) ? { type: "question", answers: {}, cancelled: true } : pending.projection.parseResponse(value2.result);
|
|
33630
|
+
} catch (error51) {
|
|
33631
|
+
this.#diagnose(error51);
|
|
33632
|
+
response = { type: "question", answers: {}, cancelled: true };
|
|
33633
|
+
}
|
|
33634
|
+
const result = await pending.thread.session.execute({
|
|
33635
|
+
type: "interaction.respond",
|
|
33636
|
+
interactionId: pending.interaction.interactionId,
|
|
33637
|
+
response
|
|
33638
|
+
});
|
|
33639
|
+
if (!result.ok && result.error.code !== "invalidState") {
|
|
33640
|
+
this.#diagnose(`Question response failed: ${result.error.message}`);
|
|
33641
|
+
}
|
|
33642
|
+
return true;
|
|
32561
33643
|
});
|
|
32562
|
-
if (!result.ok && result.error.code !== "invalidState") {
|
|
32563
|
-
this.#diagnose(`Question response failed: ${result.error.message}`);
|
|
32564
|
-
}
|
|
32565
|
-
return true;
|
|
32566
33644
|
}
|
|
32567
33645
|
async #cancelExpiredQuestion(requestId) {
|
|
32568
33646
|
const pending = this.#pendingDesktopQuestions.get(requestId);
|
|
32569
33647
|
if (!pending) return;
|
|
32570
|
-
await this.#
|
|
32571
|
-
|
|
32572
|
-
|
|
32573
|
-
|
|
32574
|
-
|
|
33648
|
+
await this.#externalRuntime.idleRelease.runOperation(pending.thread.id, async () => {
|
|
33649
|
+
if (this.#externalRuntime.get(pending.thread.id) !== pending.thread || this.#externalRuntime.idleRelease.failure(pending.thread))
|
|
33650
|
+
return;
|
|
33651
|
+
await this.#resolveDesktopQuestion(pending.interaction.interactionId);
|
|
33652
|
+
const result = await pending.thread.session.execute({
|
|
33653
|
+
type: "interaction.respond",
|
|
33654
|
+
interactionId: pending.interaction.interactionId,
|
|
33655
|
+
response: { type: "question", answers: {}, cancelled: true }
|
|
33656
|
+
});
|
|
33657
|
+
if (!result.ok && result.error.code !== "invalidState") {
|
|
33658
|
+
this.#diagnose(`Question expiry failed: ${result.error.message}`);
|
|
33659
|
+
}
|
|
32575
33660
|
});
|
|
32576
|
-
if (!result.ok && result.error.code !== "invalidState") {
|
|
32577
|
-
this.#diagnose(`Question expiry failed: ${result.error.message}`);
|
|
32578
|
-
}
|
|
32579
33661
|
}
|
|
32580
33662
|
#retireDesktopQuestion(interactionId) {
|
|
32581
33663
|
for (const [requestId, pending] of this.#pendingDesktopQuestions) {
|
|
@@ -32643,8 +33725,9 @@ var AppServerHost = class {
|
|
|
32643
33725
|
}
|
|
32644
33726
|
await this.#writer.json(projection);
|
|
32645
33727
|
}
|
|
32646
|
-
#dispatchDesktopRequest(run) {
|
|
32647
|
-
|
|
33728
|
+
#dispatchDesktopRequest(run, threadId2) {
|
|
33729
|
+
const task = threadId2 ? this.#externalRuntime.idleRelease.runOperation(threadId2, run) : run();
|
|
33730
|
+
void task.catch((error51) => this.#diagnose(error51));
|
|
32648
33731
|
}
|
|
32649
33732
|
#diagnose(error51) {
|
|
32650
33733
|
this.#options.diagnosticOutput.write(`codexhost Host Runtime: ${errorMessage3(error51)}
|
|
@@ -32655,7 +33738,7 @@ var AppServerHost = class {
|
|
|
32655
33738
|
// packages/host-runtime/src/native-account-host.ts
|
|
32656
33739
|
import { mkdir as mkdir6, realpath as realpath3 } from "node:fs/promises";
|
|
32657
33740
|
import { homedir } from "node:os";
|
|
32658
|
-
import
|
|
33741
|
+
import path16 from "node:path";
|
|
32659
33742
|
|
|
32660
33743
|
// packages/host-runtime/src/codex-runtime/owned-official-backends.ts
|
|
32661
33744
|
import { createHash as createHash7, randomBytes } from "node:crypto";
|
|
@@ -32665,7 +33748,7 @@ import { Writable as Writable2 } from "node:stream";
|
|
|
32665
33748
|
import { createServer } from "node:http";
|
|
32666
33749
|
import net from "node:net";
|
|
32667
33750
|
import { chmod as chmod3, lstat as lstat6, mkdir as mkdir5, rm as rm5 } from "node:fs/promises";
|
|
32668
|
-
import
|
|
33751
|
+
import path14 from "node:path";
|
|
32669
33752
|
import { PassThrough } from "node:stream";
|
|
32670
33753
|
|
|
32671
33754
|
// node_modules/ws/wrapper.mjs
|
|
@@ -32683,7 +33766,7 @@ var wrapper_default = import_websocket.default;
|
|
|
32683
33766
|
import { randomUUID as randomUUID9 } from "node:crypto";
|
|
32684
33767
|
import { chmod as chmod2, lstat as lstat5, mkdir as mkdir4, open as open5, readFile as readFile6, readdir as readdir4, rename as rename3, rm as rm4 } from "node:fs/promises";
|
|
32685
33768
|
import { uptime } from "node:os";
|
|
32686
|
-
import
|
|
33769
|
+
import path13 from "node:path";
|
|
32687
33770
|
import { setTimeout as delay4 } from "node:timers/promises";
|
|
32688
33771
|
var LOCK_RETRY_COUNT = 200;
|
|
32689
33772
|
var LOCK_RETRY_DELAY_MS = 25;
|
|
@@ -32757,7 +33840,7 @@ async function readLockEntrySnapshot(filePath) {
|
|
|
32757
33840
|
source,
|
|
32758
33841
|
identity: { dev: metadata.dev, ino: metadata.ino },
|
|
32759
33842
|
mtimeMs: metadata.mtimeMs,
|
|
32760
|
-
record: record3 &&
|
|
33843
|
+
record: record3 && path13.basename(filePath) === lockEntryName(record3.ownerToken) ? record3 : null
|
|
32761
33844
|
};
|
|
32762
33845
|
}
|
|
32763
33846
|
function lockEntryIsAbandoned(snapshot) {
|
|
@@ -32778,7 +33861,7 @@ async function readLockEntryCatalog(lockDirectory) {
|
|
|
32778
33861
|
let unsettled = false;
|
|
32779
33862
|
for (const name of names) {
|
|
32780
33863
|
if (!name.startsWith(LOCK_ENTRY_PREFIX) || !name.endsWith(LOCK_ENTRY_SUFFIX)) continue;
|
|
32781
|
-
const snapshot = await readLockEntrySnapshot(
|
|
33864
|
+
const snapshot = await readLockEntrySnapshot(path13.join(lockDirectory, name));
|
|
32782
33865
|
if (snapshot === null) continue;
|
|
32783
33866
|
if (lockEntryIsAbandoned(snapshot)) {
|
|
32784
33867
|
if (!await removeAbandonedLockEntry(snapshot)) unsettled = true;
|
|
@@ -32806,7 +33889,7 @@ async function preparePrivateLockDirectory(lockDirectory) {
|
|
|
32806
33889
|
await chmod2(lockDirectory, 448);
|
|
32807
33890
|
}
|
|
32808
33891
|
async function writeLockRecordAtomic(lockDirectory, entryPath, record3) {
|
|
32809
|
-
const temporary =
|
|
33892
|
+
const temporary = path13.join(lockDirectory, `.tmp-${record3.ownerToken}-${randomUUID9()}`);
|
|
32810
33893
|
const handle = await open5(temporary, "wx", 384);
|
|
32811
33894
|
try {
|
|
32812
33895
|
await handle.writeFile(`${JSON.stringify(record3)}
|
|
@@ -32882,7 +33965,7 @@ async function withRemoteAppServerSocketInitializationLock(socketPath, action) {
|
|
|
32882
33965
|
const lockDirectory = `${socketPath}.initializers`;
|
|
32883
33966
|
await preparePrivateLockDirectory(lockDirectory);
|
|
32884
33967
|
const ownerToken = randomUUID9();
|
|
32885
|
-
const entryPath =
|
|
33968
|
+
const entryPath = path13.join(lockDirectory, lockEntryName(ownerToken));
|
|
32886
33969
|
const baseRecord = {
|
|
32887
33970
|
version: 2,
|
|
32888
33971
|
ownerToken,
|
|
@@ -33056,14 +34139,14 @@ function remoteAppServerSocketPath(environment, listenUrl = "unix://") {
|
|
|
33056
34139
|
throw new Error("Remote app-server listener must use a Unix URL");
|
|
33057
34140
|
}
|
|
33058
34141
|
const explicit = listenUrl.slice("unix://".length);
|
|
33059
|
-
if (explicit.length > 0) return
|
|
33060
|
-
const codexHome = environment.CODEX_HOME ?? (environment.HOME ?
|
|
34142
|
+
if (explicit.length > 0) return path14.posix.resolve(decodeURIComponent(explicit));
|
|
34143
|
+
const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path14.posix.join(environment.HOME, ".codex") : void 0);
|
|
33061
34144
|
if (!codexHome)
|
|
33062
34145
|
throw new Error("CODEX_HOME or HOME is required for the remote app-server socket");
|
|
33063
|
-
return
|
|
34146
|
+
return path14.posix.join(codexHome, "app-server-control", "app-server-control.sock");
|
|
33064
34147
|
}
|
|
33065
34148
|
function officialListenerArgumentsForRemoteListener(arguments_2, socketPath) {
|
|
33066
|
-
if (!
|
|
34149
|
+
if (!path14.posix.isAbsolute(socketPath)) {
|
|
33067
34150
|
throw new Error("Shared official app-server socket path must be absolute");
|
|
33068
34151
|
}
|
|
33069
34152
|
if (remoteUnixListenerUrl(arguments_2) === null) {
|
|
@@ -33174,7 +34257,7 @@ async function removeStaleSocket(socketPath) {
|
|
|
33174
34257
|
await rm5(socketPath, { force: true });
|
|
33175
34258
|
}
|
|
33176
34259
|
async function prepareRemoteAppServerSocketDirectory(socketPath) {
|
|
33177
|
-
const socketDirectory =
|
|
34260
|
+
const socketDirectory = path14.dirname(socketPath);
|
|
33178
34261
|
const existing = await lstat6(socketDirectory).catch((error51) => {
|
|
33179
34262
|
if (error51.code === "ENOENT") return null;
|
|
33180
34263
|
throw error51;
|
|
@@ -33381,18 +34464,18 @@ function createRemoteAppServerWebSocketListener(input) {
|
|
|
33381
34464
|
import { spawn as spawn3 } from "node:child_process";
|
|
33382
34465
|
import { randomUUID as randomUUID10 } from "node:crypto";
|
|
33383
34466
|
import { lstat as lstat7, rm as rm6 } from "node:fs/promises";
|
|
33384
|
-
import
|
|
34467
|
+
import path15 from "node:path";
|
|
33385
34468
|
var DEFAULT_CLOSE_TIMEOUT_MS = 2e3;
|
|
33386
34469
|
var DEFAULT_LISTEN_TIMEOUT_MS = 1e4;
|
|
33387
34470
|
function remoteOfficialAppServerSocketPath(desktopControlSocketPath, token = randomUUID10()) {
|
|
33388
|
-
if (!
|
|
34471
|
+
if (!path15.posix.isAbsolute(desktopControlSocketPath)) {
|
|
33389
34472
|
throw new Error("Desktop control socket path must be absolute");
|
|
33390
34473
|
}
|
|
33391
34474
|
if (!/^[A-Za-z0-9-]+$/u.test(token) || !/[A-Za-z0-9]/u.test(token)) {
|
|
33392
34475
|
throw new Error("Shared official app-server socket token is invalid");
|
|
33393
34476
|
}
|
|
33394
34477
|
const compactToken = token.replaceAll("-", "").slice(0, 15);
|
|
33395
|
-
return
|
|
34478
|
+
return path15.posix.join(path15.posix.dirname(desktopControlSocketPath), `.c-${compactToken}.sock`);
|
|
33396
34479
|
}
|
|
33397
34480
|
function errorMessage4(error51) {
|
|
33398
34481
|
return error51 instanceof Error ? error51.message : String(error51);
|
|
@@ -33875,19 +34958,19 @@ function createOwnedUnixBackend(input) {
|
|
|
33875
34958
|
|
|
33876
34959
|
// packages/host-runtime/src/native-account-host.ts
|
|
33877
34960
|
async function canonicalCodexHome(home) {
|
|
33878
|
-
const absolute =
|
|
34961
|
+
const absolute = path16.resolve(home);
|
|
33879
34962
|
try {
|
|
33880
34963
|
return await realpath3(absolute);
|
|
33881
34964
|
} catch (error51) {
|
|
33882
34965
|
if (!(error51 instanceof Error && "code" in error51 && error51.code === "ENOENT")) throw error51;
|
|
33883
|
-
const parent =
|
|
34966
|
+
const parent = path16.dirname(absolute);
|
|
33884
34967
|
if (parent === absolute) throw error51;
|
|
33885
|
-
return
|
|
34968
|
+
return path16.join(await canonicalCodexHome(parent), path16.basename(absolute));
|
|
33886
34969
|
}
|
|
33887
34970
|
}
|
|
33888
34971
|
async function prepareLocalCodex(input) {
|
|
33889
34972
|
const home = await canonicalCodexHome(
|
|
33890
|
-
input.environment.CODEX_HOME ??
|
|
34973
|
+
input.environment.CODEX_HOME ?? path16.join(homedir(), ".codex")
|
|
33891
34974
|
);
|
|
33892
34975
|
await mkdir6(home, { recursive: true });
|
|
33893
34976
|
const scope = new OfficialRuntimeScope({
|
|
@@ -34054,17 +35137,17 @@ var DelegationControlRegistry = class {
|
|
|
34054
35137
|
|
|
34055
35138
|
// packages/host-runtime/src/installed-harness-plugins.ts
|
|
34056
35139
|
import os3 from "node:os";
|
|
34057
|
-
import
|
|
35140
|
+
import path18 from "node:path";
|
|
34058
35141
|
import { fileURLToPath } from "node:url";
|
|
34059
35142
|
|
|
34060
35143
|
// packages/host-runtime/src/launcher-url-opener.ts
|
|
34061
35144
|
import { spawn as spawn4 } from "node:child_process";
|
|
34062
|
-
import
|
|
35145
|
+
import path17 from "node:path";
|
|
34063
35146
|
var LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["127.0.0.1", "localhost", "[::1]"]);
|
|
34064
35147
|
var OPEN_TIMEOUT_MS = 1e4;
|
|
34065
35148
|
function createLauncherUrlOpener(environment, spawnLauncher = (command, arguments_2, options2) => spawn4(command, arguments_2, options2)) {
|
|
34066
35149
|
const launcher = environment.CODEXHOST_LAUNCHER_EXECUTABLE;
|
|
34067
|
-
if (!launcher || !
|
|
35150
|
+
if (!launcher || !path17.isAbsolute(launcher)) return void 0;
|
|
34068
35151
|
const launcherEnvironment = Object.fromEntries(
|
|
34069
35152
|
Object.entries(environment).filter(([name]) => {
|
|
34070
35153
|
const normalized = name.toUpperCase();
|
|
@@ -34122,9 +35205,9 @@ function installedHarnessPluginOptions(environment, managedRemoteHost = false, h
|
|
|
34122
35205
|
const opener = managedRemoteHost ? void 0 : createLauncherUrlOpener(environment);
|
|
34123
35206
|
return {
|
|
34124
35207
|
pluginRoots: [
|
|
34125
|
-
|
|
34126
|
-
environment[HARNESS_PLUGIN_DIRECTORY_ENV] ??
|
|
34127
|
-
environment.CODEXHOST_DATA_DIR ?
|
|
35208
|
+
path18.join(path18.dirname(fileURLToPath(hostRuntimeUrl)), "plugins"),
|
|
35209
|
+
environment[HARNESS_PLUGIN_DIRECTORY_ENV] ?? path18.join(
|
|
35210
|
+
environment.CODEXHOST_DATA_DIR ? path18.resolve(environment.CODEXHOST_DATA_DIR) : path18.join(os3.homedir(), ".codexhost"),
|
|
34128
35211
|
"plugins"
|
|
34129
35212
|
)
|
|
34130
35213
|
],
|
|
@@ -34252,9 +35335,9 @@ async function startDelegationControlServer(input) {
|
|
|
34252
35335
|
import { createHash as createHash8, randomUUID as randomUUID11 } from "node:crypto";
|
|
34253
35336
|
import { mkdir as mkdir7, open as open6, readFile as readFile7, rename as rename4, rm as rm7, stat as stat3 } from "node:fs/promises";
|
|
34254
35337
|
import os4 from "node:os";
|
|
34255
|
-
import
|
|
35338
|
+
import path19 from "node:path";
|
|
34256
35339
|
var SKILL_VERSION = 7;
|
|
34257
|
-
var SKILL_RELATIVE_PATH =
|
|
35340
|
+
var SKILL_RELATIVE_PATH = path19.join("skills", "codexhost-delegation", "SKILL.md");
|
|
34258
35341
|
var PREVIOUS_MANAGED_DIGESTS = [
|
|
34259
35342
|
"9d2f491850fb0b4084a31ba9b5e4a550b5e833747af322090d8ed0ff80b88c30",
|
|
34260
35343
|
"2bb0aebb9b06febbc6c0c0bcdb0b32506c7cdbf8dc3b734cc6b2a86621270e4e",
|
|
@@ -34327,8 +35410,8 @@ async function readOptional(filePath) {
|
|
|
34327
35410
|
}
|
|
34328
35411
|
}
|
|
34329
35412
|
async function atomicWrite(filePath, content) {
|
|
34330
|
-
await mkdir7(
|
|
34331
|
-
const temporaryPath =
|
|
35413
|
+
await mkdir7(path19.dirname(filePath), { recursive: true, mode: 448 });
|
|
35414
|
+
const temporaryPath = path19.join(path19.dirname(filePath), `.SKILL.md.${randomUUID11()}.tmp`);
|
|
34332
35415
|
const handle = await open6(temporaryPath, "wx", 384);
|
|
34333
35416
|
try {
|
|
34334
35417
|
await handle.writeFile(content, "utf8");
|
|
@@ -34345,8 +35428,8 @@ async function atomicWrite(filePath, content) {
|
|
|
34345
35428
|
async function installDelegationSkills(input = {}) {
|
|
34346
35429
|
const home = input.homeDirectory ?? os4.homedir();
|
|
34347
35430
|
const destinations = [
|
|
34348
|
-
|
|
34349
|
-
|
|
35431
|
+
path19.join(home, ".agents", SKILL_RELATIVE_PATH),
|
|
35432
|
+
path19.join(home, ".claude", SKILL_RELATIVE_PATH)
|
|
34350
35433
|
];
|
|
34351
35434
|
const knownDigests = /* @__PURE__ */ new Set([
|
|
34352
35435
|
CURRENT_DIGEST,
|
|
@@ -34413,7 +35496,7 @@ async function installDelegationSkills(input = {}) {
|
|
|
34413
35496
|
// packages/host-runtime/src/remote-control-app-server.ts
|
|
34414
35497
|
import { randomUUID as randomUUID12 } from "node:crypto";
|
|
34415
35498
|
import { mkdir as mkdir8, open as open7, rename as rename5, rm as rm8 } from "node:fs/promises";
|
|
34416
|
-
import
|
|
35499
|
+
import path20 from "node:path";
|
|
34417
35500
|
var REMOTE_CONTROL_BRIDGE_PIPE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_PIPE";
|
|
34418
35501
|
var REMOTE_CONTROL_BRIDGE_NODE_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_NODE_PATH";
|
|
34419
35502
|
var REMOTE_CONTROL_BRIDGE_RUNTIME_ENV = "CODEXHOST_REMOTE_CONTROL_BRIDGE_RUNTIME_PATH";
|
|
@@ -34424,8 +35507,8 @@ var BRIDGE_READY_METHOD = "codexhost/remote-control-bridge/ready";
|
|
|
34424
35507
|
function absoluteEnvironmentPath2(environment, name, fallback, platform = process.platform) {
|
|
34425
35508
|
const value2 = environment[name] ?? fallback;
|
|
34426
35509
|
if (!value2) return null;
|
|
34427
|
-
if (
|
|
34428
|
-
return platform === "win32" &&
|
|
35510
|
+
if (path20.isAbsolute(value2)) return path20.normalize(value2);
|
|
35511
|
+
return platform === "win32" && path20.win32.isAbsolute(value2) ? path20.win32.normalize(value2) : null;
|
|
34429
35512
|
}
|
|
34430
35513
|
function nodeCompatibleWindowsPath(value2) {
|
|
34431
35514
|
if (value2.startsWith("\\\\?\\UNC\\")) return `\\\\${value2.slice(8)}`;
|
|
@@ -34439,13 +35522,13 @@ function remoteControlBridgePipePath(processId = process.pid, instanceId = rando
|
|
|
34439
35522
|
}
|
|
34440
35523
|
function remoteControlBridgeDescriptorPath(environment) {
|
|
34441
35524
|
const root = environment.LOCALAPPDATA;
|
|
34442
|
-
if (!root || !
|
|
34443
|
-
return
|
|
35525
|
+
if (!root || !path20.isAbsolute(root)) return null;
|
|
35526
|
+
return path20.join(path20.normalize(root), "codexhost", REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE);
|
|
34444
35527
|
}
|
|
34445
35528
|
async function publishRemoteControlAppServerDescriptor(plan) {
|
|
34446
|
-
const directory =
|
|
35529
|
+
const directory = path20.dirname(plan.descriptorPath);
|
|
34447
35530
|
await mkdir8(directory, { recursive: true, mode: 448 });
|
|
34448
|
-
const temporaryPath =
|
|
35531
|
+
const temporaryPath = path20.join(
|
|
34449
35532
|
directory,
|
|
34450
35533
|
`.${REMOTE_CONTROL_BRIDGE_DESCRIPTOR_FILE}.${plan.descriptor.ownerPid}.${randomUUID12()}.tmp`
|
|
34451
35534
|
);
|
|
@@ -34746,9 +35829,9 @@ function hasLauncherManagedUpdateRuntime(environment, hostRuntimePath) {
|
|
|
34746
35829
|
if (!environment[UPDATE_RUNTIME_ENV.launcherPid]) return false;
|
|
34747
35830
|
const npmPackageRoot = environment[UPDATE_RUNTIME_ENV.npmPackageRoot];
|
|
34748
35831
|
if (!npmPackageRoot || !hostRuntimePath) return true;
|
|
34749
|
-
if (!
|
|
34750
|
-
const runtimePackageRoot =
|
|
34751
|
-
return
|
|
35832
|
+
if (!path21.isAbsolute(npmPackageRoot) || !path21.isAbsolute(hostRuntimePath)) return false;
|
|
35833
|
+
const runtimePackageRoot = path21.dirname(path21.dirname(path21.normalize(hostRuntimePath)));
|
|
35834
|
+
return path21.relative(path21.normalize(npmPackageRoot), runtimePackageRoot) === "";
|
|
34752
35835
|
}
|
|
34753
35836
|
function requiredRuntimeConfiguration(environment) {
|
|
34754
35837
|
const stockCodexPath = environment[STOCK_CODEX_PATH_ENV];
|
|
@@ -34894,8 +35977,8 @@ async function runHostRuntime(input) {
|
|
|
34894
35977
|
const socketPath = remoteAppServerSocketPath(delegationEnvironment, listenUrl);
|
|
34895
35978
|
const officialPlan = createRemoteOfficialAppServerPlan(input.arguments, socketPath);
|
|
34896
35979
|
const officialRuntimeScope = new OfficialRuntimeScope({
|
|
34897
|
-
permanentHome:
|
|
34898
|
-
delegationEnvironment.CODEX_HOME ??
|
|
35980
|
+
permanentHome: path21.resolve(
|
|
35981
|
+
delegationEnvironment.CODEX_HOME ?? path21.join(homedir2(), ".codex")
|
|
34899
35982
|
),
|
|
34900
35983
|
diagnosticOutput: process.stderr,
|
|
34901
35984
|
createBackend: () => createOwnedUnixBackend({
|
|
@@ -34991,7 +36074,7 @@ import {
|
|
|
34991
36074
|
stat as stat4,
|
|
34992
36075
|
writeFile as writeFile3
|
|
34993
36076
|
} from "node:fs/promises";
|
|
34994
|
-
import
|
|
36077
|
+
import path22 from "node:path";
|
|
34995
36078
|
var MANIFEST_FORMAT = 1;
|
|
34996
36079
|
var WRAPPER_MARKER = "# codexhost remote SSH wrapper v1";
|
|
34997
36080
|
var PROFILE_START = "# >>> codexhost remote SSH >>>";
|
|
@@ -35002,25 +36085,25 @@ function resolvePaths(options2) {
|
|
|
35002
36085
|
if (!configuredHome) {
|
|
35003
36086
|
throw new Error("A non-root HOME is required for remote Host installation");
|
|
35004
36087
|
}
|
|
35005
|
-
const home =
|
|
35006
|
-
if (!home || home ===
|
|
36088
|
+
const home = path22.resolve(configuredHome);
|
|
36089
|
+
if (!home || home === path22.parse(home).root) {
|
|
35007
36090
|
throw new Error("A non-root HOME is required for remote Host installation");
|
|
35008
36091
|
}
|
|
35009
|
-
const installRoot =
|
|
35010
|
-
const profilePath =
|
|
35011
|
-
options2.profilePath ??
|
|
36092
|
+
const installRoot = path22.resolve(options2.installRoot ?? path22.join(home, ".codexhost", "remote"));
|
|
36093
|
+
const profilePath = path22.resolve(
|
|
36094
|
+
options2.profilePath ?? path22.join(
|
|
35012
36095
|
home,
|
|
35013
|
-
|
|
36096
|
+
path22.basename(environment.SHELL ?? "") === "zsh" ? ".zshenv" : path22.basename(environment.SHELL ?? "") === "bash" ? ".bashrc" : ".profile"
|
|
35014
36097
|
)
|
|
35015
36098
|
);
|
|
35016
|
-
const binDirectory =
|
|
36099
|
+
const binDirectory = path22.join(installRoot, "bin");
|
|
35017
36100
|
return {
|
|
35018
36101
|
home,
|
|
35019
36102
|
installRoot,
|
|
35020
36103
|
binDirectory,
|
|
35021
|
-
wrapperPath:
|
|
35022
|
-
manifestPath:
|
|
35023
|
-
dataDirectory:
|
|
36104
|
+
wrapperPath: path22.join(binDirectory, "codex"),
|
|
36105
|
+
manifestPath: path22.join(installRoot, "manifest.json"),
|
|
36106
|
+
dataDirectory: path22.join(installRoot, "data"),
|
|
35024
36107
|
profilePath
|
|
35025
36108
|
};
|
|
35026
36109
|
}
|
|
@@ -35039,7 +36122,7 @@ async function fileSha256(filePath) {
|
|
|
35039
36122
|
return createHash9("sha256").update(await readFile8(filePath)).digest("hex");
|
|
35040
36123
|
}
|
|
35041
36124
|
async function executable(filePath, label) {
|
|
35042
|
-
const absolute =
|
|
36125
|
+
const absolute = path22.resolve(filePath);
|
|
35043
36126
|
try {
|
|
35044
36127
|
if (!(await stat4(absolute)).isFile()) throw new Error("not a regular file");
|
|
35045
36128
|
await access(absolute, fsConstants.X_OK);
|
|
@@ -35049,7 +36132,7 @@ async function executable(filePath, label) {
|
|
|
35049
36132
|
return absolute;
|
|
35050
36133
|
}
|
|
35051
36134
|
async function existingFile(filePath, label) {
|
|
35052
|
-
const absolute =
|
|
36135
|
+
const absolute = path22.resolve(filePath);
|
|
35053
36136
|
try {
|
|
35054
36137
|
const metadata = await stat4(absolute);
|
|
35055
36138
|
if (!metadata.isFile()) throw new Error("not a regular file");
|
|
@@ -35059,9 +36142,9 @@ async function existingFile(filePath, label) {
|
|
|
35059
36142
|
return absolute;
|
|
35060
36143
|
}
|
|
35061
36144
|
async function discoverExecutable(name, environment) {
|
|
35062
|
-
for (const directory of (environment.PATH ?? "").split(
|
|
36145
|
+
for (const directory of (environment.PATH ?? "").split(path22.delimiter)) {
|
|
35063
36146
|
if (!directory) continue;
|
|
35064
|
-
const candidate =
|
|
36147
|
+
const candidate = path22.resolve(directory, name);
|
|
35065
36148
|
try {
|
|
35066
36149
|
await access(candidate, fsConstants.X_OK);
|
|
35067
36150
|
return candidate;
|
|
@@ -35072,10 +36155,10 @@ async function discoverExecutable(name, environment) {
|
|
|
35072
36155
|
return null;
|
|
35073
36156
|
}
|
|
35074
36157
|
async function writeAtomic(filePath, contents, mode) {
|
|
35075
|
-
await mkdir9(
|
|
35076
|
-
const temporary =
|
|
35077
|
-
|
|
35078
|
-
`.${
|
|
36158
|
+
await mkdir9(path22.dirname(filePath), { recursive: true, mode: 448 });
|
|
36159
|
+
const temporary = path22.join(
|
|
36160
|
+
path22.dirname(filePath),
|
|
36161
|
+
`.${path22.basename(filePath)}.${process.pid}.${randomUUID13()}.tmp`
|
|
35079
36162
|
);
|
|
35080
36163
|
try {
|
|
35081
36164
|
if (typeof contents === "string") {
|
|
@@ -35096,10 +36179,10 @@ async function writeAtomic(filePath, contents, mode) {
|
|
|
35096
36179
|
}
|
|
35097
36180
|
}
|
|
35098
36181
|
async function writeAtomicExecutable(filePath, sourcePath) {
|
|
35099
|
-
await mkdir9(
|
|
35100
|
-
const temporary =
|
|
35101
|
-
|
|
35102
|
-
`.${
|
|
36182
|
+
await mkdir9(path22.dirname(filePath), { recursive: true, mode: 448 });
|
|
36183
|
+
const temporary = path22.join(
|
|
36184
|
+
path22.dirname(filePath),
|
|
36185
|
+
`.${path22.basename(filePath)}.${process.pid}.${randomUUID13()}.tmp`
|
|
35103
36186
|
);
|
|
35104
36187
|
try {
|
|
35105
36188
|
await copyFile3(sourcePath, temporary);
|
|
@@ -35140,8 +36223,8 @@ function removeManagedProfileBlock(contents) {
|
|
|
35140
36223
|
function installManagedProfileBlock(contents, manifest) {
|
|
35141
36224
|
const base = removeManagedProfileBlock(contents);
|
|
35142
36225
|
const environment = [
|
|
35143
|
-
`export CODEX_INSTALL_DIR=${shellQuote(
|
|
35144
|
-
`export PATH=${shellQuote(
|
|
36226
|
+
`export CODEX_INSTALL_DIR=${shellQuote(path22.dirname(manifest.wrapperPath))}`,
|
|
36227
|
+
`export PATH=${shellQuote(path22.dirname(manifest.wrapperPath))}:${shellQuote(path22.dirname(manifest.nodePath))}:${shellQuote(path22.dirname(manifest.stockCodexPath))}:"\${PATH:-/usr/local/bin:/usr/bin:/bin}"`,
|
|
35145
36228
|
`export CODEXHOST_STOCK_CODEX_PATH=${shellQuote(manifest.stockCodexPath)}`,
|
|
35146
36229
|
`export CODEXHOST_HOST_NODE_PATH=${shellQuote(manifest.nodePath)}`,
|
|
35147
36230
|
`export CODEXHOST_HOST_RUNTIME_PATH=${shellQuote(manifest.hostRuntimePath)}`,
|
|
@@ -35158,7 +36241,7 @@ function installManagedProfileBlock(contents, manifest) {
|
|
|
35158
36241
|
PROFILE_END,
|
|
35159
36242
|
""
|
|
35160
36243
|
].join("\n");
|
|
35161
|
-
if (
|
|
36244
|
+
if (path22.basename(manifest.profilePath) === ".bashrc") return `${block}${base}`;
|
|
35162
36245
|
const separator = base.length > 0 && !base.endsWith("\n") ? "\n" : "";
|
|
35163
36246
|
return `${base}${separator}${block}`;
|
|
35164
36247
|
}
|
|
@@ -35223,9 +36306,9 @@ async function readManifest(filePath) {
|
|
|
35223
36306
|
];
|
|
35224
36307
|
const optionalPaths = ["claudeCommand", "profileBackupPath"];
|
|
35225
36308
|
if (manifest.format !== MANIFEST_FORMAT || Object.keys(manifest).some((key) => !allowed.has(key)) || requiredPaths.some(
|
|
35226
|
-
(key) => typeof manifest[key] !== "string" || !
|
|
36309
|
+
(key) => typeof manifest[key] !== "string" || !path22.isAbsolute(manifest[key])
|
|
35227
36310
|
) || optionalPaths.some(
|
|
35228
|
-
(key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !
|
|
36311
|
+
(key) => manifest[key] !== void 0 && (typeof manifest[key] !== "string" || !path22.isAbsolute(manifest[key]))
|
|
35229
36312
|
) || manifest.entrypointSha256 !== void 0 && (typeof manifest.entrypointSha256 !== "string" || !/^[a-f0-9]{64}$/u.test(manifest.entrypointSha256))) {
|
|
35230
36313
|
throw new Error("Remote Host manifest has an unsupported format");
|
|
35231
36314
|
}
|
|
@@ -35454,7 +36537,7 @@ async function uninstallRemoteHost(options2) {
|
|
|
35454
36537
|
import { spawn as spawn5 } from "node:child_process";
|
|
35455
36538
|
import { stat as stat5 } from "node:fs/promises";
|
|
35456
36539
|
import net3 from "node:net";
|
|
35457
|
-
import
|
|
36540
|
+
import path23 from "node:path";
|
|
35458
36541
|
import { Duplex } from "node:stream";
|
|
35459
36542
|
|
|
35460
36543
|
// packages/host-runtime/src/app-server-websocket-options.ts
|
|
@@ -35481,9 +36564,9 @@ function classifyRemoteHostProbeResponse(response, socketPath) {
|
|
|
35481
36564
|
}
|
|
35482
36565
|
var lifecycleDependencyOverrides = {};
|
|
35483
36566
|
function socketPathFor(environment) {
|
|
35484
|
-
const codexHome = environment.CODEX_HOME ?? (environment.HOME ?
|
|
36567
|
+
const codexHome = environment.CODEX_HOME ?? (environment.HOME ? path23.join(environment.HOME, ".codex") : void 0);
|
|
35485
36568
|
if (!codexHome) throw new Error("CODEX_HOME or HOME is required for remote Host lifecycle");
|
|
35486
|
-
return
|
|
36569
|
+
return path23.join(codexHome, "app-server-control", "app-server-control.sock");
|
|
35487
36570
|
}
|
|
35488
36571
|
async function defaultSocketExists(socketPath) {
|
|
35489
36572
|
const metadata = await stat5(socketPath).catch((error51) => {
|
|
@@ -35613,7 +36696,7 @@ function installedManifest(status) {
|
|
|
35613
36696
|
function managedEnvironment(manifest, environment) {
|
|
35614
36697
|
return {
|
|
35615
36698
|
...environment,
|
|
35616
|
-
CODEX_INSTALL_DIR:
|
|
36699
|
+
CODEX_INSTALL_DIR: path23.dirname(manifest.wrapperPath),
|
|
35617
36700
|
CODEXHOST_STOCK_CODEX_PATH: manifest.stockCodexPath,
|
|
35618
36701
|
CODEXHOST_HOST_NODE_PATH: manifest.nodePath,
|
|
35619
36702
|
CODEXHOST_HOST_RUNTIME_PATH: manifest.hostRuntimePath,
|
|
@@ -35621,7 +36704,7 @@ function managedEnvironment(manifest, environment) {
|
|
|
35621
36704
|
CODEXHOST_DEFAULT_AGENT: "codex",
|
|
35622
36705
|
CODEXHOST_REMOTE_SSH_MANAGED: "1",
|
|
35623
36706
|
...manifest.claudeCommand ? { CODEXHOST_CLAUDE_COMMAND: manifest.claudeCommand } : {},
|
|
35624
|
-
PATH: `${
|
|
36707
|
+
PATH: `${path23.dirname(manifest.wrapperPath)}${path23.delimiter}${path23.dirname(manifest.stockCodexPath)}${path23.delimiter}${environment.PATH ?? "/usr/bin:/bin"}`
|
|
35625
36708
|
};
|
|
35626
36709
|
}
|
|
35627
36710
|
async function defaultRunTerminator(manifest, socketPath, role, environment) {
|
|
@@ -35963,25 +37046,25 @@ function consumeBrokerFrames(socket, onFrame, onError) {
|
|
|
35963
37046
|
|
|
35964
37047
|
// packages/harness-broker/dist/paths.js
|
|
35965
37048
|
import os5 from "node:os";
|
|
35966
|
-
import
|
|
37049
|
+
import path24 from "node:path";
|
|
35967
37050
|
var HARNESS_BROKER_DESCRIPTOR_ENV = "CODEXHOST_CLAUDE_BROKER_DESCRIPTOR";
|
|
35968
37051
|
var HARNESS_BROKER_DESCRIPTOR_FILE = "claude-code-broker-v1.json";
|
|
35969
37052
|
var HARNESS_BROKER_SOCKET_FILE = "claude-code-broker-v1.sock";
|
|
35970
37053
|
function defaultHarnessBrokerDirectory(environment = process.env) {
|
|
35971
37054
|
const home = environment.HOME || os5.homedir();
|
|
35972
|
-
return
|
|
37055
|
+
return path24.join(home, ".codexhost", "harness-broker");
|
|
35973
37056
|
}
|
|
35974
37057
|
function defaultHarnessBrokerDescriptorPath(environment = process.env, harnessId = "claude-code") {
|
|
35975
37058
|
harnessPluginIdSchema.parse(harnessId);
|
|
35976
37059
|
if (harnessId !== "claude-code")
|
|
35977
|
-
return
|
|
35978
|
-
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ??
|
|
37060
|
+
return path24.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.json`);
|
|
37061
|
+
return environment[HARNESS_BROKER_DESCRIPTOR_ENV] ?? path24.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_DESCRIPTOR_FILE);
|
|
35979
37062
|
}
|
|
35980
37063
|
function defaultHarnessBrokerSocketPath(environment = process.env, harnessId = "claude-code") {
|
|
35981
37064
|
harnessPluginIdSchema.parse(harnessId);
|
|
35982
37065
|
if (harnessId !== "claude-code")
|
|
35983
|
-
return
|
|
35984
|
-
return
|
|
37066
|
+
return path24.join(defaultHarnessBrokerDirectory(environment), `${harnessId}-broker-v1.sock`);
|
|
37067
|
+
return path24.join(defaultHarnessBrokerDirectory(environment), HARNESS_BROKER_SOCKET_FILE);
|
|
35985
37068
|
}
|
|
35986
37069
|
|
|
35987
37070
|
// packages/harness-broker/dist/validation.js
|
|
@@ -36218,7 +37301,7 @@ var harnessOutputSchema = external_exports.custom((value2) => {
|
|
|
36218
37301
|
import { randomBytes as randomBytes3, randomUUID as randomUUID14 } from "node:crypto";
|
|
36219
37302
|
import { chmod as chmod5, lstat as lstat9, mkdir as mkdir10, open as open8, readFile as readFile9, rename as rename7, rm as rm10 } from "node:fs/promises";
|
|
36220
37303
|
import net4, {} from "node:net";
|
|
36221
|
-
import
|
|
37304
|
+
import path25 from "node:path";
|
|
36222
37305
|
function harnessError(message, retryable = true) {
|
|
36223
37306
|
return { code: "unavailable", message, retryable, stage: "harnessBroker" };
|
|
36224
37307
|
}
|
|
@@ -36341,13 +37424,13 @@ async function prepareUnixSocketPath(socketPath) {
|
|
|
36341
37424
|
}
|
|
36342
37425
|
async function startHarnessBrokerServer(input) {
|
|
36343
37426
|
harnessPluginIdSchema.parse(input.adapter.harnessId);
|
|
36344
|
-
if (process.platform !== "win32" &&
|
|
37427
|
+
if (process.platform !== "win32" && path25.dirname(input.descriptorPath) !== path25.dirname(input.socketPath)) {
|
|
36345
37428
|
throw new Error("Harness broker descriptor and socket must share one private directory");
|
|
36346
37429
|
}
|
|
36347
37430
|
if (process.platform === "darwin" && Buffer.byteLength(input.socketPath) > 103) {
|
|
36348
37431
|
throw new Error("Harness broker Unix socket path is too long for macOS");
|
|
36349
37432
|
}
|
|
36350
|
-
await privateDirectory(
|
|
37433
|
+
await privateDirectory(path25.dirname(input.descriptorPath));
|
|
36351
37434
|
await assertNoLiveDescriptor(input.descriptorPath);
|
|
36352
37435
|
if (process.platform !== "win32")
|
|
36353
37436
|
await prepareUnixSocketPath(input.socketPath);
|