@codexhost/cli-win32-x64 0.1.2 → 0.1.4
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/app/codexhost-distribution.json +1 -1
- package/app/desktop-controller.mjs +94 -115
- package/app/host-runtime.mjs +64 -43
- package/app/renderer-extension.js +198 -47
- package/bin/codexhost.exe +0 -0
- package/libexec/codexhost-shim.exe +0 -0
- package/libexec/codexhost-updater.exe +0 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@ Run Pi and Claude Code as first-class external harnesses inside Codex Desktop.
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
|
-
npm install -g @codexhost/cli@0.1.
|
|
10
|
+
npm install -g @codexhost/cli@0.1.4
|
|
11
11
|
```
|
|
12
12
|
|
|
13
13
|
Do not install this package directly. npm selects it through the optional dependencies of `@codexhost/cli`.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"schemaVersion":1,"version":"0.1.
|
|
1
|
+
{"schemaVersion":1,"version":"0.1.4","distribution":"npm","target":"windows-x64"}
|
|
@@ -788,30 +788,12 @@ async function installRendererDraftPrewarmPolicy(inspector, rendererWebContentsI
|
|
|
788
788
|
}
|
|
789
789
|
|
|
790
790
|
// packages/desktop-control/src/renderer-control-session.ts
|
|
791
|
-
var RendererCompatibilityError = class extends Error {
|
|
792
|
-
constructor(capability, reason, cause) {
|
|
793
|
-
super(`Renderer compatibility boundary unavailable: ${capability}`, { cause });
|
|
794
|
-
this.capability = capability;
|
|
795
|
-
this.reason = reason;
|
|
796
|
-
this.name = "RendererCompatibilityError";
|
|
797
|
-
}
|
|
798
|
-
capability;
|
|
799
|
-
reason;
|
|
800
|
-
};
|
|
801
791
|
function isRecord4(value) {
|
|
802
792
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
803
793
|
}
|
|
804
794
|
function sleep(milliseconds) {
|
|
805
795
|
return new Promise((resolve) => setTimeout(resolve, milliseconds));
|
|
806
796
|
}
|
|
807
|
-
async function requireCompatibilityBoundary(capability, reason, operation) {
|
|
808
|
-
try {
|
|
809
|
-
return await operation();
|
|
810
|
-
} catch (error) {
|
|
811
|
-
if (error instanceof RendererCompatibilityError) throw error;
|
|
812
|
-
throw new RendererCompatibilityError(capability, reason, error);
|
|
813
|
-
}
|
|
814
|
-
}
|
|
815
797
|
function sameAgents(actual, expected) {
|
|
816
798
|
return actual.length === expected.length && actual.every((agent, index) => agent === expected[index]);
|
|
817
799
|
}
|
|
@@ -1040,39 +1022,26 @@ var InstalledRendererControlSession = class {
|
|
|
1040
1022
|
);
|
|
1041
1023
|
const existing = await this.operations.readBinding(this.inspector, selected.id).catch(() => null);
|
|
1042
1024
|
if (existing !== null) {
|
|
1043
|
-
const binding2 =
|
|
1044
|
-
"agent-routing",
|
|
1045
|
-
"agent-routing-structure-unavailable",
|
|
1046
|
-
() => validateBindingStatus(existing, this.enabledAgents)
|
|
1047
|
-
);
|
|
1025
|
+
const binding2 = validateBindingStatus(existing, this.enabledAgents);
|
|
1048
1026
|
this.#snapshot = { ...this.#snapshot, renderer: selected, binding: binding2 };
|
|
1049
1027
|
return this.#snapshot;
|
|
1050
1028
|
}
|
|
1051
|
-
const titlePolicyReadiness = await
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
() => waitForRendererTitlePolicyReady(
|
|
1055
|
-
() => this.operations.markTitlePolicyReady(this.inspector, selected.id),
|
|
1056
|
-
{ timeoutMs: this.timeoutMs, pollIntervalMs: this.pollIntervalMs }
|
|
1057
|
-
)
|
|
1029
|
+
const titlePolicyReadiness = await waitForRendererTitlePolicyReady(
|
|
1030
|
+
() => this.operations.markTitlePolicyReady(this.inspector, selected.id),
|
|
1031
|
+
{ timeoutMs: this.timeoutMs, pollIntervalMs: this.pollIntervalMs }
|
|
1058
1032
|
);
|
|
1059
1033
|
await this.operations.execute(this.inspector, selected.id, this.rendererSource);
|
|
1060
|
-
const binding = await
|
|
1061
|
-
|
|
1062
|
-
|
|
1063
|
-
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
this.enabledAgents,
|
|
1068
|
-
this.timeoutMs,
|
|
1069
|
-
this.pollIntervalMs
|
|
1070
|
-
)
|
|
1034
|
+
const binding = await waitForBinding(
|
|
1035
|
+
this.inspector,
|
|
1036
|
+
this.operations,
|
|
1037
|
+
selected.id,
|
|
1038
|
+
this.enabledAgents,
|
|
1039
|
+
this.timeoutMs,
|
|
1040
|
+
this.pollIntervalMs
|
|
1071
1041
|
);
|
|
1072
|
-
const draftPrewarmPolicy = await
|
|
1073
|
-
|
|
1074
|
-
|
|
1075
|
-
() => this.operations.installDraftPrewarmPolicy(this.inspector, selected.id)
|
|
1042
|
+
const draftPrewarmPolicy = await this.operations.installDraftPrewarmPolicy(
|
|
1043
|
+
this.inspector,
|
|
1044
|
+
selected.id
|
|
1076
1045
|
);
|
|
1077
1046
|
this.#snapshot = {
|
|
1078
1047
|
...this.#snapshot,
|
|
@@ -1124,41 +1093,28 @@ async function createRendererControlSession(options) {
|
|
|
1124
1093
|
const pollIntervalMs = options.pollIntervalMs ?? 250;
|
|
1125
1094
|
const operations = options.operations ?? defaultOperations;
|
|
1126
1095
|
const initial = await waitForRenderer(options.inspector, operations, timeoutMs, pollIntervalMs);
|
|
1127
|
-
const titlePolicy = await
|
|
1128
|
-
"title-isolation",
|
|
1129
|
-
"title-isolation-structure-unavailable",
|
|
1130
|
-
() => operations.installTitlePolicy(options.inspector, initial.id)
|
|
1131
|
-
);
|
|
1096
|
+
const titlePolicy = await operations.installTitlePolicy(options.inspector, initial.id);
|
|
1132
1097
|
await operations.reload(options.inspector, initial.id);
|
|
1133
1098
|
const selected = await waitForRenderer(options.inspector, operations, timeoutMs, pollIntervalMs);
|
|
1134
|
-
const titlePolicyReadiness = await
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
() => waitForRendererTitlePolicyReady(
|
|
1138
|
-
() => operations.markTitlePolicyReady(options.inspector, selected.id),
|
|
1139
|
-
{
|
|
1140
|
-
timeoutMs,
|
|
1141
|
-
pollIntervalMs
|
|
1142
|
-
}
|
|
1143
|
-
)
|
|
1144
|
-
);
|
|
1145
|
-
await operations.execute(options.inspector, selected.id, options.rendererSource);
|
|
1146
|
-
const binding = await requireCompatibilityBoundary(
|
|
1147
|
-
"agent-routing",
|
|
1148
|
-
"agent-routing-structure-unavailable",
|
|
1149
|
-
() => waitForBinding(
|
|
1150
|
-
options.inspector,
|
|
1151
|
-
operations,
|
|
1152
|
-
selected.id,
|
|
1153
|
-
enabledAgents,
|
|
1099
|
+
const titlePolicyReadiness = await waitForRendererTitlePolicyReady(
|
|
1100
|
+
() => operations.markTitlePolicyReady(options.inspector, selected.id),
|
|
1101
|
+
{
|
|
1154
1102
|
timeoutMs,
|
|
1155
1103
|
pollIntervalMs
|
|
1156
|
-
|
|
1104
|
+
}
|
|
1105
|
+
);
|
|
1106
|
+
await operations.execute(options.inspector, selected.id, options.rendererSource);
|
|
1107
|
+
const binding = await waitForBinding(
|
|
1108
|
+
options.inspector,
|
|
1109
|
+
operations,
|
|
1110
|
+
selected.id,
|
|
1111
|
+
enabledAgents,
|
|
1112
|
+
timeoutMs,
|
|
1113
|
+
pollIntervalMs
|
|
1157
1114
|
);
|
|
1158
|
-
const draftPrewarmPolicy = await
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
() => operations.installDraftPrewarmPolicy(options.inspector, selected.id)
|
|
1115
|
+
const draftPrewarmPolicy = await operations.installDraftPrewarmPolicy(
|
|
1116
|
+
options.inspector,
|
|
1117
|
+
selected.id
|
|
1162
1118
|
);
|
|
1163
1119
|
return new InstalledRendererControlSession(
|
|
1164
1120
|
options.inspector,
|
|
@@ -1203,6 +1159,8 @@ var PRODUCTION_INSTALL_TIMEOUT_MS = 9e4;
|
|
|
1203
1159
|
var DESKTOP_CONTROLLER_READINESS_MAX_BYTES = 512;
|
|
1204
1160
|
var TRANSIENT_INSTALL_ATTEMPTS = 3;
|
|
1205
1161
|
var TRANSIENT_INSTALL_RETRY_MS = 250;
|
|
1162
|
+
var RECOVERY_RETRY_INITIAL_MS = 3e4;
|
|
1163
|
+
var RECOVERY_RETRY_MAX_MS = 3e5;
|
|
1206
1164
|
function validCompatibilityIssue(state, issue) {
|
|
1207
1165
|
const keys = Object.keys(issue);
|
|
1208
1166
|
if (state === "compatible-with-warning") {
|
|
@@ -1217,24 +1175,10 @@ function validCompatibilityIssue(state, issue) {
|
|
|
1217
1175
|
"settings-surface"
|
|
1218
1176
|
].includes(issue.capability) && issue.reason === "capability-unavailable" && issue.observedIdentity === void 0 && keys.length === 2;
|
|
1219
1177
|
}
|
|
1220
|
-
|
|
1221
|
-
const pair = `${issue.capability}:${issue.reason}`;
|
|
1222
|
-
return [
|
|
1223
|
-
"title-isolation:title-isolation-structure-unavailable",
|
|
1224
|
-
"draft-routing:draft-routing-structure-unavailable",
|
|
1225
|
-
"agent-routing:agent-routing-structure-unavailable"
|
|
1226
|
-
].includes(pair) && issue.observedIdentity === void 0 && keys.length === 2;
|
|
1227
|
-
}
|
|
1228
|
-
return state === "detection-failed" && issue.capability === "compatibility-detection" && issue.reason === "inspection-failed" && issue.observedIdentity === void 0 && keys.length === 2;
|
|
1178
|
+
return false;
|
|
1229
1179
|
}
|
|
1230
1180
|
function serializeDesktopControllerReadiness(readiness) {
|
|
1231
|
-
if (readiness.schemaVersion !== 2 || ![
|
|
1232
|
-
"compatible",
|
|
1233
|
-
"compatible-with-warning",
|
|
1234
|
-
"degraded",
|
|
1235
|
-
"incompatible",
|
|
1236
|
-
"detection-failed"
|
|
1237
|
-
].includes(readiness.state) || !Array.isArray(readiness.issues) || readiness.issues.length > 1 || readiness.state === "compatible" && readiness.issues.length !== 0 || readiness.state !== "compatible" && (readiness.issues.length !== 1 || !readiness.issues[0] || !validCompatibilityIssue(readiness.state, readiness.issues[0])) || Object.keys(readiness).length !== 3) {
|
|
1181
|
+
if (readiness.schemaVersion !== 2 || !["compatible", "compatible-with-warning", "degraded"].includes(readiness.state) || !Array.isArray(readiness.issues) || readiness.issues.length > 1 || readiness.state === "compatible" && readiness.issues.length !== 0 || readiness.state !== "compatible" && (readiness.issues.length !== 1 || !readiness.issues[0] || !validCompatibilityIssue(readiness.state, readiness.issues[0])) || Object.keys(readiness).length !== 3) {
|
|
1238
1182
|
throw new Error("Desktop Controller readiness is invalid");
|
|
1239
1183
|
}
|
|
1240
1184
|
const line = JSON.stringify(readiness);
|
|
@@ -1358,12 +1302,23 @@ async function installProductionSession(options, dependencies) {
|
|
|
1358
1302
|
throw new Error("Desktop Controller exhausted Renderer installation attempts");
|
|
1359
1303
|
}
|
|
1360
1304
|
async function runDesktopController(options, signal, dependencies = defaultDependencies) {
|
|
1305
|
+
const configuration = `Object.defineProperty(window, "__codexhostProductionConfigV1", { configurable: true, value: { defaultAgent: ${JSON.stringify(options.defaultAgent)} } });`;
|
|
1306
|
+
const now = dependencies.now ?? Date.now;
|
|
1361
1307
|
let session;
|
|
1362
|
-
|
|
1308
|
+
let nextRecoveryAt = 0;
|
|
1309
|
+
let recoveryDelayMs = RECOVERY_RETRY_INITIAL_MS;
|
|
1310
|
+
const recordRecoveryFailure = () => {
|
|
1311
|
+
nextRecoveryAt = now() + recoveryDelayMs;
|
|
1312
|
+
recoveryDelayMs = Math.min(recoveryDelayMs * 2, RECOVERY_RETRY_MAX_MS);
|
|
1313
|
+
};
|
|
1314
|
+
const recordRecoverySuccess = () => {
|
|
1315
|
+
nextRecoveryAt = 0;
|
|
1316
|
+
recoveryDelayMs = RECOVERY_RETRY_INITIAL_MS;
|
|
1317
|
+
};
|
|
1318
|
+
const createSession = async () => {
|
|
1363
1319
|
const rendererSource = await dependencies.readRenderer(options.rendererPath);
|
|
1364
1320
|
if (rendererSource.trim().length === 0) throw new Error("production Renderer Bundle is empty");
|
|
1365
|
-
|
|
1366
|
-
session = await installProductionSession(
|
|
1321
|
+
return installProductionSession(
|
|
1367
1322
|
{
|
|
1368
1323
|
inspectorEndpoint: options.inspectorEndpoint,
|
|
1369
1324
|
rendererSource: `${configuration}
|
|
@@ -1373,19 +1328,13 @@ ${rendererSource}`,
|
|
|
1373
1328
|
},
|
|
1374
1329
|
dependencies
|
|
1375
1330
|
);
|
|
1376
|
-
}
|
|
1377
|
-
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
schemaVersion: 2,
|
|
1384
|
-
state: "detection-failed",
|
|
1385
|
-
issues: [{ capability: "compatibility-detection", reason: "inspection-failed" }]
|
|
1386
|
-
}
|
|
1387
|
-
);
|
|
1388
|
-
return;
|
|
1331
|
+
};
|
|
1332
|
+
try {
|
|
1333
|
+
session = await createSession();
|
|
1334
|
+
recordRecoverySuccess();
|
|
1335
|
+
} catch {
|
|
1336
|
+
session = void 0;
|
|
1337
|
+
recordRecoveryFailure();
|
|
1389
1338
|
}
|
|
1390
1339
|
let operation = Promise.resolve(void 0);
|
|
1391
1340
|
const useSession = (callback) => {
|
|
@@ -1396,22 +1345,45 @@ ${rendererSource}`,
|
|
|
1396
1345
|
);
|
|
1397
1346
|
return next;
|
|
1398
1347
|
};
|
|
1348
|
+
const resetSession = () => {
|
|
1349
|
+
session?.close();
|
|
1350
|
+
session = void 0;
|
|
1351
|
+
};
|
|
1352
|
+
const ensureSession = async () => {
|
|
1353
|
+
if (!session) session = await createSession();
|
|
1354
|
+
else await session.ensureInstalled();
|
|
1355
|
+
return session;
|
|
1356
|
+
};
|
|
1357
|
+
const recoverSession = async () => {
|
|
1358
|
+
try {
|
|
1359
|
+
const current = await ensureSession();
|
|
1360
|
+
recordRecoverySuccess();
|
|
1361
|
+
return current;
|
|
1362
|
+
} catch (error) {
|
|
1363
|
+
resetSession();
|
|
1364
|
+
recordRecoveryFailure();
|
|
1365
|
+
throw error;
|
|
1366
|
+
}
|
|
1367
|
+
};
|
|
1399
1368
|
let attachmentServer;
|
|
1400
1369
|
try {
|
|
1401
1370
|
attachmentServer = await dependencies.startAttachmentServer({
|
|
1402
1371
|
port: options.attachmentPort,
|
|
1403
1372
|
nonce: options.attachmentNonce,
|
|
1404
1373
|
attach: () => useSession(async () => {
|
|
1405
|
-
await
|
|
1406
|
-
await
|
|
1374
|
+
const current = await recoverSession();
|
|
1375
|
+
await current.activateDesktop();
|
|
1407
1376
|
}),
|
|
1408
1377
|
compatibilityUpdate: () => useSession(async () => {
|
|
1409
|
-
await
|
|
1410
|
-
return
|
|
1378
|
+
const current = await recoverSession();
|
|
1379
|
+
return current.requestCompatibilityUpdate();
|
|
1411
1380
|
}),
|
|
1412
|
-
shutdown: () => useSession(() =>
|
|
1381
|
+
shutdown: () => useSession(async () => {
|
|
1382
|
+
const current = await recoverSession();
|
|
1383
|
+
await current.quitDesktop();
|
|
1384
|
+
})
|
|
1413
1385
|
});
|
|
1414
|
-
const issues = session
|
|
1386
|
+
const issues = session?.snapshot.titlePolicy.warnings ?? [];
|
|
1415
1387
|
dependencies.ready({
|
|
1416
1388
|
schemaVersion: 2,
|
|
1417
1389
|
state: issues.length === 0 ? "compatible" : "compatible-with-warning",
|
|
@@ -1419,12 +1391,19 @@ ${rendererSource}`,
|
|
|
1419
1391
|
});
|
|
1420
1392
|
while (!signal.aborted) {
|
|
1421
1393
|
await dependencies.sleep(dependencies.monitorIntervalMs);
|
|
1422
|
-
if (
|
|
1394
|
+
if (signal.aborted) continue;
|
|
1395
|
+
await useSession(async () => {
|
|
1396
|
+
if (!session && now() < nextRecoveryAt) return;
|
|
1397
|
+
try {
|
|
1398
|
+
await recoverSession();
|
|
1399
|
+
} catch {
|
|
1400
|
+
}
|
|
1401
|
+
});
|
|
1423
1402
|
}
|
|
1424
1403
|
} finally {
|
|
1425
1404
|
await attachmentServer?.close();
|
|
1426
1405
|
await operation;
|
|
1427
|
-
|
|
1406
|
+
resetSession();
|
|
1428
1407
|
}
|
|
1429
1408
|
}
|
|
1430
1409
|
|
package/app/host-runtime.mjs
CHANGED
|
@@ -50582,7 +50582,7 @@ function isHostApprovalRequestId(value) {
|
|
|
50582
50582
|
function isHostQuestionRequestId(value) {
|
|
50583
50583
|
return typeof value === "number" && Number.isSafeInteger(value) && value >= HOST_QUESTION_REQUEST_ID_MIN && value <= HOST_QUESTION_REQUEST_ID_MAX;
|
|
50584
50584
|
}
|
|
50585
|
-
function classifyCreateRequestRoute(request,
|
|
50585
|
+
function classifyCreateRequestRoute(request, defaultAgent2) {
|
|
50586
50586
|
const route = decodeCreateRoute(request);
|
|
50587
50587
|
if (!route) return null;
|
|
50588
50588
|
if (route.harnessId !== "codex") {
|
|
@@ -50596,8 +50596,8 @@ function classifyCreateRequestRoute(request, defaultAgent) {
|
|
|
50596
50596
|
return {
|
|
50597
50597
|
requestMethod: "thread/start",
|
|
50598
50598
|
modelCarrier: "official-model",
|
|
50599
|
-
selectedHarness:
|
|
50600
|
-
selectionSource:
|
|
50599
|
+
selectedHarness: defaultAgent2,
|
|
50600
|
+
selectionSource: defaultAgent2 === "pi" ? "default-agent" : "official-model"
|
|
50601
50601
|
};
|
|
50602
50602
|
}
|
|
50603
50603
|
function requestObject(request) {
|
|
@@ -52789,13 +52789,25 @@ async function acquireUpdateOperationLock(stateDirectory) {
|
|
|
52789
52789
|
}
|
|
52790
52790
|
};
|
|
52791
52791
|
}
|
|
52792
|
+
function processIsAlive(processId) {
|
|
52793
|
+
if (!Number.isSafeInteger(processId) || processId <= 0)
|
|
52794
|
+
return false;
|
|
52795
|
+
try {
|
|
52796
|
+
process.kill(processId, 0);
|
|
52797
|
+
return true;
|
|
52798
|
+
} catch (error52) {
|
|
52799
|
+
return error52.code === "EPERM";
|
|
52800
|
+
}
|
|
52801
|
+
}
|
|
52792
52802
|
async function recoverUpdateOperationLock(stateDirectory) {
|
|
52793
52803
|
const lockPath = path9.join(stateDirectory, LOCK_FILE);
|
|
52794
52804
|
if (!await regularFile(lockPath))
|
|
52795
52805
|
return;
|
|
52806
|
+
let ownerPid;
|
|
52796
52807
|
let statusPath;
|
|
52797
52808
|
try {
|
|
52798
52809
|
const value = JSON.parse(await readFile3(lockPath, "utf8"));
|
|
52810
|
+
ownerPid = value.ownerPid;
|
|
52799
52811
|
statusPath = value.statusPath;
|
|
52800
52812
|
} catch {
|
|
52801
52813
|
return;
|
|
@@ -52804,8 +52816,9 @@ async function recoverUpdateOperationLock(stateDirectory) {
|
|
|
52804
52816
|
return;
|
|
52805
52817
|
try {
|
|
52806
52818
|
const status = parseUpdateStatus(JSON.parse(await readFile3(statusPath, "utf8")));
|
|
52807
|
-
if (TERMINAL_PHASES.has(status.phase))
|
|
52819
|
+
if (TERMINAL_PHASES.has(status.phase) || typeof ownerPid !== "number" || !processIsAlive(ownerPid)) {
|
|
52808
52820
|
await rm3(lockPath, { force: true });
|
|
52821
|
+
}
|
|
52809
52822
|
} catch {
|
|
52810
52823
|
}
|
|
52811
52824
|
}
|
|
@@ -53149,24 +53162,36 @@ function createBackgroundUpdateManager(dependencies = {}) {
|
|
|
53149
53162
|
// packages/host-runtime/src/update-coordinator.ts
|
|
53150
53163
|
var ERROR_MAX_LENGTH = 500;
|
|
53151
53164
|
var CONTROLLER_TIMEOUT_MS = 5e3;
|
|
53152
|
-
|
|
53153
|
-
|
|
53154
|
-
const check2 = await coordinator.check();
|
|
53155
|
-
if (check2.updateAvailable && check2.installationAvailable) {
|
|
53156
|
-
void coordinator.start().catch(() => void 0);
|
|
53157
|
-
return "update-started";
|
|
53158
|
-
}
|
|
53159
|
-
if (check2.error === null && check2.latestVersion !== null && check2.currentVersion === check2.latestVersion) {
|
|
53160
|
-
return "current";
|
|
53161
|
-
}
|
|
53162
|
-
} catch {
|
|
53163
|
-
}
|
|
53164
|
-
return "unavailable";
|
|
53165
|
-
}
|
|
53165
|
+
var UPDATER_READY_TIMEOUT_MS = 1e4;
|
|
53166
|
+
var UPDATER_READY_POLL_MS = 20;
|
|
53166
53167
|
function boundedError(error52) {
|
|
53167
53168
|
const message3 = error52 instanceof Error ? error52.message : String(error52);
|
|
53168
53169
|
return message3.slice(0, ERROR_MAX_LENGTH) || "Update operation failed";
|
|
53169
53170
|
}
|
|
53171
|
+
function delay4(milliseconds) {
|
|
53172
|
+
return new Promise((resolve2) => setTimeout(resolve2, milliseconds));
|
|
53173
|
+
}
|
|
53174
|
+
async function waitForUpdaterReady(manager, statusPath) {
|
|
53175
|
+
const deadline = Date.now() + UPDATER_READY_TIMEOUT_MS;
|
|
53176
|
+
while (Date.now() < deadline) {
|
|
53177
|
+
const status = await manager.readStatus(statusPath);
|
|
53178
|
+
switch (status?.phase) {
|
|
53179
|
+
case "waiting-for-exit":
|
|
53180
|
+
case "installing":
|
|
53181
|
+
case "restarting":
|
|
53182
|
+
case "succeeded":
|
|
53183
|
+
return;
|
|
53184
|
+
case "failed":
|
|
53185
|
+
throw new Error(status.error ?? "Background Updater failed before Desktop shutdown");
|
|
53186
|
+
case "prepared":
|
|
53187
|
+
break;
|
|
53188
|
+
default:
|
|
53189
|
+
throw new Error("Background Updater reported an unexpected startup phase");
|
|
53190
|
+
}
|
|
53191
|
+
await delay4(UPDATER_READY_POLL_MS);
|
|
53192
|
+
}
|
|
53193
|
+
throw new Error("Background Updater did not become ready before Desktop shutdown");
|
|
53194
|
+
}
|
|
53170
53195
|
function publicStatus(status) {
|
|
53171
53196
|
return {
|
|
53172
53197
|
version: status.version,
|
|
@@ -53207,7 +53232,8 @@ function requestControllerShutdown(controller) {
|
|
|
53207
53232
|
});
|
|
53208
53233
|
}
|
|
53209
53234
|
function createHostUpdateCoordinator(options) {
|
|
53210
|
-
const
|
|
53235
|
+
const platform = options.platform ?? process.platform;
|
|
53236
|
+
const manager = options.manager ?? createBackgroundUpdateManager({ platform });
|
|
53211
53237
|
const contextPromise = resolveInstalledUpdateContext({
|
|
53212
53238
|
hostRuntimePath: options.hostRuntimePath,
|
|
53213
53239
|
...options.environment ? { environment: options.environment } : {},
|
|
@@ -53350,7 +53376,8 @@ function createHostUpdateCoordinator(options) {
|
|
|
53350
53376
|
onPrepared
|
|
53351
53377
|
});
|
|
53352
53378
|
}
|
|
53353
|
-
manager.start(prepared2);
|
|
53379
|
+
if (platform !== "darwin") manager.start(prepared2);
|
|
53380
|
+
await waitForUpdaterReady(manager, prepared2.statusPath);
|
|
53354
53381
|
shutdownPending = context.controller;
|
|
53355
53382
|
scheduleShutdown();
|
|
53356
53383
|
} catch (error52) {
|
|
@@ -53387,31 +53414,25 @@ function createHostUpdateCoordinator(options) {
|
|
|
53387
53414
|
// packages/host-runtime/src/release-main.ts
|
|
53388
53415
|
var STOCK_CODEX_PATH_ENV = "CODEXHOST_STOCK_CODEX_PATH";
|
|
53389
53416
|
var DEFAULT_AGENT_ENV = "CODEXHOST_DEFAULT_AGENT";
|
|
53390
|
-
var COMPATIBILITY_UPDATE_ARGUMENT = "--codexhost-compatibility-update";
|
|
53391
53417
|
var arguments_ = process.argv.slice(2);
|
|
53392
53418
|
var updateCoordinator = createHostUpdateCoordinator({
|
|
53393
53419
|
hostRuntimePath: fileURLToPath(import.meta.url),
|
|
53394
53420
|
environment: process.env
|
|
53395
53421
|
});
|
|
53396
|
-
|
|
53397
|
-
|
|
53398
|
-
|
|
53399
|
-
|
|
53400
|
-
|
|
53401
|
-
|
|
53402
|
-
|
|
53403
|
-
|
|
53404
|
-
|
|
53405
|
-
|
|
53406
|
-
|
|
53407
|
-
|
|
53408
|
-
|
|
53409
|
-
|
|
53410
|
-
|
|
53411
|
-
|
|
53412
|
-
|
|
53413
|
-
updateCoordinator
|
|
53414
|
-
});
|
|
53415
|
-
void prefetchClaudeCodeModelCatalog(externalAdapters);
|
|
53416
|
-
process.exitCode = await host.run();
|
|
53417
|
-
}
|
|
53422
|
+
var stockCodexPath = process.env[STOCK_CODEX_PATH_ENV];
|
|
53423
|
+
if (!stockCodexPath) throw new Error(`${STOCK_CODEX_PATH_ENV} is required`);
|
|
53424
|
+
var defaultAgent = process.env[DEFAULT_AGENT_ENV];
|
|
53425
|
+
if (defaultAgent !== "codex" && defaultAgent !== "pi") {
|
|
53426
|
+
throw new Error(`${DEFAULT_AGENT_ENV} must be 'codex' or 'pi'`);
|
|
53427
|
+
}
|
|
53428
|
+
var externalAdapters = createExternalHarnessAdapters(process.env);
|
|
53429
|
+
var host = new AppServerHost({
|
|
53430
|
+
stockCodexPath,
|
|
53431
|
+
arguments: arguments_,
|
|
53432
|
+
defaultAgent,
|
|
53433
|
+
environment: process.env,
|
|
53434
|
+
externalAdapters,
|
|
53435
|
+
updateCoordinator
|
|
53436
|
+
});
|
|
53437
|
+
void prefetchClaudeCodeModelCatalog(externalAdapters);
|
|
53438
|
+
process.exitCode = await host.run();
|
|
@@ -17223,9 +17223,52 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17223
17223
|
var THREAD_PERMISSION_MODE_SELECT_METHOD = "codexhost/thread/permission-mode/select";
|
|
17224
17224
|
var THREAD_OWNERSHIP_LIST_METHOD = "codexhost/thread/ownership/list";
|
|
17225
17225
|
var THREAD_USAGE_INSPECT_METHOD = "codexhost/thread/usage/inspect";
|
|
17226
|
+
var THREAD_TOKEN_USAGE_UPDATED_METHOD = "thread/tokenUsage/updated";
|
|
17226
17227
|
var UPDATE_CHECK_METHOD = "codexhost/update/check";
|
|
17227
17228
|
var UPDATE_START_METHOD = "codexhost/update/start";
|
|
17228
17229
|
var UPDATE_STATUS_METHOD = "codexhost/update/status";
|
|
17230
|
+
function isRecord4(value) {
|
|
17231
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17232
|
+
}
|
|
17233
|
+
function notifiedThreadId(notification) {
|
|
17234
|
+
if (!isRecord4(notification) || notification.method !== THREAD_TOKEN_USAGE_UPDATED_METHOD) {
|
|
17235
|
+
return null;
|
|
17236
|
+
}
|
|
17237
|
+
const params = notification.params;
|
|
17238
|
+
if (!isRecord4(params)) return null;
|
|
17239
|
+
const parsed = hostThreadIdSchema.safeParse(params.threadId);
|
|
17240
|
+
return parsed.success ? parsed.data : null;
|
|
17241
|
+
}
|
|
17242
|
+
function createThreadUsageSubscriptionRelay() {
|
|
17243
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
17244
|
+
let removeNotificationCallback = null;
|
|
17245
|
+
return {
|
|
17246
|
+
connect(client) {
|
|
17247
|
+
if (removeNotificationCallback || listeners.size === 0) return;
|
|
17248
|
+
try {
|
|
17249
|
+
removeNotificationCallback = client.subscribeThreadUsage?.((update) => {
|
|
17250
|
+
for (const listener of listeners) listener(update);
|
|
17251
|
+
}) ?? null;
|
|
17252
|
+
} catch {
|
|
17253
|
+
removeNotificationCallback = null;
|
|
17254
|
+
}
|
|
17255
|
+
},
|
|
17256
|
+
subscribe(listener) {
|
|
17257
|
+
listeners.add(listener);
|
|
17258
|
+
return () => {
|
|
17259
|
+
listeners.delete(listener);
|
|
17260
|
+
if (listeners.size > 0) return;
|
|
17261
|
+
removeNotificationCallback?.();
|
|
17262
|
+
removeNotificationCallback = null;
|
|
17263
|
+
};
|
|
17264
|
+
},
|
|
17265
|
+
dispose() {
|
|
17266
|
+
removeNotificationCallback?.();
|
|
17267
|
+
removeNotificationCallback = null;
|
|
17268
|
+
listeners.clear();
|
|
17269
|
+
}
|
|
17270
|
+
};
|
|
17271
|
+
}
|
|
17229
17272
|
function createRendererModelClient(candidates) {
|
|
17230
17273
|
const managers = candidates.filter(
|
|
17231
17274
|
(candidate) => typeof candidate.sendRequest === "function"
|
|
@@ -17279,6 +17322,29 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17279
17322
|
return result;
|
|
17280
17323
|
},
|
|
17281
17324
|
inspectThreadUsage,
|
|
17325
|
+
subscribeThreadUsage(listener) {
|
|
17326
|
+
if (typeof manager.addNotificationCallback !== "function") return () => void 0;
|
|
17327
|
+
let disposed = false;
|
|
17328
|
+
const generations = /* @__PURE__ */ new Map();
|
|
17329
|
+
const removeNotificationCallback = manager.addNotificationCallback(
|
|
17330
|
+
THREAD_TOKEN_USAGE_UPDATED_METHOD,
|
|
17331
|
+
(notification) => {
|
|
17332
|
+
const threadId = notifiedThreadId(notification);
|
|
17333
|
+
if (!threadId) return;
|
|
17334
|
+
const generation = (generations.get(threadId) ?? 0) + 1;
|
|
17335
|
+
generations.set(threadId, generation);
|
|
17336
|
+
void inspectThreadUsage({ threadId }).then((update) => {
|
|
17337
|
+
if (!disposed && generations.get(threadId) === generation) listener(update);
|
|
17338
|
+
}).catch(() => void 0);
|
|
17339
|
+
}
|
|
17340
|
+
);
|
|
17341
|
+
return () => {
|
|
17342
|
+
if (disposed) return;
|
|
17343
|
+
disposed = true;
|
|
17344
|
+
generations.clear();
|
|
17345
|
+
removeNotificationCallback();
|
|
17346
|
+
};
|
|
17347
|
+
},
|
|
17282
17348
|
selectThreadModel,
|
|
17283
17349
|
selectThreadThinking,
|
|
17284
17350
|
selectThreadPermissionMode,
|
|
@@ -17331,7 +17397,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17331
17397
|
function isTransportModelId(model) {
|
|
17332
17398
|
return isPiTransportModelId(model) || isClaudeTransportModelId(model);
|
|
17333
17399
|
}
|
|
17334
|
-
function
|
|
17400
|
+
function isRecord5(value) {
|
|
17335
17401
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17336
17402
|
}
|
|
17337
17403
|
function piTransportModelId(model, thinkingOptionId) {
|
|
@@ -17402,7 +17468,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17402
17468
|
return (typeof value === "object" || typeof value === "function") && value !== null && typeof value.prewarmThreadStart === "function";
|
|
17403
17469
|
}
|
|
17404
17470
|
function isActiveRequestManager(value) {
|
|
17405
|
-
if (!
|
|
17471
|
+
if (!isRecord5(value) || typeof value.sendRequest !== "function") return false;
|
|
17406
17472
|
const source = Function.prototype.toString.call(value.sendRequest);
|
|
17407
17473
|
return source.includes("send-cli-request-for-host") && hasPrewarmMethod(value.requestClient);
|
|
17408
17474
|
}
|
|
@@ -17438,7 +17504,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17438
17504
|
let hook = fiber.memoizedState;
|
|
17439
17505
|
for (let hookIndex = 0; hook && hookIndex < 100; hookIndex += 1) {
|
|
17440
17506
|
const hookState = hook.memoizedState;
|
|
17441
|
-
if (
|
|
17507
|
+
if (isRecord5(hookState)) {
|
|
17442
17508
|
const requestClient = hookState.requestClient;
|
|
17443
17509
|
if (isActiveRequestManager(hookState) && matchesCurrentPrewarmSignature(hookState)) {
|
|
17444
17510
|
targets.add(hookState);
|
|
@@ -17455,10 +17521,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17455
17521
|
return [...targets];
|
|
17456
17522
|
}
|
|
17457
17523
|
function isModelAtomState(value) {
|
|
17458
|
-
return
|
|
17524
|
+
return isRecord5(value) && isRecord5(value.atom) && typeof value.get === "function" && typeof value.set === "function";
|
|
17459
17525
|
}
|
|
17460
17526
|
function isModelSelection(value) {
|
|
17461
|
-
return value === null ||
|
|
17527
|
+
return value === null || isRecord5(value) && "model" in value && "reasoningEffort" in value;
|
|
17462
17528
|
}
|
|
17463
17529
|
function sameModelPowerSelection(left, right) {
|
|
17464
17530
|
return left === right || left !== null && right !== null && left.model === right.model && left.reasoningEffort === right.reasoningEffort;
|
|
@@ -17470,7 +17536,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17470
17536
|
const first = pairs[0];
|
|
17471
17537
|
if (!first) return null;
|
|
17472
17538
|
const value = first.optimistic.get();
|
|
17473
|
-
if (
|
|
17539
|
+
if (isRecord5(value) && "modelSettings" in value) return first.optimistic;
|
|
17474
17540
|
if (first.optimistic.atom === first.committed.atom) return null;
|
|
17475
17541
|
if (!pairs.every(
|
|
17476
17542
|
(pair) => pair.optimistic.atom === first.optimistic.atom && pair.committed.atom === first.committed.atom && sameTarget2(pair.target, first.target)
|
|
@@ -17504,7 +17570,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17504
17570
|
let fiber = fiberName ? Object.getOwnPropertyDescriptor(button, fiberName)?.value : null;
|
|
17505
17571
|
for (let depth = 0; fiber && depth < 60; depth += 1) {
|
|
17506
17572
|
const props = fiber.memoizedProps;
|
|
17507
|
-
if (
|
|
17573
|
+
if (isRecord5(props) && typeof props.onSelectModel === "function" && typeof props.onSelectReasoningEffort === "function" && "reasoningEffort" in props && isRecord5(props.fallbackPowerSelection)) {
|
|
17508
17574
|
matches.push({ callback: props.onSelectModel, value: props.reasoningEffort });
|
|
17509
17575
|
}
|
|
17510
17576
|
const parent = fiber.return;
|
|
@@ -17529,9 +17595,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17529
17595
|
let fiber = fiberName ? Object.getOwnPropertyDescriptor(button, fiberName)?.value : null;
|
|
17530
17596
|
for (let depth = 0; fiber && depth < 60; depth += 1) {
|
|
17531
17597
|
const props = fiber.memoizedProps;
|
|
17532
|
-
if (!control &&
|
|
17598
|
+
if (!control && isRecord5(props) && "model" in props && "reasoningEffort" in props && typeof props.onSelectModel === "function") {
|
|
17533
17599
|
const selection = { model: props.model, reasoningEffort: props.reasoningEffort };
|
|
17534
|
-
const fallbackSelection =
|
|
17600
|
+
const fallbackSelection = isRecord5(props.fallbackPowerSelection) ? props.fallbackPowerSelection : null;
|
|
17535
17601
|
control = {
|
|
17536
17602
|
codexSelection: isTransportModelId(selection.model) ? fallbackSelection : selection,
|
|
17537
17603
|
selection,
|
|
@@ -17557,8 +17623,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17557
17623
|
let fiber = findComposerFiber(composer);
|
|
17558
17624
|
for (let depth = 0; fiber && depth < 120; depth += 1) {
|
|
17559
17625
|
const updateQueue = fiber.updateQueue;
|
|
17560
|
-
const memoCache =
|
|
17561
|
-
const data =
|
|
17626
|
+
const memoCache = isRecord5(updateQueue) ? updateQueue.memoCache : null;
|
|
17627
|
+
const data = isRecord5(memoCache) && Array.isArray(memoCache.data) ? memoCache.data : [];
|
|
17562
17628
|
for (let index = 0; index + 1 < data.length; index += 1) {
|
|
17563
17629
|
const compact = data[index];
|
|
17564
17630
|
const resolved = data[index + 1];
|
|
@@ -17571,7 +17637,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17571
17637
|
} catch {
|
|
17572
17638
|
continue;
|
|
17573
17639
|
}
|
|
17574
|
-
if (!
|
|
17640
|
+
if (!isRecord5(value) || !("modelSettings" in value)) continue;
|
|
17575
17641
|
const target = resolved[2] === null || resolved[2].startsWith("client-new-thread:") ? ["default", resolved[2]] : ["conversation", resolved[2]];
|
|
17576
17642
|
compactPairs.push({ optimistic: compact[1], committed: resolved[3], target });
|
|
17577
17643
|
}
|
|
@@ -17633,7 +17699,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17633
17699
|
reasoningEffort: reasoningEffort.value
|
|
17634
17700
|
};
|
|
17635
17701
|
}
|
|
17636
|
-
if (!
|
|
17702
|
+
if (!isRecord5(current) || !("modelSettings" in current)) return null;
|
|
17637
17703
|
const picker = findModelPickerControl(composer);
|
|
17638
17704
|
if (!picker.found) return null;
|
|
17639
17705
|
return {
|
|
@@ -17648,10 +17714,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17648
17714
|
};
|
|
17649
17715
|
}
|
|
17650
17716
|
function isMainProcessTitlePolicyReady(value) {
|
|
17651
|
-
return
|
|
17717
|
+
return isRecord5(value) && value.state === "ready";
|
|
17652
17718
|
}
|
|
17653
17719
|
function isDraftPrewarmPolicyReady(value) {
|
|
17654
|
-
return
|
|
17720
|
+
return isRecord5(value) && value.state === "ready" && typeof value.clear === "function";
|
|
17655
17721
|
}
|
|
17656
17722
|
async function waitForRendererDraftPrewarmPolicy(target) {
|
|
17657
17723
|
const deadline = Date.now() + DRAFT_PREWARM_POLICY_WAIT_TIMEOUT_MS;
|
|
@@ -17695,9 +17761,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17695
17761
|
dispose() {
|
|
17696
17762
|
}
|
|
17697
17763
|
});
|
|
17764
|
+
const usageSubscription = createThreadUsageSubscriptionRelay();
|
|
17698
17765
|
const currentModelClient = () => {
|
|
17699
17766
|
const client = createRendererModelClient(findActivePrewarmTargets(document));
|
|
17700
17767
|
if (!client) throw new Error("Renderer Model request manager is unavailable");
|
|
17768
|
+
usageSubscription.connect(client);
|
|
17701
17769
|
return client;
|
|
17702
17770
|
};
|
|
17703
17771
|
const modelControl = Object.freeze({
|
|
@@ -17705,6 +17773,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17705
17773
|
inspectHarness: (input) => currentModelClient().inspectHarness(input),
|
|
17706
17774
|
inspectThread: (input) => currentModelClient().inspectThread(input),
|
|
17707
17775
|
inspectThreadUsage: (input) => currentModelClient().inspectThreadUsage(input),
|
|
17776
|
+
subscribeThreadUsage: (listener) => usageSubscription.subscribe(listener),
|
|
17708
17777
|
listThreadOwnership: (input) => currentModelClient().listThreadOwnership(input),
|
|
17709
17778
|
selectThreadModel: (input) => currentModelClient().selectThreadModel(input),
|
|
17710
17779
|
selectThreadThinking: (input) => currentModelClient().selectThreadThinking(input),
|
|
@@ -17783,6 +17852,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17783
17852
|
disposed = true;
|
|
17784
17853
|
observer.disconnect();
|
|
17785
17854
|
forkControl.dispose();
|
|
17855
|
+
usageSubscription.dispose();
|
|
17786
17856
|
modelController = null;
|
|
17787
17857
|
officialSelection = null;
|
|
17788
17858
|
hasOfficialSelection = false;
|
|
@@ -17827,11 +17897,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17827
17897
|
return null;
|
|
17828
17898
|
}
|
|
17829
17899
|
}
|
|
17830
|
-
function
|
|
17900
|
+
function isRecord6(value) {
|
|
17831
17901
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17832
17902
|
}
|
|
17833
17903
|
function parseExternalConfiguration(value) {
|
|
17834
|
-
if (!
|
|
17904
|
+
if (!isRecord6(value)) return void 0;
|
|
17835
17905
|
const model = harnessModelRefSchema.safeParse(value.model);
|
|
17836
17906
|
if (!model.success) return void 0;
|
|
17837
17907
|
const thinkingOptionId = harnessThinkingOptionIdSchema.safeParse(value.thinkingOptionId);
|
|
@@ -17846,9 +17916,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17846
17916
|
const raw = storage.getItem(RENDERER_NEW_THREAD_PREFERENCE_KEY);
|
|
17847
17917
|
if (!raw) return void 0;
|
|
17848
17918
|
const parsed = JSON.parse(raw);
|
|
17849
|
-
if (!
|
|
17919
|
+
if (!isRecord6(parsed) || parsed.version !== 1) return void 0;
|
|
17850
17920
|
if (!KNOWN_RENDERER_AGENTS.some((agent) => agent === parsed.lastAgent)) return void 0;
|
|
17851
|
-
const externalByAgent =
|
|
17921
|
+
const externalByAgent = isRecord6(parsed.externalByAgent) ? parsed.externalByAgent : {};
|
|
17852
17922
|
const pi = parseExternalConfiguration(externalByAgent.pi);
|
|
17853
17923
|
const claudeCode = parseExternalConfiguration(externalByAgent["claude-code"]);
|
|
17854
17924
|
return {
|
|
@@ -17918,7 +17988,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17918
17988
|
var GET_LOCALE_OVERRIDE_URL = "vscode://codex/get-setting";
|
|
17919
17989
|
var GET_LOCALE_INFO_URL = "vscode://codex/locale-info";
|
|
17920
17990
|
var DEFAULT_LOCALE_REQUEST_TIMEOUT_MS = 750;
|
|
17921
|
-
function
|
|
17991
|
+
function isRecord7(value) {
|
|
17922
17992
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17923
17993
|
}
|
|
17924
17994
|
function canonicalLocale(value) {
|
|
@@ -17940,7 +18010,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17940
18010
|
return new DOMException("The operation was aborted", "AbortError");
|
|
17941
18011
|
}
|
|
17942
18012
|
function parseLocaleOverride(value) {
|
|
17943
|
-
if (!
|
|
18013
|
+
if (!isRecord7(value) || !("value" in value)) {
|
|
17944
18014
|
throw new Error("Codex locale override response is malformed");
|
|
17945
18015
|
}
|
|
17946
18016
|
if (value.value === null) return { value: null };
|
|
@@ -17955,7 +18025,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17955
18025
|
return locale;
|
|
17956
18026
|
}
|
|
17957
18027
|
function parseLocaleInfo(value) {
|
|
17958
|
-
if (!
|
|
18028
|
+
if (!isRecord7(value)) throw new Error("Codex locale info response is malformed");
|
|
17959
18029
|
return {
|
|
17960
18030
|
ideLocale: optionalLocale(value.ideLocale, "IDE locale"),
|
|
17961
18031
|
systemLocale: optionalLocale(value.systemLocale, "system locale")
|
|
@@ -17984,7 +18054,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17984
18054
|
const onAbort = () => settle(() => reject(abortError()));
|
|
17985
18055
|
const onMessage = (event) => {
|
|
17986
18056
|
const message2 = event.data;
|
|
17987
|
-
if (!
|
|
18057
|
+
if (!isRecord7(message2) || message2.type !== "fetch-response") return;
|
|
17988
18058
|
if (message2.requestId !== requestId) return;
|
|
17989
18059
|
if (message2.responseType !== "success" || typeof message2.status !== "number" || message2.status < 200 || message2.status >= 300 || typeof message2.bodyJsonString !== "string") {
|
|
17990
18060
|
settle(() => reject(new Error("Codex locale request failed")));
|
|
@@ -18130,7 +18200,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18130
18200
|
updateSucceeded: "Update installed successfully.",
|
|
18131
18201
|
updateFailed: "Update failed.",
|
|
18132
18202
|
updateRetry: "Retry",
|
|
18133
|
-
|
|
18203
|
+
updateDownloadFromReleases: "Download from GitHub Releases",
|
|
18134
18204
|
pageLabels: Object.freeze({
|
|
18135
18205
|
connections: "Connections",
|
|
18136
18206
|
"model-pool": "Model Pool",
|
|
@@ -18175,7 +18245,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18175
18245
|
updateSucceeded: "\u66F4\u65B0\u5B89\u88C5\u6210\u529F\u3002",
|
|
18176
18246
|
updateFailed: "\u66F4\u65B0\u5931\u8D25\u3002",
|
|
18177
18247
|
updateRetry: "\u91CD\u8BD5",
|
|
18178
|
-
|
|
18248
|
+
updateDownloadFromReleases: "\u524D\u5F80 GitHub Releases \u4E0B\u8F7D",
|
|
18179
18249
|
pageLabels: Object.freeze({
|
|
18180
18250
|
connections: "\u8FDE\u63A5",
|
|
18181
18251
|
"model-pool": "\u6A21\u578B\u6C60",
|
|
@@ -18521,6 +18591,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18521
18591
|
}
|
|
18522
18592
|
|
|
18523
18593
|
// src/settings/pages.ts
|
|
18594
|
+
var CODEXHOST_RELEASES_LATEST_URL = "https://github.com/BytePioneer-AI/codex-host/releases/latest";
|
|
18524
18595
|
var DEFAULT_RENDERER_SETTINGS_PAGE_IDS = [
|
|
18525
18596
|
"connections",
|
|
18526
18597
|
"model-pool",
|
|
@@ -18625,7 +18696,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18625
18696
|
const panel = document2.createElement("section");
|
|
18626
18697
|
panel.className = "settings-update-panel";
|
|
18627
18698
|
panel.setAttribute("aria-live", "polite");
|
|
18628
|
-
|
|
18699
|
+
const actions = document2.createElement("div");
|
|
18700
|
+
actions.className = "settings-update-actions";
|
|
18701
|
+
const releaseLink = document2.createElement("a");
|
|
18702
|
+
releaseLink.className = "settings-update-link";
|
|
18703
|
+
releaseLink.href = CODEXHOST_RELEASES_LATEST_URL;
|
|
18704
|
+
releaseLink.target = "_blank";
|
|
18705
|
+
releaseLink.rel = "noopener noreferrer";
|
|
18706
|
+
releaseLink.append(
|
|
18707
|
+
messages.updateDownloadFromReleases,
|
|
18708
|
+
createRendererSettingsIcon("external-link", 14)
|
|
18709
|
+
);
|
|
18710
|
+
actions.append(releaseLink);
|
|
18711
|
+
context.content.append(heading, metadata, panel, actions);
|
|
18629
18712
|
let pollTimer;
|
|
18630
18713
|
let pollAttempts = 0;
|
|
18631
18714
|
let pending = false;
|
|
@@ -18730,6 +18813,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18730
18813
|
const renderCheck = (result, client) => {
|
|
18731
18814
|
currentVersionValue.textContent = `v${result.currentVersion}`;
|
|
18732
18815
|
installationValue.textContent = installationLabel(result.installation, messages);
|
|
18816
|
+
if (result.releaseNotesUrl) releaseLink.href = result.releaseNotesUrl;
|
|
18733
18817
|
const operationMessage = statusMessage(result.status, messages);
|
|
18734
18818
|
if (isPendingStatus(result.status)) {
|
|
18735
18819
|
renderPendingStatus(result.status, operationMessage ?? messages.updatePreparing);
|
|
@@ -18765,15 +18849,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18765
18849
|
update.addEventListener("click", () => start(client));
|
|
18766
18850
|
panel.append(update);
|
|
18767
18851
|
}
|
|
18768
|
-
if (result.releaseNotesUrl) {
|
|
18769
|
-
const notes = document2.createElement("a");
|
|
18770
|
-
notes.className = "settings-update-link";
|
|
18771
|
-
notes.href = result.releaseNotesUrl;
|
|
18772
|
-
notes.target = "_blank";
|
|
18773
|
-
notes.rel = "noopener noreferrer";
|
|
18774
|
-
notes.append(messages.updateViewRelease, createRendererSettingsIcon("external-link", 14));
|
|
18775
|
-
panel.append(notes);
|
|
18776
|
-
}
|
|
18777
18852
|
if (result.error) {
|
|
18778
18853
|
const error51 = document2.createElement("p");
|
|
18779
18854
|
error51.className = "settings-update-error";
|
|
@@ -18829,7 +18904,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18829
18904
|
}
|
|
18830
18905
|
|
|
18831
18906
|
// src/settings/shell.css
|
|
18832
|
-
var shell_default = ':host {\n --settings-bg: #181818;\n --settings-sidebar: #1c1c1c;\n --settings-panel: transparent;\n --settings-text: #f5f5f5;\n --settings-muted: #a1a1a1;\n --settings-border: rgb(255 255 255 / 10%);\n --settings-divider: rgb(255 255 255 / 10%);\n --settings-hover: rgb(255 255 255 / 6%);\n --settings-active: rgb(51 156 255 / 12%);\n --settings-focus: #339cff;\n color: var(--settings-text);\n color-scheme: dark;\n font:\n 14px/1.5 system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n letter-spacing: 0;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n letter-spacing: 0;\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\nbutton {\n color: inherit;\n}\n\n[hidden] {\n display: none !important;\n}\n\n.codexhost-settings-dialog {\n width: min(1120px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 32px));\n max-width: none;\n max-height: none;\n margin: auto;\n padding: 0;\n overflow: hidden;\n color: var(--settings-text);\n background: var(--settings-bg);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n box-shadow: 0 24px 64px rgb(0 0 0 / 38%);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: rgb(0 0 0 / 52%);\n}\n\n.settings-frame,\n.settings-layout {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n}\n\n.settings-frame {\n display: flex;\n flex-direction: column;\n}\n\n.settings-layout {\n flex: 1;\n display: grid;\n grid-template-columns: 240px minmax(0, 1fr);\n background: var(--settings-bg);\n}\n\n.settings-sidebar {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n background: var(--settings-sidebar);\n border-right: 1px solid var(--settings-border);\n padding-top: 28px;\n}\n\n.settings-header {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 64px;\n flex: none;\n padding: 0 16px;\n border-bottom: 1px solid var(--settings-border);\n}\n\n.settings-brand {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-brand__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n flex: none;\n color: var(--settings-text);\n}\n\n.settings-brand__mark .codexhost-settings-icon {\n width: 32px;\n height: 32px;\n object-fit: contain;\n}\n\n.settings-brand__copy {\n display: flex;\n min-width: 0;\n align-items: baseline;\n gap: 0;\n line-height: 20px;\n}\n\n.settings-brand__name {\n overflow: hidden;\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-brand__title {\n margin-left: 14px;\n padding-left: 14px;\n color: var(--settings-muted);\n font-size: 14px;\n font-weight: 400;\n border-left: 1px solid var(--settings-border);\n}\n\n.settings-nav {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 4px;\n padding: 0 12px 16px;\n overflow-y: auto;\n}\n\n.settings-nav-button {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n width: 100%;\n position: relative;\n min-height: 40px;\n flex: none;\n gap: 12px;\n padding: 8px 12px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 21px;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: 10px;\n cursor: pointer;\n}\n\n.settings-nav-button .codexhost-settings-icon {\n width: 18px;\n height: 18px;\n opacity: 0.9;\n}\n\n.settings-nav-button:hover {\n background: var(--settings-hover);\n}\n\n.settings-nav-button[aria-current="page"] {\n background: var(--settings-active);\n color: var(--settings-focus);\n}\n\n.settings-nav-button[aria-current="page"]::before {\n position: absolute;\n left: 0;\n width: 3px;\n height: 22px;\n content: "";\n background: var(--settings-focus);\n border-radius: 0 3px 3px 0;\n}\n\n.settings-nav-button span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex: none;\n padding: 0;\n color: var(--settings-muted);\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n}\n\n.settings-icon-button:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-icon-button:focus-visible,\n.settings-nav-button:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 1px;\n}\n\n.settings-page {\n display: block;\n position: relative;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n background: var(--settings-bg);\n scrollbar-gutter: stable;\n}\n\n.settings-page__content {\n width: min(930px, calc(100% - 80px));\n margin-inline: auto;\n}\n\n.settings-page__content {\n min-width: 0;\n padding: 44px 0 56px;\n}\n\n.settings-section-label {\n min-height: auto;\n padding: 0 0 28px;\n color: var(--settings-text);\n font-size: 24px;\n font-weight: 600;\n line-height: 30px;\n}\n\n.settings-status-list,\n.settings-empty {\n overflow: hidden;\n background: var(--settings-panel);\n}\n\n.settings-status-row {\n display: grid;\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\n position: relative;\n align-items: center;\n min-height: 88px;\n gap: 28px;\n padding: 16px 0;\n}\n\n.settings-status-row:not(:last-child)::after {\n content: "";\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 1px;\n background: var(--settings-divider);\n}\n\n.settings-status-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n color: var(--settings-text);\n gap: 14px;\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-status-row__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n flex: none;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 7%);\n border-radius: 50%;\n}\n\n.settings-status-badge {\n flex: none;\n padding: 5px 12px;\n color: var(--settings-muted);\n font-size: 13px;\n font-weight: 500;\n line-height: 18px;\n background: rgb(255 255 255 / 9%);\n border: 1px solid rgb(255 255 255 / 6%);\n border-radius: 6px;\n}\n\n.settings-status-row__detail {\n min-width: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-empty {\n display: flex;\n align-items: center;\n min-height: 72px;\n padding: 12px 16px;\n}\n\n.settings-empty > div {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n\n.settings-empty strong {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 500;\n line-height: 19px;\n}\n\n.settings-empty span {\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 19px;\n}\n\n.settings-page-error {\n padding: 16px;\n color: var(--settings-text);\n font-size: 13px;\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 20px;\n}\n\n.settings-update-metadata {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 24px;\n margin-bottom: 24px;\n padding: 0 4px 20px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-update-metadata__item {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n\n.settings-update-metadata__item span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-metadata__item strong {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-update-panel {\n display: grid;\n gap: 16px;\n min-height: 128px;\n padding: 20px;\n color: var(--settings-text);\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n}\n\n.settings-update-panel > strong,\n.settings-update-panel > span,\n.settings-update-summary,\n.settings-update-error {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-panel > span,\n.settings-update-summary {\n color: var(--settings-muted);\n}\n\n.settings-update-error {\n color: #ef4444;\n}\n\n.settings-update-progress {\n width: 100%;\n height: 8px;\n accent-color: #238be8;\n}\n\n.settings-update-progress-detail {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-notes {\n max-height: 240px;\n padding: 14px;\n overflow: auto;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n background: rgb(255 255 255 / 4%);\n border: 1px solid var(--settings-divider);\n border-radius: 6px;\n}\n\n.settings-update-version-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: 20px;\n min-height: 32px;\n color: var(--settings-muted);\n font-size: 13px;\n}\n\n.settings-update-version-row strong {\n color: var(--settings-text);\n font-size: 15px;\n}\n\n.settings-command-button,\n.settings-update-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: fit-content;\n min-height: 36px;\n gap: 8px;\n padding: 8px 12px;\n color: white;\n font: inherit;\n font-size: 13px;\n text-decoration: none;\n background: #1677d2;\n border: 1px solid #238be8;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.settings-command-button--secondary,\n.settings-update-link {\n color: var(--settings-text);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button:hover,\n.settings-update-link:hover {\n filter: brightness(1.08);\n}\n\n.settings-command-button:focus-visible,\n.settings-update-link:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 2px;\n}\n\n.codexhost-settings-icon {\n display: block;\n flex: none;\n stroke: currentColor;\n}\n\n@media (max-width: 720px) {\n .codexhost-settings-dialog {\n width: calc(100vw - 16px);\n height: calc(100vh - 16px);\n border-radius: 10px;\n }\n\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .settings-sidebar {\n border-right: 0;\n border-bottom: 1px solid var(--settings-border);\n }\n\n .settings-header {\n height: 56px;\n padding-inline: 14px;\n }\n\n .settings-sidebar {\n padding-top: 20px;\n }\n\n .settings-nav {\n flex: none;\n flex-direction: row;\n gap: 4px;\n padding: 7px 8px 8px;\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n .settings-nav-button {\n width: auto;\n min-width: max-content;\n min-height: 34px;\n grid-template-columns: 16px auto;\n border-radius: 10px;\n }\n\n .settings-page__content {\n width: calc(100% - 40px);\n }\n\n .settings-page__content {\n padding-top: 32px;\n padding-bottom: 32px;\n }\n\n .settings-section-label {\n padding-bottom: 20px;\n font-size: 20px;\n line-height: 26px;\n }\n\n .settings-status-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 16px;\n }\n\n .settings-status-row__detail {\n grid-column: 1 / -1;\n margin: -8px 0 0 58px;\n }\n}\n\n@media (forced-colors: active) {\n :host,\n :host([data-theme="dark"]) {\n --settings-bg: Canvas;\n --settings-sidebar: Canvas;\n --settings-panel: Canvas;\n --settings-text: CanvasText;\n --settings-muted: GrayText;\n --settings-border: ButtonBorder;\n --settings-divider: ButtonBorder;\n --settings-hover: Highlight;\n --settings-active: Highlight;\n --settings-focus: Highlight;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
|
|
18907
|
+
var shell_default = ':host {\n --settings-bg: #181818;\n --settings-sidebar: #1c1c1c;\n --settings-panel: transparent;\n --settings-text: #f5f5f5;\n --settings-muted: #a1a1a1;\n --settings-border: rgb(255 255 255 / 10%);\n --settings-divider: rgb(255 255 255 / 10%);\n --settings-hover: rgb(255 255 255 / 6%);\n --settings-active: rgb(51 156 255 / 12%);\n --settings-focus: #339cff;\n color: var(--settings-text);\n color-scheme: dark;\n font:\n 14px/1.5 system-ui,\n -apple-system,\n BlinkMacSystemFont,\n "Segoe UI",\n sans-serif;\n letter-spacing: 0;\n}\n\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n letter-spacing: 0;\n}\n\nbutton,\ninput,\nselect {\n font: inherit;\n}\n\nbutton {\n color: inherit;\n}\n\n[hidden] {\n display: none !important;\n}\n\n.codexhost-settings-dialog {\n width: min(1120px, calc(100vw - 32px));\n height: min(780px, calc(100vh - 32px));\n max-width: none;\n max-height: none;\n margin: auto;\n padding: 0;\n overflow: hidden;\n color: var(--settings-text);\n background: var(--settings-bg);\n border: 1px solid var(--settings-border);\n border-radius: 12px;\n box-shadow: 0 24px 64px rgb(0 0 0 / 38%);\n}\n\n.codexhost-settings-dialog::backdrop {\n background: rgb(0 0 0 / 52%);\n}\n\n.settings-frame,\n.settings-layout {\n width: 100%;\n height: 100%;\n min-width: 0;\n min-height: 0;\n}\n\n.settings-frame {\n display: flex;\n flex-direction: column;\n}\n\n.settings-layout {\n flex: 1;\n display: grid;\n grid-template-columns: 240px minmax(0, 1fr);\n background: var(--settings-bg);\n}\n\n.settings-sidebar {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex-direction: column;\n overflow: hidden;\n background: var(--settings-sidebar);\n border-right: 1px solid var(--settings-border);\n padding-top: 28px;\n}\n\n.settings-header {\n display: flex;\n align-items: center;\n min-width: 0;\n height: 64px;\n flex: none;\n padding: 0 16px;\n border-bottom: 1px solid var(--settings-border);\n}\n\n.settings-brand {\n display: flex;\n align-items: center;\n min-width: 0;\n gap: 8px;\n}\n\n.settings-brand__mark {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 36px;\n height: 36px;\n flex: none;\n color: var(--settings-text);\n}\n\n.settings-brand__mark .codexhost-settings-icon {\n width: 32px;\n height: 32px;\n object-fit: contain;\n}\n\n.settings-brand__copy {\n display: flex;\n min-width: 0;\n align-items: baseline;\n gap: 0;\n line-height: 20px;\n}\n\n.settings-brand__name {\n overflow: hidden;\n color: var(--settings-text);\n font-size: 14px;\n font-weight: 500;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-brand__title {\n margin-left: 14px;\n padding-left: 14px;\n color: var(--settings-muted);\n font-size: 14px;\n font-weight: 400;\n border-left: 1px solid var(--settings-border);\n}\n\n.settings-nav {\n display: flex;\n min-width: 0;\n min-height: 0;\n flex: 1;\n flex-direction: column;\n gap: 4px;\n padding: 0 12px 16px;\n overflow-y: auto;\n}\n\n.settings-nav-button {\n display: grid;\n grid-template-columns: 16px minmax(0, 1fr);\n align-items: center;\n width: 100%;\n position: relative;\n min-height: 40px;\n flex: none;\n gap: 12px;\n padding: 8px 12px;\n color: var(--settings-text);\n font-size: 14px;\n line-height: 21px;\n text-align: left;\n background: transparent;\n border: 0;\n border-radius: 10px;\n cursor: pointer;\n}\n\n.settings-nav-button .codexhost-settings-icon {\n width: 18px;\n height: 18px;\n opacity: 0.9;\n}\n\n.settings-nav-button:hover {\n background: var(--settings-hover);\n}\n\n.settings-nav-button[aria-current="page"] {\n background: var(--settings-active);\n color: var(--settings-focus);\n}\n\n.settings-nav-button[aria-current="page"]::before {\n position: absolute;\n left: 0;\n width: 3px;\n height: 22px;\n content: "";\n background: var(--settings-focus);\n border-radius: 0 3px 3px 0;\n}\n\n.settings-nav-button span {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.settings-icon-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 28px;\n height: 28px;\n flex: none;\n padding: 0;\n color: var(--settings-muted);\n background: transparent;\n border: 0;\n border-radius: 8px;\n cursor: pointer;\n}\n\n.settings-icon-button:hover {\n color: var(--settings-text);\n background: var(--settings-hover);\n}\n\n.settings-icon-button:focus-visible,\n.settings-nav-button:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 1px;\n}\n\n.settings-page {\n display: block;\n position: relative;\n min-width: 0;\n min-height: 0;\n overflow-y: auto;\n background: var(--settings-bg);\n scrollbar-gutter: stable;\n}\n\n.settings-page__content {\n width: min(930px, calc(100% - 80px));\n margin-inline: auto;\n}\n\n.settings-page__content {\n min-width: 0;\n padding: 44px 0 56px;\n}\n\n.settings-section-label {\n min-height: auto;\n padding: 0 0 28px;\n color: var(--settings-text);\n font-size: 24px;\n font-weight: 600;\n line-height: 30px;\n}\n\n.settings-status-list,\n.settings-empty {\n overflow: hidden;\n background: var(--settings-panel);\n}\n\n.settings-status-row {\n display: grid;\n grid-template-columns: minmax(170px, 1fr) auto minmax(280px, 1.45fr);\n position: relative;\n align-items: center;\n min-height: 88px;\n gap: 28px;\n padding: 16px 0;\n}\n\n.settings-status-row:not(:last-child)::after {\n content: "";\n position: absolute;\n right: 0;\n bottom: 0;\n left: 0;\n height: 1px;\n background: var(--settings-divider);\n}\n\n.settings-status-row__identity {\n display: inline-flex;\n align-items: center;\n min-width: 0;\n color: var(--settings-text);\n gap: 14px;\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-status-row__icon {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 44px;\n height: 44px;\n flex: none;\n color: var(--settings-muted);\n background: rgb(255 255 255 / 7%);\n border-radius: 50%;\n}\n\n.settings-status-badge {\n flex: none;\n padding: 5px 12px;\n color: var(--settings-muted);\n font-size: 13px;\n font-weight: 500;\n line-height: 18px;\n background: rgb(255 255 255 / 9%);\n border: 1px solid rgb(255 255 255 / 6%);\n border-radius: 6px;\n}\n\n.settings-status-row__detail {\n min-width: 0;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-empty {\n display: flex;\n align-items: center;\n min-height: 72px;\n padding: 12px 16px;\n}\n\n.settings-empty > div {\n display: grid;\n min-width: 0;\n gap: 2px;\n}\n\n.settings-empty strong {\n color: var(--settings-text);\n font-size: 13px;\n font-weight: 500;\n line-height: 19px;\n}\n\n.settings-empty span {\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 19px;\n}\n\n.settings-page-error {\n padding: 16px;\n color: var(--settings-text);\n font-size: 13px;\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 20px;\n}\n\n.settings-update-metadata {\n display: grid;\n grid-template-columns: repeat(2, minmax(0, 1fr));\n gap: 24px;\n margin-bottom: 24px;\n padding: 0 4px 20px;\n border-bottom: 1px solid var(--settings-divider);\n}\n\n.settings-update-metadata__item {\n display: grid;\n min-width: 0;\n gap: 4px;\n}\n\n.settings-update-metadata__item span {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-metadata__item strong {\n min-width: 0;\n overflow-wrap: anywhere;\n color: var(--settings-text);\n font-size: 15px;\n font-weight: 500;\n line-height: 22px;\n}\n\n.settings-update-panel {\n display: grid;\n gap: 16px;\n min-height: 128px;\n padding: 20px;\n color: var(--settings-text);\n background: var(--settings-panel);\n border: 1px solid var(--settings-border);\n border-radius: 8px;\n}\n\n.settings-update-panel > strong,\n.settings-update-panel > span,\n.settings-update-summary,\n.settings-update-error {\n margin: 0;\n overflow-wrap: anywhere;\n font-size: 13px;\n line-height: 20px;\n}\n\n.settings-update-panel > span,\n.settings-update-summary {\n color: var(--settings-muted);\n}\n\n.settings-update-error {\n color: #ef4444;\n}\n\n.settings-update-progress {\n width: 100%;\n height: 8px;\n accent-color: #238be8;\n}\n\n.settings-update-progress-detail {\n color: var(--settings-muted);\n font-size: 12px;\n line-height: 18px;\n}\n\n.settings-update-notes {\n max-height: 240px;\n padding: 14px;\n overflow: auto;\n color: var(--settings-muted);\n font-size: 13px;\n line-height: 20px;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n background: rgb(255 255 255 / 4%);\n border: 1px solid var(--settings-divider);\n border-radius: 6px;\n}\n\n.settings-update-version-row {\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n gap: 20px;\n min-height: 32px;\n color: var(--settings-muted);\n font-size: 13px;\n}\n\n.settings-update-version-row strong {\n color: var(--settings-text);\n font-size: 15px;\n}\n\n.settings-update-actions {\n display: flex;\n min-width: 0;\n margin-top: 16px;\n}\n\n.settings-command-button,\n.settings-update-link {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: fit-content;\n min-height: 36px;\n gap: 8px;\n padding: 8px 12px;\n color: white;\n font: inherit;\n font-size: 13px;\n text-decoration: none;\n background: #1677d2;\n border: 1px solid #238be8;\n border-radius: 6px;\n cursor: pointer;\n}\n\n.settings-command-button--secondary,\n.settings-update-link {\n color: var(--settings-text);\n background: transparent;\n border-color: var(--settings-border);\n}\n\n.settings-command-button:hover,\n.settings-update-link:hover {\n filter: brightness(1.08);\n}\n\n.settings-command-button:focus-visible,\n.settings-update-link:focus-visible {\n outline: 2px solid var(--settings-focus);\n outline-offset: 2px;\n}\n\n.codexhost-settings-icon {\n display: block;\n flex: none;\n stroke: currentColor;\n}\n\n@media (max-width: 720px) {\n .codexhost-settings-dialog {\n width: calc(100vw - 16px);\n height: calc(100vh - 16px);\n border-radius: 10px;\n }\n\n .settings-layout {\n grid-template-columns: minmax(0, 1fr);\n grid-template-rows: auto minmax(0, 1fr);\n }\n\n .settings-sidebar {\n border-right: 0;\n border-bottom: 1px solid var(--settings-border);\n }\n\n .settings-header {\n height: 56px;\n padding-inline: 14px;\n }\n\n .settings-sidebar {\n padding-top: 20px;\n }\n\n .settings-nav {\n flex: none;\n flex-direction: row;\n gap: 4px;\n padding: 7px 8px 8px;\n overflow-x: auto;\n overflow-y: hidden;\n }\n\n .settings-nav-button {\n width: auto;\n min-width: max-content;\n min-height: 34px;\n grid-template-columns: 16px auto;\n border-radius: 10px;\n }\n\n .settings-page__content {\n width: calc(100% - 40px);\n }\n\n .settings-page__content {\n padding-top: 32px;\n padding-bottom: 32px;\n }\n\n .settings-section-label {\n padding-bottom: 20px;\n font-size: 20px;\n line-height: 26px;\n }\n\n .settings-status-row {\n grid-template-columns: minmax(0, 1fr) auto;\n gap: 16px;\n }\n\n .settings-status-row__detail {\n grid-column: 1 / -1;\n margin: -8px 0 0 58px;\n }\n}\n\n@media (forced-colors: active) {\n :host,\n :host([data-theme="dark"]) {\n --settings-bg: Canvas;\n --settings-sidebar: Canvas;\n --settings-panel: Canvas;\n --settings-text: CanvasText;\n --settings-muted: GrayText;\n --settings-border: ButtonBorder;\n --settings-divider: ButtonBorder;\n --settings-hover: Highlight;\n --settings-active: Highlight;\n --settings-focus: Highlight;\n }\n}\n\n@media (prefers-reduced-motion: reduce) {\n *,\n *::before,\n *::after {\n scroll-behavior: auto !important;\n }\n}\n';
|
|
18833
18908
|
|
|
18834
18909
|
// src/settings/shell.ts
|
|
18835
18910
|
var SETTINGS_SHELL_ATTRIBUTE = "data-codexhost-settings-shell";
|
|
@@ -19265,6 +19340,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19265
19340
|
}
|
|
19266
19341
|
|
|
19267
19342
|
// src/renderer-settings-lifecycle.ts
|
|
19343
|
+
var UPDATE_CHECK_TIMEOUT_MS = 5e3;
|
|
19344
|
+
var UPDATE_RETRY_DELAYS_MS = [1e3, 3e3, 1e4, 3e4];
|
|
19268
19345
|
function installRendererSettingsLifecycle(ownerWindow = window, options = {}) {
|
|
19269
19346
|
const lifecycleController = new AbortController();
|
|
19270
19347
|
let locale = resolveRendererSettingsLocale(ownerWindow.navigator.languages);
|
|
@@ -19272,6 +19349,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19272
19349
|
let trigger = null;
|
|
19273
19350
|
let localeRequest = null;
|
|
19274
19351
|
let checkedUpdateClient = null;
|
|
19352
|
+
let retryUpdateClient = null;
|
|
19353
|
+
let updateRetryTimer = null;
|
|
19354
|
+
let updateRetryAttempt = 0;
|
|
19275
19355
|
let updateCheckGeneration = 0;
|
|
19276
19356
|
let updateAvailable = false;
|
|
19277
19357
|
let openGeneration = 0;
|
|
@@ -19334,16 +19414,65 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19334
19414
|
localeRequest = request;
|
|
19335
19415
|
return request;
|
|
19336
19416
|
};
|
|
19417
|
+
const clearUpdateRetry = () => {
|
|
19418
|
+
if (updateRetryTimer === null) return;
|
|
19419
|
+
ownerWindow.clearTimeout(updateRetryTimer);
|
|
19420
|
+
updateRetryTimer = null;
|
|
19421
|
+
};
|
|
19422
|
+
const scheduleUpdateRetry = (client) => {
|
|
19423
|
+
if (disposed || updateRetryTimer !== null) return;
|
|
19424
|
+
const delay = UPDATE_RETRY_DELAYS_MS[updateRetryAttempt];
|
|
19425
|
+
if (delay === void 0) return;
|
|
19426
|
+
updateRetryAttempt += 1;
|
|
19427
|
+
updateRetryTimer = ownerWindow.setTimeout(() => {
|
|
19428
|
+
updateRetryTimer = null;
|
|
19429
|
+
if (disposed || options.getUpdateClient?.() !== client) return;
|
|
19430
|
+
refreshUpdateIndicator();
|
|
19431
|
+
}, delay);
|
|
19432
|
+
};
|
|
19433
|
+
const checkUpdateWithTimeout = (client) => new Promise((resolve, reject) => {
|
|
19434
|
+
const timeout = ownerWindow.setTimeout(
|
|
19435
|
+
() => reject(new Error("Update indicator check timed out")),
|
|
19436
|
+
UPDATE_CHECK_TIMEOUT_MS
|
|
19437
|
+
);
|
|
19438
|
+
void client.checkUpdate().then(
|
|
19439
|
+
(result) => {
|
|
19440
|
+
ownerWindow.clearTimeout(timeout);
|
|
19441
|
+
resolve(result);
|
|
19442
|
+
},
|
|
19443
|
+
(error51) => {
|
|
19444
|
+
ownerWindow.clearTimeout(timeout);
|
|
19445
|
+
reject(error51);
|
|
19446
|
+
}
|
|
19447
|
+
);
|
|
19448
|
+
});
|
|
19337
19449
|
const refreshUpdateIndicator = () => {
|
|
19338
19450
|
const client = options.getUpdateClient?.() ?? null;
|
|
19339
19451
|
if (!client || checkedUpdateClient === client) return;
|
|
19452
|
+
if (retryUpdateClient !== client) {
|
|
19453
|
+
clearUpdateRetry();
|
|
19454
|
+
retryUpdateClient = client;
|
|
19455
|
+
updateRetryAttempt = 0;
|
|
19456
|
+
}
|
|
19340
19457
|
checkedUpdateClient = client;
|
|
19341
19458
|
const generation = ++updateCheckGeneration;
|
|
19342
|
-
void client
|
|
19459
|
+
void checkUpdateWithTimeout(client).then((result) => {
|
|
19343
19460
|
if (disposed || generation !== updateCheckGeneration) return;
|
|
19344
19461
|
updateAvailable = result.updateAvailable;
|
|
19345
19462
|
trigger?.setUpdateAvailable(updateAvailable);
|
|
19463
|
+
if (result.error === null) {
|
|
19464
|
+
updateRetryAttempt = 0;
|
|
19465
|
+
clearUpdateRetry();
|
|
19466
|
+
return;
|
|
19467
|
+
}
|
|
19468
|
+
checkedUpdateClient = null;
|
|
19469
|
+
scheduleUpdateRetry(client);
|
|
19346
19470
|
}).catch(() => {
|
|
19471
|
+
if (disposed || generation !== updateCheckGeneration || checkedUpdateClient !== client) {
|
|
19472
|
+
return;
|
|
19473
|
+
}
|
|
19474
|
+
checkedUpdateClient = null;
|
|
19475
|
+
scheduleUpdateRetry(client);
|
|
19347
19476
|
});
|
|
19348
19477
|
};
|
|
19349
19478
|
mount();
|
|
@@ -19364,6 +19493,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19364
19493
|
openGeneration += 1;
|
|
19365
19494
|
updateCheckGeneration += 1;
|
|
19366
19495
|
lifecycleController.abort();
|
|
19496
|
+
clearUpdateRetry();
|
|
19367
19497
|
trigger?.dispose();
|
|
19368
19498
|
shell?.dispose();
|
|
19369
19499
|
trigger = null;
|
|
@@ -19513,6 +19643,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19513
19643
|
let adapterDispose = null;
|
|
19514
19644
|
let applyAdapterAgent = null;
|
|
19515
19645
|
let modelControl = null;
|
|
19646
|
+
let usageNotificationDispose = null;
|
|
19516
19647
|
const sidebarAgentIcons = installRendererSidebarAgentIcons({
|
|
19517
19648
|
getClient: () => modelControl
|
|
19518
19649
|
});
|
|
@@ -19569,6 +19700,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19569
19700
|
mounted.usage
|
|
19570
19701
|
);
|
|
19571
19702
|
};
|
|
19703
|
+
const applyThreadUsageUpdate = (update) => {
|
|
19704
|
+
for (const mounted of mountedByComposer.values()) {
|
|
19705
|
+
if (threadIdFromComposerModelTarget(mounted.modelTarget) !== update.threadId) continue;
|
|
19706
|
+
mounted.usageRequestGeneration += 1;
|
|
19707
|
+
mounted.usage = update.usage;
|
|
19708
|
+
usageRefreshAttempts.delete(mounted.composer);
|
|
19709
|
+
renderMounted(mounted);
|
|
19710
|
+
}
|
|
19711
|
+
};
|
|
19572
19712
|
const refreshThreadUsage = async (mounted) => {
|
|
19573
19713
|
const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
|
|
19574
19714
|
if (!threadId || !modelControl || controller.get(mounted.composer).agent === "codex") {
|
|
@@ -19632,6 +19772,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19632
19772
|
return;
|
|
19633
19773
|
}
|
|
19634
19774
|
const generation = controller.beginOwnershipRequest(mounted.composer);
|
|
19775
|
+
const usageGeneration = mounted.usageRequestGeneration;
|
|
19635
19776
|
mounted.ownershipStatus = "loading";
|
|
19636
19777
|
renderMounted(mounted);
|
|
19637
19778
|
try {
|
|
@@ -19641,7 +19782,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
19641
19782
|
return;
|
|
19642
19783
|
}
|
|
19643
19784
|
const { agent, model, thinkingOptionId, permissionModeId } = restoredThreadOwnership(inspection);
|
|
19644
|
-
mounted.
|
|
19785
|
+
if (mounted.usageRequestGeneration === usageGeneration) {
|
|
19786
|
+
mounted.usage = inspection.owner === "external" ? inspection.usage ?? null : null;
|
|
19787
|
+
}
|
|
19645
19788
|
const restored = controller.restore(
|
|
19646
19789
|
mounted.composer,
|
|
19647
19790
|
agent,
|
|
@@ -20542,15 +20685,6 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20542
20685
|
};
|
|
20543
20686
|
const mutationObserver = new MutationObserver((mutations) => {
|
|
20544
20687
|
transferReplacedComposers(mutations);
|
|
20545
|
-
for (const mounted of mountedByComposer.values()) {
|
|
20546
|
-
const anchor = nativeContextUsageControlForComposer(mounted.composer);
|
|
20547
|
-
if (!anchor) continue;
|
|
20548
|
-
const changed = mutations.some((mutation) => {
|
|
20549
|
-
const target = mutation.target instanceof Element ? mutation.target : mutation.target.parentElement;
|
|
20550
|
-
return target === anchor || target === anchor.parentElement || anchor.contains(target);
|
|
20551
|
-
});
|
|
20552
|
-
if (changed) scheduleThreadUsageRefresh(mounted);
|
|
20553
|
-
}
|
|
20554
20688
|
scheduleScan(mutations.some(mutationMayChangeComposerTarget));
|
|
20555
20689
|
});
|
|
20556
20690
|
const onAdapterStatus = () => {
|
|
@@ -20622,11 +20756,26 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20622
20756
|
return startCompatibilityUpdate(modelControl);
|
|
20623
20757
|
},
|
|
20624
20758
|
setAdapter(status, dispose, applyAgent, nextModelControl) {
|
|
20759
|
+
usageNotificationDispose?.();
|
|
20760
|
+
usageNotificationDispose = null;
|
|
20625
20761
|
adapterDispose?.();
|
|
20626
20762
|
adapterDispose = dispose ?? null;
|
|
20627
20763
|
applyAdapterAgent = applyAgent ?? null;
|
|
20628
20764
|
modelControl = nextModelControl ?? null;
|
|
20765
|
+
try {
|
|
20766
|
+
usageNotificationDispose = modelControl?.subscribeThreadUsage?.(applyThreadUsageUpdate) ?? null;
|
|
20767
|
+
} catch {
|
|
20768
|
+
usageNotificationDispose = null;
|
|
20769
|
+
}
|
|
20629
20770
|
adapterStatus = status;
|
|
20771
|
+
const installedModelControl = modelControl;
|
|
20772
|
+
queueMicrotask(() => {
|
|
20773
|
+
if (disposed || modelControl !== installedModelControl) return;
|
|
20774
|
+
try {
|
|
20775
|
+
settingsLifecycle.refresh();
|
|
20776
|
+
} catch {
|
|
20777
|
+
}
|
|
20778
|
+
});
|
|
20630
20779
|
sidebarAgentIcons.refresh();
|
|
20631
20780
|
void refreshHarnessAvailability();
|
|
20632
20781
|
const connected = connectedComposers();
|
|
@@ -20648,6 +20797,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
20648
20797
|
dispose() {
|
|
20649
20798
|
if (disposed) return;
|
|
20650
20799
|
disposed = true;
|
|
20800
|
+
usageNotificationDispose?.();
|
|
20801
|
+
usageNotificationDispose = null;
|
|
20651
20802
|
adapterDispose?.();
|
|
20652
20803
|
adapterDispose = null;
|
|
20653
20804
|
applyAdapterAgent = null;
|
package/bin/codexhost.exe
CHANGED
|
Binary file
|
|
Binary file
|
|
Binary file
|