@codexhost/cli-linux-arm64 0.11.0 → 0.12.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/app/codexhost-distribution.json +1 -1
- package/app/console-server.mjs +44 -2
- package/app/console-web.js +2216 -492
- package/app/desktop-controller.mjs +391 -189
- package/app/host-runtime.mjs +3917 -625
- package/app/plugins/antigravity/plugin.mjs +15634 -15526
- package/app/plugins/claude-code/plugin.mjs +215 -70
- package/app/plugins/codebuddy/plugin.mjs +1260 -827
- package/app/plugins/cursor-cli/plugin.mjs +529 -370
- package/app/plugins/deepseek-harness/plugin.mjs +25467 -26242
- package/app/plugins/enabled.json +2 -1
- package/app/plugins/grok/plugin.mjs +936 -505
- package/app/plugins/hermes/plugin.mjs +18659 -23012
- package/app/plugins/kimi-code/plugin.mjs +1046 -703
- package/app/plugins/kiro-cli/plugin.mjs +959 -590
- package/app/plugins/omp/plugin.mjs +1038 -576
- package/app/plugins/opencode/plugin.mjs +961 -700
- package/app/plugins/pi/plugin.mjs +15911 -15724
- package/app/plugins/qoder/plugin.mjs +679 -375
- package/app/plugins/qoder-cn/plugin.mjs +345 -39
- package/app/plugins/workbuddy/plugin.mjs +417 -40
- package/app/plugins/zcode/assets/icon.svg +8 -0
- package/app/plugins/zcode/manifest.json +14 -0
- package/app/plugins/zcode/plugin.mjs +19202 -0
- package/app/renderer-extension.js +2495 -486
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/package.json +1 -1
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"hermes",
|
|
24
24
|
"qoder",
|
|
25
25
|
"qoder-cn",
|
|
26
|
-
"kimi-code"
|
|
26
|
+
"kimi-code",
|
|
27
|
+
"zcode"
|
|
27
28
|
];
|
|
28
29
|
var DEFAULT_RENDERER_AGENTS = KNOWN_RENDERER_AGENTS;
|
|
29
30
|
function defaultIdFactory(sequence) {
|
|
@@ -163,6 +164,8 @@
|
|
|
163
164
|
else if (agent === "qoder-cn") delete state.qoderCnModel;
|
|
164
165
|
if (agent === "kimi-code" && model) state.kimiCodeModel = model;
|
|
165
166
|
else if (agent === "kimi-code") delete state.kimiCodeModel;
|
|
167
|
+
if (agent === "zcode" && model) state.zcodeModel = model;
|
|
168
|
+
else if (agent === "zcode") delete state.zcodeModel;
|
|
166
169
|
if (agent === "pi" && thinkingOptionId) state.piThinkingOptionId = thinkingOptionId;
|
|
167
170
|
else if (agent === "pi") delete state.piThinkingOptionId;
|
|
168
171
|
if (agent === "claude-code" && thinkingOptionId) {
|
|
@@ -196,6 +199,9 @@
|
|
|
196
199
|
if (agent === "kimi-code" && thinkingOptionId) {
|
|
197
200
|
state.kimiCodeThinkingOptionId = thinkingOptionId;
|
|
198
201
|
} else if (agent === "kimi-code") delete state.kimiCodeThinkingOptionId;
|
|
202
|
+
if (agent === "zcode" && thinkingOptionId) {
|
|
203
|
+
state.zcodeThinkingOptionId = thinkingOptionId;
|
|
204
|
+
} else if (agent === "zcode") delete state.zcodeThinkingOptionId;
|
|
199
205
|
if (agent !== "codex") {
|
|
200
206
|
const permissionModeByAgent = {};
|
|
201
207
|
for (const candidate of [
|
|
@@ -213,7 +219,8 @@
|
|
|
213
219
|
"hermes",
|
|
214
220
|
"qoder",
|
|
215
221
|
"qoder-cn",
|
|
216
|
-
"kimi-code"
|
|
222
|
+
"kimi-code",
|
|
223
|
+
"zcode"
|
|
217
224
|
]) {
|
|
218
225
|
const current = state.permissionModeByAgent?.[candidate];
|
|
219
226
|
if (candidate !== agent && current) permissionModeByAgent[candidate] = current;
|
|
@@ -244,6 +251,7 @@
|
|
|
244
251
|
if (agent === "qoder") return state.qoderModel;
|
|
245
252
|
if (agent === "qoder-cn") return state.qoderCnModel;
|
|
246
253
|
if (agent === "kimi-code") return state.kimiCodeModel;
|
|
254
|
+
if (agent === "zcode") return state.zcodeModel;
|
|
247
255
|
return void 0;
|
|
248
256
|
}
|
|
249
257
|
thinkingOptionForAgent(composer, agent) {
|
|
@@ -260,6 +268,7 @@
|
|
|
260
268
|
if (agent === "qoder") return state.qoderThinkingOptionId;
|
|
261
269
|
if (agent === "qoder-cn") return state.qoderCnThinkingOptionId;
|
|
262
270
|
if (agent === "kimi-code") return state.kimiCodeThinkingOptionId;
|
|
271
|
+
if (agent === "zcode") return state.zcodeThinkingOptionId;
|
|
263
272
|
return void 0;
|
|
264
273
|
}
|
|
265
274
|
permissionModeForAgent(composer, agent) {
|
|
@@ -290,6 +299,7 @@
|
|
|
290
299
|
else if (agent === "qoder") state.qoderModel = model;
|
|
291
300
|
else if (agent === "qoder-cn") state.qoderCnModel = model;
|
|
292
301
|
else if (agent === "kimi-code") state.kimiCodeModel = model;
|
|
302
|
+
else if (agent === "zcode") state.zcodeModel = model;
|
|
293
303
|
else state.antigravityModel = model;
|
|
294
304
|
return state;
|
|
295
305
|
}
|
|
@@ -351,6 +361,10 @@
|
|
|
351
361
|
state.kimiCodeThinkingOptionId = thinkingOptionId;
|
|
352
362
|
} else if (agent === "kimi-code") {
|
|
353
363
|
delete state.kimiCodeThinkingOptionId;
|
|
364
|
+
} else if (agent === "zcode" && thinkingOptionId) {
|
|
365
|
+
state.zcodeThinkingOptionId = thinkingOptionId;
|
|
366
|
+
} else if (agent === "zcode") {
|
|
367
|
+
delete state.zcodeThinkingOptionId;
|
|
354
368
|
}
|
|
355
369
|
return state;
|
|
356
370
|
}
|
|
@@ -439,6 +453,213 @@
|
|
|
439
453
|
}
|
|
440
454
|
};
|
|
441
455
|
|
|
456
|
+
// src/codex-ssh-adapter.ts
|
|
457
|
+
var record = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
458
|
+
function createCodexSshClient(ownerWindow) {
|
|
459
|
+
function request(operation, params, signal) {
|
|
460
|
+
const bridge = ownerWindow.electronBridge;
|
|
461
|
+
if (!bridge?.sendMessageFromView)
|
|
462
|
+
return Promise.reject(new Error("Codex SSH settings are unavailable in this window"));
|
|
463
|
+
if (signal?.aborted) return Promise.reject(new DOMException("Aborted", "AbortError"));
|
|
464
|
+
return new Promise((resolve, reject) => {
|
|
465
|
+
const requestId = ownerWindow.crypto.randomUUID();
|
|
466
|
+
const finish = (error51, value) => {
|
|
467
|
+
ownerWindow.clearTimeout(timer);
|
|
468
|
+
ownerWindow.removeEventListener("message", receive);
|
|
469
|
+
signal?.removeEventListener("abort", abort);
|
|
470
|
+
if (error51) reject(error51);
|
|
471
|
+
else resolve(value);
|
|
472
|
+
};
|
|
473
|
+
const abort = () => finish(new DOMException("Aborted", "AbortError"));
|
|
474
|
+
const receive = (event) => {
|
|
475
|
+
const message = event.data;
|
|
476
|
+
if (!record(message) || message.type !== "fetch-response" || message.requestId !== requestId)
|
|
477
|
+
return;
|
|
478
|
+
if (message.responseType !== "success" || typeof message.status !== "number" || message.status < 200 || message.status >= 300 || typeof message.bodyJsonString !== "string") {
|
|
479
|
+
finish(new Error("Codex SSH request failed; check the native Connections settings"));
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
try {
|
|
483
|
+
finish(null, JSON.parse(message.bodyJsonString));
|
|
484
|
+
} catch {
|
|
485
|
+
finish(new Error("Invalid Codex SSH response"));
|
|
486
|
+
}
|
|
487
|
+
};
|
|
488
|
+
const timer = ownerWindow.setTimeout(
|
|
489
|
+
() => finish(new Error("Codex SSH request timed out; refresh before retrying")),
|
|
490
|
+
15e3
|
|
491
|
+
);
|
|
492
|
+
ownerWindow.addEventListener("message", receive);
|
|
493
|
+
signal?.addEventListener("abort", abort, { once: true });
|
|
494
|
+
try {
|
|
495
|
+
Promise.resolve(
|
|
496
|
+
bridge.sendMessageFromView({
|
|
497
|
+
type: "fetch",
|
|
498
|
+
requestId,
|
|
499
|
+
method: "POST",
|
|
500
|
+
url: `vscode://codex/${operation}`,
|
|
501
|
+
body: JSON.stringify(params),
|
|
502
|
+
reportUploadProgress: false
|
|
503
|
+
})
|
|
504
|
+
).catch((error51) => finish(error51));
|
|
505
|
+
} catch (error51) {
|
|
506
|
+
finish(error51);
|
|
507
|
+
}
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
async function list(signal) {
|
|
511
|
+
const result = await request("refresh-remote-connections", {}, signal);
|
|
512
|
+
if (!record(result) || !Array.isArray(result.remoteConnections))
|
|
513
|
+
throw new Error("Invalid Codex SSH connection list");
|
|
514
|
+
return result.remoteConnections.filter(
|
|
515
|
+
(item) => !(record(item) && ["wsl", "remote-control"].includes(String(item.source)))
|
|
516
|
+
).map((item) => {
|
|
517
|
+
if (!record(item) || typeof item.hostId !== "string" || typeof item.displayName !== "string" || !["codex-managed", "discovered"].includes(String(item.source)) || typeof item.sshHost !== "string" || typeof item.autoConnect !== "boolean" || !(item.sshAlias == null || typeof item.sshAlias === "string") || !(item.identity == null || typeof item.identity === "string") || !(item.sshPort == null || Number.isInteger(item.sshPort) && Number(item.sshPort) > 0 && Number(item.sshPort) <= 65535)) {
|
|
518
|
+
throw new Error(
|
|
519
|
+
"This Codex version uses an unsupported SSH configuration; open native settings"
|
|
520
|
+
);
|
|
521
|
+
}
|
|
522
|
+
return {
|
|
523
|
+
...item,
|
|
524
|
+
sshAlias: item.sshAlias ?? null,
|
|
525
|
+
identity: item.identity ?? null,
|
|
526
|
+
sshPort: item.sshPort ?? null
|
|
527
|
+
};
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
function saved(connection) {
|
|
531
|
+
return {
|
|
532
|
+
hostId: connection.hostId,
|
|
533
|
+
displayName: connection.displayName,
|
|
534
|
+
source: connection.source,
|
|
535
|
+
alias: connection.sshAlias,
|
|
536
|
+
hostname: connection.source === "discovered" ? null : connection.sshHost,
|
|
537
|
+
sshPort: connection.source === "discovered" ? null : connection.sshPort,
|
|
538
|
+
identity: connection.source === "discovered" ? null : connection.identity,
|
|
539
|
+
...connection.connectionAnalyticsId ? { connectionAnalyticsId: connection.connectionAnalyticsId } : {}
|
|
540
|
+
};
|
|
541
|
+
}
|
|
542
|
+
async function mutate(previous, draft, signal) {
|
|
543
|
+
const current = await list(signal);
|
|
544
|
+
if (previous) {
|
|
545
|
+
const latest = current.find((item) => item.hostId === previous.hostId);
|
|
546
|
+
if (!latest || JSON.stringify(saved(latest)) !== JSON.stringify(saved(previous))) {
|
|
547
|
+
throw new Error("This connection changed in Codex. Refresh and edit it again.");
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
const next = current.filter((item) => item.hostId !== previous?.hostId).map(saved);
|
|
551
|
+
if (draft) {
|
|
552
|
+
const hostname3 = draft.hostname.trim();
|
|
553
|
+
const displayName = draft.displayName.trim();
|
|
554
|
+
if (!displayName || !hostname3 || hostname3.startsWith("-") || /\s/u.test(hostname3) || draft.sshPort !== null && (!Number.isInteger(draft.sshPort) || draft.sshPort < 1 || draft.sshPort > 65535)) {
|
|
555
|
+
throw new Error("Enter a name, SSH hostname (or alias), and a port between 1 and 65535");
|
|
556
|
+
}
|
|
557
|
+
if (current.some(
|
|
558
|
+
(item) => item.hostId !== previous?.hostId && item.displayName.trim() === displayName
|
|
559
|
+
)) {
|
|
560
|
+
throw new Error("A connection with this name already exists");
|
|
561
|
+
}
|
|
562
|
+
if (previous?.source === "discovered" && (hostname3 !== previous.sshHost || draft.sshPort !== previous.sshPort || draft.identity !== previous.identity)) {
|
|
563
|
+
throw new Error("Edit SSH-config connection details in native Codex settings");
|
|
564
|
+
}
|
|
565
|
+
next.push(
|
|
566
|
+
previous?.source === "discovered" ? { ...saved(previous), displayName } : {
|
|
567
|
+
hostId: previous?.hostId ?? `remote-ssh-codex-managed:${ownerWindow.crypto.randomUUID()}`,
|
|
568
|
+
displayName,
|
|
569
|
+
source: "codex-managed",
|
|
570
|
+
alias: null,
|
|
571
|
+
hostname: hostname3,
|
|
572
|
+
sshPort: draft.sshPort,
|
|
573
|
+
identity: draft.identity?.trim() || null,
|
|
574
|
+
...previous?.connectionAnalyticsId ? { connectionAnalyticsId: previous.connectionAnalyticsId } : {}
|
|
575
|
+
}
|
|
576
|
+
);
|
|
577
|
+
}
|
|
578
|
+
await request("save-codex-managed-remote-ssh-connections", { remoteConnections: next }, signal);
|
|
579
|
+
}
|
|
580
|
+
return {
|
|
581
|
+
list,
|
|
582
|
+
save: (draft, previous, signal) => mutate(previous, draft, signal),
|
|
583
|
+
remove: (previous, signal) => mutate(previous, null, signal),
|
|
584
|
+
async connect(hostId, enabled, signal) {
|
|
585
|
+
await request("set-remote-connection-auto-connect", { hostId, autoConnect: enabled }, signal);
|
|
586
|
+
},
|
|
587
|
+
async state(hostId, signal) {
|
|
588
|
+
const result = await request("app-server-connection-state", { hostId }, signal);
|
|
589
|
+
if (!record(result) || typeof result.state !== "string")
|
|
590
|
+
throw new Error("Invalid Codex connection state");
|
|
591
|
+
return {
|
|
592
|
+
state: result.state,
|
|
593
|
+
error: typeof result.error === "string" ? result.error : record(result.error) && typeof result.error.message === "string" ? result.error.message : null
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
// src/remote-connections-control.ts
|
|
600
|
+
function remoteUpdateTarget(local, remote) {
|
|
601
|
+
if (!remote.updateSupported || !remote.remote || !remote.installedVersion || !local?.runningVersion)
|
|
602
|
+
return null;
|
|
603
|
+
if (["installing", "restarting", "failed"].includes(remote.update.phase)) return null;
|
|
604
|
+
const stable = /^(\d+)\.(\d+)\.(\d+)$/u;
|
|
605
|
+
if (!stable.test(local.runningVersion) || !stable.test(remote.installedVersion)) return null;
|
|
606
|
+
const left = local.runningVersion.split(".").map(Number);
|
|
607
|
+
const right = remote.installedVersion.split(".").map(Number);
|
|
608
|
+
const index = left.findIndex((part, index2) => part !== right[index2]);
|
|
609
|
+
if (index >= 0 && (left[index] ?? 0) > (right[index] ?? 0)) return local.runningVersion;
|
|
610
|
+
if (index < 0 && remote.restartRequired) return remote.installedVersion;
|
|
611
|
+
return null;
|
|
612
|
+
}
|
|
613
|
+
function createRemoteConnectionsControl(ownerWindow, getClient) {
|
|
614
|
+
async function bounded(operation) {
|
|
615
|
+
let timer;
|
|
616
|
+
try {
|
|
617
|
+
return await Promise.race([
|
|
618
|
+
operation,
|
|
619
|
+
new Promise((_, reject) => {
|
|
620
|
+
timer = ownerWindow.setTimeout(
|
|
621
|
+
() => reject(new Error("Remote service did not respond; reconnect and retry")),
|
|
622
|
+
8e3
|
|
623
|
+
);
|
|
624
|
+
})
|
|
625
|
+
]);
|
|
626
|
+
} finally {
|
|
627
|
+
ownerWindow.clearTimeout(timer);
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
const control = {
|
|
631
|
+
ssh: createCodexSshClient(ownerWindow),
|
|
632
|
+
async setup(connection, action, version2) {
|
|
633
|
+
const client = getClient("local");
|
|
634
|
+
if (!client?.setupSsh)
|
|
635
|
+
throw new Error("SSH installation is unavailable; update local codexhost and restart");
|
|
636
|
+
return client.setupSsh({
|
|
637
|
+
hostname: connection.sshAlias ?? connection.sshHost,
|
|
638
|
+
port: connection.sshPort,
|
|
639
|
+
identity: connection.identity,
|
|
640
|
+
action,
|
|
641
|
+
version: version2 ?? null
|
|
642
|
+
});
|
|
643
|
+
},
|
|
644
|
+
async runtime(hostId) {
|
|
645
|
+
const client = getClient(hostId);
|
|
646
|
+
if (!client?.runtimeStatus)
|
|
647
|
+
throw new Error(
|
|
648
|
+
"Version management is unavailable; update codexhost on this host and reconnect"
|
|
649
|
+
);
|
|
650
|
+
return bounded(client.runtimeStatus());
|
|
651
|
+
},
|
|
652
|
+
async update(hostId, version2) {
|
|
653
|
+
if (hostId === "local") throw new Error("Choose a remote SSH connection");
|
|
654
|
+
const client = getClient(hostId);
|
|
655
|
+
if (!client?.updateRemote)
|
|
656
|
+
throw new Error("Remote update is unavailable; update this remote once and reconnect");
|
|
657
|
+
return bounded(client.updateRemote(version2));
|
|
658
|
+
}
|
|
659
|
+
};
|
|
660
|
+
return control;
|
|
661
|
+
}
|
|
662
|
+
|
|
442
663
|
// ../../node_modules/zod/v4/classic/external.js
|
|
443
664
|
var external_exports = {};
|
|
444
665
|
__export(external_exports, {
|
|
@@ -633,7 +854,7 @@
|
|
|
633
854
|
promise: () => promise,
|
|
634
855
|
property: () => _property,
|
|
635
856
|
readonly: () => readonly,
|
|
636
|
-
record: () =>
|
|
857
|
+
record: () => record2,
|
|
637
858
|
refine: () => refine,
|
|
638
859
|
regex: () => _regex,
|
|
639
860
|
regexes: () => regexes_exports,
|
|
@@ -12971,7 +13192,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
12971
13192
|
preprocess: () => preprocess,
|
|
12972
13193
|
promise: () => promise,
|
|
12973
13194
|
readonly: () => readonly,
|
|
12974
|
-
record: () =>
|
|
13195
|
+
record: () => record2,
|
|
12975
13196
|
refine: () => refine,
|
|
12976
13197
|
set: () => set,
|
|
12977
13198
|
strictObject: () => strictObject,
|
|
@@ -13940,7 +14161,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
13940
14161
|
inst.keyType = def.keyType;
|
|
13941
14162
|
inst.valueType = def.valueType;
|
|
13942
14163
|
});
|
|
13943
|
-
function
|
|
14164
|
+
function record2(keyType, valueType, params) {
|
|
13944
14165
|
if (!valueType || !valueType._zod) {
|
|
13945
14166
|
return new ZodRecord({
|
|
13946
14167
|
type: "record",
|
|
@@ -14407,7 +14628,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
14407
14628
|
}, ...args);
|
|
14408
14629
|
function json(params) {
|
|
14409
14630
|
const jsonSchema = lazy(() => {
|
|
14410
|
-
return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema),
|
|
14631
|
+
return union([string2(params), number2(), boolean2(), _null3(), array(jsonSchema), record2(string2(), jsonSchema)]);
|
|
14411
14632
|
});
|
|
14412
14633
|
return jsonSchema;
|
|
14413
14634
|
}
|
|
@@ -15043,6 +15264,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15043
15264
|
"codexhost/harness/display-settings/get",
|
|
15044
15265
|
"codexhost/harness/display-settings/set",
|
|
15045
15266
|
"codexhost/harness/inspect",
|
|
15267
|
+
"codexhost/harness/installation",
|
|
15046
15268
|
"codexhost/harness/launch-settings/get",
|
|
15047
15269
|
"codexhost/harness/launch-settings/set",
|
|
15048
15270
|
"codexhost/harness/web-ui/open",
|
|
@@ -15728,14 +15950,17 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15728
15950
|
var HARNESS_INSTALLATION_METHOD = "codexhost/harness/installation";
|
|
15729
15951
|
var harnessInstallationParamsSchema = external_exports.object({
|
|
15730
15952
|
harnessId: harnessIdSchema,
|
|
15731
|
-
action: external_exports.enum(["check", "update"])
|
|
15953
|
+
action: external_exports.enum(["check", "update", "install"])
|
|
15732
15954
|
}).strict();
|
|
15733
15955
|
var harnessInstallationStateSchema = external_exports.object({
|
|
15734
15956
|
currentVersion: external_exports.string().min(1).max(128),
|
|
15735
15957
|
latestVersion: external_exports.string().min(1).max(128),
|
|
15736
15958
|
updateAvailable: external_exports.boolean(),
|
|
15737
15959
|
canUpdate: external_exports.boolean(),
|
|
15738
|
-
|
|
15960
|
+
// Adapter-owned diagnostic text; UI uses messageCode rather than displaying it verbatim.
|
|
15961
|
+
message: external_exports.string().max(2048).optional(),
|
|
15962
|
+
messageCode: external_exports.string().min(1).max(128).optional(),
|
|
15963
|
+
latestVersionKind: external_exports.enum(["unknown", "tracking-branch"]).optional()
|
|
15739
15964
|
}).strict();
|
|
15740
15965
|
|
|
15741
15966
|
// ../shared-contracts/dist/codex-accounts.js
|
|
@@ -16061,6 +16286,41 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16061
16286
|
return `${HARNESS_COMMAND_MENTION_PATH_PREFIX}${encodeURIComponent(name).replace(/[()]/gu, (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`)}`;
|
|
16062
16287
|
}
|
|
16063
16288
|
|
|
16289
|
+
// ../shared-contracts/dist/remote-runtime.js
|
|
16290
|
+
var RUNTIME_STATUS_METHOD = "codexhost/runtime/status";
|
|
16291
|
+
var REMOTE_UPDATE_METHOD = "codexhost/remote/update";
|
|
16292
|
+
var remoteUpdatePhaseSchema = external_exports.enum([
|
|
16293
|
+
"idle",
|
|
16294
|
+
"installing",
|
|
16295
|
+
"restarting",
|
|
16296
|
+
"succeeded",
|
|
16297
|
+
"failed"
|
|
16298
|
+
]);
|
|
16299
|
+
var runtimeStatusSchema = external_exports.object({
|
|
16300
|
+
runningVersion: external_exports.string().nullable(),
|
|
16301
|
+
installedVersion: external_exports.string().nullable(),
|
|
16302
|
+
restartRequired: external_exports.boolean(),
|
|
16303
|
+
remote: external_exports.boolean(),
|
|
16304
|
+
updateSupported: external_exports.boolean(),
|
|
16305
|
+
update: external_exports.object({
|
|
16306
|
+
phase: remoteUpdatePhaseSchema,
|
|
16307
|
+
targetVersion: external_exports.string().nullable(),
|
|
16308
|
+
error: external_exports.string().nullable()
|
|
16309
|
+
})
|
|
16310
|
+
});
|
|
16311
|
+
var remoteUpdateParamsSchema = external_exports.object({
|
|
16312
|
+
version: external_exports.string().regex(/^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/u)
|
|
16313
|
+
}).strict();
|
|
16314
|
+
var REMOTE_SSH_SETUP_METHOD = "codexhost/remote/ssh-setup";
|
|
16315
|
+
var remoteSshSetupParamsSchema = external_exports.object({
|
|
16316
|
+
hostname: external_exports.string().min(1).max(1024).refine((value) => !value.startsWith("-") && !/\s/u.test(value)),
|
|
16317
|
+
port: external_exports.number().int().min(1).max(65535).nullable(),
|
|
16318
|
+
identity: external_exports.string().max(4096).nullable(),
|
|
16319
|
+
action: external_exports.enum(["inspect", "install", "update", "repair"]),
|
|
16320
|
+
version: external_exports.string().regex(/^\d+\.\d+\.\d+$/u).nullable()
|
|
16321
|
+
}).strict();
|
|
16322
|
+
var remoteSshSetupResultSchema = external_exports.object({ state: external_exports.enum(["installed", "not-installed"]) }).strict();
|
|
16323
|
+
|
|
16064
16324
|
// ../shared-contracts/dist/index.js
|
|
16065
16325
|
var workspaceContractVersionSchema = external_exports.literal(WORKSPACE_CONTRACT_VERSION);
|
|
16066
16326
|
|
|
@@ -16172,6 +16432,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16172
16432
|
return sharedStore;
|
|
16173
16433
|
}
|
|
16174
16434
|
|
|
16435
|
+
// src/assets/zcode-agent.svg
|
|
16436
|
+
var zcode_agent_default = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 30 30">%0A <path fill="%232D2D2D" stroke="%23FFFFFF" stroke-width="0.6317" stroke-miterlimit="10" d="M24.51,28.51H5.49c-2.21,0-4-1.79-4-4V5.49c0-2.21,1.79-4,4-4h19.03c2.21,0,4,1.79,4,4v19.03C28.51,26.72,26.72,28.51,24.51,28.51z"/>%0A <g fill="%23FFFFFF">%0A <path d="M15.47,7.1l-1.3,1.85c-0.2,0.29-0.54,0.47-0.9,0.47h-7.1V7.09C6.16,7.1,15.47,7.1,15.47,7.1z"/>%0A <polygon points="24.3,7.1 13.14,22.91 5.7,22.91 16.86,7.1"/>%0A <path d="M14.53,22.91l1.31-1.86c0.2-0.29,0.54-0.47,0.9-0.47h7.09v2.33H14.53z"/>%0A </g>%0A</svg>%0A';
|
|
16437
|
+
|
|
16175
16438
|
// src/assets/kimi-agent.svg
|
|
16176
16439
|
var kimi_agent_default = 'data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="40" height="40" viewBox="0 0 40 40" fill="none">%0A <rect width="40" height="40" rx="10" fill="%23000000"/>%0A <path d="M31.6957 7.11414C32.8305 7.11414 33.7505 8.0341 33.7505 9.16893V9.16893C33.7505 10.3038 32.8305 11.2237 31.6957 11.2237L29.8826 11.2237C29.7491 11.2237 29.6409 11.1155 29.6409 10.982L29.6409 9.16893C29.6409 8.0341 30.5609 7.11414 31.6957 7.11414Z" fill="%231783FF"/>%0A <path d="M20.1757 19.0798L27.9302 11.3864C28.0761 11.2413 27.9939 10.9498 27.8056 10.9498H23.633C23.5877 10.9498 23.5438 10.9683 23.5084 11.0038L15.1533 19.2911C15.023 19.4192 14.8304 19.305 14.8304 19.0998V11.1951C14.8304 11.0593 14.7411 10.9498 14.6321 10.9498H11.7569C11.6478 10.9498 11.5586 11.0593 11.5586 11.1951V28.2387C11.5586 28.3745 11.6478 28.484 11.7569 28.484H14.6321C14.7411 28.484 14.8304 28.3745 14.8304 28.2387V24.7661C14.8304 24.6921 14.8573 24.6211 14.904 24.5748L17.4945 22.0047C17.5568 21.943 17.6432 21.9337 17.7126 21.98L24.6414 27.0786C25.7759 27.8423 27.0436 28.3112 28.331 28.4501C28.4458 28.4624 28.5449 28.3483 28.5449 28.2048V24.9343C28.5449 24.8093 28.4698 24.7075 28.3693 24.6921C27.6115 24.5733 26.8722 24.2802 26.2037 23.8297L20.2054 19.487C20.0808 19.4037 20.0652 19.1893 20.1757 19.0798Z" fill="%23FFFFFF"/>%0A</svg>%0A';
|
|
16177
16440
|
|
|
@@ -16225,7 +16488,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16225
16488
|
hermes: "Hermes",
|
|
16226
16489
|
qoder: "Qoder",
|
|
16227
16490
|
"qoder-cn": "Qoder CN",
|
|
16228
|
-
"kimi-code": "Kimi Code"
|
|
16491
|
+
"kimi-code": "Kimi Code",
|
|
16492
|
+
zcode: "ZCode"
|
|
16229
16493
|
};
|
|
16230
16494
|
var PI_PATHS = [
|
|
16231
16495
|
{
|
|
@@ -16301,9 +16565,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16301
16565
|
image.style.flex = "none";
|
|
16302
16566
|
return image;
|
|
16303
16567
|
}
|
|
16304
|
-
if (agent === "antigravity" || agent === "kiro-cli" || agent === "codebuddy" || agent === "workbuddy" || agent === "cursor-cli" || agent === "kimi-code") {
|
|
16568
|
+
if (agent === "antigravity" || agent === "kiro-cli" || agent === "codebuddy" || agent === "workbuddy" || agent === "cursor-cli" || agent === "kimi-code" || agent === "zcode") {
|
|
16305
16569
|
const image = ownerDocument.createElement("img");
|
|
16306
|
-
image.src = agent === "kimi-code" ? kimi_agent_default : agent === "codebuddy" ? codebuddy_agent_default : agent === "workbuddy" ? workbuddy_agent_default : agent === "cursor-cli" ? cursor_agent_default : agent === "kiro-cli" ? kiro_agent_default : antigravity_agent_default;
|
|
16570
|
+
image.src = agent === "zcode" ? zcode_agent_default : agent === "kimi-code" ? kimi_agent_default : agent === "codebuddy" ? codebuddy_agent_default : agent === "workbuddy" ? workbuddy_agent_default : agent === "cursor-cli" ? cursor_agent_default : agent === "kiro-cli" ? kiro_agent_default : antigravity_agent_default;
|
|
16307
16571
|
image.alt = "";
|
|
16308
16572
|
image.draggable = false;
|
|
16309
16573
|
image.style.width = `${size}px`;
|
|
@@ -16838,11 +17102,11 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16838
17102
|
input.type = "text";
|
|
16839
17103
|
input.autocomplete = "off";
|
|
16840
17104
|
input.spellcheck = false;
|
|
16841
|
-
input.placeholder = messages.launchPathPlaceholder;
|
|
17105
|
+
input.placeholder = agent === "zcode" ? messages.launchPathZcodePlaceholder : messages.launchPathPlaceholder;
|
|
16842
17106
|
input.setAttribute("aria-label", messages.launchPathLabel);
|
|
16843
17107
|
label.append(input);
|
|
16844
17108
|
const help = document2.createElement("p");
|
|
16845
|
-
help.textContent = messages.launchPathWorkbuddyHelp;
|
|
17109
|
+
help.textContent = agent === "zcode" ? messages.launchPathZcodeHelp : messages.launchPathWorkbuddyHelp;
|
|
16846
17110
|
const actions = document2.createElement("div");
|
|
16847
17111
|
actions.className = "settings-harness-launch__actions";
|
|
16848
17112
|
const save = document2.createElement("button");
|
|
@@ -16921,6 +17185,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16921
17185
|
];
|
|
16922
17186
|
var node = ["Requires Node.js (including npm).", "\u9700\u5148\u5B89\u88C5 Node.js\uFF08\u5305\u542B npm\uFF09\u3002"];
|
|
16923
17187
|
var guides = {
|
|
17188
|
+
zcode: {
|
|
17189
|
+
// codexhost runs the Agent CLI bundled with the installed ZCode Desktop.
|
|
17190
|
+
url: "https://github.com/BytePioneer-AI/codex-host/blob/main/docs/harnesses/zcode/zcode-harness-integration.md#%E5%AE%89%E8%A3%85",
|
|
17191
|
+
commands: [],
|
|
17192
|
+
before: [
|
|
17193
|
+
"Install ZCode Desktop and sign in with a Start Plan account. If ZCode is not in the default location (/Applications/ZCode.app on macOS, %LOCALAPPDATA%\\Programs\\ZCode on Windows, /opt/ZCode on Linux), set its path in the connection settings.",
|
|
17194
|
+
"\u8BF7\u5B89\u88C5 ZCode Desktop \u5E76\u767B\u5F55 Start Plan \u8D26\u53F7\u3002ZCode \u4E0D\u5728\u9ED8\u8BA4\u5B89\u88C5\u4F4D\u7F6E\uFF08macOS \u4E3A /Applications/ZCode.app\uFF0CWindows \u4E3A %LOCALAPPDATA%\\Programs\\ZCode\uFF0CLinux \u4E3A /opt/ZCode\uFF09\u65F6\uFF0C\u53EF\u5728\u8FDE\u63A5\u8BBE\u7F6E\u4E2D\u586B\u5199\u5176\u8DEF\u5F84\u3002"
|
|
17195
|
+
],
|
|
17196
|
+
downloads: [{ label: "ZCode", url: "https://zcode.z.ai/" }],
|
|
17197
|
+
after: [
|
|
17198
|
+
"Check again after signing in. The ZCode Desktop window does not need to stay open.",
|
|
17199
|
+
"\u767B\u5F55\u540E\u91CD\u65B0\u68C0\u6D4B\uFF1B\u4F7F\u7528\u65F6\u4E0D\u9700\u8981\u4FDD\u6301 ZCode \u7A97\u53E3\u6253\u5F00\u3002"
|
|
17200
|
+
]
|
|
17201
|
+
},
|
|
16924
17202
|
pi: {
|
|
16925
17203
|
url: "https://pi.dev/",
|
|
16926
17204
|
commands: shells(
|
|
@@ -16939,11 +17217,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16939
17217
|
},
|
|
16940
17218
|
"deepseek-harness": {
|
|
16941
17219
|
url: "https://github.com/deepseek-ai/deepseek-harness#run",
|
|
16942
|
-
|
|
16943
|
-
commands: npm("@deepseek-ai/dsh@0.1.5-rc.1"),
|
|
17220
|
+
commands: npm("@deepseek-ai/dsh@latest"),
|
|
16944
17221
|
before: [
|
|
16945
|
-
"Requires Node.js. Installs
|
|
16946
|
-
"\u9700\u5148\u5B89\u88C5 Node.js\u3002\
|
|
17222
|
+
"Requires Node.js. Installs npm's latest version; connection still requires native protocol validation.",
|
|
17223
|
+
"\u9700\u5148\u5B89\u88C5 Node.js\u3002\u5B89\u88C5 npm \u6700\u65B0\u7248\u672C\uFF1B\u8FDE\u63A5\u4ECD\u9700\u901A\u8FC7\u539F\u751F\u534F\u8BAE\u6821\u9A8C\u3002"
|
|
16947
17224
|
],
|
|
16948
17225
|
after: [
|
|
16949
17226
|
"Check again, then open Web UI to configure your provider. Stop any manually started dsh web first.",
|
|
@@ -17002,17 +17279,13 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17002
17279
|
url: "https://www.workbuddy.ai/docs/workbuddy/Quickstart",
|
|
17003
17280
|
commands: [],
|
|
17004
17281
|
before: [
|
|
17005
|
-
"
|
|
17006
|
-
"\u8BF7\u5B89\u88C5 WorkBuddy \u684C\u9762\u5E94\u7528\
|
|
17282
|
+
"Download and install the WorkBuddy desktop app.",
|
|
17283
|
+
"\u8BF7\u4E0B\u8F7D\u5E76\u5B89\u88C5 WorkBuddy \u684C\u9762\u5E94\u7528\u3002"
|
|
17007
17284
|
],
|
|
17008
17285
|
downloads: [
|
|
17009
17286
|
{
|
|
17010
|
-
label: "
|
|
17011
|
-
url: "https://www.workbuddy.ai/
|
|
17012
|
-
},
|
|
17013
|
-
{
|
|
17014
|
-
label: "Windows",
|
|
17015
|
-
url: "https://www.workbuddy.ai/docs/workbuddy/From-Beginner-to-Expert-Guide/Installation-Win-Guide"
|
|
17287
|
+
label: "WorkBuddy",
|
|
17288
|
+
url: "https://www.workbuddy.ai/"
|
|
17016
17289
|
}
|
|
17017
17290
|
],
|
|
17018
17291
|
after: [
|
|
@@ -17066,6 +17339,9 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17066
17339
|
after: start("kimi")
|
|
17067
17340
|
}
|
|
17068
17341
|
};
|
|
17342
|
+
function harnessHasInstallCommands(agent) {
|
|
17343
|
+
return guides[agent].commands.length > 0;
|
|
17344
|
+
}
|
|
17069
17345
|
function harnessInstallationGuide(agent, locale) {
|
|
17070
17346
|
const guide = guides[agent];
|
|
17071
17347
|
const index = locale === "zh-CN" ? 1 : 0;
|
|
@@ -17073,7 +17349,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17073
17349
|
}
|
|
17074
17350
|
|
|
17075
17351
|
// src/settings/harness-installation-panel.ts
|
|
17076
|
-
function createHarnessInstallationPanel(document2, agent, hostId, messages, copy,
|
|
17352
|
+
function createHarnessInstallationPanel(document2, agent, hostId, messages, copy, installation) {
|
|
17077
17353
|
const zh = messages.locale === "zh-CN";
|
|
17078
17354
|
const guide = harnessInstallationGuide(agent, messages.locale);
|
|
17079
17355
|
const panel = document2.createElement("div");
|
|
@@ -17087,6 +17363,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17087
17363
|
paragraph(zh ? "\u8BF7\u5728\u8FDC\u7A0B Host \u4E0A\u5B89\u88C5\u3002" : "Install on the remote Host.");
|
|
17088
17364
|
}
|
|
17089
17365
|
if (guide.before) paragraph(guide.before);
|
|
17366
|
+
const install2 = installation && guide.commands.length > 0 ? document2.createElement("button") : null;
|
|
17367
|
+
if (install2 && installation) {
|
|
17368
|
+
install2.type = "button";
|
|
17369
|
+
install2.className = "settings-command-button";
|
|
17370
|
+
install2.dataset.connectionAction = "install";
|
|
17371
|
+
install2.disabled = installation.status !== "idle";
|
|
17372
|
+
install2.textContent = installation.status === "installing" ? messages.connectionStatusInstalling : installation.status === "checking" ? messages.connectionStatusChecking : zh ? "\u4E00\u952E\u5B89\u88C5" : "Install automatically";
|
|
17373
|
+
install2.addEventListener("click", () => {
|
|
17374
|
+
if (install2.disabled) return;
|
|
17375
|
+
install2.disabled = true;
|
|
17376
|
+
install2.textContent = messages.connectionStatusInstalling;
|
|
17377
|
+
installation.run();
|
|
17378
|
+
});
|
|
17379
|
+
if (guide.commands.length > 1) panel.append(install2);
|
|
17380
|
+
}
|
|
17090
17381
|
for (const { terminal, command } of guide.commands) {
|
|
17091
17382
|
const block = document2.createElement("div");
|
|
17092
17383
|
block.className = "settings-harness-installation-command";
|
|
@@ -17104,40 +17395,153 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17104
17395
|
button.setAttribute("aria-label", `${copyLabel}: ${terminal}`);
|
|
17105
17396
|
button.append(createRendererSettingsIcon("copy", 16), copyLabel);
|
|
17106
17397
|
button.addEventListener("click", () => copy(button, command, copyLabel));
|
|
17107
|
-
|
|
17398
|
+
const actions = document2.createElement("div");
|
|
17399
|
+
actions.className = "settings-harness-installation-actions";
|
|
17400
|
+
if (install2 && guide.commands.length === 1) actions.append(install2);
|
|
17401
|
+
actions.append(button);
|
|
17402
|
+
block.append(label, pre, actions);
|
|
17108
17403
|
panel.append(block);
|
|
17109
17404
|
}
|
|
17110
|
-
const link = (url2, label) => {
|
|
17111
|
-
const anchor = document2.createElement("a");
|
|
17112
|
-
anchor.className = "settings-command-button settings-command-button--secondary";
|
|
17113
|
-
anchor.href = url2;
|
|
17114
|
-
anchor.target = "_blank";
|
|
17115
|
-
anchor.rel = "noopener noreferrer";
|
|
17116
|
-
anchor.append(label, createRendererSettingsIcon("external-link", 14));
|
|
17117
|
-
panel.append(anchor);
|
|
17118
|
-
};
|
|
17119
17405
|
for (const download of guide.downloads ?? []) {
|
|
17120
|
-
link(
|
|
17121
|
-
|
|
17122
|
-
|
|
17123
|
-
|
|
17406
|
+
const link = document2.createElement("a");
|
|
17407
|
+
link.className = "settings-command-button settings-command-button--secondary";
|
|
17408
|
+
link.href = download.url;
|
|
17409
|
+
link.target = "_blank";
|
|
17410
|
+
link.rel = "noopener noreferrer";
|
|
17411
|
+
link.textContent = zh ? "\u4E0B\u8F7D" : "Download";
|
|
17412
|
+
link.setAttribute("aria-label", `${link.textContent} ${download.label}`);
|
|
17413
|
+
panel.append(link);
|
|
17124
17414
|
}
|
|
17125
17415
|
paragraph(guide.after);
|
|
17126
|
-
const check2 = document2.createElement("button");
|
|
17127
|
-
check2.type = "button";
|
|
17128
|
-
check2.className = "settings-command-button";
|
|
17129
|
-
check2.dataset.connectionAction = "check-install";
|
|
17130
|
-
check2.textContent = zh ? "\u91CD\u65B0\u68C0\u6D4B" : "Check again";
|
|
17131
|
-
check2.addEventListener("click", () => {
|
|
17132
|
-
check2.disabled = true;
|
|
17133
|
-
check2.textContent = messages.connectionRefreshing;
|
|
17134
|
-
refresh();
|
|
17135
|
-
});
|
|
17136
|
-
panel.append(check2);
|
|
17137
|
-
link(guide.url, zh ? "\u67E5\u770B\u5B98\u65B9\u5B89\u88C5\u8BF4\u660E" : "View official installation instructions");
|
|
17138
17416
|
return panel;
|
|
17139
17417
|
}
|
|
17140
17418
|
|
|
17419
|
+
// src/settings/harness-official-websites.ts
|
|
17420
|
+
var HARNESS_OFFICIAL_WEBSITES = {
|
|
17421
|
+
pi: "https://pi.dev/",
|
|
17422
|
+
"claude-code": "https://code.claude.com/",
|
|
17423
|
+
"deepseek-harness": "https://github.com/deepseek-ai/deepseek-harness",
|
|
17424
|
+
opencode: "https://opencode.ai/",
|
|
17425
|
+
grok: "https://www.npmjs.com/package/@xai-official/grok",
|
|
17426
|
+
omp: "https://github.com/can1357/oh-my-pi",
|
|
17427
|
+
antigravity: "https://antigravity.google/",
|
|
17428
|
+
"kiro-cli": "https://kiro.dev/",
|
|
17429
|
+
codebuddy: "https://www.codebuddy.ai/",
|
|
17430
|
+
workbuddy: "https://www.workbuddy.ai/",
|
|
17431
|
+
"cursor-cli": "https://cursor.com/",
|
|
17432
|
+
hermes: "https://hermes-agent.nousresearch.com/",
|
|
17433
|
+
qoder: "https://qoder.com/",
|
|
17434
|
+
"qoder-cn": "https://qoder.cn/",
|
|
17435
|
+
"kimi-code": "https://code.kimi.com/",
|
|
17436
|
+
zcode: "https://zcode.z.ai/"
|
|
17437
|
+
};
|
|
17438
|
+
|
|
17439
|
+
// src/settings/harness-install-store.ts
|
|
17440
|
+
function errorMessage(error51) {
|
|
17441
|
+
return typeof error51 === "object" && error51 !== null && "message" in error51 && typeof error51.message === "string" ? error51.message.slice(0, 2048) : "Could not install the Harness. Check the official installation guide and retry.";
|
|
17442
|
+
}
|
|
17443
|
+
var stores = /* @__PURE__ */ new WeakMap();
|
|
17444
|
+
function createStore(diagnostics) {
|
|
17445
|
+
const states = /* @__PURE__ */ new Map();
|
|
17446
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
17447
|
+
const key = (host, agent) => JSON.stringify([host, agent]);
|
|
17448
|
+
const notify = () => listeners.forEach((listener) => listener());
|
|
17449
|
+
return {
|
|
17450
|
+
get: (host, agent) => states.get(key(host, agent)),
|
|
17451
|
+
clearErrors() {
|
|
17452
|
+
for (const [id, state] of states) if (state.status === "error") states.delete(id);
|
|
17453
|
+
notify();
|
|
17454
|
+
},
|
|
17455
|
+
subscribe(listener) {
|
|
17456
|
+
listeners.add(listener);
|
|
17457
|
+
return () => {
|
|
17458
|
+
listeners.delete(listener);
|
|
17459
|
+
};
|
|
17460
|
+
},
|
|
17461
|
+
async install(host, agent) {
|
|
17462
|
+
const id = key(host, agent);
|
|
17463
|
+
const previous = states.get(id);
|
|
17464
|
+
if (!diagnostics.installation || previous && previous.status !== "error") return;
|
|
17465
|
+
states.set(id, { status: "installing" });
|
|
17466
|
+
notify();
|
|
17467
|
+
let failure;
|
|
17468
|
+
try {
|
|
17469
|
+
await diagnostics.installation(host, agent, "install");
|
|
17470
|
+
states.set(id, { status: "checking" });
|
|
17471
|
+
notify();
|
|
17472
|
+
} catch (error51) {
|
|
17473
|
+
failure = errorMessage(error51);
|
|
17474
|
+
}
|
|
17475
|
+
try {
|
|
17476
|
+
await diagnostics.refresh(host);
|
|
17477
|
+
const refreshed = diagnostics.snapshot().hosts.find((candidate) => candidate.hostId === host)?.agents.find((candidate) => candidate.agent === agent);
|
|
17478
|
+
if (refreshed?.availability === "ready") failure = void 0;
|
|
17479
|
+
} catch (error51) {
|
|
17480
|
+
failure ??= errorMessage(error51);
|
|
17481
|
+
}
|
|
17482
|
+
if (failure) states.set(id, { status: "error", error: failure });
|
|
17483
|
+
else states.delete(id);
|
|
17484
|
+
notify();
|
|
17485
|
+
}
|
|
17486
|
+
};
|
|
17487
|
+
}
|
|
17488
|
+
function harnessInstallStore(diagnostics) {
|
|
17489
|
+
let store = stores.get(diagnostics);
|
|
17490
|
+
if (!store) {
|
|
17491
|
+
store = createStore(diagnostics);
|
|
17492
|
+
stores.set(diagnostics, store);
|
|
17493
|
+
}
|
|
17494
|
+
return store;
|
|
17495
|
+
}
|
|
17496
|
+
|
|
17497
|
+
// src/settings/harness-version-messages.ts
|
|
17498
|
+
var harnessVersionEnglish = Object.freeze({
|
|
17499
|
+
unknown: "Unknown",
|
|
17500
|
+
trackingBranch: "Tracking branch (new commits)",
|
|
17501
|
+
notes: Object.freeze({
|
|
17502
|
+
"original-installer": "Use the original installer, package manager, or launcher to update this installation.",
|
|
17503
|
+
"claude-policy-restricted": "Claude updates are restricted by the installation's settings or policy.",
|
|
17504
|
+
"codebuddy-npm-required": "Use CodeBuddy's native updater or original package manager. Latest-version checks here require an identified npm installation.",
|
|
17505
|
+
"deepseek-original-installer": "Update with the original installer. Python, desktop, and project-local installations are not upgraded through global npm.",
|
|
17506
|
+
"kiro-native-updater": "Use Kiro CLI's original installer or native updater to check for and install updates.",
|
|
17507
|
+
"zcode-desktop-updater": "The CLI ships inside ZCode Desktop. Update ZCode Desktop itself to update it.",
|
|
17508
|
+
"qoder-check-unavailable": "This Qoder China release does not expose a non-installing update check. Use its original installer.",
|
|
17509
|
+
"hermes-update-plan-unavailable": "This Hermes release does not expose a safe update plan. Use the original installer.",
|
|
17510
|
+
"hermes-externally-managed": "This Hermes installation is managed externally. Update it through its desktop app, container, or original package manager.",
|
|
17511
|
+
"hermes-update-channel": "Uses Hermes's configured update channel. Gateway restarts are deferred; existing processes keep their running code.",
|
|
17512
|
+
"hermes-manual-update": "Use the native updater manually. Safe non-interactive updates require a clean source checkout, commit identity, and Gateway restart deferral."
|
|
17513
|
+
})
|
|
17514
|
+
});
|
|
17515
|
+
var harnessVersionChinese = Object.freeze({
|
|
17516
|
+
unknown: "\u672A\u77E5",
|
|
17517
|
+
trackingBranch: "\u8DDF\u8E2A\u5206\u652F\uFF08\u6709\u65B0\u63D0\u4EA4\uFF09",
|
|
17518
|
+
notes: Object.freeze({
|
|
17519
|
+
"original-installer": "\u8BF7\u4F7F\u7528\u539F\u5B89\u88C5\u7A0B\u5E8F\u3001\u5305\u7BA1\u7406\u5668\u6216\u542F\u52A8\u5668\u66F4\u65B0\u6B64\u5B89\u88C5\u3002",
|
|
17520
|
+
"claude-policy-restricted": "\u6B64 Claude \u5B89\u88C5\u7684\u8BBE\u7F6E\u6216\u7B56\u7565\u9650\u5236\u4E86\u66F4\u65B0\u3002",
|
|
17521
|
+
"codebuddy-npm-required": "\u8BF7\u4F7F\u7528 CodeBuddy \u539F\u751F\u66F4\u65B0\u5668\u6216\u539F\u5305\u7BA1\u7406\u5668\u66F4\u65B0\u3002\u6B64\u5904\u4EC5\u80FD\u67E5\u8BE2\u5DF2\u8BC6\u522B\u7684 npm \u5B89\u88C5\u7684\u6700\u65B0\u7248\u672C\u3002",
|
|
17522
|
+
"deepseek-original-installer": "\u8BF7\u4F7F\u7528\u539F\u5B89\u88C5\u65B9\u5F0F\u66F4\u65B0\u3002Python\u3001\u684C\u9762\u5E94\u7528\u53CA\u9879\u76EE\u5185\u5B89\u88C5\u4E0D\u4F1A\u901A\u8FC7\u5168\u5C40 npm \u66F4\u65B0\u3002",
|
|
17523
|
+
"kiro-native-updater": "\u8BF7\u4F7F\u7528 Kiro CLI \u539F\u5B89\u88C5\u7A0B\u5E8F\u6216\u539F\u751F\u66F4\u65B0\u5668\u68C0\u67E5\u5E76\u5B89\u88C5\u66F4\u65B0\u3002",
|
|
17524
|
+
"zcode-desktop-updater": "CLI \u968F ZCode Desktop \u4E00\u8D77\u53D1\u5E03\uFF0C\u8BF7\u76F4\u63A5\u66F4\u65B0 ZCode Desktop\u3002",
|
|
17525
|
+
"qoder-check-unavailable": "\u6B64 Qoder \u4E2D\u56FD\u7248\u5C1A\u4E0D\u652F\u6301\u53EA\u68C0\u67E5\u3001\u4E0D\u5B89\u88C5\u7684\u66F4\u65B0\u67E5\u8BE2\uFF0C\u8BF7\u4F7F\u7528\u539F\u5B89\u88C5\u65B9\u5F0F\u66F4\u65B0\u3002",
|
|
17526
|
+
"hermes-update-plan-unavailable": "\u6B64 Hermes \u7248\u672C\u4E0D\u63D0\u4F9B\u5B89\u5168\u7684\u66F4\u65B0\u8BA1\u5212\uFF0C\u8BF7\u4F7F\u7528\u539F\u5B89\u88C5\u65B9\u5F0F\u66F4\u65B0\u3002",
|
|
17527
|
+
"hermes-externally-managed": "\u6B64 Hermes \u5B89\u88C5\u7531\u5916\u90E8\u5DE5\u5177\u7BA1\u7406\uFF0C\u8BF7\u901A\u8FC7\u5176\u684C\u9762\u5E94\u7528\u3001\u5BB9\u5668\u6216\u539F\u5305\u7BA1\u7406\u5668\u66F4\u65B0\u3002",
|
|
17528
|
+
"hermes-update-channel": "\u4F7F\u7528 Hermes \u914D\u7F6E\u7684\u66F4\u65B0\u6E20\u9053\uFF0C\u6682\u4E0D\u91CD\u542F Gateway\uFF1B\u73B0\u6709\u8FDB\u7A0B\u7EE7\u7EED\u8FD0\u884C\u539F\u6709\u4EE3\u7801\u3002",
|
|
17529
|
+
"hermes-manual-update": "\u8BF7\u624B\u52A8\u4F7F\u7528\u539F\u751F\u66F4\u65B0\u5668\u3002\u5B89\u5168\u7684\u975E\u4EA4\u4E92\u66F4\u65B0\u8981\u6C42\u6E90\u7801\u76EE\u5F55\u65E0\u672A\u63D0\u4EA4\u4FEE\u6539\u3001\u53EF\u8BC6\u522B\u5F53\u524D\u63D0\u4EA4\uFF0C\u5E76\u652F\u6301\u63A8\u8FDF Gateway \u91CD\u542F\u3002"
|
|
17530
|
+
})
|
|
17531
|
+
});
|
|
17532
|
+
function harnessVersionLabel(state, messages) {
|
|
17533
|
+
if (!state) return "\u2014";
|
|
17534
|
+
if (state.latestVersionKind === "unknown" || state.latestVersion === "Unknown")
|
|
17535
|
+
return messages.unknown;
|
|
17536
|
+
if (state.latestVersionKind === "tracking-branch" || state.latestVersion === "Tracking branch (new commits)")
|
|
17537
|
+
return messages.trackingBranch;
|
|
17538
|
+
return state.latestVersion;
|
|
17539
|
+
}
|
|
17540
|
+
function harnessVersionNote(state, messages) {
|
|
17541
|
+
const code = state?.messageCode;
|
|
17542
|
+
return code && Object.hasOwn(messages.notes, code) ? messages.notes[code] : void 0;
|
|
17543
|
+
}
|
|
17544
|
+
|
|
17141
17545
|
// src/settings/harness-version-panel.ts
|
|
17142
17546
|
function createHarnessVersionPanel(document2, messages, signal, agent, client) {
|
|
17143
17547
|
const panel = document2.createElement("section");
|
|
@@ -17158,29 +17562,21 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17158
17562
|
update.type = "button";
|
|
17159
17563
|
update.className = "settings-command-button settings-command-button--secondary";
|
|
17160
17564
|
update.dataset.harnessVersionAction = "update";
|
|
17161
|
-
const guide = document2.createElement("a");
|
|
17162
|
-
guide.className = update.className;
|
|
17163
|
-
guide.href = harnessInstallationGuide(agent, messages.locale).url;
|
|
17164
|
-
guide.target = "_blank";
|
|
17165
|
-
guide.rel = "noopener noreferrer";
|
|
17166
|
-
guide.append(
|
|
17167
|
-
messages.connectionOpenInstallation,
|
|
17168
|
-
createRendererSettingsIcon("external-link", 14)
|
|
17169
|
-
);
|
|
17170
17565
|
const note = document2.createElement("p");
|
|
17171
17566
|
note.className = "settings-connection-issue-note";
|
|
17172
17567
|
note.textContent = messages.harnessVersionNote;
|
|
17173
|
-
actions.append(update
|
|
17568
|
+
actions.append(update);
|
|
17174
17569
|
panel.append(heading, versions, status, actions, note);
|
|
17175
17570
|
let state;
|
|
17176
17571
|
let busy = false;
|
|
17177
17572
|
let unsupported = false;
|
|
17178
17573
|
const render = () => {
|
|
17179
17574
|
current.textContent = `${messages.harnessVersionCurrent}: ${state?.currentVersion ?? "\u2014"}`;
|
|
17180
|
-
latest.textContent = `${messages.harnessVersionLatest}: ${state
|
|
17575
|
+
latest.textContent = `${messages.harnessVersionLatest}: ${harnessVersionLabel(state, messages.harnessVersion)}`;
|
|
17181
17576
|
update.disabled = busy || signal.aborted || !state?.canUpdate || !state.updateAvailable;
|
|
17182
17577
|
update.textContent = state?.canUpdate && state.latestVersion !== "Unknown" && !state.updateAvailable ? messages.harnessVersionUpToDate : messages.harnessVersionUpdate;
|
|
17183
|
-
|
|
17578
|
+
const detail = harnessVersionNote(state, messages.harnessVersion);
|
|
17579
|
+
note.textContent = detail ? `${detail} ${messages.harnessVersionNote}` : messages.harnessVersionNote;
|
|
17184
17580
|
};
|
|
17185
17581
|
const run = async (action) => {
|
|
17186
17582
|
if (busy || unsupported || signal.aborted) return;
|
|
@@ -17213,6 +17609,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17213
17609
|
// src/settings/connections-page.ts
|
|
17214
17610
|
var CODEXHOST_GITHUB_ISSUES_NEW_URL = "https://github.com/BytePioneer-AI/codex-host/issues/new";
|
|
17215
17611
|
function connectionStatusLabel(availability, messages, hasError = false) {
|
|
17612
|
+
if (availability === "updating") return messages.connectionStatusUpdating;
|
|
17216
17613
|
if (hasError && availability !== "notInstalled") return messages.connectionStatusError;
|
|
17217
17614
|
if (availability === "ready") return messages.connectionStatusReady;
|
|
17218
17615
|
if (availability === "checking") return messages.connectionStatusChecking;
|
|
@@ -17223,6 +17620,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17223
17620
|
return availability === "installing" ? messages.connectionStatusInstalling : messages.connectionStatusUnsupported;
|
|
17224
17621
|
}
|
|
17225
17622
|
function connectionStatusTone(availability, hasError = false) {
|
|
17623
|
+
if (availability === "updating") return "checking";
|
|
17226
17624
|
if (hasError && availability !== "notInstalled") return "failed";
|
|
17227
17625
|
if (availability === "ready") return "ready";
|
|
17228
17626
|
if (availability === "checking" || availability === "installing") return "checking";
|
|
@@ -17248,16 +17646,6 @@ ${error51.stderrTail}`] : []
|
|
|
17248
17646
|
] : []
|
|
17249
17647
|
].join("\n");
|
|
17250
17648
|
}
|
|
17251
|
-
function detailLine(document2, label, value) {
|
|
17252
|
-
const line = document2.createElement("div");
|
|
17253
|
-
line.className = "settings-connection-detail-line";
|
|
17254
|
-
const name = document2.createElement("span");
|
|
17255
|
-
name.textContent = label;
|
|
17256
|
-
const content = document2.createElement("code");
|
|
17257
|
-
content.textContent = value;
|
|
17258
|
-
line.append(name, content);
|
|
17259
|
-
return line;
|
|
17260
|
-
}
|
|
17261
17649
|
function setCopyButtonLabel(button, label) {
|
|
17262
17650
|
button.replaceChildren(createRendererSettingsIcon("copy", 16), label);
|
|
17263
17651
|
}
|
|
@@ -17380,20 +17768,23 @@ ${error51.stderrTail}`] : []
|
|
|
17380
17768
|
status.className = "settings-connection-row__status";
|
|
17381
17769
|
status.dataset.connectionTone = connectionStatusTone(item.availability, item.error !== null);
|
|
17382
17770
|
status.setAttribute("role", "cell");
|
|
17383
|
-
status.textContent = connectionStatusLabel(item.availability, messages, item.error !== null);
|
|
17771
|
+
status.textContent = item.error?.code === "authenticationRequired" ? messages.connectionLoginRequired : item.error?.code === "configurationRequired" ? messages.connectionConfigurationRequired : connectionStatusLabel(item.availability, messages, item.error !== null);
|
|
17384
17772
|
const action = document2.createElement("div");
|
|
17385
17773
|
action.className = "settings-connection-row__action";
|
|
17386
17774
|
action.setAttribute("role", "cell");
|
|
17387
|
-
if (item.agentSnapshot?.availability === "notInstalled") {
|
|
17775
|
+
if (item.agentSnapshot?.availability === "notInstalled" && item.install) {
|
|
17388
17776
|
const install2 = document2.createElement("button");
|
|
17389
17777
|
install2.type = "button";
|
|
17390
17778
|
install2.className = "settings-connection-install-link";
|
|
17391
17779
|
install2.addEventListener("click", (event) => {
|
|
17392
17780
|
event.stopPropagation();
|
|
17393
17781
|
select();
|
|
17782
|
+
item.install?.();
|
|
17394
17783
|
});
|
|
17395
|
-
install2.
|
|
17396
|
-
|
|
17784
|
+
install2.disabled = item.availability === "installing" || item.availability === "checking";
|
|
17785
|
+
const installLabel = messages.connectionInstall;
|
|
17786
|
+
install2.setAttribute("aria-label", `${installLabel}: ${item.name}`);
|
|
17787
|
+
install2.title = installLabel;
|
|
17397
17788
|
install2.append(createRendererSettingsIcon("download", 17));
|
|
17398
17789
|
action.append(install2);
|
|
17399
17790
|
} else if (item.error) {
|
|
@@ -17429,6 +17820,7 @@ ${error51.stderrTail}`] : []
|
|
|
17429
17820
|
select();
|
|
17430
17821
|
});
|
|
17431
17822
|
row.addEventListener("keydown", (event) => {
|
|
17823
|
+
if (event.target?.closest?.("button, a")) return;
|
|
17432
17824
|
if (event.key !== "Enter" && event.key !== " ") return;
|
|
17433
17825
|
event.preventDefault();
|
|
17434
17826
|
select();
|
|
@@ -17453,10 +17845,22 @@ ${error51.stderrTail}`] : []
|
|
|
17453
17845
|
const title = document2.createElement("strong");
|
|
17454
17846
|
title.textContent = item.name;
|
|
17455
17847
|
identity.append(createConnectionIdentityIcon(document2, item, 20), title);
|
|
17848
|
+
if (item.agentSnapshot) {
|
|
17849
|
+
const website = document2.createElement("a");
|
|
17850
|
+
website.className = "settings-connection-website";
|
|
17851
|
+
website.href = HARNESS_OFFICIAL_WEBSITES[item.agentSnapshot.agent];
|
|
17852
|
+
website.target = "_blank";
|
|
17853
|
+
website.rel = "noopener noreferrer";
|
|
17854
|
+
website.title = messages.connectionOfficialWebsite;
|
|
17855
|
+
website.setAttribute("aria-label", `${messages.connectionOfficialWebsite}: ${item.name}`);
|
|
17856
|
+
website.append(createRendererSettingsIcon("external-link", 13));
|
|
17857
|
+
website.addEventListener("click", (event) => event.stopPropagation());
|
|
17858
|
+
identity.append(website);
|
|
17859
|
+
}
|
|
17456
17860
|
const status = document2.createElement("span");
|
|
17457
17861
|
status.className = "settings-connection-row__status";
|
|
17458
17862
|
status.dataset.connectionTone = connectionStatusTone(item.availability, item.error !== null);
|
|
17459
|
-
status.textContent = connectionStatusLabel(item.availability, messages, item.error !== null);
|
|
17863
|
+
status.textContent = item.error?.code === "authenticationRequired" ? messages.connectionLoginRequired : item.error?.code === "configurationRequired" ? messages.connectionConfigurationRequired : item.agentSnapshot && item.availability === "ready" && !item.error ? messages.connectionStatusConnected : connectionStatusLabel(item.availability, messages, item.error !== null);
|
|
17460
17864
|
header.append(identity, status);
|
|
17461
17865
|
return header;
|
|
17462
17866
|
}
|
|
@@ -17464,6 +17868,13 @@ ${error51.stderrTail}`] : []
|
|
|
17464
17868
|
inspector.replaceChildren(createInspectorHeader(document2, item, messages));
|
|
17465
17869
|
const body = document2.createElement("div");
|
|
17466
17870
|
body.className = "settings-connection-inspector__body";
|
|
17871
|
+
if (item.installError) {
|
|
17872
|
+
const error51 = document2.createElement("div");
|
|
17873
|
+
error51.className = "settings-connection-error-summary";
|
|
17874
|
+
error51.setAttribute("role", "alert");
|
|
17875
|
+
error51.textContent = item.installError;
|
|
17876
|
+
body.append(error51);
|
|
17877
|
+
}
|
|
17467
17878
|
if (item.agentSnapshot?.agent === "deepseek-harness") {
|
|
17468
17879
|
const compatibility = document2.createElement("p");
|
|
17469
17880
|
compatibility.className = "settings-connection-compatibility";
|
|
@@ -17471,52 +17882,49 @@ ${error51.stderrTail}`] : []
|
|
|
17471
17882
|
body.append(compatibility);
|
|
17472
17883
|
}
|
|
17473
17884
|
if (item.agentSnapshot?.availability === "notInstalled") {
|
|
17474
|
-
const
|
|
17475
|
-
|
|
17476
|
-
const
|
|
17477
|
-
|
|
17478
|
-
|
|
17479
|
-
|
|
17480
|
-
|
|
17481
|
-
|
|
17482
|
-
|
|
17483
|
-
|
|
17484
|
-
|
|
17485
|
-
|
|
17486
|
-
|
|
17487
|
-
|
|
17488
|
-
|
|
17489
|
-
|
|
17490
|
-
|
|
17491
|
-
|
|
17492
|
-
|
|
17885
|
+
const zh = messages.locale === "zh-CN";
|
|
17886
|
+
const busy = item.availability === "installing" || item.availability === "checking";
|
|
17887
|
+
const note = (text) => {
|
|
17888
|
+
const paragraph = document2.createElement("p");
|
|
17889
|
+
paragraph.textContent = text;
|
|
17890
|
+
body.append(paragraph);
|
|
17891
|
+
};
|
|
17892
|
+
if (busy) note(messages.connectionInstallRunning);
|
|
17893
|
+
body.append(
|
|
17894
|
+
createHarnessInstallationPanel(
|
|
17895
|
+
document2,
|
|
17896
|
+
item.agentSnapshot.agent,
|
|
17897
|
+
hostId,
|
|
17898
|
+
messages,
|
|
17899
|
+
(button, command, label) => copyDiagnosticsToClipboard(document2, button, command, messages, label),
|
|
17900
|
+
item.install ? {
|
|
17901
|
+
run: item.install,
|
|
17902
|
+
status: busy ? item.availability : "idle"
|
|
17903
|
+
} : void 0
|
|
17904
|
+
)
|
|
17493
17905
|
);
|
|
17494
|
-
|
|
17906
|
+
const check2 = document2.createElement("button");
|
|
17907
|
+
check2.type = "button";
|
|
17908
|
+
check2.className = "settings-command-button";
|
|
17909
|
+
check2.dataset.connectionAction = "check-install";
|
|
17910
|
+
check2.textContent = zh ? "\u91CD\u65B0\u68C0\u6D4B" : "Check again";
|
|
17911
|
+
check2.disabled = busy;
|
|
17912
|
+
check2.addEventListener("click", () => {
|
|
17913
|
+
check2.disabled = true;
|
|
17914
|
+
check2.textContent = messages.connectionRefreshing;
|
|
17915
|
+
refresh();
|
|
17916
|
+
});
|
|
17917
|
+
body.append(check2);
|
|
17495
17918
|
} else if (item.error) {
|
|
17496
17919
|
const summary = document2.createElement("div");
|
|
17497
17920
|
summary.className = "settings-connection-error-summary";
|
|
17498
17921
|
const title = document2.createElement("strong");
|
|
17499
|
-
|
|
17922
|
+
const needsLogin = item.error.code === "authenticationRequired";
|
|
17923
|
+
const needsConfiguration = item.error.code === "configurationRequired";
|
|
17924
|
+
title.textContent = needsLogin ? messages.connectionLoginRequired : needsConfiguration ? messages.connectionConfigurationRequired : messages.connectionErrorTitle;
|
|
17500
17925
|
const description = document2.createElement("p");
|
|
17501
|
-
description.textContent = item.error.message;
|
|
17926
|
+
description.textContent = needsLogin ? messages.connectionLoginDescription : needsConfiguration ? messages.connectionConfigurationDescription : item.error.message;
|
|
17502
17927
|
summary.append(title, description);
|
|
17503
|
-
const metadata = document2.createElement("div");
|
|
17504
|
-
metadata.className = "settings-connection-error-metadata";
|
|
17505
|
-
metadata.append(
|
|
17506
|
-
detailLine(document2, messages.connectionErrorCode, item.error.code),
|
|
17507
|
-
detailLine(document2, messages.connectionRetryable, String(item.error.retryable))
|
|
17508
|
-
);
|
|
17509
|
-
if (item.error.stage) {
|
|
17510
|
-
metadata.append(detailLine(document2, messages.connectionFailureStage, item.error.stage));
|
|
17511
|
-
}
|
|
17512
|
-
if (item.error.durationMs !== void 0) {
|
|
17513
|
-
metadata.append(
|
|
17514
|
-
detailLine(document2, messages.connectionDuration, `${item.error.durationMs} ms`)
|
|
17515
|
-
);
|
|
17516
|
-
}
|
|
17517
|
-
if (item.error.diagnostic) {
|
|
17518
|
-
metadata.append(detailLine(document2, messages.connectionDiagnostic, item.error.diagnostic));
|
|
17519
|
-
}
|
|
17520
17928
|
const logHeader = document2.createElement("div");
|
|
17521
17929
|
logHeader.className = "settings-connection-error-log-header";
|
|
17522
17930
|
const logTitle = document2.createElement("strong");
|
|
@@ -17532,7 +17940,7 @@ ${error51.stderrTail}`] : []
|
|
|
17532
17940
|
logHeader.append(logTitle, copy);
|
|
17533
17941
|
const log = document2.createElement("pre");
|
|
17534
17942
|
log.className = "settings-connection-stderr";
|
|
17535
|
-
log.textContent =
|
|
17943
|
+
log.textContent = report;
|
|
17536
17944
|
const actions = document2.createElement("div");
|
|
17537
17945
|
actions.className = "settings-connection-error-actions";
|
|
17538
17946
|
const issue2 = document2.createElement("a");
|
|
@@ -17545,16 +17953,16 @@ ${error51.stderrTail}`] : []
|
|
|
17545
17953
|
const issueNote = document2.createElement("p");
|
|
17546
17954
|
issueNote.className = "settings-connection-issue-note";
|
|
17547
17955
|
issueNote.textContent = messages.connectionIssueDescription;
|
|
17548
|
-
body.append(summary,
|
|
17956
|
+
body.append(summary, logHeader, log, actions, issueNote);
|
|
17549
17957
|
} else {
|
|
17550
17958
|
const status = document2.createElement("div");
|
|
17551
17959
|
status.className = "settings-connection-state-summary";
|
|
17552
17960
|
const title = document2.createElement("strong");
|
|
17553
17961
|
title.textContent = connectionStatusLabel(item.availability, messages);
|
|
17554
17962
|
const description = document2.createElement("p");
|
|
17555
|
-
description.textContent = item.availability === "ready" ? messages.connectionReadyDescription : messages.connectionUnavailableDescription;
|
|
17963
|
+
description.textContent = item.availability === "updating" ? messages.harnessVersionUpdating : item.availability === "ready" ? messages.connectionReadyDescription : messages.connectionUnavailableDescription;
|
|
17556
17964
|
status.append(title, description);
|
|
17557
|
-
body.append(status);
|
|
17965
|
+
if (!item.agentSnapshot || item.availability !== "ready") body.append(status);
|
|
17558
17966
|
if (item.openWebUi) {
|
|
17559
17967
|
const open = document2.createElement("button");
|
|
17560
17968
|
open.type = "button";
|
|
@@ -17578,7 +17986,7 @@ ${error51.stderrTail}`] : []
|
|
|
17578
17986
|
const agent = item.agentSnapshot?.agent;
|
|
17579
17987
|
const getLaunchSettings = diagnostics?.getLaunchSettings?.bind(diagnostics);
|
|
17580
17988
|
const setLaunchSettings = diagnostics?.setLaunchSettings?.bind(diagnostics);
|
|
17581
|
-
if (hostId === "local" && agent === "workbuddy" && getLaunchSettings && setLaunchSettings) {
|
|
17989
|
+
if (hostId === "local" && (agent === "zcode" || agent === "workbuddy") && getLaunchSettings && setLaunchSettings) {
|
|
17582
17990
|
launchControls = existingLaunchControls ?? createHarnessLaunchControls(document2, messages, agent, {
|
|
17583
17991
|
get: () => getLaunchSettings(hostId, agent),
|
|
17584
17992
|
set: (path) => setLaunchSettings(hostId, agent, path)
|
|
@@ -17672,9 +18080,11 @@ ${error51.stderrTail}`] : []
|
|
|
17672
18080
|
let selectedItemKey = null;
|
|
17673
18081
|
let launchControls = null;
|
|
17674
18082
|
const versionPanels = /* @__PURE__ */ new Map();
|
|
18083
|
+
const updatingVersions = /* @__PURE__ */ new Set();
|
|
17675
18084
|
let latestSnapshot = null;
|
|
17676
18085
|
let disposeHostScroller = () => void 0;
|
|
17677
18086
|
const diagnostics = getDiagnostics();
|
|
18087
|
+
const installs = diagnostics ? harnessInstallStore(diagnostics) : null;
|
|
17678
18088
|
const runRefresh = () => {
|
|
17679
18089
|
if (pending || !diagnostics) return;
|
|
17680
18090
|
pending = true;
|
|
@@ -17685,6 +18095,7 @@ ${error51.stderrTail}`] : []
|
|
|
17685
18095
|
);
|
|
17686
18096
|
void context.runLatest(() => diagnostics.refresh(), {
|
|
17687
18097
|
success() {
|
|
18098
|
+
installs?.clearErrors();
|
|
17688
18099
|
pending = false;
|
|
17689
18100
|
refresh.disabled = false;
|
|
17690
18101
|
refresh.replaceChildren(
|
|
@@ -17728,12 +18139,11 @@ ${error51.stderrTail}`] : []
|
|
|
17728
18139
|
latestSnapshot = snapshot;
|
|
17729
18140
|
disposeHostScroller();
|
|
17730
18141
|
disposeHostScroller = () => void 0;
|
|
17731
|
-
content.replaceChildren();
|
|
17732
18142
|
if (!snapshot) {
|
|
17733
18143
|
const empty = document2.createElement("div");
|
|
17734
18144
|
empty.className = "settings-empty";
|
|
17735
18145
|
empty.textContent = messages.connectionNoRuntime;
|
|
17736
|
-
content.
|
|
18146
|
+
content.replaceChildren(empty);
|
|
17737
18147
|
return;
|
|
17738
18148
|
}
|
|
17739
18149
|
const selectedHost = (selectedHostId ? snapshot.hosts.find((host) => host.hostId === selectedHostId) : void 0) ?? snapshot.hosts.find((host) => host.active) ?? snapshot.hosts.find((host) => host.hostId === "local") ?? snapshot.hosts[0];
|
|
@@ -17805,7 +18215,24 @@ ${error51.stderrTail}`] : []
|
|
|
17805
18215
|
const inspector = document2.createElement("aside");
|
|
17806
18216
|
inspector.className = "settings-connection-inspector";
|
|
17807
18217
|
inspector.setAttribute("aria-live", "polite");
|
|
17808
|
-
const items = connectionItems(snapshot, selectedHost, messages, diagnostics)
|
|
18218
|
+
const items = connectionItems(snapshot, selectedHost, messages, diagnostics).map(
|
|
18219
|
+
(item) => {
|
|
18220
|
+
const agent = item.agentSnapshot?.agent;
|
|
18221
|
+
if (!agent) return item;
|
|
18222
|
+
const state = installs?.get(selectedHost.hostId, agent);
|
|
18223
|
+
return {
|
|
18224
|
+
...item,
|
|
18225
|
+
...state ? { availability: state.status } : {},
|
|
18226
|
+
...updatingVersions.has(JSON.stringify([selectedHost.hostId, agent])) ? { availability: "updating" } : {},
|
|
18227
|
+
...state?.error ? { installError: state.error } : {},
|
|
18228
|
+
...diagnostics?.installation && harnessHasInstallCommands(agent) ? {
|
|
18229
|
+
install: () => {
|
|
18230
|
+
void installs?.install(selectedHost.hostId, agent);
|
|
18231
|
+
}
|
|
18232
|
+
} : {}
|
|
18233
|
+
};
|
|
18234
|
+
}
|
|
18235
|
+
);
|
|
17809
18236
|
if (!items.some((item) => item.key === selectedItemKey)) {
|
|
17810
18237
|
const requestedFocus = pendingFocusAgent;
|
|
17811
18238
|
pendingFocusAgent = null;
|
|
@@ -17835,13 +18262,23 @@ ${error51.stderrTail}`] : []
|
|
|
17835
18262
|
launchControls = { hostId: selectedHost.hostId, itemKey: item.key, element };
|
|
17836
18263
|
const agent = item.agentSnapshot?.agent;
|
|
17837
18264
|
const installation = diagnostics?.installation?.bind(diagnostics);
|
|
17838
|
-
if (agent && item.availability !== "notInstalled" && item.availability !== "checking" && installation) {
|
|
18265
|
+
if (agent && item.agentSnapshot?.availability !== "notInstalled" && item.availability !== "installing" && item.availability !== "checking" && installation) {
|
|
17839
18266
|
const key = JSON.stringify([selectedHost.hostId, agent]);
|
|
17840
18267
|
let panel = versionPanels.get(key);
|
|
17841
18268
|
if (!panel) {
|
|
17842
18269
|
const hostId = selectedHost.hostId;
|
|
17843
18270
|
panel = createHarnessVersionPanel(document2, messages, context.signal, agent, {
|
|
17844
|
-
run
|
|
18271
|
+
async run(action) {
|
|
18272
|
+
if (action !== "update") return installation(hostId, agent, action);
|
|
18273
|
+
updatingVersions.add(key);
|
|
18274
|
+
if (diagnostics) render(diagnostics.snapshot());
|
|
18275
|
+
try {
|
|
18276
|
+
return await installation(hostId, agent, action);
|
|
18277
|
+
} finally {
|
|
18278
|
+
updatingVersions.delete(key);
|
|
18279
|
+
if (!context.signal.aborted && diagnostics) render(diagnostics.snapshot());
|
|
18280
|
+
}
|
|
18281
|
+
}
|
|
17845
18282
|
});
|
|
17846
18283
|
versionPanels.set(key, panel);
|
|
17847
18284
|
}
|
|
@@ -17866,7 +18303,7 @@ ${error51.stderrTail}`] : []
|
|
|
17866
18303
|
const agentByKey = new Map(groupableItems.map((item) => [item.key, item]));
|
|
17867
18304
|
const preferenceOrder = groupPreference.list(
|
|
17868
18305
|
new Set(
|
|
17869
|
-
groupableItems.filter((item) => item.availability === "notInstalled").map((item) => item.agentSnapshot.agent)
|
|
18306
|
+
groupableItems.filter((item) => item.agentSnapshot.availability === "notInstalled").map((item) => item.agentSnapshot.agent)
|
|
17870
18307
|
)
|
|
17871
18308
|
).filter((entry) => agentByKey.has(entry.agent));
|
|
17872
18309
|
for (const item of groupableItems) {
|
|
@@ -18007,7 +18444,7 @@ ${error51.stderrTail}`] : []
|
|
|
18007
18444
|
if (selectedItem) selectItem(selectedItem);
|
|
18008
18445
|
list.append(hostStrip, tableHeader, rows);
|
|
18009
18446
|
layout.append(list, inspector);
|
|
18010
|
-
content.
|
|
18447
|
+
content.replaceChildren(layout);
|
|
18011
18448
|
disposeHostScroller = configureHostScroller(
|
|
18012
18449
|
document2,
|
|
18013
18450
|
hostStrip,
|
|
@@ -18018,7 +18455,14 @@ ${error51.stderrTail}`] : []
|
|
|
18018
18455
|
const selectedTab = [...tabs.children].find(
|
|
18019
18456
|
(child) => child.getAttribute("aria-selected") === "true"
|
|
18020
18457
|
);
|
|
18021
|
-
selectedTab
|
|
18458
|
+
if (selectedTab) {
|
|
18459
|
+
const left = selectedTab.offsetLeft;
|
|
18460
|
+
const right = left + selectedTab.offsetWidth;
|
|
18461
|
+
if (left < tabs.scrollLeft) tabs.scrollLeft = left;
|
|
18462
|
+
else if (right > tabs.scrollLeft + tabs.clientWidth) {
|
|
18463
|
+
tabs.scrollLeft = right - tabs.clientWidth;
|
|
18464
|
+
}
|
|
18465
|
+
}
|
|
18022
18466
|
};
|
|
18023
18467
|
render(diagnostics?.snapshot() ?? null);
|
|
18024
18468
|
const unsubscribeGroup = groupPreference.subscribe(
|
|
@@ -18033,8 +18477,10 @@ ${error51.stderrTail}`] : []
|
|
|
18033
18477
|
}
|
|
18034
18478
|
refresh.addEventListener("click", runRefresh);
|
|
18035
18479
|
const unsubscribe = diagnostics.subscribe(() => render(diagnostics.snapshot()));
|
|
18480
|
+
const unsubscribeInstalls = installs?.subscribe(() => render(diagnostics.snapshot()));
|
|
18036
18481
|
return () => {
|
|
18037
18482
|
disposeHostScroller();
|
|
18483
|
+
unsubscribeInstalls?.();
|
|
18038
18484
|
unsubscribe();
|
|
18039
18485
|
unsubscribeGroup();
|
|
18040
18486
|
};
|
|
@@ -18241,19 +18687,20 @@ ${error51.stderrTail}`] : []
|
|
|
18241
18687
|
connectionCopyDetails: "Copy diagnostics",
|
|
18242
18688
|
connectionCopied: "Copied",
|
|
18243
18689
|
connectionCopyFailed: "Copy failed",
|
|
18244
|
-
connectionErrorCode: "Error code",
|
|
18245
18690
|
connectionErrorMessage: "Error message",
|
|
18246
|
-
connectionRetryable: "Retryable",
|
|
18247
|
-
connectionFailureStage: "Failure stage",
|
|
18248
|
-
connectionDuration: "Duration",
|
|
18249
|
-
connectionDiagnostic: "Diagnostic",
|
|
18250
18691
|
connectionNoRuntime: "The renderer request bridge is not available yet.",
|
|
18251
18692
|
connectionStatusReady: "Ready",
|
|
18693
|
+
connectionStatusConnected: "Connected",
|
|
18694
|
+
connectionLoginRequired: "Login required",
|
|
18695
|
+
connectionConfigurationRequired: "Setup required",
|
|
18696
|
+
connectionConfigurationDescription: "Configure a Provider and its required credentials in this Harness on the selected Host, then check the connection again.",
|
|
18697
|
+
connectionLoginDescription: "Complete login or authentication setup in this Harness on the selected Host, then check the connection again.",
|
|
18252
18698
|
connectionStatusChecking: "Checking",
|
|
18253
18699
|
connectionStatusNotInstalled: "Not installed",
|
|
18254
18700
|
connectionStatusUnavailable: "Unavailable",
|
|
18255
18701
|
connectionStatusError: "Error",
|
|
18256
18702
|
connectionStatusInstalling: "Installing",
|
|
18703
|
+
connectionStatusUpdating: "Updating",
|
|
18257
18704
|
connectionStatusUnsupported: "Unsupported",
|
|
18258
18705
|
connectionComponent: "Component",
|
|
18259
18706
|
connectionStatus: "Status",
|
|
@@ -18262,6 +18709,8 @@ ${error51.stderrTail}`] : []
|
|
|
18262
18709
|
launchPathLabel: "Installed application path",
|
|
18263
18710
|
launchPathPlaceholder: "Installation folder, e.g. D:\\program\\WorkBuddy",
|
|
18264
18711
|
launchPathWorkbuddyHelp: "This integration requires the WorkBuddy app. If it is not detected automatically, enter its installation folder. codexhost locates the required files inside it. Restart codexhost after saving to apply.",
|
|
18712
|
+
launchPathZcodePlaceholder: "Application path, e.g. /Applications/ZCode.app or D:\\program\\ZCode",
|
|
18713
|
+
launchPathZcodeHelp: "This integration requires the ZCode Desktop app. If it is not detected automatically, enter its application path (the .app bundle on macOS, the installation folder on Windows and Linux). codexhost locates the required files inside it. Restart codexhost after saving to apply.",
|
|
18265
18714
|
launchPathSave: "Save path",
|
|
18266
18715
|
launchPathReset: "Clear override",
|
|
18267
18716
|
launchPathRestart: "Saved. Restart codexhost to apply; running sessions are unchanged.",
|
|
@@ -18271,11 +18720,13 @@ ${error51.stderrTail}`] : []
|
|
|
18271
18720
|
launchPathLoading: "Loading launch settings\u2026",
|
|
18272
18721
|
launchPathLoadError: "Could not load launch settings. Reopen this detail panel to retry.",
|
|
18273
18722
|
launchPathSaveError: "Could not save. Enter an existing absolute installation folder on this Host and check configuration permissions.",
|
|
18274
|
-
|
|
18723
|
+
connectionOfficialWebsite: "Visit official website",
|
|
18275
18724
|
connectionOpenHarnessWeb: "Open DeepSeek Harness Web",
|
|
18276
|
-
connectionDeepSeekTestedVersions: "Supported DSH versions: 0.1.
|
|
18725
|
+
connectionDeepSeekTestedVersions: "Supported DSH versions: 0.1.7-rc.1, 0.1.7-rc.2, 0.2.0-rc.1 and 0.2.0-rc.2. Versions newer than 0.2.0-rc.2 can be tried, but compatibility may be limited; versions older than 0.1.7-rc.1 must be upgraded first.",
|
|
18277
18726
|
connectionInstall: "Install",
|
|
18278
18727
|
connectionInstallDescription: "This Harness was not detected.",
|
|
18728
|
+
connectionInstallRunning: "Installing on the selected Host. You can leave this page; login or setup may still be required afterward.",
|
|
18729
|
+
harnessVersion: harnessVersionEnglish,
|
|
18279
18730
|
harnessVersionTitle: "Harness CLI version",
|
|
18280
18731
|
harnessVersionCurrent: "Current version",
|
|
18281
18732
|
harnessVersionLatest: "Latest version",
|
|
@@ -18362,6 +18813,7 @@ ${error51.stderrTail}`] : []
|
|
|
18362
18813
|
aboutConsoleFailed: "The console could not be opened",
|
|
18363
18814
|
pageLabels: Object.freeze({
|
|
18364
18815
|
connections: "Connections",
|
|
18816
|
+
"remote-connections": "Remote connections",
|
|
18365
18817
|
appearance: "General",
|
|
18366
18818
|
accounts: "Accounts",
|
|
18367
18819
|
"session-import": "Session Import",
|
|
@@ -18505,19 +18957,20 @@ ${error51.stderrTail}`] : []
|
|
|
18505
18957
|
connectionCopyDetails: "\u590D\u5236\u8BCA\u65AD\u4FE1\u606F",
|
|
18506
18958
|
connectionCopied: "\u5DF2\u590D\u5236",
|
|
18507
18959
|
connectionCopyFailed: "\u590D\u5236\u5931\u8D25",
|
|
18508
|
-
connectionErrorCode: "\u9519\u8BEF\u7801",
|
|
18509
18960
|
connectionErrorMessage: "\u9519\u8BEF\u4FE1\u606F",
|
|
18510
|
-
connectionRetryable: "\u53EF\u91CD\u8BD5",
|
|
18511
|
-
connectionFailureStage: "\u5931\u8D25\u9636\u6BB5",
|
|
18512
|
-
connectionDuration: "\u68C0\u67E5\u8017\u65F6",
|
|
18513
|
-
connectionDiagnostic: "\u8BCA\u65AD\u4FE1\u606F",
|
|
18514
18961
|
connectionNoRuntime: "Renderer \u8BF7\u6C42\u6865\u5C1A\u672A\u53EF\u7528\u3002",
|
|
18515
18962
|
connectionStatusReady: "\u6B63\u5E38",
|
|
18963
|
+
connectionStatusConnected: "\u5DF2\u8FDE\u63A5",
|
|
18964
|
+
connectionLoginRequired: "\u9700\u8981\u767B\u5F55",
|
|
18965
|
+
connectionConfigurationRequired: "\u9700\u8981\u914D\u7F6E",
|
|
18966
|
+
connectionConfigurationDescription: "\u8BF7\u5728\u6240\u9009 Host \u4E0A\u914D\u7F6E\u8BE5 Harness \u7684 Provider \u53CA\u6240\u9700\u8BA4\u8BC1\u4FE1\u606F\uFF0C\u7136\u540E\u91CD\u65B0\u68C0\u6D4B\u8FDE\u63A5\u3002",
|
|
18967
|
+
connectionLoginDescription: "\u8BF7\u5728\u6240\u9009 Host \u4E0A\u5B8C\u6210\u8BE5 Harness \u7684\u767B\u5F55\u6216\u8BA4\u8BC1\u914D\u7F6E\uFF0C\u7136\u540E\u91CD\u65B0\u68C0\u6D4B\u8FDE\u63A5\u3002",
|
|
18516
18968
|
connectionStatusChecking: "\u68C0\u67E5\u4E2D",
|
|
18517
18969
|
connectionStatusNotInstalled: "\u672A\u5B89\u88C5",
|
|
18518
18970
|
connectionStatusUnavailable: "\u4E0D\u53EF\u7528",
|
|
18519
18971
|
connectionStatusError: "\u9519\u8BEF",
|
|
18520
18972
|
connectionStatusInstalling: "\u5B89\u88C5\u4E2D",
|
|
18973
|
+
connectionStatusUpdating: "\u66F4\u65B0\u4E2D",
|
|
18521
18974
|
connectionStatusUnsupported: "\u4E0D\u652F\u6301",
|
|
18522
18975
|
connectionComponent: "\u7EC4\u4EF6",
|
|
18523
18976
|
connectionStatus: "\u72B6\u6001",
|
|
@@ -18526,6 +18979,8 @@ ${error51.stderrTail}`] : []
|
|
|
18526
18979
|
launchPathLabel: "\u5E94\u7528\u5B89\u88C5\u8DEF\u5F84",
|
|
18527
18980
|
launchPathPlaceholder: "\u586B\u5199\u5B89\u88C5\u76EE\u5F55\uFF0C\u4F8B\u5982 D:\\program\\WorkBuddy",
|
|
18528
18981
|
launchPathWorkbuddyHelp: "\u6B64\u63A5\u5165\u4F9D\u8D56 WorkBuddy \u5E94\u7528\u3002\u82E5\u672A\u81EA\u52A8\u8BC6\u522B\uFF0C\u8BF7\u586B\u5199\u5E94\u7528\u5B89\u88C5\u76EE\u5F55\uFF0Ccodexhost \u4F1A\u81EA\u52A8\u5B9A\u4F4D\u6240\u9700\u6587\u4EF6\u3002\u4FDD\u5B58\u540E\u91CD\u542F codexhost \u751F\u6548\u3002",
|
|
18982
|
+
launchPathZcodePlaceholder: "\u586B\u5199\u5E94\u7528\u8DEF\u5F84\uFF0C\u4F8B\u5982 /Applications/ZCode.app \u6216 D:\\program\\ZCode",
|
|
18983
|
+
launchPathZcodeHelp: "\u6B64\u63A5\u5165\u4F9D\u8D56 ZCode Desktop \u5E94\u7528\u3002\u82E5\u672A\u81EA\u52A8\u8BC6\u522B\uFF0C\u8BF7\u586B\u5199\u5E94\u7528\u8DEF\u5F84\uFF08macOS \u4E3A .app\uFF0CWindows \u548C Linux \u4E3A\u5B89\u88C5\u76EE\u5F55\uFF09\uFF0Ccodexhost \u4F1A\u81EA\u52A8\u5B9A\u4F4D\u6240\u9700\u6587\u4EF6\u3002\u4FDD\u5B58\u540E\u91CD\u542F codexhost \u751F\u6548\u3002",
|
|
18529
18984
|
launchPathSave: "\u4FDD\u5B58\u8DEF\u5F84",
|
|
18530
18985
|
launchPathReset: "\u6E05\u9664\u81EA\u5B9A\u4E49\u8DEF\u5F84",
|
|
18531
18986
|
launchPathRestart: "\u5DF2\u4FDD\u5B58\uFF0C\u91CD\u542F codexhost \u540E\u751F\u6548\uFF1B\u5F53\u524D\u8FD0\u884C\u4E2D\u7684\u4F1A\u8BDD\u4E0D\u53D7\u5F71\u54CD\u3002",
|
|
@@ -18535,11 +18990,13 @@ ${error51.stderrTail}`] : []
|
|
|
18535
18990
|
launchPathLoading: "\u6B63\u5728\u8BFB\u53D6\u542F\u52A8\u8BBE\u7F6E\u2026",
|
|
18536
18991
|
launchPathLoadError: "\u65E0\u6CD5\u8BFB\u53D6\u542F\u52A8\u8BBE\u7F6E\uFF0C\u8BF7\u91CD\u65B0\u6253\u5F00\u6B64\u8BE6\u60C5\u9762\u677F\u91CD\u8BD5\u3002",
|
|
18537
18992
|
launchPathSaveError: "\u4FDD\u5B58\u5931\u8D25\u3002\u8BF7\u586B\u5199\u6B64 Host \u4E0A\u5B9E\u9645\u5B58\u5728\u7684\u5B89\u88C5\u76EE\u5F55\u7EDD\u5BF9\u8DEF\u5F84\uFF0C\u5E76\u786E\u8BA4\u914D\u7F6E\u76EE\u5F55\u53EF\u5199\u3002",
|
|
18538
|
-
|
|
18993
|
+
connectionOfficialWebsite: "\u8BBF\u95EE\u5B98\u7F51",
|
|
18539
18994
|
connectionOpenHarnessWeb: "\u6253\u5F00 DeepSeek Harness Web",
|
|
18540
|
-
connectionDeepSeekTestedVersions: "\u652F\u6301 DSH \u7248\u672C\uFF1A0.1.
|
|
18995
|
+
connectionDeepSeekTestedVersions: "\u652F\u6301 DSH \u7248\u672C\uFF1A0.1.7-rc.1\u30010.1.7-rc.2\u30010.2.0-rc.1 \u548C 0.2.0-rc.2\u3002\u9AD8\u4E8E 0.2.0-rc.2 \u7684\u7248\u672C\u53EF\u4EE5\u5C1D\u8BD5\u8FDE\u63A5\uFF0C\u4F46\u9002\u914D\u5EA6\u53EF\u80FD\u6709\u9650\uFF1B\u4F4E\u4E8E 0.1.7-rc.1 \u7684\u7248\u672C\u9700\u8981\u5148\u5347\u7EA7\u3002",
|
|
18541
18996
|
connectionInstall: "\u5B89\u88C5",
|
|
18542
18997
|
connectionInstallDescription: "\u5C1A\u672A\u68C0\u6D4B\u5230\u8BE5 Harness\u3002",
|
|
18998
|
+
connectionInstallRunning: "\u6B63\u5728\u6240\u9009 Host \u4E0A\u5B89\u88C5\uFF0C\u79BB\u5F00\u9875\u9762\u4E0D\u4F1A\u4E2D\u65AD\u3002\u5B89\u88C5\u540E\u53EF\u80FD\u4ECD\u9700\u767B\u5F55\u6216\u914D\u7F6E\u3002",
|
|
18999
|
+
harnessVersion: harnessVersionChinese,
|
|
18543
19000
|
harnessVersionTitle: "Harness CLI \u7248\u672C",
|
|
18544
19001
|
harnessVersionCurrent: "\u5F53\u524D\u7248\u672C",
|
|
18545
19002
|
harnessVersionLatest: "\u6700\u65B0\u7248\u672C",
|
|
@@ -18626,6 +19083,7 @@ ${error51.stderrTail}`] : []
|
|
|
18626
19083
|
aboutConsoleFailed: "\u63A7\u5236\u53F0\u6253\u5F00\u5931\u8D25",
|
|
18627
19084
|
pageLabels: Object.freeze({
|
|
18628
19085
|
connections: "\u8FDE\u63A5",
|
|
19086
|
+
"remote-connections": "\u8FDC\u7A0B\u8FDE\u63A5",
|
|
18629
19087
|
appearance: "\u901A\u7528",
|
|
18630
19088
|
accounts: "\u8D26\u53F7",
|
|
18631
19089
|
"session-import": "\u4F1A\u8BDD\u5BFC\u5165",
|
|
@@ -18684,7 +19142,8 @@ ${error51.stderrTail}`] : []
|
|
|
18684
19142
|
hermes: "https://hermes-agent.nousresearch.com/docs",
|
|
18685
19143
|
qoder: "https://docs.qoder.com/",
|
|
18686
19144
|
"qoder-cn": "https://docs.qoder.cn/",
|
|
18687
|
-
"kimi-code": "https://moonshotai.github.io/kimi-code/en/guides/getting-started.html"
|
|
19145
|
+
"kimi-code": "https://moonshotai.github.io/kimi-code/en/guides/getting-started.html",
|
|
19146
|
+
zcode: "https://github.com/BytePioneer-AI/codex-host/blob/main/docs/harnesses/zcode/zcode-harness-integration.md#%E5%AE%89%E8%A3%85"
|
|
18688
19147
|
};
|
|
18689
19148
|
var CONTROL_ATTRIBUTE = "data-codexhost-agent-control";
|
|
18690
19149
|
var AGENT_MENU_WIDTH = 224;
|
|
@@ -22027,7 +22486,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
22027
22486
|
const thinkingReady = availableThinkingOptions.length === 0 || availableThinkingOptions.some(({ id }) => id === modelView.selectedThinkingOptionId);
|
|
22028
22487
|
const modelReady = selectedModel !== void 0 && selectedCatalogModel !== void 0;
|
|
22029
22488
|
const modelBlocked = state.agent !== "codex" && (modelView.status === "selecting" || !modelReady || !thinkingReady);
|
|
22030
|
-
const permissionModeBlocked = state.agent !== "codex" &&
|
|
22489
|
+
const permissionModeBlocked = state.agent !== "codex" && !isPermissionModeControlReady(permissionModeView);
|
|
22031
22490
|
const submissionBlocked = switching || ownershipError || modelBlocked || permissionModeBlocked;
|
|
22032
22491
|
if (submissionBlocked && control.sendDisabledBeforeSwitch === null) {
|
|
22033
22492
|
control.sendDisabledBeforeSwitch = control.sendButton.disabled;
|
|
@@ -22665,6 +23124,18 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
22665
23124
|
};
|
|
22666
23125
|
}
|
|
22667
23126
|
|
|
23127
|
+
// src/renderer-native-thread.ts
|
|
23128
|
+
function isRecord3(value) {
|
|
23129
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23130
|
+
}
|
|
23131
|
+
async function verifyNativeCodexThread(sendRequest, threadId) {
|
|
23132
|
+
const native = await sendRequest("thread/read", { threadId, includeTurns: false });
|
|
23133
|
+
const thread = isRecord3(native) ? native.thread : null;
|
|
23134
|
+
if (!isRecord3(thread) || thread.id !== threadId || typeof thread.modelProvider !== "string" || !thread.modelProvider || thread.modelProvider === "codexhost" || typeof thread.cliVersion !== "string" || !thread.cliVersion || thread.cliVersion === "codexhost") {
|
|
23135
|
+
throw new Error("Native Thread response cannot establish Codex ownership");
|
|
23136
|
+
}
|
|
23137
|
+
}
|
|
23138
|
+
|
|
22668
23139
|
// src/renderer-session-import-client.ts
|
|
22669
23140
|
var RendererSessionImportUnavailableError = class extends Error {
|
|
22670
23141
|
constructor() {
|
|
@@ -22739,15 +23210,15 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
22739
23210
|
var CODEX_ACCOUNT_LIST_METHOD = "codexhost/account/list";
|
|
22740
23211
|
var CODEX_ACCOUNT_REFRESH_METHOD = "codexhost/account/refresh";
|
|
22741
23212
|
var CODEX_ACCOUNT_CHANGED_METHOD = "codexhost/account/changed";
|
|
22742
|
-
function
|
|
23213
|
+
function isRecord4(value) {
|
|
22743
23214
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
22744
23215
|
}
|
|
22745
23216
|
function notifiedThreadId(notification) {
|
|
22746
|
-
if (!
|
|
23217
|
+
if (!isRecord4(notification) || !THREAD_USAGE_REFRESH_METHODS.includes(notification.method)) {
|
|
22747
23218
|
return null;
|
|
22748
23219
|
}
|
|
22749
23220
|
const params = notification.params;
|
|
22750
|
-
if (!
|
|
23221
|
+
if (!isRecord4(params)) return null;
|
|
22751
23222
|
const parsed = hostThreadIdSchema.safeParse(params.threadId);
|
|
22752
23223
|
return parsed.success ? parsed.data : null;
|
|
22753
23224
|
}
|
|
@@ -22919,14 +23390,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
22919
23390
|
result = await manager.sendRequest(THREAD_INSPECT_METHOD, params);
|
|
22920
23391
|
} catch (error51) {
|
|
22921
23392
|
if (!(error51 instanceof RendererMethodUnavailableError)) throw error51;
|
|
22922
|
-
|
|
22923
|
-
threadId: params.threadId,
|
|
22924
|
-
includeTurns: false
|
|
22925
|
-
});
|
|
22926
|
-
const thread = isRecord3(native) ? native.thread : null;
|
|
22927
|
-
if (!isRecord3(thread) || thread.id !== params.threadId || typeof thread.modelProvider !== "string" || !thread.modelProvider || thread.modelProvider === "codexhost" || typeof thread.cliVersion !== "string" || !thread.cliVersion || thread.cliVersion === "codexhost") {
|
|
22928
|
-
throw new Error("Native Thread response cannot establish Codex ownership");
|
|
22929
|
-
}
|
|
23393
|
+
await verifyNativeCodexThread(manager.sendRequest, params.threadId);
|
|
22930
23394
|
return { owner: "codex", locked: true };
|
|
22931
23395
|
}
|
|
22932
23396
|
return threadInspectionSchema.parse(result);
|
|
@@ -22973,6 +23437,24 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
22973
23437
|
selectThreadModel,
|
|
22974
23438
|
selectThreadThinking,
|
|
22975
23439
|
selectThreadPermissionMode,
|
|
23440
|
+
async setupSsh(input) {
|
|
23441
|
+
return remoteSshSetupResultSchema.parse(
|
|
23442
|
+
await manager.sendRequest(REMOTE_SSH_SETUP_METHOD, remoteSshSetupParamsSchema.parse(input))
|
|
23443
|
+
);
|
|
23444
|
+
},
|
|
23445
|
+
async runtimeStatus() {
|
|
23446
|
+
try {
|
|
23447
|
+
return runtimeStatusSchema.parse(await source.sendRequest(RUNTIME_STATUS_METHOD, {}));
|
|
23448
|
+
} catch (error51) {
|
|
23449
|
+
if (!isUnsupportedMethod(error51, RUNTIME_STATUS_METHOD)) throw error51;
|
|
23450
|
+
throw new RendererMethodUnavailableError(RUNTIME_STATUS_METHOD, error51);
|
|
23451
|
+
}
|
|
23452
|
+
},
|
|
23453
|
+
async updateRemote(version2) {
|
|
23454
|
+
return runtimeStatusSchema.parse(
|
|
23455
|
+
await manager.sendRequest(REMOTE_UPDATE_METHOD, { version: version2 })
|
|
23456
|
+
);
|
|
23457
|
+
},
|
|
22976
23458
|
async checkUpdate() {
|
|
22977
23459
|
const result = await manager.sendRequest(
|
|
22978
23460
|
UPDATE_CHECK_METHOD,
|
|
@@ -23051,7 +23533,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23051
23533
|
throw new Error("Renderer Account notification callback is unavailable");
|
|
23052
23534
|
}
|
|
23053
23535
|
return notifications.addNotificationCallback(CODEX_ACCOUNT_CHANGED_METHOD, (notification) => {
|
|
23054
|
-
if (!
|
|
23536
|
+
if (!isRecord4(notification) || notification.method !== CODEX_ACCOUNT_CHANGED_METHOD) return;
|
|
23055
23537
|
const state = codexAccountChangedSchema.safeParse(notification.params);
|
|
23056
23538
|
if (state.success) listener(state.data);
|
|
23057
23539
|
});
|
|
@@ -23060,16 +23542,16 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23060
23542
|
}
|
|
23061
23543
|
|
|
23062
23544
|
// src/renderer-external-queue.ts
|
|
23063
|
-
function
|
|
23545
|
+
function isRecord5(value) {
|
|
23064
23546
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
23065
23547
|
}
|
|
23066
23548
|
function installRendererExternalQueue(target) {
|
|
23067
|
-
if (!
|
|
23549
|
+
if (!isRecord5(target) || typeof target.getTurnCoordinator !== "function" || typeof target.getConversation !== "function") {
|
|
23068
23550
|
return null;
|
|
23069
23551
|
}
|
|
23070
23552
|
const coordinator = target.getTurnCoordinator();
|
|
23071
|
-
const queue =
|
|
23072
|
-
if (!
|
|
23553
|
+
const queue = isRecord5(coordinator) ? coordinator.serverQueue : null;
|
|
23554
|
+
if (!isRecord5(queue) || typeof queue.isEnabled !== "function") return null;
|
|
23073
23555
|
const descriptor = Object.getOwnPropertyDescriptor(queue, "isEnabled");
|
|
23074
23556
|
if (!descriptor?.writable) return null;
|
|
23075
23557
|
const original = queue.isEnabled;
|
|
@@ -23078,7 +23560,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23078
23560
|
const threadId = args[0];
|
|
23079
23561
|
if (typeof threadId === "string") {
|
|
23080
23562
|
const conversation = getConversation.call(target, threadId);
|
|
23081
|
-
if (
|
|
23563
|
+
if (isRecord5(conversation) && conversation.id === threadId && // Reserved transport marker from externalThreadValue, retained by
|
|
23082
23564
|
// Desktop in both newly created and hydrated conversation metadata.
|
|
23083
23565
|
conversation.modelProvider === "codexhost") {
|
|
23084
23566
|
return false;
|
|
@@ -23093,19 +23575,20 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23093
23575
|
}
|
|
23094
23576
|
|
|
23095
23577
|
// src/renderer-external-steering.ts
|
|
23096
|
-
|
|
23578
|
+
var THREAD_OWNERSHIP_LIST_METHOD2 = "codexhost/thread/ownership/list";
|
|
23579
|
+
function isRecord6(value) {
|
|
23097
23580
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
23098
23581
|
}
|
|
23099
23582
|
function isManager(value) {
|
|
23100
|
-
return
|
|
23583
|
+
return isRecord6(value) && ["sendRequest", "steerTurn", "startTurn", "getTurnCoordinator"].every(
|
|
23101
23584
|
(key) => typeof value[key] === "function"
|
|
23102
23585
|
);
|
|
23103
23586
|
}
|
|
23104
23587
|
function submissionHost(manager) {
|
|
23105
23588
|
const coordinator = manager.getTurnCoordinator();
|
|
23106
|
-
const options =
|
|
23107
|
-
const host =
|
|
23108
|
-
if (!
|
|
23589
|
+
const options = isRecord6(coordinator) ? coordinator.options : null;
|
|
23590
|
+
const host = isRecord6(options) ? options.submissionHost : null;
|
|
23591
|
+
if (!isRecord6(host) || typeof host.getActiveTurnId !== "function" || typeof host.hasPendingTurnStart !== "function") {
|
|
23109
23592
|
throw new Error("Desktop turn submission binding is unavailable");
|
|
23110
23593
|
}
|
|
23111
23594
|
return {
|
|
@@ -23147,20 +23630,20 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23147
23630
|
var INTERRUPTED_QUEUE_REASON = "Interrupted before the steer was accepted.";
|
|
23148
23631
|
async function preserveQueuedFollowUps(manager, threadId) {
|
|
23149
23632
|
const coordinator = manager.getTurnCoordinator();
|
|
23150
|
-
if (!
|
|
23633
|
+
if (!isRecord6(coordinator) || typeof coordinator.loadMessages !== "function" || typeof coordinator.readMessages !== "function" || typeof coordinator.mutate !== "function") {
|
|
23151
23634
|
throw new Error("Desktop follow-up queue binding is unavailable");
|
|
23152
23635
|
}
|
|
23153
23636
|
await coordinator.loadMessages.call(coordinator, threadId);
|
|
23154
23637
|
const messages = coordinator.readMessages.call(coordinator, threadId);
|
|
23155
23638
|
if (!Array.isArray(messages)) throw new Error("Desktop follow-up queue is unavailable");
|
|
23156
23639
|
const alreadyPaused = new Set(
|
|
23157
|
-
messages.filter((message) =>
|
|
23640
|
+
messages.filter((message) => isRecord6(message) && message.pausedReason != null).map((message) => message.id)
|
|
23158
23641
|
);
|
|
23159
23642
|
return () => {
|
|
23160
23643
|
coordinator.mutate.call(coordinator, threadId, (current) => {
|
|
23161
23644
|
if (!Array.isArray(current)) return current;
|
|
23162
23645
|
return current.map((message) => {
|
|
23163
|
-
if (!
|
|
23646
|
+
if (!isRecord6(message) || alreadyPaused.has(message.id) || message.pausedReason !== INTERRUPTED_QUEUE_REASON)
|
|
23164
23647
|
return message;
|
|
23165
23648
|
const resumed = { ...message };
|
|
23166
23649
|
delete resumed.pausedReason;
|
|
@@ -23178,9 +23661,9 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23178
23661
|
const pending = /* @__PURE__ */ new Map();
|
|
23179
23662
|
let disposed = false;
|
|
23180
23663
|
const send = function(method, params, options) {
|
|
23181
|
-
const messageId =
|
|
23182
|
-
const route = typeof messageId === "string" &&
|
|
23183
|
-
if (method !== "turn/start" || !
|
|
23664
|
+
const messageId = isRecord6(params) ? params.clientUserMessageId : null;
|
|
23665
|
+
const route = typeof messageId === "string" && isRecord6(params) ? routes.get(`${params.threadId}\0${messageId}`) : void 0;
|
|
23666
|
+
if (method !== "turn/start" || !isRecord6(params) || !route || route.threadId !== params.threadId) {
|
|
23184
23667
|
return originalSend.call(manager, method, params, options);
|
|
23185
23668
|
}
|
|
23186
23669
|
if (disposed) return Promise.reject(new Error("External steering binding was disposed"));
|
|
@@ -23199,7 +23682,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23199
23682
|
options
|
|
23200
23683
|
)
|
|
23201
23684
|
).then((response) => {
|
|
23202
|
-
if (!
|
|
23685
|
+
if (!isRecord6(response) || typeof response.turnId !== "string" || !response.turnId) {
|
|
23203
23686
|
throw new Error("External steering returned no replacement Turn identity");
|
|
23204
23687
|
}
|
|
23205
23688
|
return {
|
|
@@ -23230,7 +23713,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23230
23713
|
] = args;
|
|
23231
23714
|
if (typeof threadId !== "string") return originalSteer.apply(manager, args);
|
|
23232
23715
|
const role = manager.getStreamRole?.(threadId);
|
|
23233
|
-
if (
|
|
23716
|
+
if (isRecord6(role) && role.role === "follower") return originalSteer.apply(manager, args);
|
|
23234
23717
|
let host = null;
|
|
23235
23718
|
let expectedTurnId;
|
|
23236
23719
|
try {
|
|
@@ -23238,26 +23721,36 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23238
23721
|
expectedTurnId = host.getActiveTurnId(threadId);
|
|
23239
23722
|
} catch {
|
|
23240
23723
|
}
|
|
23241
|
-
|
|
23242
|
-
|
|
23724
|
+
let ownershipResponse;
|
|
23725
|
+
try {
|
|
23726
|
+
ownershipResponse = await originalSend.call(manager, THREAD_OWNERSHIP_LIST_METHOD2, {
|
|
23243
23727
|
threadIds: [threadId]
|
|
23244
|
-
})
|
|
23245
|
-
)
|
|
23728
|
+
});
|
|
23729
|
+
} catch (error51) {
|
|
23730
|
+
if (!isUnsupportedMethod(error51, THREAD_OWNERSHIP_LIST_METHOD2)) throw error51;
|
|
23731
|
+
await verifyNativeCodexThread(
|
|
23732
|
+
(method, params) => originalSend.call(manager, method, params),
|
|
23733
|
+
threadId
|
|
23734
|
+
);
|
|
23735
|
+
if (disposed) throw new Error("External steering binding was disposed");
|
|
23736
|
+
return originalSteer.apply(manager, args);
|
|
23737
|
+
}
|
|
23738
|
+
const ownership = threadOwnershipListResultSchema.parse(ownershipResponse);
|
|
23246
23739
|
const owner = ownership.threads.find((thread) => thread.threadId === threadId)?.owner;
|
|
23247
23740
|
if (!owner) throw new Error("Thread ownership could not be resolved for steering");
|
|
23248
23741
|
if (disposed) throw new Error("External steering binding was disposed");
|
|
23249
23742
|
if (owner === "codex") return originalSteer.apply(manager, args);
|
|
23250
23743
|
if (!host) throw new Error("Desktop turn submission binding is unavailable");
|
|
23251
23744
|
const currentRole = manager.getStreamRole?.(threadId);
|
|
23252
|
-
if (
|
|
23745
|
+
if (isRecord6(currentRole) && currentRole.role === "follower")
|
|
23253
23746
|
return originalSteer.apply(manager, args);
|
|
23254
23747
|
if (!Array.isArray(input) || input.length === 0 || input.some(
|
|
23255
|
-
(item) => !
|
|
23256
|
-
) || !input.some((item) =>
|
|
23748
|
+
(item) => !isRecord6(item) || item.type !== "text" || typeof item.text !== "string"
|
|
23749
|
+
) || !input.some((item) => isRecord6(item) && typeof item.text === "string" && item.text.trim())) {
|
|
23257
23750
|
throw new Error("External steering requires non-empty text input");
|
|
23258
23751
|
}
|
|
23259
23752
|
if (toolOutput != null) throw new Error("External steering cannot replace a tool response");
|
|
23260
|
-
if (!
|
|
23753
|
+
if (!isRecord6(restoreMessage) || !isRecord6(restoreMessage.context)) {
|
|
23261
23754
|
throw new Error("Desktop steering message context is unavailable");
|
|
23262
23755
|
}
|
|
23263
23756
|
const messageId = typeof clientUserMessageId === "string" && clientUserMessageId ? clientUserMessageId : typeof restoreMessage.id === "string" && restoreMessage.id ? restoreMessage.id : crypto.randomUUID();
|
|
@@ -23305,7 +23798,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23305
23798
|
},
|
|
23306
23799
|
onMessageAdded
|
|
23307
23800
|
);
|
|
23308
|
-
if (!
|
|
23801
|
+
if (!isRecord6(response) || !isRecord6(response.turn) || typeof response.turn.id !== "string") {
|
|
23309
23802
|
throw new Error("Desktop returned no replacement Turn identity");
|
|
23310
23803
|
}
|
|
23311
23804
|
try {
|
|
@@ -23336,9 +23829,9 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23336
23829
|
}
|
|
23337
23830
|
|
|
23338
23831
|
// src/renderer-thread-reference-capability.ts
|
|
23339
|
-
var
|
|
23832
|
+
var record3 = (value) => typeof value === "object" && value !== null;
|
|
23340
23833
|
function restoreThreadReferenceCapability(client, manager, isCurrent) {
|
|
23341
|
-
if (!
|
|
23834
|
+
if (!record3(manager) || !record3(manager.storage)) return client;
|
|
23342
23835
|
const storage = manager.storage;
|
|
23343
23836
|
const read = storage.readValue;
|
|
23344
23837
|
const write = storage.writeValue;
|
|
@@ -23373,11 +23866,11 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23373
23866
|
}
|
|
23374
23867
|
|
|
23375
23868
|
// src/renderer-manual-compaction.ts
|
|
23376
|
-
function
|
|
23869
|
+
function isRecord7(value) {
|
|
23377
23870
|
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
23378
23871
|
}
|
|
23379
23872
|
function installRendererManualCompaction(target, hostId, messages) {
|
|
23380
|
-
if (!messages || typeof messages.addEventListener !== "function" || typeof messages.removeEventListener !== "function" || !
|
|
23873
|
+
if (!messages || typeof messages.addEventListener !== "function" || typeof messages.removeEventListener !== "function" || !isRecord7(target) || typeof target.registerPendingManualContextCompaction !== "function" || typeof target.getConversation !== "function") {
|
|
23381
23874
|
return null;
|
|
23382
23875
|
}
|
|
23383
23876
|
const register = target.registerPendingManualContextCompaction;
|
|
@@ -23386,18 +23879,18 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23386
23879
|
const listener = (event) => {
|
|
23387
23880
|
if (event.source != null && event.source !== messages) return;
|
|
23388
23881
|
const message = event.data;
|
|
23389
|
-
if (!
|
|
23882
|
+
if (!isRecord7(message) || message.type !== "mcp-notification" || message.hostId !== hostId || message.method !== THREAD_MANUAL_COMPACTION_STARTED_METHOD) {
|
|
23390
23883
|
return;
|
|
23391
23884
|
}
|
|
23392
23885
|
const params = threadManualCompactionStartedSchema.safeParse(message.params);
|
|
23393
23886
|
if (!params.success) return;
|
|
23394
23887
|
const { threadId } = params.data;
|
|
23395
23888
|
const conversation = getConversation.call(target, threadId);
|
|
23396
|
-
if (!
|
|
23889
|
+
if (!isRecord7(conversation) || conversation.id !== threadId || conversation.modelProvider !== "codexhost") {
|
|
23397
23890
|
return;
|
|
23398
23891
|
}
|
|
23399
23892
|
const role = getStreamRole?.call(target, threadId);
|
|
23400
|
-
if (
|
|
23893
|
+
if (isRecord7(role) && role.role === "follower") return;
|
|
23401
23894
|
register.call(target, threadId);
|
|
23402
23895
|
};
|
|
23403
23896
|
messages.addEventListener("message", listener);
|
|
@@ -23575,7 +24068,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23575
24068
|
var SIDEBAR_THREAD_HOST_ID_ATTRIBUTE = "data-app-action-sidebar-thread-host-id";
|
|
23576
24069
|
var SIDEBAR_AGENT_ICON_ATTRIBUTE = "data-codexhost-sidebar-agent-icon";
|
|
23577
24070
|
var OWNERSHIP_RETRY_DELAYS_MS = [100, 300, 800, 1500, 3e3];
|
|
23578
|
-
function
|
|
24071
|
+
function isRecord8(value) {
|
|
23579
24072
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23580
24073
|
}
|
|
23581
24074
|
function sidebarThreadAttributes(element) {
|
|
@@ -23602,19 +24095,19 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23602
24095
|
const fiberName = fiberNames[0];
|
|
23603
24096
|
if (fiberNames.length !== 1 || !fiberName) return null;
|
|
23604
24097
|
const firstFiber2 = Object.getOwnPropertyDescriptor(element, fiberName)?.value;
|
|
23605
|
-
if (!
|
|
24098
|
+
if (!isRecord8(firstFiber2)) return null;
|
|
23606
24099
|
const candidates = /* @__PURE__ */ new Set();
|
|
23607
24100
|
let fiber = firstFiber2;
|
|
23608
24101
|
for (let depth = 0; fiber && depth < 12; depth += 1) {
|
|
23609
24102
|
const props = fiber.memoizedProps;
|
|
23610
|
-
if (
|
|
24103
|
+
if (isRecord8(props) && isRecord8(props.dataAttributes)) {
|
|
23611
24104
|
const dataAttributes = props.dataAttributes;
|
|
23612
24105
|
const threadId = hostThreadIdSchema.safeParse(props.conversationId);
|
|
23613
24106
|
if (threadId.success && dataAttributes[SIDEBAR_THREAD_ROW_ATTRIBUTE] === rowMarker && dataAttributes[SIDEBAR_THREAD_ID_ATTRIBUTE] === taskKey && dataAttributes[SIDEBAR_THREAD_HOST_ID_ATTRIBUTE] === hostId) {
|
|
23614
24107
|
candidates.add(threadId.data);
|
|
23615
24108
|
}
|
|
23616
24109
|
}
|
|
23617
|
-
fiber =
|
|
24110
|
+
fiber = isRecord8(fiber.return) ? fiber.return : null;
|
|
23618
24111
|
}
|
|
23619
24112
|
return candidates.size === 1 ? candidates.values().next().value ?? null : null;
|
|
23620
24113
|
}
|
|
@@ -23635,6 +24128,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23635
24128
|
if (ownership.harnessId === "qoder") return "qoder";
|
|
23636
24129
|
if (ownership.harnessId === "qoder-cn") return "qoder-cn";
|
|
23637
24130
|
if (ownership.harnessId === "kimi-code") return "kimi-code";
|
|
24131
|
+
if (ownership.harnessId === "zcode") return "zcode";
|
|
23638
24132
|
return null;
|
|
23639
24133
|
}
|
|
23640
24134
|
function sidebarAgentIconAnchor(titleTrigger, title) {
|
|
@@ -23983,7 +24477,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23983
24477
|
if (row) finish(row);
|
|
23984
24478
|
});
|
|
23985
24479
|
}
|
|
23986
|
-
function
|
|
24480
|
+
function isRecord9(value) {
|
|
23987
24481
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
23988
24482
|
}
|
|
23989
24483
|
function firstFiber(element) {
|
|
@@ -23993,7 +24487,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
23993
24487
|
const name = names[0];
|
|
23994
24488
|
if (names.length !== 1 || !name) return null;
|
|
23995
24489
|
const value = Object.getOwnPropertyDescriptor(element, name)?.value;
|
|
23996
|
-
return
|
|
24490
|
+
return isRecord9(value) ? value : null;
|
|
23997
24491
|
}
|
|
23998
24492
|
function directForkAncestors(first) {
|
|
23999
24493
|
const ancestors = [];
|
|
@@ -24003,7 +24497,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24003
24497
|
if (seen.has(fiber)) return [];
|
|
24004
24498
|
seen.add(fiber);
|
|
24005
24499
|
ancestors.push(fiber);
|
|
24006
|
-
fiber =
|
|
24500
|
+
fiber = isRecord9(fiber.return) ? fiber.return : null;
|
|
24007
24501
|
}
|
|
24008
24502
|
return ancestors;
|
|
24009
24503
|
}
|
|
@@ -24021,7 +24515,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24021
24515
|
let hasForkCallback = false;
|
|
24022
24516
|
for (const fiber of ancestors) {
|
|
24023
24517
|
const props = fiber.memoizedProps;
|
|
24024
|
-
if (!
|
|
24518
|
+
if (!isRecord9(props)) continue;
|
|
24025
24519
|
if (!hasForkCallback && typeof props.onFork !== "function" && ownsOtherCallback(fiber, props)) {
|
|
24026
24520
|
return null;
|
|
24027
24521
|
}
|
|
@@ -24053,7 +24547,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24053
24547
|
if (!threadId.success || !turnId.success) return null;
|
|
24054
24548
|
const fiber = firstFiber(button);
|
|
24055
24549
|
const buttonProps = fiber?.memoizedProps;
|
|
24056
|
-
if (!fiber || !
|
|
24550
|
+
if (!fiber || !isRecord9(buttonProps) || !Object.hasOwn(buttonProps, "aria-busy")) return null;
|
|
24057
24551
|
return forkTargetFromAncestors(button, threadId.data, turnId.data, directForkAncestors(fiber)) ?? forkTargetFromAncestors(button, threadId.data, turnId.data, committedReactAncestors(fiber));
|
|
24058
24552
|
}
|
|
24059
24553
|
var BrowserRendererForkDom = class {
|
|
@@ -24162,12 +24656,12 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24162
24656
|
if (agent === "kiro-cli") return encodeHarnessPluginRoute({ harnessId: KIRO_CLI_HARNESS_ID });
|
|
24163
24657
|
if (agent === "codebuddy" || agent === "workbuddy" || agent === "cursor-cli")
|
|
24164
24658
|
return encodeHarnessPluginRoute({ harnessId: harnessIdSchema.parse(agent) });
|
|
24165
|
-
if (agent === "qoder" || agent === "qoder-cn" || agent === "kimi-code") {
|
|
24659
|
+
if (agent === "qoder" || agent === "qoder-cn" || agent === "kimi-code" || agent === "zcode") {
|
|
24166
24660
|
return encodeHarnessPluginRoute({ harnessId: harnessIdSchema.parse(agent) });
|
|
24167
24661
|
}
|
|
24168
24662
|
return null;
|
|
24169
24663
|
}
|
|
24170
|
-
function
|
|
24664
|
+
function isRecord10(value) {
|
|
24171
24665
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24172
24666
|
}
|
|
24173
24667
|
function piTransportModelId(model, thinkingOptionId) {
|
|
@@ -24426,7 +24920,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24426
24920
|
let fiber = findComposerFiber(composer);
|
|
24427
24921
|
for (let depth = 0; fiber && depth < 120; depth += 1) {
|
|
24428
24922
|
const props = fiber.memoizedProps;
|
|
24429
|
-
if (
|
|
24923
|
+
if (isRecord10(props) && "conversationId" in props && props.conversationId != null) {
|
|
24430
24924
|
const candidate = hostThreadIdSchema.safeParse(props.conversationId);
|
|
24431
24925
|
if (!candidate.success || threadId !== void 0 && threadId !== candidate.data) {
|
|
24432
24926
|
return null;
|
|
@@ -24439,12 +24933,12 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24439
24933
|
return threadId;
|
|
24440
24934
|
}
|
|
24441
24935
|
function isLegacySevenSlotDraftWrapper(value) {
|
|
24442
|
-
if (!Array.isArray(value) || value.length !== 7 || value[3] !== value[5] || value[3] !== value[6] || !
|
|
24936
|
+
if (!Array.isArray(value) || value.length !== 7 || value[3] !== value[5] || value[3] !== value[6] || !isRecord10(value[3]) || typeof value[3].get !== "function" || typeof value[2] !== "string" && value[2] !== null) {
|
|
24443
24937
|
return false;
|
|
24444
24938
|
}
|
|
24445
24939
|
try {
|
|
24446
24940
|
const draft = value[3].get();
|
|
24447
|
-
return
|
|
24941
|
+
return isRecord10(draft) && "modelSettings" in draft && "isManuallyChanged" in draft;
|
|
24448
24942
|
} catch {
|
|
24449
24943
|
return false;
|
|
24450
24944
|
}
|
|
@@ -24478,8 +24972,8 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24478
24972
|
let fiber = findComposerFiber(composer);
|
|
24479
24973
|
for (let depth = 0; fiber && depth < 120; depth += 1) {
|
|
24480
24974
|
const updateQueue = fiber.updateQueue;
|
|
24481
|
-
const memoCache =
|
|
24482
|
-
const data =
|
|
24975
|
+
const memoCache = isRecord10(updateQueue) ? updateQueue.memoCache : null;
|
|
24976
|
+
const data = isRecord10(memoCache) && Array.isArray(memoCache.data) ? memoCache.data : [];
|
|
24483
24977
|
for (const value of data) {
|
|
24484
24978
|
const draftId = draftIdFromMemoValue(value);
|
|
24485
24979
|
if (draftId) draftIds.add(draftId);
|
|
@@ -24506,7 +25000,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24506
25000
|
return ["default", draftIds.values().next().value];
|
|
24507
25001
|
}
|
|
24508
25002
|
function isDraftPrewarmPolicyReady(value) {
|
|
24509
|
-
return
|
|
25003
|
+
return isRecord10(value) && value.state === "ready" && typeof value.hostId === "string" && value.hostId.length > 0 && typeof value.select === "function" && typeof value.clear === "function";
|
|
24510
25004
|
}
|
|
24511
25005
|
async function waitForRendererDraftPrewarmPolicy(target, composer) {
|
|
24512
25006
|
const deadline = Date.now() + DRAFT_PREWARM_POLICY_WAIT_TIMEOUT_MS;
|
|
@@ -24526,7 +25020,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24526
25020
|
...model ? { model } : {},
|
|
24527
25021
|
...thinkingOptionId && agent !== "cursor-cli" ? { thinkingOptionId } : {},
|
|
24528
25022
|
...permissionModeId ? { permissionModeId } : {}
|
|
24529
|
-
}) : agent === "hermes" ? hermesTransportModelId(model, permissionModeId) : agent === "qoder" || agent === "qoder-cn" || agent === "kimi-code" ? encodeHarnessPluginRoute({
|
|
25023
|
+
}) : agent === "hermes" ? hermesTransportModelId(model, permissionModeId) : agent === "qoder" || agent === "qoder-cn" || agent === "kimi-code" || agent === "zcode" ? encodeHarnessPluginRoute({
|
|
24530
25024
|
harnessId: harnessIdSchema.parse(agent),
|
|
24531
25025
|
...model ? { model } : {},
|
|
24532
25026
|
...thinkingOptionId ? { thinkingOptionId } : {},
|
|
@@ -24567,13 +25061,15 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24567
25061
|
const route = disposed ? null : window.__codexhostHostRoutingV1?.forComposer() ?? null;
|
|
24568
25062
|
const client = clients.forRoute(route);
|
|
24569
25063
|
usageSubscription.connect(client);
|
|
24570
|
-
|
|
24571
|
-
|
|
24572
|
-
)
|
|
25064
|
+
const localClient = disposed ? null : route?.hostId === "local" ? client : clients.forHost("local");
|
|
25065
|
+
idleReleaseSync.connect(localClient);
|
|
25066
|
+
const connected = !disposed && (client !== null || localClient !== null || (window.__codexhostHostRoutingV1?.knownHostIds?.() ?? []).some(
|
|
25067
|
+
(hostId) => window.__codexhostHostRoutingV1?.forHost(hostId) != null
|
|
25068
|
+
));
|
|
24573
25069
|
updateStatus(
|
|
24574
|
-
|
|
24575
|
-
|
|
24576
|
-
|
|
25070
|
+
connected ? "ready" : "installing",
|
|
25071
|
+
connected ? "ready" : fiberWalkLimited ? "react-fiber-walk-limit-exceeded" : "draft-routing-policy-unavailable",
|
|
25072
|
+
connected ? "request-bridge" : null
|
|
24577
25073
|
);
|
|
24578
25074
|
return route;
|
|
24579
25075
|
};
|
|
@@ -24588,10 +25084,14 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24588
25084
|
return client;
|
|
24589
25085
|
};
|
|
24590
25086
|
const modelControl = Object.freeze({
|
|
24591
|
-
currentHostId: () => {
|
|
25087
|
+
currentHostId: (composer) => {
|
|
25088
|
+
if (composer) {
|
|
25089
|
+
return disposed ? null : window.__codexhostHostRoutingV1?.hostIdForComposer(composer) ?? null;
|
|
25090
|
+
}
|
|
24592
25091
|
const route = currentRequestRoute();
|
|
24593
25092
|
return disposed ? null : route?.hostId ?? window.__codexhostHostRoutingV1?.hostIdForComposer() ?? null;
|
|
24594
25093
|
},
|
|
25094
|
+
knownHostIds: () => disposed ? [] : window.__codexhostHostRoutingV1?.knownHostIds?.() ?? [],
|
|
24595
25095
|
clientForHost: (hostId) => disposed ? null : clients.forHost(hostId),
|
|
24596
25096
|
listHarnessPlugins: async () => {
|
|
24597
25097
|
const client = settingsModelClient();
|
|
@@ -24768,11 +25268,11 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24768
25268
|
return null;
|
|
24769
25269
|
}
|
|
24770
25270
|
}
|
|
24771
|
-
function
|
|
25271
|
+
function isRecord11(value) {
|
|
24772
25272
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24773
25273
|
}
|
|
24774
25274
|
function parseExternalConfiguration(value) {
|
|
24775
|
-
if (!
|
|
25275
|
+
if (!isRecord11(value)) return void 0;
|
|
24776
25276
|
const model = harnessModelRefSchema.safeParse(value.model);
|
|
24777
25277
|
if (!model.success) return void 0;
|
|
24778
25278
|
const thinkingOptionId = harnessThinkingOptionIdSchema.safeParse(value.thinkingOptionId);
|
|
@@ -24789,9 +25289,9 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24789
25289
|
const raw = storage.getItem(RENDERER_NEW_THREAD_PREFERENCE_KEY);
|
|
24790
25290
|
if (!raw) return void 0;
|
|
24791
25291
|
const parsed = JSON.parse(raw);
|
|
24792
|
-
if (!
|
|
25292
|
+
if (!isRecord11(parsed) || parsed.version !== 1) return void 0;
|
|
24793
25293
|
if (!KNOWN_RENDERER_AGENTS.some((agent) => agent === parsed.lastAgent)) return void 0;
|
|
24794
|
-
const externalByAgent =
|
|
25294
|
+
const externalByAgent = isRecord11(parsed.externalByAgent) ? parsed.externalByAgent : {};
|
|
24795
25295
|
const parsedExternal = Object.fromEntries(
|
|
24796
25296
|
KNOWN_RENDERER_AGENTS.filter(
|
|
24797
25297
|
(agent) => agent !== "codex"
|
|
@@ -24919,7 +25419,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24919
25419
|
var GET_LOCALE_OVERRIDE_URL = "vscode://codex/get-setting";
|
|
24920
25420
|
var GET_LOCALE_INFO_URL = "vscode://codex/locale-info";
|
|
24921
25421
|
var DEFAULT_LOCALE_REQUEST_TIMEOUT_MS = 750;
|
|
24922
|
-
function
|
|
25422
|
+
function isRecord12(value) {
|
|
24923
25423
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
24924
25424
|
}
|
|
24925
25425
|
function canonicalLocale(value) {
|
|
@@ -24941,7 +25441,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24941
25441
|
return new DOMException("The operation was aborted", "AbortError");
|
|
24942
25442
|
}
|
|
24943
25443
|
function parseLocaleOverride(value) {
|
|
24944
|
-
if (!
|
|
25444
|
+
if (!isRecord12(value) || !("value" in value)) {
|
|
24945
25445
|
throw new Error("Codex locale override response is malformed");
|
|
24946
25446
|
}
|
|
24947
25447
|
if (value.value === null) return { value: null };
|
|
@@ -24956,7 +25456,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24956
25456
|
return locale;
|
|
24957
25457
|
}
|
|
24958
25458
|
function parseLocaleInfo(value) {
|
|
24959
|
-
if (!
|
|
25459
|
+
if (!isRecord12(value)) throw new Error("Codex locale info response is malformed");
|
|
24960
25460
|
return {
|
|
24961
25461
|
ideLocale: optionalLocale(value.ideLocale, "IDE locale"),
|
|
24962
25462
|
systemLocale: optionalLocale(value.systemLocale, "system locale")
|
|
@@ -24985,7 +25485,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
24985
25485
|
const onAbort = () => settle(() => reject(abortError2()));
|
|
24986
25486
|
const onMessage = (event) => {
|
|
24987
25487
|
const message2 = event.data;
|
|
24988
|
-
if (!
|
|
25488
|
+
if (!isRecord12(message2) || message2.type !== "fetch-response") return;
|
|
24989
25489
|
if (message2.requestId !== requestId) return;
|
|
24990
25490
|
if (message2.responseType !== "success" || typeof message2.status !== "number" || message2.status < 200 || message2.status >= 300 || typeof message2.bodyJsonString !== "string") {
|
|
24991
25491
|
settle(() => reject(new Error("Codex locale request failed")));
|
|
@@ -25094,6 +25594,1061 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
25094
25594
|
});
|
|
25095
25595
|
}
|
|
25096
25596
|
|
|
25597
|
+
// src/settings/remote-failure-messages.ts
|
|
25598
|
+
var REMOTE_FAILURE_CHINESE = Object.freeze({
|
|
25599
|
+
// SSH helper: installing, updating and repairing over SSH.
|
|
25600
|
+
"Invalid SSH address or port": "SSH \u5730\u5740\u6216\u7AEF\u53E3\u65E0\u6548",
|
|
25601
|
+
"Install requires a published stable version": "\u53EA\u80FD\u5B89\u88C5\u5DF2\u53D1\u5E03\u7684\u6B63\u5F0F\u7248\u672C",
|
|
25602
|
+
"SSH operation timed out; check the remote computer before retrying": "SSH \u64CD\u4F5C\u8D85\u65F6\uFF0C\u8BF7\u68C0\u67E5\u8FDC\u7A0B\u7535\u8111\u540E\u91CD\u8BD5",
|
|
25603
|
+
"Remote service is already installed. Connect and use its update button": "\u8FDC\u7A0B\u670D\u52A1\u5DF2\u7ECF\u5B89\u88C5\uFF0C\u8BF7\u8FDE\u63A5\u540E\u4F7F\u7528\u66F4\u65B0\u6309\u94AE",
|
|
25604
|
+
"Remote service is not installed. Use Install and connect instead": "\u8FDC\u7A0B\u670D\u52A1\u5C1A\u672A\u5B89\u88C5\uFF0C\u8BF7\u4F7F\u7528\u300C\u5B89\u88C5\u5E76\u8FDE\u63A5\u300D",
|
|
25605
|
+
"This release is not published on npm, or the remote computer cannot reach the registry": "\u8BE5\u7248\u672C\u5C1A\u672A\u53D1\u5E03\u5230 npm\uFF0C\u6216\u8FDC\u7A0B\u7535\u8111\u65E0\u6CD5\u8BBF\u95EE npm \u4ED3\u5E93",
|
|
25606
|
+
"codexhost was installed but is not on the remote PATH. Update this remote manually": "codexhost \u5DF2\u5B89\u88C5\uFF0C\u4F46\u4E0D\u5728\u8FDC\u7A0B\u7535\u8111\u7684 PATH \u4E2D\uFF0C\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u624B\u52A8\u66F4\u65B0",
|
|
25607
|
+
"Only Mac and Linux remote computers are supported": "\u53EA\u652F\u6301 Mac \u548C Linux \u8FDC\u7A0B\u7535\u8111",
|
|
25608
|
+
"Node.js, npm or Codex CLI was not found over SSH. Install them on the remote computer and make sure non-interactive SSH sessions have them on PATH": "\u901A\u8FC7 SSH \u627E\u4E0D\u5230 Node.js\u3001npm \u6216 Codex CLI\u3002\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u5B89\u88C5\u5B83\u4EEC\uFF0C\u5E76\u786E\u4FDD\u975E\u4EA4\u4E92\u5F0F SSH \u4F1A\u8BDD\u7684 PATH \u4E2D\u5305\u542B\u5B83\u4EEC",
|
|
25609
|
+
"npm installation failed. Check network access and global installation permissions": "npm \u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u548C\u5168\u5C40\u5B89\u88C5\u6743\u9650",
|
|
25610
|
+
"Remote service configuration failed. Check Codex CLI and the remote desktop login": "\u8FDC\u7A0B\u670D\u52A1\u914D\u7F6E\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5 Codex CLI \u4EE5\u53CA\u8FDC\u7A0B\u7535\u8111\u7684\u684C\u9762\u767B\u5F55\u72B6\u6001",
|
|
25611
|
+
"Remote service could not stop. Check the remote service before retrying": "\u8FDC\u7A0B\u670D\u52A1\u65E0\u6CD5\u505C\u6B62\uFF0C\u8BF7\u68C0\u67E5\u8FDC\u7A0B\u670D\u52A1\u540E\u91CD\u8BD5",
|
|
25612
|
+
"Remote connection configuration could not be removed. Check file permissions": "\u65E0\u6CD5\u79FB\u9664\u8FDC\u7A0B\u8FDE\u63A5\u914D\u7F6E\uFF0C\u8BF7\u68C0\u67E5\u6587\u4EF6\u6743\u9650",
|
|
25613
|
+
"Another remote installation is in progress. Wait and check again": "\u53E6\u4E00\u9879\u8FDC\u7A0B\u5B89\u88C5\u6B63\u5728\u8FDB\u884C\uFF0C\u8BF7\u7A0D\u540E\u91CD\u65B0\u68C0\u6D4B",
|
|
25614
|
+
"Remote service was installed but could not start. Check the remote service and retry connecting": "\u8FDC\u7A0B\u670D\u52A1\u5DF2\u5B89\u88C5\u4F46\u65E0\u6CD5\u542F\u52A8\uFF0C\u8BF7\u68C0\u67E5\u8FDC\u7A0B\u670D\u52A1\u540E\u91CD\u65B0\u8FDE\u63A5",
|
|
25615
|
+
"SSH failed. Check the address, key authentication and trusted host key": "SSH \u8FDE\u63A5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u5730\u5740\u3001\u5BC6\u94A5\u8BA4\u8BC1\u4EE5\u53CA\u4E3B\u673A\u5BC6\u94A5\u662F\u5426\u5DF2\u4FE1\u4EFB",
|
|
25616
|
+
"Unexpected SSH inspection response": "SSH \u68C0\u6D4B\u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u7ED3\u679C",
|
|
25617
|
+
"SSH installation failed; check the remote computer and retry": "SSH \u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u8FDC\u7A0B\u7535\u8111\u540E\u91CD\u8BD5",
|
|
25618
|
+
"SSH installation helper is unavailable. Update local codexhost and restart.": "SSH \u5B89\u88C5\u7EC4\u4EF6\u4E0D\u53EF\u7528\uFF0C\u8BF7\u66F4\u65B0\u672C\u673A codexhost \u540E\u91CD\u542F",
|
|
25619
|
+
"SSH installation must run from the local computer": "SSH \u5B89\u88C5\u53EA\u80FD\u4ECE\u672C\u673A\u53D1\u8D77",
|
|
25620
|
+
"An SSH operation is already running for this connection": "\u8FD9\u4E2A\u8FDE\u63A5\u5DF2\u6709 SSH \u64CD\u4F5C\u6B63\u5728\u8FDB\u884C",
|
|
25621
|
+
// Remote service: updating or restarting itself.
|
|
25622
|
+
"Another codexhost update is active; finish it before retrying": "\u53E6\u4E00\u9879 codexhost \u66F4\u65B0\u6B63\u5728\u8FDB\u884C\uFF0C\u8BF7\u7B49\u5B83\u5B8C\u6210\u540E\u91CD\u8BD5",
|
|
25623
|
+
"The remote installation changed before the update acquired its lock; refresh and retry": "\u66F4\u65B0\u5F00\u59CB\u524D\u8FDC\u7A0B\u5B89\u88C5\u53D1\u751F\u4E86\u53D8\u5316\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5",
|
|
25624
|
+
"Could not identify the global npm installation": "\u65E0\u6CD5\u8BC6\u522B\u8FDC\u7A0B\u7535\u8111\u7684\u5168\u5C40 npm \u5B89\u88C5",
|
|
25625
|
+
"npm uses a different global installation; update this remote manually": "\u8FDC\u7A0B\u7535\u8111\u7684 npm \u4F7F\u7528\u4E86\u53E6\u4E00\u5904\u5168\u5C40\u5B89\u88C5\uFF0C\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u624B\u52A8\u66F4\u65B0",
|
|
25626
|
+
"The requested release is unavailable or npm cannot reach the registry": "\u76EE\u6807\u7248\u672C\u4E0D\u5B58\u5728\uFF0C\u6216\u8FDC\u7A0B\u7535\u8111\u65E0\u6CD5\u8BBF\u95EE npm \u4ED3\u5E93",
|
|
25627
|
+
"npm installation failed; check remote network access and write permissions": "npm \u5B89\u88C5\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u8FDC\u7A0B\u7535\u8111\u7684\u7F51\u7EDC\u548C\u5199\u5165\u6743\u9650",
|
|
25628
|
+
"Installed remote version does not match the requested version": "\u8FDC\u7A0B\u5B89\u88C5\u7684\u7248\u672C\u4E0E\u8BF7\u6C42\u7684\u7248\u672C\u4E0D\u4E00\u81F4",
|
|
25629
|
+
"Remote stop failed": "\u66F4\u65B0\u5DF2\u5B89\u88C5\uFF0C\u4F46\u505C\u6B62\u65E7\u670D\u52A1\u5931\u8D25",
|
|
25630
|
+
"Remote install failed": "\u66F4\u65B0\u5DF2\u5B89\u88C5\uFF0C\u4F46\u91CD\u65B0\u914D\u7F6E\u8FDC\u7A0B\u670D\u52A1\u5931\u8D25",
|
|
25631
|
+
"Remote start failed": "\u66F4\u65B0\u5DF2\u5B89\u88C5\uFF0C\u4F46\u542F\u52A8\u8FDC\u7A0B\u670D\u52A1\u5931\u8D25",
|
|
25632
|
+
"The previous remote update was interrupted; retry the update": "\u4E0A\u4E00\u6B21\u8FDC\u7A0B\u66F4\u65B0\u88AB\u4E2D\u65AD\uFF0C\u8BF7\u91CD\u8BD5",
|
|
25633
|
+
"Remote updater did not start": "\u8FDC\u7A0B\u66F4\u65B0\u7A0B\u5E8F\u672A\u80FD\u542F\u52A8",
|
|
25634
|
+
"Remote updater could not be started": "\u65E0\u6CD5\u542F\u52A8\u8FDC\u7A0B\u66F4\u65B0\u7A0B\u5E8F",
|
|
25635
|
+
"Remote updater is unavailable": "\u8FDC\u7A0B\u66F4\u65B0\u7A0B\u5E8F\u4E0D\u53EF\u7528",
|
|
25636
|
+
"Another remote update is already pending": "\u5DF2\u6709\u53E6\u4E00\u9879\u8FDC\u7A0B\u66F4\u65B0\u5728\u7B49\u5F85\u6267\u884C",
|
|
25637
|
+
"Remote update requires an npm installation with the current updater": "\u8FDC\u7A0B\u66F4\u65B0\u9700\u8981\u901A\u8FC7 npm \u5B89\u88C5\u5E76\u5E26\u6709\u5F53\u524D\u7248\u672C\u7684\u66F4\u65B0\u7A0B\u5E8F",
|
|
25638
|
+
"Remote downgrades are not automatic; update this computer first": "\u4E0D\u4F1A\u81EA\u52A8\u964D\u4F4E\u8FDC\u7A0B\u7248\u672C\uFF0C\u8BF7\u5148\u66F4\u65B0\u672C\u673A",
|
|
25639
|
+
"The remote installation changed; refresh versions before retrying": "\u8FDC\u7A0B\u5B89\u88C5\u53D1\u751F\u4E86\u53D8\u5316\uFF0C\u8BF7\u5237\u65B0\u7248\u672C\u540E\u91CD\u8BD5",
|
|
25640
|
+
"Remote service is updating; reconnect shortly": "\u8FDC\u7A0B\u670D\u52A1\u6B63\u5728\u66F4\u65B0\uFF0C\u8BF7\u7A0D\u540E\u91CD\u65B0\u8FDE\u63A5",
|
|
25641
|
+
"Runtime version management is unavailable in this build": "\u5F53\u524D\u6784\u5EFA\u4E0D\u652F\u6301\u7248\u672C\u7BA1\u7406",
|
|
25642
|
+
// This window's bridge to the remote service.
|
|
25643
|
+
"Remote service did not respond; reconnect and retry": "\u8FDC\u7A0B\u670D\u52A1\u6CA1\u6709\u54CD\u5E94\uFF0C\u8BF7\u91CD\u65B0\u8FDE\u63A5\u540E\u91CD\u8BD5",
|
|
25644
|
+
"SSH installation is unavailable; update local codexhost and restart": "SSH \u5B89\u88C5\u4E0D\u53EF\u7528\uFF0C\u8BF7\u66F4\u65B0\u672C\u673A codexhost \u540E\u91CD\u542F",
|
|
25645
|
+
"Version management is unavailable; update codexhost on this host and reconnect": "\u7248\u672C\u7BA1\u7406\u4E0D\u53EF\u7528\uFF0C\u8BF7\u66F4\u65B0\u8FD9\u53F0\u7535\u8111\u4E0A\u7684 codexhost \u540E\u91CD\u65B0\u8FDE\u63A5",
|
|
25646
|
+
"Remote update is unavailable; update this remote once and reconnect": "\u8FDC\u7A0B\u66F4\u65B0\u4E0D\u53EF\u7528\uFF0C\u8BF7\u5148\u624B\u52A8\u66F4\u65B0\u4E00\u6B21\u8FD9\u53F0\u8FDC\u7A0B\u7535\u8111\u518D\u91CD\u65B0\u8FDE\u63A5",
|
|
25647
|
+
// Codex SSH bridge: reading and saving connections.
|
|
25648
|
+
"Codex SSH settings are unavailable in this window": "\u6B64\u7A97\u53E3\u65E0\u6CD5\u4F7F\u7528 Codex SSH \u8BBE\u7F6E",
|
|
25649
|
+
"Codex SSH request failed; check the native Connections settings": "Codex SSH \u8BF7\u6C42\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u539F\u751F\u7684\u8FDE\u63A5\u8BBE\u7F6E",
|
|
25650
|
+
"Invalid Codex SSH response": "Codex SSH \u8FD4\u56DE\u4E86\u65E0\u6CD5\u8BC6\u522B\u7684\u7ED3\u679C",
|
|
25651
|
+
"Codex SSH request timed out; refresh before retrying": "Codex SSH \u8BF7\u6C42\u8D85\u65F6\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u8BD5",
|
|
25652
|
+
"Invalid Codex SSH connection list": "Codex \u8FD4\u56DE\u7684 SSH \u8FDE\u63A5\u5217\u8868\u65E0\u6CD5\u8BC6\u522B",
|
|
25653
|
+
"This Codex version uses an unsupported SSH configuration; open native settings": "\u5F53\u524D Codex \u7248\u672C\u7684 SSH \u914D\u7F6E\u683C\u5F0F\u4E0D\u53D7\u652F\u6301\uFF0C\u8BF7\u5728\u539F\u751F\u8BBE\u7F6E\u4E2D\u7BA1\u7406",
|
|
25654
|
+
"This connection changed in Codex. Refresh and edit it again.": "\u8FD9\u4E2A\u8FDE\u63A5\u5DF2\u5728 Codex \u4E2D\u88AB\u4FEE\u6539\uFF0C\u8BF7\u5237\u65B0\u540E\u91CD\u65B0\u7F16\u8F91",
|
|
25655
|
+
"Enter a name, SSH hostname (or alias), and a port between 1 and 65535": "\u8BF7\u586B\u5199\u540D\u79F0\u3001SSH \u4E3B\u673A\u540D\uFF08\u6216\u522B\u540D\uFF09\uFF0C\u7AEF\u53E3\u9700\u5728 1 \u5230 65535 \u4E4B\u95F4",
|
|
25656
|
+
"A connection with this name already exists": "\u5DF2\u5B58\u5728\u540C\u540D\u7684\u8FDE\u63A5",
|
|
25657
|
+
"Edit SSH-config connection details in native Codex settings": "\u6765\u81EA SSH \u914D\u7F6E\u7684\u8FDE\u63A5\uFF0C\u8BF7\u5728 Codex \u539F\u751F\u8BBE\u7F6E\u4E2D\u4FEE\u6539\u8BE6\u7EC6\u4FE1\u606F",
|
|
25658
|
+
"Invalid Codex connection state": "Codex \u8FD4\u56DE\u7684\u8FDE\u63A5\u72B6\u6001\u65E0\u6CD5\u8BC6\u522B"
|
|
25659
|
+
});
|
|
25660
|
+
function localizeRemoteFailure(message, t) {
|
|
25661
|
+
const text = message.replace(/^Error:\s*/u, "");
|
|
25662
|
+
const detail = text.indexOf(": ");
|
|
25663
|
+
const chinese = REMOTE_FAILURE_CHINESE[text] ?? (detail > 0 ? REMOTE_FAILURE_CHINESE[text.slice(0, detail)] : void 0);
|
|
25664
|
+
return chinese ? t(chinese, text) : text;
|
|
25665
|
+
}
|
|
25666
|
+
|
|
25667
|
+
// src/settings/remote-connections-card.ts
|
|
25668
|
+
var STABLE_VERSION = /^\d+\.\d+\.\d+$/u;
|
|
25669
|
+
function remoteErrorMessage(error51) {
|
|
25670
|
+
return error51 instanceof Error && error51.message ? error51.message : String(error51);
|
|
25671
|
+
}
|
|
25672
|
+
function remoteVersionIssue(error51) {
|
|
25673
|
+
const outdated = typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === -32601;
|
|
25674
|
+
return { outdated, message: remoteErrorMessage(error51) };
|
|
25675
|
+
}
|
|
25676
|
+
function remoteElement(document2, tag, className = "", text = "") {
|
|
25677
|
+
const result = document2.createElement(tag);
|
|
25678
|
+
if (className) result.className = className;
|
|
25679
|
+
if (text) result.textContent = text;
|
|
25680
|
+
return result;
|
|
25681
|
+
}
|
|
25682
|
+
function remoteInstallVersion(local) {
|
|
25683
|
+
const version2 = local?.runningVersion;
|
|
25684
|
+
return version2 && STABLE_VERSION.test(version2) ? version2 : null;
|
|
25685
|
+
}
|
|
25686
|
+
function remoteMaintenanceTarget(local, remote) {
|
|
25687
|
+
if (!remote.updateSupported) return null;
|
|
25688
|
+
return newerLocalVersion(local, remote) ?? (remote.restartRequired ? remote.installedVersion : null);
|
|
25689
|
+
}
|
|
25690
|
+
function newerLocalVersion(local, remote) {
|
|
25691
|
+
return remoteUpdateTarget(local, { ...remote, update: { ...remote.update, phase: "idle" } });
|
|
25692
|
+
}
|
|
25693
|
+
function remoteBusy(remote) {
|
|
25694
|
+
return !!remote && ["installing", "restarting"].includes(remote.update.phase);
|
|
25695
|
+
}
|
|
25696
|
+
function remoteTroubled(row) {
|
|
25697
|
+
if (row.remote) return row.remote.update.phase === "failed";
|
|
25698
|
+
if (row.state === "connecting") return false;
|
|
25699
|
+
return !(row.state === "disconnected" && !row.connection.autoConnect);
|
|
25700
|
+
}
|
|
25701
|
+
function connectionState(row, t) {
|
|
25702
|
+
switch (row.state) {
|
|
25703
|
+
case null:
|
|
25704
|
+
return ["progress", t("\u68C0\u6D4B\u4E2D\u2026", "Checking\u2026")];
|
|
25705
|
+
case "connected":
|
|
25706
|
+
return ["success", t("\u5DF2\u8FDE\u63A5", "Connected")];
|
|
25707
|
+
case "connecting":
|
|
25708
|
+
return ["progress", t("\u8FDE\u63A5\u4E2D\u2026", "Connecting\u2026")];
|
|
25709
|
+
case "disconnected":
|
|
25710
|
+
return ["neutral", t("\u672A\u8FDE\u63A5", "Disconnected")];
|
|
25711
|
+
case "error":
|
|
25712
|
+
return ["danger", t("\u8FDE\u63A5\u5931\u8D25", "Connection failed")];
|
|
25713
|
+
default:
|
|
25714
|
+
return ["neutral", t("\u72B6\u6001\u672A\u77E5", "Unknown state")];
|
|
25715
|
+
}
|
|
25716
|
+
}
|
|
25717
|
+
function serviceSummary(row, local, t) {
|
|
25718
|
+
const { remote } = row;
|
|
25719
|
+
const hints = [];
|
|
25720
|
+
if (!remote) {
|
|
25721
|
+
if (row.probing) return { title: t("\u6B63\u5728\u68C0\u6D4B\u8FDC\u7A0B\u670D\u52A1\u2026", "Checking remote service\u2026"), hints };
|
|
25722
|
+
if (row.installation === "not-installed") {
|
|
25723
|
+
const version2 = remoteInstallVersion(local);
|
|
25724
|
+
hints.push(
|
|
25725
|
+
version2 ? [
|
|
25726
|
+
"neutral",
|
|
25727
|
+
t(
|
|
25728
|
+
`\u5C06\u5B89\u88C5\u4E0E\u672C\u673A\u76F8\u540C\u7684\u7248\u672C ${version2}`,
|
|
25729
|
+
`Installs version ${version2}, matching this computer`
|
|
25730
|
+
)
|
|
25731
|
+
] : [
|
|
25732
|
+
"warning",
|
|
25733
|
+
t(
|
|
25734
|
+
"\u672C\u673A\u7248\u672C\u4E0D\u53EF\u7528\u4E8E\u5B89\u88C5\uFF0C\u8BF7\u4F7F\u7528\u6B63\u5F0F\u53D1\u5E03\u7248\u672C\u3002",
|
|
25735
|
+
"Install from a published local release."
|
|
25736
|
+
)
|
|
25737
|
+
]
|
|
25738
|
+
);
|
|
25739
|
+
return { title: t("\u9700\u8981\u5B89\u88C5\u8FDC\u7A0B\u670D\u52A1", "Remote service needs installation"), hints };
|
|
25740
|
+
}
|
|
25741
|
+
if (row.remoteIssue?.outdated) {
|
|
25742
|
+
const version2 = remoteInstallVersion(local);
|
|
25743
|
+
hints.push(
|
|
25744
|
+
version2 ? [
|
|
25745
|
+
"neutral",
|
|
25746
|
+
t(
|
|
25747
|
+
`\u66F4\u65B0\u5230\u672C\u673A\u7248\u672C ${version2} \u540E\u53EF\u5728\u8FD9\u91CC\u67E5\u770B\u548C\u7BA1\u7406\u7248\u672C\u3002`,
|
|
25748
|
+
`Update to this computer's version ${version2} to manage versions here.`
|
|
25749
|
+
)
|
|
25750
|
+
] : [
|
|
25751
|
+
"warning",
|
|
25752
|
+
t(
|
|
25753
|
+
"\u672C\u673A\u4E0D\u662F\u6B63\u5F0F\u53D1\u5E03\u7248\u672C\uFF0C\u65E0\u6CD5\u4ECE\u8FD9\u91CC\u66F4\u65B0\uFF1B\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u624B\u52A8\u66F4\u65B0 codexhost\u3002",
|
|
25754
|
+
"This computer is not running a published release, so it cannot update the remote. Update codexhost on the remote computer manually."
|
|
25755
|
+
)
|
|
25756
|
+
]
|
|
25757
|
+
);
|
|
25758
|
+
return { title: t("\u8FDC\u7A0B\u670D\u52A1\u9700\u8981\u66F4\u65B0", "Remote service needs an update"), hints };
|
|
25759
|
+
}
|
|
25760
|
+
hints.push([
|
|
25761
|
+
"neutral",
|
|
25762
|
+
row.state === "connecting" || row.state === "disconnected" && !row.connection.autoConnect ? t("\u8FDE\u63A5\u540E\u663E\u793A\u8FDC\u7A0B\u670D\u52A1\u7248\u672C\u3002", "Connect to see the remote service version.") : t(
|
|
25763
|
+
"\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6\u8FDC\u7A0B\u7248\u672C\uFF0C\u53EF\u5237\u65B0\u6216\u91CD\u65B0\u8FDE\u63A5\u540E\u518D\u8BD5\u3002",
|
|
25764
|
+
"Remote version information is temporarily unavailable. Refresh or reconnect to retry."
|
|
25765
|
+
)
|
|
25766
|
+
]);
|
|
25767
|
+
if (row.remoteIssue)
|
|
25768
|
+
hints.push([
|
|
25769
|
+
"danger",
|
|
25770
|
+
`${t("\u539F\u56E0", "Reason")}: ${localizeRemoteFailure(row.remoteIssue.message, t)}`
|
|
25771
|
+
]);
|
|
25772
|
+
return { title: t("\u8FDC\u7A0B\u670D\u52A1", "Remote service"), hints };
|
|
25773
|
+
}
|
|
25774
|
+
const busy = remoteBusy(remote);
|
|
25775
|
+
const installed = (busy ? remote.runningVersion : remote.installedVersion) ?? remote.runningVersion ?? "\u2014";
|
|
25776
|
+
const title = !busy && remote.runningVersion && remote.runningVersion !== remote.installedVersion ? t(
|
|
25777
|
+
`\u8FDC\u7A0B\u670D\u52A1 ${installed} \xB7 \u8FD0\u884C\u4E2D ${remote.runningVersion}`,
|
|
25778
|
+
`Remote service ${installed} \xB7 running ${remote.runningVersion}`
|
|
25779
|
+
) : t(`\u8FDC\u7A0B\u670D\u52A1 ${installed}`, `Remote service ${installed}`);
|
|
25780
|
+
const phases = {
|
|
25781
|
+
idle: null,
|
|
25782
|
+
installing: ["progress", t("\u6B63\u5728\u66F4\u65B0\u8FDC\u7A0B\u670D\u52A1\u2026", "Updating remote service\u2026")],
|
|
25783
|
+
restarting: ["progress", t("\u6B63\u5728\u91CD\u542F\uFF0C\u8BF7\u7A0D\u5019\u91CD\u8FDE\u2026", "Restarting; reconnecting shortly\u2026")],
|
|
25784
|
+
// The record outlives the update; the version line already shows the result.
|
|
25785
|
+
succeeded: null,
|
|
25786
|
+
failed: ["danger", t("\u66F4\u65B0\u5931\u8D25\uFF0C\u53EF\u4EE5\u91CD\u8BD5", "Update failed; you can retry")]
|
|
25787
|
+
};
|
|
25788
|
+
const phase = phases[remote.update.phase];
|
|
25789
|
+
if (phase) hints.push(phase);
|
|
25790
|
+
if (remote.update.error) hints.push(["danger", localizeRemoteFailure(remote.update.error, t)]);
|
|
25791
|
+
if (remote.restartRequired && !busy)
|
|
25792
|
+
hints.push([
|
|
25793
|
+
"warning",
|
|
25794
|
+
t("\u9700\u8981\u91CD\u542F\u4EE5\u4F7F\u7528\u5DF2\u5B89\u88C5\u7684\u7248\u672C", "Restart needed to use the installed version")
|
|
25795
|
+
]);
|
|
25796
|
+
const newer = newerLocalVersion(local, remote);
|
|
25797
|
+
const localVersion = local?.runningVersion;
|
|
25798
|
+
if (remoteBusy(remote)) {
|
|
25799
|
+
} else if (newer && remote.installedVersion !== localVersion)
|
|
25800
|
+
hints.push([
|
|
25801
|
+
"warning",
|
|
25802
|
+
t(`\u6709\u66F4\u65B0\u53EF\u7528 \xB7 \u672C\u673A\u4E3A ${newer}`, `Update available \xB7 this computer runs ${newer}`)
|
|
25803
|
+
]);
|
|
25804
|
+
else if (localVersion && remote.installedVersion === localVersion && !remote.restartRequired)
|
|
25805
|
+
hints.push(["success", t("\u4E0E\u672C\u673A\u7248\u672C\u4E00\u81F4", "Matches this computer")]);
|
|
25806
|
+
if (localVersion && remote.installedVersion && localVersion !== remote.installedVersion && !newer)
|
|
25807
|
+
hints.push([
|
|
25808
|
+
"warning",
|
|
25809
|
+
t(
|
|
25810
|
+
"\u7248\u672C\u4E0D\u540C\uFF0C\u8BF7\u5148\u68C0\u67E5\u672C\u673A\u66F4\u65B0\uFF1B\u4E0D\u4F1A\u81EA\u52A8\u964D\u4F4E\u8FDC\u7A0B\u7248\u672C\u3002",
|
|
25811
|
+
"Versions differ. Check for a local update; the remote version will not be downgraded."
|
|
25812
|
+
)
|
|
25813
|
+
]);
|
|
25814
|
+
return { title, hints };
|
|
25815
|
+
}
|
|
25816
|
+
function renderRemoteCard(document2, row, local, t, onAction) {
|
|
25817
|
+
const { connection, remote } = row;
|
|
25818
|
+
const locked = row.pending !== null;
|
|
25819
|
+
const command = (action, label, primary = false) => {
|
|
25820
|
+
const button = remoteElement(
|
|
25821
|
+
document2,
|
|
25822
|
+
"button",
|
|
25823
|
+
primary ? "settings-command-button" : "settings-command-button settings-command-button--secondary",
|
|
25824
|
+
label
|
|
25825
|
+
);
|
|
25826
|
+
button.type = "button";
|
|
25827
|
+
button.dataset.action = action;
|
|
25828
|
+
button.disabled = locked;
|
|
25829
|
+
button.addEventListener("click", () => onAction(action));
|
|
25830
|
+
return button;
|
|
25831
|
+
};
|
|
25832
|
+
const card = remoteElement(document2, "section", "settings-remote-card");
|
|
25833
|
+
card.dataset.hostId = connection.hostId;
|
|
25834
|
+
card.setAttribute("aria-label", connection.displayName);
|
|
25835
|
+
card.setAttribute("aria-busy", String(locked));
|
|
25836
|
+
const head = remoteElement(document2, "div", "settings-remote-card__head");
|
|
25837
|
+
const identity = remoteElement(document2, "div", "settings-remote-card__identity");
|
|
25838
|
+
const titleLine = remoteElement(document2, "div", "settings-remote-card__title");
|
|
25839
|
+
const [tone, stateLabel] = connectionState(row, t);
|
|
25840
|
+
const state = remoteElement(document2, "span", "settings-remote-card__state", stateLabel);
|
|
25841
|
+
state.dataset.tone = tone;
|
|
25842
|
+
titleLine.append(remoteElement(document2, "h3", "", connection.displayName), state);
|
|
25843
|
+
const address = `${connection.sshAlias ?? connection.sshHost}${connection.sshPort ? `:${connection.sshPort}` : ""}`;
|
|
25844
|
+
const addressLine = remoteElement(document2, "div", "settings-remote-card__address", address);
|
|
25845
|
+
addressLine.title = address;
|
|
25846
|
+
if (connection.source === "discovered")
|
|
25847
|
+
addressLine.append(
|
|
25848
|
+
remoteElement(document2, "span", "settings-status-badge", t("SSH \u914D\u7F6E", "SSH config"))
|
|
25849
|
+
);
|
|
25850
|
+
identity.append(titleLine, addressLine);
|
|
25851
|
+
const headActions = remoteElement(document2, "div", "settings-remote-card__actions");
|
|
25852
|
+
if (row.installation !== "not-installed" && !row.probing) {
|
|
25853
|
+
if (row.state === "error" && connection.autoConnect)
|
|
25854
|
+
headActions.append(command("reconnect", t("\u91CD\u65B0\u8FDE\u63A5", "Reconnect")));
|
|
25855
|
+
headActions.append(
|
|
25856
|
+
command("toggle", connection.autoConnect ? t("\u65AD\u5F00", "Disconnect") : t("\u8FDE\u63A5", "Connect"))
|
|
25857
|
+
);
|
|
25858
|
+
}
|
|
25859
|
+
headActions.append(command("edit", t("\u7F16\u8F91", "Edit")));
|
|
25860
|
+
const remove = remoteElement(
|
|
25861
|
+
document2,
|
|
25862
|
+
"button",
|
|
25863
|
+
"settings-icon-button settings-remote-card__remove"
|
|
25864
|
+
);
|
|
25865
|
+
remove.type = "button";
|
|
25866
|
+
remove.dataset.action = "remove";
|
|
25867
|
+
remove.disabled = locked;
|
|
25868
|
+
remove.title = t("\u79FB\u9664", "Remove");
|
|
25869
|
+
remove.setAttribute("aria-label", t("\u79FB\u9664", "Remove"));
|
|
25870
|
+
remove.append(createRendererSettingsIcon("trash", 15));
|
|
25871
|
+
remove.addEventListener("click", () => onAction("remove"));
|
|
25872
|
+
headActions.append(remove);
|
|
25873
|
+
head.append(identity, headActions);
|
|
25874
|
+
card.append(head);
|
|
25875
|
+
if (row.stateError) {
|
|
25876
|
+
const detail = remoteElement(
|
|
25877
|
+
document2,
|
|
25878
|
+
"p",
|
|
25879
|
+
"settings-remote-card__detail",
|
|
25880
|
+
localizeRemoteFailure(row.stateError, t)
|
|
25881
|
+
);
|
|
25882
|
+
detail.dataset.tone = "danger";
|
|
25883
|
+
card.append(detail);
|
|
25884
|
+
}
|
|
25885
|
+
const service = remoteElement(document2, "div", "settings-remote-card__service");
|
|
25886
|
+
const copy = remoteElement(document2, "div", "settings-remote-card__service-copy");
|
|
25887
|
+
const hint = (hintTone, text, live = false) => {
|
|
25888
|
+
const line = remoteElement(document2, "p", "settings-remote-card__hint");
|
|
25889
|
+
line.dataset.tone = hintTone;
|
|
25890
|
+
if (hintTone === "progress")
|
|
25891
|
+
line.append(remoteElement(document2, "span", "settings-remote-spinner"));
|
|
25892
|
+
line.append(text);
|
|
25893
|
+
if (live) line.setAttribute("role", hintTone === "danger" ? "alert" : "status");
|
|
25894
|
+
return line;
|
|
25895
|
+
};
|
|
25896
|
+
const summary = serviceSummary(row, local, t);
|
|
25897
|
+
copy.append(remoteElement(document2, "div", "settings-remote-card__service-title", summary.title));
|
|
25898
|
+
if (row.pending) copy.append(hint("progress", row.pending, true));
|
|
25899
|
+
else {
|
|
25900
|
+
for (const [hintTone, text] of summary.hints) copy.append(hint(hintTone, text));
|
|
25901
|
+
if (row.notice)
|
|
25902
|
+
copy.append(hint(row.notice.tone, localizeRemoteFailure(row.notice.text, t), true));
|
|
25903
|
+
}
|
|
25904
|
+
const serviceActions = remoteElement(document2, "div", "settings-remote-card__actions");
|
|
25905
|
+
if (!row.probing) {
|
|
25906
|
+
const outdated = !remote && !!row.remoteIssue?.outdated && row.installation !== "not-installed";
|
|
25907
|
+
if (outdated) {
|
|
25908
|
+
const upgrade = command("upgrade", t("\u66F4\u65B0\u8FDC\u7A0B\u670D\u52A1", "Update remote service"), true);
|
|
25909
|
+
upgrade.disabled ||= !remoteInstallVersion(local);
|
|
25910
|
+
serviceActions.append(upgrade);
|
|
25911
|
+
} else if (remoteTroubled(row)) {
|
|
25912
|
+
if (row.installation !== "not-installed") {
|
|
25913
|
+
const repair = command("repair", t("\u4FEE\u590D\u8FDC\u7A0B\u670D\u52A1", "Repair remote service"));
|
|
25914
|
+
repair.title = t(
|
|
25915
|
+
"\u505C\u6B62\u5E76\u91CD\u65B0\u914D\u7F6E\u8FDC\u7A0B\u670D\u52A1\uFF0C\u4E0D\u4F1A\u66F4\u65B0\u7248\u672C\u3002",
|
|
25916
|
+
"Stops and reconfigures the remote service. It does not change the version."
|
|
25917
|
+
);
|
|
25918
|
+
serviceActions.append(repair);
|
|
25919
|
+
}
|
|
25920
|
+
if (!remote) serviceActions.append(command("recheck", t("\u91CD\u65B0\u68C0\u6D4B", "Check again")));
|
|
25921
|
+
}
|
|
25922
|
+
const target = remote ? remoteMaintenanceTarget(local, remote) : null;
|
|
25923
|
+
if (row.installation === "not-installed") {
|
|
25924
|
+
const install2 = command("install", t("\u5B89\u88C5\u5E76\u8FDE\u63A5", "Install and connect"), true);
|
|
25925
|
+
install2.disabled ||= !remoteInstallVersion(local);
|
|
25926
|
+
serviceActions.append(install2);
|
|
25927
|
+
} else if (remote && target && !remoteBusy(remote)) {
|
|
25928
|
+
const update = command(
|
|
25929
|
+
"update",
|
|
25930
|
+
target === remote.installedVersion ? t("\u91CD\u542F\u5E76\u8FDE\u63A5", "Restart and connect") : t("\u66F4\u65B0\u5230\u672C\u673A\u7248\u672C", "Match local version"),
|
|
25931
|
+
true
|
|
25932
|
+
);
|
|
25933
|
+
serviceActions.append(update);
|
|
25934
|
+
}
|
|
25935
|
+
}
|
|
25936
|
+
service.append(copy, serviceActions);
|
|
25937
|
+
card.append(service);
|
|
25938
|
+
return card;
|
|
25939
|
+
}
|
|
25940
|
+
|
|
25941
|
+
// src/settings/preference-ui.ts
|
|
25942
|
+
var nextPreferenceId = 0;
|
|
25943
|
+
function preferenceId(prefix) {
|
|
25944
|
+
nextPreferenceId += 1;
|
|
25945
|
+
return `codexhost-${prefix}-${nextPreferenceId}`;
|
|
25946
|
+
}
|
|
25947
|
+
function createPreferenceGroup(document2, title) {
|
|
25948
|
+
const group = document2.createElement("section");
|
|
25949
|
+
group.className = "mt-7 first-of-type:mt-0";
|
|
25950
|
+
const header = document2.createElement("div");
|
|
25951
|
+
header.className = "mb-2 flex min-h-6 items-center gap-2 px-1";
|
|
25952
|
+
const heading = document2.createElement("h3");
|
|
25953
|
+
heading.id = preferenceId("preference-group");
|
|
25954
|
+
heading.className = "m-0 text-[13px] leading-5 font-semibold text-settings-text";
|
|
25955
|
+
heading.textContent = title;
|
|
25956
|
+
header.append(heading);
|
|
25957
|
+
const card = document2.createElement("div");
|
|
25958
|
+
card.className = "rounded-[10px] border border-settings-border bg-settings-panel";
|
|
25959
|
+
group.setAttribute("aria-labelledby", heading.id);
|
|
25960
|
+
group.append(header, card);
|
|
25961
|
+
return { group, header, card };
|
|
25962
|
+
}
|
|
25963
|
+
function createPreferenceItem(document2, input) {
|
|
25964
|
+
const item = document2.createElement("div");
|
|
25965
|
+
item.className = "flex min-h-[60px] items-center justify-between gap-6 border-t border-settings-divider px-4 py-3 first:border-t-0";
|
|
25966
|
+
const copy = document2.createElement("div");
|
|
25967
|
+
copy.className = "flex min-w-0 flex-col gap-0.5";
|
|
25968
|
+
const heading = document2.createElement("div");
|
|
25969
|
+
heading.className = "flex items-center gap-1.5";
|
|
25970
|
+
const title = document2.createElement("label");
|
|
25971
|
+
title.htmlFor = input.controlId;
|
|
25972
|
+
title.className = "cursor-pointer text-[13px] leading-5 font-medium text-settings-text";
|
|
25973
|
+
title.textContent = input.title;
|
|
25974
|
+
heading.append(title);
|
|
25975
|
+
if (input.help) heading.append(createHelpTooltip(document2, input.help.label, input.help.lines));
|
|
25976
|
+
const description = document2.createElement("div");
|
|
25977
|
+
description.id = preferenceId("preference-description");
|
|
25978
|
+
description.className = "text-xs leading-[18px] text-settings-muted data-[invalid=true]:text-settings-danger";
|
|
25979
|
+
description.textContent = input.description;
|
|
25980
|
+
copy.append(heading, description);
|
|
25981
|
+
item.append(copy);
|
|
25982
|
+
return { item, description };
|
|
25983
|
+
}
|
|
25984
|
+
function createHelpTooltip(document2, label, lines) {
|
|
25985
|
+
const wrapper = document2.createElement("span");
|
|
25986
|
+
wrapper.className = "group relative inline-flex";
|
|
25987
|
+
const button = document2.createElement("button");
|
|
25988
|
+
button.type = "button";
|
|
25989
|
+
button.className = "inline-flex size-4 cursor-help items-center justify-center rounded-full border-0 bg-transparent p-0 text-settings-subtle transition-colors hover:text-settings-text focus-visible:text-settings-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-settings-focus";
|
|
25990
|
+
button.setAttribute("aria-label", label);
|
|
25991
|
+
button.append(createRendererSettingsIcon("help", 14));
|
|
25992
|
+
const tooltip = document2.createElement("div");
|
|
25993
|
+
tooltip.id = preferenceId("preference-tooltip");
|
|
25994
|
+
tooltip.setAttribute("role", "tooltip");
|
|
25995
|
+
tooltip.className = "pointer-events-none invisible absolute top-full left-0 z-20 mt-2 w-80 rounded-lg border border-settings-border bg-settings-panel px-3 py-2.5 text-xs leading-[18px] font-normal text-settings-text opacity-0 shadow-[0_10px_30px_rgb(0_0_0/0.22)] transition-opacity duration-150 group-hover:visible group-hover:opacity-100 group-focus-within:visible group-focus-within:opacity-100";
|
|
25996
|
+
const list = document2.createElement("ul");
|
|
25997
|
+
list.className = "m-0 grid list-disc gap-1 pl-4 marker:text-settings-subtle";
|
|
25998
|
+
for (const line of lines) {
|
|
25999
|
+
const item = document2.createElement("li");
|
|
26000
|
+
item.textContent = line;
|
|
26001
|
+
list.append(item);
|
|
26002
|
+
}
|
|
26003
|
+
tooltip.append(list);
|
|
26004
|
+
button.setAttribute("aria-describedby", tooltip.id);
|
|
26005
|
+
button.addEventListener("keydown", (event) => {
|
|
26006
|
+
if (event.key === "Escape") button.blur();
|
|
26007
|
+
});
|
|
26008
|
+
wrapper.append(button, tooltip);
|
|
26009
|
+
return wrapper;
|
|
26010
|
+
}
|
|
26011
|
+
function createPreferenceSwitch(document2, id, describedBy) {
|
|
26012
|
+
const input = document2.createElement("input");
|
|
26013
|
+
input.type = "checkbox";
|
|
26014
|
+
input.id = id;
|
|
26015
|
+
input.setAttribute("role", "switch");
|
|
26016
|
+
input.setAttribute("aria-describedby", describedBy);
|
|
26017
|
+
input.className = "relative m-0 h-5 w-9 shrink-0 cursor-pointer appearance-none rounded-full bg-settings-surface-hover ring-1 ring-settings-border transition-colors ring-inset before:absolute before:top-0.5 before:left-0.5 before:size-4 before:rounded-full before:bg-white before:shadow-[0_1px_2px_rgb(0_0_0/0.3)] before:transition-transform checked:bg-settings-focus checked:ring-transparent checked:before:translate-x-4 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-settings-focus";
|
|
26018
|
+
return input;
|
|
26019
|
+
}
|
|
26020
|
+
function createNumberField(document2, input) {
|
|
26021
|
+
const field = document2.createElement("div");
|
|
26022
|
+
field.className = "flex h-8 shrink-0 items-center gap-1.5 rounded-md border border-settings-border bg-settings-surface px-2.5 transition-colors focus-within:border-settings-focus data-[invalid=true]:border-settings-danger";
|
|
26023
|
+
const control = document2.createElement("input");
|
|
26024
|
+
control.type = "number";
|
|
26025
|
+
control.id = input.id;
|
|
26026
|
+
control.min = String(input.min);
|
|
26027
|
+
control.max = String(input.max);
|
|
26028
|
+
control.step = "1";
|
|
26029
|
+
control.setAttribute("aria-describedby", input.describedBy);
|
|
26030
|
+
control.className = "w-14 border-0 bg-transparent p-0 text-right text-[13px] leading-5 text-settings-text tabular-nums outline-none";
|
|
26031
|
+
const unit = document2.createElement("span");
|
|
26032
|
+
unit.className = "text-xs text-settings-muted";
|
|
26033
|
+
unit.setAttribute("aria-hidden", "true");
|
|
26034
|
+
unit.textContent = input.unit;
|
|
26035
|
+
field.append(control, unit);
|
|
26036
|
+
return { field, control };
|
|
26037
|
+
}
|
|
26038
|
+
|
|
26039
|
+
// src/settings/remote-connections-dialogs.ts
|
|
26040
|
+
function createRemoteDialog({ container, signal, t }, title) {
|
|
26041
|
+
if (signal.aborted || container.querySelector("dialog")) return null;
|
|
26042
|
+
const document2 = container.ownerDocument;
|
|
26043
|
+
const modal = remoteElement(
|
|
26044
|
+
document2,
|
|
26045
|
+
"dialog",
|
|
26046
|
+
"settings-account-dialog settings-credential-dialog settings-remote-dialog"
|
|
26047
|
+
);
|
|
26048
|
+
const form = remoteElement(document2, "form");
|
|
26049
|
+
const heading = remoteElement(document2, "h2", "", title);
|
|
26050
|
+
heading.id = preferenceId("remote-dialog-title");
|
|
26051
|
+
modal.setAttribute("aria-labelledby", heading.id);
|
|
26052
|
+
const body = remoteElement(document2, "div", "settings-credential-dialog__body");
|
|
26053
|
+
const error51 = remoteElement(document2, "p", "settings-credential-dialog__error");
|
|
26054
|
+
error51.setAttribute("role", "alert");
|
|
26055
|
+
const actions = remoteElement(document2, "div", "settings-credential-dialog__actions");
|
|
26056
|
+
const cancel = remoteElement(
|
|
26057
|
+
document2,
|
|
26058
|
+
"button",
|
|
26059
|
+
"settings-command-button settings-command-button--secondary",
|
|
26060
|
+
t("\u53D6\u6D88", "Cancel")
|
|
26061
|
+
);
|
|
26062
|
+
cancel.type = "button";
|
|
26063
|
+
const confirm = remoteElement(document2, "button", "settings-command-button");
|
|
26064
|
+
confirm.type = "submit";
|
|
26065
|
+
actions.append(cancel, confirm);
|
|
26066
|
+
form.append(heading, body, error51, actions);
|
|
26067
|
+
modal.append(form);
|
|
26068
|
+
let busy = false;
|
|
26069
|
+
let labels = { idle: "", busy: "" };
|
|
26070
|
+
const setBusy = (next) => {
|
|
26071
|
+
busy = next;
|
|
26072
|
+
cancel.disabled = confirm.disabled = next;
|
|
26073
|
+
confirm.textContent = next ? labels.busy : labels.idle;
|
|
26074
|
+
modal.setAttribute("aria-busy", String(next));
|
|
26075
|
+
};
|
|
26076
|
+
const dispose = () => modal.remove();
|
|
26077
|
+
cancel.addEventListener("click", () => modal.close());
|
|
26078
|
+
modal.addEventListener("cancel", (event) => {
|
|
26079
|
+
if (busy) event.preventDefault();
|
|
26080
|
+
});
|
|
26081
|
+
modal.addEventListener("close", () => {
|
|
26082
|
+
signal.removeEventListener("abort", dispose);
|
|
26083
|
+
dispose();
|
|
26084
|
+
});
|
|
26085
|
+
signal.addEventListener("abort", dispose, { once: true });
|
|
26086
|
+
return {
|
|
26087
|
+
form,
|
|
26088
|
+
body,
|
|
26089
|
+
submit(operation) {
|
|
26090
|
+
if (busy) return;
|
|
26091
|
+
error51.textContent = "";
|
|
26092
|
+
setBusy(true);
|
|
26093
|
+
operation().then(
|
|
26094
|
+
() => modal.close(),
|
|
26095
|
+
(failure) => {
|
|
26096
|
+
if (signal.aborted) return;
|
|
26097
|
+
setBusy(false);
|
|
26098
|
+
error51.textContent = localizeRemoteFailure(remoteErrorMessage(failure), t);
|
|
26099
|
+
}
|
|
26100
|
+
);
|
|
26101
|
+
},
|
|
26102
|
+
show(confirmLabel, busyLabel, danger = false) {
|
|
26103
|
+
labels = { idle: confirmLabel, busy: busyLabel };
|
|
26104
|
+
confirm.textContent = confirmLabel;
|
|
26105
|
+
if (danger)
|
|
26106
|
+
confirm.className = "settings-command-button settings-command-button--secondary settings-command-button--danger";
|
|
26107
|
+
container.append(modal);
|
|
26108
|
+
modal.showModal();
|
|
26109
|
+
}
|
|
26110
|
+
};
|
|
26111
|
+
}
|
|
26112
|
+
function openRemoteConnectionEditor(options) {
|
|
26113
|
+
const { t, previous } = options;
|
|
26114
|
+
const dialog = createRemoteDialog(
|
|
26115
|
+
options,
|
|
26116
|
+
previous ? t("\u7F16\u8F91\u8FDE\u63A5", "Edit connection") : t("\u6DFB\u52A0 SSH \u8FDE\u63A5", "Add SSH connection")
|
|
26117
|
+
);
|
|
26118
|
+
if (!dialog) return;
|
|
26119
|
+
const document2 = options.container.ownerDocument;
|
|
26120
|
+
const field = (label, value, placeholder = "", hint = "") => {
|
|
26121
|
+
const wrapper = remoteElement(document2, "div", "settings-credential-dialog__field");
|
|
26122
|
+
const input = remoteElement(document2, "input");
|
|
26123
|
+
input.id = preferenceId("remote-field");
|
|
26124
|
+
input.value = value;
|
|
26125
|
+
input.placeholder = placeholder;
|
|
26126
|
+
input.autocomplete = "off";
|
|
26127
|
+
input.spellcheck = false;
|
|
26128
|
+
const caption = remoteElement(document2, "label", "", label);
|
|
26129
|
+
caption.htmlFor = input.id;
|
|
26130
|
+
wrapper.append(caption, input);
|
|
26131
|
+
if (hint) {
|
|
26132
|
+
const description = remoteElement(document2, "small", "", hint);
|
|
26133
|
+
description.id = `${input.id}-hint`;
|
|
26134
|
+
input.setAttribute("aria-describedby", description.id);
|
|
26135
|
+
wrapper.append(description);
|
|
26136
|
+
}
|
|
26137
|
+
dialog.body.append(wrapper);
|
|
26138
|
+
return input;
|
|
26139
|
+
};
|
|
26140
|
+
const name = field(t("\u540D\u79F0", "Name"), previous?.displayName ?? "");
|
|
26141
|
+
name.required = true;
|
|
26142
|
+
const addressHint = t(
|
|
26143
|
+
"user@hostname\uFF0C\u6216 ~/.ssh/config \u4E2D\u7684\u4E3B\u673A\u522B\u540D",
|
|
26144
|
+
"user@hostname, or a host alias from ~/.ssh/config"
|
|
26145
|
+
);
|
|
26146
|
+
const hostname3 = field(
|
|
26147
|
+
t("SSH \u5730\u5740", "SSH address"),
|
|
26148
|
+
previous?.sshHost ?? "",
|
|
26149
|
+
"user@hostname",
|
|
26150
|
+
addressHint
|
|
26151
|
+
);
|
|
26152
|
+
hostname3.required = true;
|
|
26153
|
+
hostname3.pattern = "[^\\s\\-]\\S*";
|
|
26154
|
+
hostname3.title = addressHint;
|
|
26155
|
+
const port = field(
|
|
26156
|
+
t("\u7AEF\u53E3\uFF08\u53EF\u9009\uFF09", "Port (optional)"),
|
|
26157
|
+
previous?.sshPort?.toString() ?? "",
|
|
26158
|
+
"22"
|
|
26159
|
+
);
|
|
26160
|
+
port.type = "number";
|
|
26161
|
+
port.min = "1";
|
|
26162
|
+
port.max = "65535";
|
|
26163
|
+
port.step = "1";
|
|
26164
|
+
const identity = field(
|
|
26165
|
+
t("\u79C1\u94A5\u8DEF\u5F84\uFF08\u53EF\u9009\uFF09", "Identity file (optional)"),
|
|
26166
|
+
previous?.identity ?? "",
|
|
26167
|
+
"~/.ssh/id_ed25519"
|
|
26168
|
+
);
|
|
26169
|
+
if (previous?.source === "discovered") {
|
|
26170
|
+
hostname3.disabled = port.disabled = identity.disabled = true;
|
|
26171
|
+
dialog.body.append(
|
|
26172
|
+
remoteElement(
|
|
26173
|
+
document2,
|
|
26174
|
+
"p",
|
|
26175
|
+
"",
|
|
26176
|
+
t(
|
|
26177
|
+
"\u6B64\u8FDE\u63A5\u6765\u81EA SSH \u914D\u7F6E\uFF0C\u8FD9\u91CC\u53EA\u80FD\u4FEE\u6539\u540D\u79F0\uFF1B\u5176\u4F59\u914D\u7F6E\u8BF7\u5728\u539F\u751F\u8BBE\u7F6E\u4E2D\u7F16\u8F91\u3002",
|
|
26178
|
+
"This connection comes from SSH config, so only its name can change here. Edit other details in native settings."
|
|
26179
|
+
)
|
|
26180
|
+
)
|
|
26181
|
+
);
|
|
26182
|
+
}
|
|
26183
|
+
dialog.form.addEventListener("submit", (event) => {
|
|
26184
|
+
event.preventDefault();
|
|
26185
|
+
dialog.submit(
|
|
26186
|
+
() => options.save({
|
|
26187
|
+
displayName: name.value,
|
|
26188
|
+
hostname: hostname3.value,
|
|
26189
|
+
sshPort: port.value ? Number(port.value) : null,
|
|
26190
|
+
identity: identity.value.trim() || null
|
|
26191
|
+
})
|
|
26192
|
+
);
|
|
26193
|
+
});
|
|
26194
|
+
dialog.show(t("\u4FDD\u5B58", "Save"), t("\u4FDD\u5B58\u4E2D\u2026", "Saving\u2026"));
|
|
26195
|
+
name.focus();
|
|
26196
|
+
name.select();
|
|
26197
|
+
}
|
|
26198
|
+
function openRemoteConnectionRemoval(options) {
|
|
26199
|
+
const { t, connection } = options;
|
|
26200
|
+
const dialog = createRemoteDialog(
|
|
26201
|
+
options,
|
|
26202
|
+
t(`\u79FB\u9664\u201C${connection.displayName}\u201D\uFF1F`, `Remove "${connection.displayName}"?`)
|
|
26203
|
+
);
|
|
26204
|
+
if (!dialog) return;
|
|
26205
|
+
dialog.body.append(
|
|
26206
|
+
remoteElement(
|
|
26207
|
+
options.container.ownerDocument,
|
|
26208
|
+
"p",
|
|
26209
|
+
"",
|
|
26210
|
+
t(
|
|
26211
|
+
"\u79FB\u9664\u8FDE\u63A5\u4E0D\u4F1A\u5220\u9664\u8FDC\u7A0B\u6587\u4EF6\u6216\u4F1A\u8BDD\u3002",
|
|
26212
|
+
"Removing a connection does not delete remote files or chats."
|
|
26213
|
+
)
|
|
26214
|
+
)
|
|
26215
|
+
);
|
|
26216
|
+
dialog.form.addEventListener("submit", (event) => {
|
|
26217
|
+
event.preventDefault();
|
|
26218
|
+
dialog.submit(options.remove);
|
|
26219
|
+
});
|
|
26220
|
+
dialog.show(t("\u79FB\u9664", "Remove"), t("\u79FB\u9664\u4E2D\u2026", "Removing\u2026"), true);
|
|
26221
|
+
}
|
|
26222
|
+
|
|
26223
|
+
// src/settings/remote-connections-page.ts
|
|
26224
|
+
var POLL_INTERVAL_MS = 5e3;
|
|
26225
|
+
var SUCCESS_NOTICE_MS = 6e3;
|
|
26226
|
+
var INSPECT_RETRY_MS = 6e4;
|
|
26227
|
+
var RESTART_GRACE_MS = 9e4;
|
|
26228
|
+
var CONNECT_REQUEST_WAIT_MS = 3e3;
|
|
26229
|
+
function createRemoteConnectionsPage(messages, getControl) {
|
|
26230
|
+
const zh = messages.locale === "zh-CN";
|
|
26231
|
+
const t = (cn, en) => zh ? cn : en;
|
|
26232
|
+
return Object.freeze({
|
|
26233
|
+
id: "remote-connections",
|
|
26234
|
+
label: messages.pageLabels["remote-connections"],
|
|
26235
|
+
icon: "gateway",
|
|
26236
|
+
mount({ content, signal }) {
|
|
26237
|
+
const document2 = content.ownerDocument;
|
|
26238
|
+
const el = (tag, className = "", text = "") => remoteElement(document2, tag, className, text);
|
|
26239
|
+
const emptyPanel = (title, detail) => {
|
|
26240
|
+
const panel = el("div", "settings-remote__empty");
|
|
26241
|
+
const copy = el("div");
|
|
26242
|
+
copy.append(el("strong", "", title), el("span", "", detail));
|
|
26243
|
+
panel.append(copy);
|
|
26244
|
+
return panel;
|
|
26245
|
+
};
|
|
26246
|
+
const root = el("div", "settings-remote");
|
|
26247
|
+
const header = el("div", "settings-remote__header");
|
|
26248
|
+
const headerCopy = el("div");
|
|
26249
|
+
const localVersion = el("p", "settings-remote__meta");
|
|
26250
|
+
headerCopy.append(
|
|
26251
|
+
el("h1", "settings-section-label", messages.pageLabels["remote-connections"]),
|
|
26252
|
+
el(
|
|
26253
|
+
"p",
|
|
26254
|
+
"settings-page-description",
|
|
26255
|
+
t(
|
|
26256
|
+
"\u901A\u8FC7 SSH \u8FDE\u63A5\u4F60\u7684 Mac \u6216 Linux \u7535\u8111\u3002\u8FDE\u63A5\u914D\u7F6E\u4E0E Codex \u5171\u7528\u3002",
|
|
26257
|
+
"Connect to a Mac or Linux computer over SSH. Connection settings are shared with Codex."
|
|
26258
|
+
)
|
|
26259
|
+
),
|
|
26260
|
+
localVersion
|
|
26261
|
+
);
|
|
26262
|
+
header.append(headerCopy);
|
|
26263
|
+
root.append(header);
|
|
26264
|
+
content.append(root);
|
|
26265
|
+
const availableControl = getControl();
|
|
26266
|
+
if (!availableControl) {
|
|
26267
|
+
root.append(
|
|
26268
|
+
emptyPanel(
|
|
26269
|
+
t("\u6B64\u7A97\u53E3\u65E0\u6CD5\u7BA1\u7406 SSH \u8FDE\u63A5", "SSH connections are unavailable in this window"),
|
|
26270
|
+
t("\u8BF7\u5728 Codex \u684C\u9762\u7A0B\u5E8F\u4E2D\u7BA1\u7406 SSH \u8FDE\u63A5\u3002", "Manage SSH connections in Codex Desktop.")
|
|
26271
|
+
)
|
|
26272
|
+
);
|
|
26273
|
+
return;
|
|
26274
|
+
}
|
|
26275
|
+
const control = availableControl;
|
|
26276
|
+
const toolbar = el("div", "settings-remote__toolbar");
|
|
26277
|
+
const refreshButton = el("button", "settings-icon-button settings-remote__refresh");
|
|
26278
|
+
refreshButton.type = "button";
|
|
26279
|
+
refreshButton.title = t("\u5237\u65B0", "Refresh");
|
|
26280
|
+
refreshButton.setAttribute("aria-label", t("\u5237\u65B0", "Refresh"));
|
|
26281
|
+
refreshButton.append(createRendererSettingsIcon("refresh", 16));
|
|
26282
|
+
const addButton = el("button", "settings-command-button");
|
|
26283
|
+
addButton.type = "button";
|
|
26284
|
+
addButton.append(createRendererSettingsIcon("add", 14), t("\u6DFB\u52A0\u8FDE\u63A5", "Add connection"));
|
|
26285
|
+
toolbar.append(refreshButton, addButton);
|
|
26286
|
+
header.append(toolbar);
|
|
26287
|
+
const banner = el("div", "settings-remote__banner");
|
|
26288
|
+
banner.setAttribute("role", "alert");
|
|
26289
|
+
banner.hidden = true;
|
|
26290
|
+
const bannerText = el("span");
|
|
26291
|
+
const retry = el(
|
|
26292
|
+
"button",
|
|
26293
|
+
"settings-command-button settings-command-button--secondary",
|
|
26294
|
+
t("\u91CD\u8BD5", "Retry")
|
|
26295
|
+
);
|
|
26296
|
+
retry.type = "button";
|
|
26297
|
+
banner.append(bannerText, retry);
|
|
26298
|
+
const placeholder = el("div", "settings-remote__placeholder");
|
|
26299
|
+
const list = el("div", "settings-remote__list");
|
|
26300
|
+
root.append(banner, placeholder, list);
|
|
26301
|
+
let local = null;
|
|
26302
|
+
let localLoaded = false;
|
|
26303
|
+
let loaded = false;
|
|
26304
|
+
let loadError = null;
|
|
26305
|
+
let order = [];
|
|
26306
|
+
let polling = false;
|
|
26307
|
+
const rows = /* @__PURE__ */ new Map();
|
|
26308
|
+
const cards = /* @__PURE__ */ new Map();
|
|
26309
|
+
const installations = /* @__PURE__ */ new Map();
|
|
26310
|
+
const probeTokens = /* @__PURE__ */ new Map();
|
|
26311
|
+
const inspectFailures = /* @__PURE__ */ new Map();
|
|
26312
|
+
const restarting = /* @__PURE__ */ new Map();
|
|
26313
|
+
const focusedElement = () => {
|
|
26314
|
+
const active = root.getRootNode().activeElement;
|
|
26315
|
+
return active instanceof HTMLElement ? active : null;
|
|
26316
|
+
};
|
|
26317
|
+
function renderPlaceholder() {
|
|
26318
|
+
if (!loaded) {
|
|
26319
|
+
const loading = el("p", "settings-remote__loading");
|
|
26320
|
+
loading.append(
|
|
26321
|
+
el("span", "settings-remote-spinner"),
|
|
26322
|
+
t("\u6B63\u5728\u8BFB\u53D6\u8FDE\u63A5\u2026", "Loading connections\u2026")
|
|
26323
|
+
);
|
|
26324
|
+
placeholder.replaceChildren(...loadError ? [] : [loading]);
|
|
26325
|
+
} else if (!order.length) {
|
|
26326
|
+
const empty = emptyPanel(
|
|
26327
|
+
t("\u8FD8\u6CA1\u6709 SSH \u8FDE\u63A5", "No SSH connections yet"),
|
|
26328
|
+
t(
|
|
26329
|
+
"\u6DFB\u52A0\u4E00\u53F0 Mac \u6216 Linux \u7535\u8111\uFF0C\u5728\u4E0A\u9762\u8FD0\u884C\u4F1A\u8BDD\u3002",
|
|
26330
|
+
"Add a Mac or Linux computer to run conversations on it."
|
|
26331
|
+
)
|
|
26332
|
+
);
|
|
26333
|
+
const add = el(
|
|
26334
|
+
"button",
|
|
26335
|
+
"settings-command-button settings-command-button--secondary",
|
|
26336
|
+
t("\u6DFB\u52A0\u8FDE\u63A5", "Add connection")
|
|
26337
|
+
);
|
|
26338
|
+
add.type = "button";
|
|
26339
|
+
add.addEventListener("click", () => edit(null));
|
|
26340
|
+
empty.append(add);
|
|
26341
|
+
placeholder.replaceChildren(empty);
|
|
26342
|
+
} else placeholder.replaceChildren();
|
|
26343
|
+
}
|
|
26344
|
+
function render() {
|
|
26345
|
+
if (signal.aborted) return;
|
|
26346
|
+
localVersion.textContent = localLoaded ? `${t("\u672C\u673A codexhost", "Local codexhost")} ${local?.runningVersion ?? t("\u7248\u672C\u6682\u65F6\u65E0\u6CD5\u8BFB\u53D6", "version is temporarily unavailable")}` : "";
|
|
26347
|
+
banner.hidden = !loadError;
|
|
26348
|
+
bannerText.textContent = loadError ? `${t("\u8BFB\u53D6\u8FDE\u63A5\u5931\u8D25", "Could not load connections")}: ${localizeRemoteFailure(loadError, t)}` : "";
|
|
26349
|
+
renderPlaceholder();
|
|
26350
|
+
for (const [hostId, card] of cards) {
|
|
26351
|
+
if (rows.has(hostId)) continue;
|
|
26352
|
+
card.element.remove();
|
|
26353
|
+
cards.delete(hostId);
|
|
26354
|
+
}
|
|
26355
|
+
const active = focusedElement();
|
|
26356
|
+
order.forEach((hostId, index) => {
|
|
26357
|
+
const row = rows.get(hostId);
|
|
26358
|
+
if (!row) return;
|
|
26359
|
+
const signature = JSON.stringify([row, local]);
|
|
26360
|
+
let card = cards.get(hostId);
|
|
26361
|
+
if (card?.signature !== signature) {
|
|
26362
|
+
const element = renderRemoteCard(
|
|
26363
|
+
document2,
|
|
26364
|
+
row,
|
|
26365
|
+
local,
|
|
26366
|
+
t,
|
|
26367
|
+
(action) => handle(row, action)
|
|
26368
|
+
);
|
|
26369
|
+
const focusedAction = active && card?.element.contains(active) ? active.dataset.action : void 0;
|
|
26370
|
+
if (card) card.element.replaceWith(element);
|
|
26371
|
+
card = { element, signature };
|
|
26372
|
+
cards.set(hostId, card);
|
|
26373
|
+
if (focusedAction) focusAction(element, focusedAction);
|
|
26374
|
+
}
|
|
26375
|
+
if (list.children[index] !== card.element)
|
|
26376
|
+
list.insertBefore(card.element, list.children[index] ?? null);
|
|
26377
|
+
});
|
|
26378
|
+
}
|
|
26379
|
+
function focusAction(card, action) {
|
|
26380
|
+
const target = card.querySelector(`[data-action="${action}"]:not(:disabled)`) ?? card.querySelector("button:not(:disabled)");
|
|
26381
|
+
target?.focus();
|
|
26382
|
+
}
|
|
26383
|
+
async function probe(row) {
|
|
26384
|
+
const { hostId } = row.connection;
|
|
26385
|
+
const token = (probeTokens.get(hostId) ?? 0) + 1;
|
|
26386
|
+
probeTokens.set(hostId, token);
|
|
26387
|
+
const state = await control.ssh.state(hostId, signal).catch((error51) => ({ state: "unknown", error: remoteErrorMessage(error51) }));
|
|
26388
|
+
let remote = null;
|
|
26389
|
+
let remoteIssue = null;
|
|
26390
|
+
if (state.state === "connected")
|
|
26391
|
+
remote = await control.runtime(hostId).catch((error51) => {
|
|
26392
|
+
remoteIssue = remoteVersionIssue(error51);
|
|
26393
|
+
return null;
|
|
26394
|
+
});
|
|
26395
|
+
let expectedGap = false;
|
|
26396
|
+
if (remote && remoteBusy(remote)) restarting.set(hostId, Date.now() + RESTART_GRACE_MS);
|
|
26397
|
+
else if (remote || (restarting.get(hostId) ?? 0) <= Date.now()) restarting.delete(hostId);
|
|
26398
|
+
else if (row.remote) {
|
|
26399
|
+
expectedGap = true;
|
|
26400
|
+
remote = { ...row.remote, update: { ...row.remote.update, phase: "restarting" } };
|
|
26401
|
+
remoteIssue = null;
|
|
26402
|
+
}
|
|
26403
|
+
if (remote) installations.set(hostId, "installed");
|
|
26404
|
+
else if (!installations.has(hostId) && Date.now() - (inspectFailures.get(hostId) ?? -INSPECT_RETRY_MS) >= INSPECT_RETRY_MS) {
|
|
26405
|
+
const inspected = await control.setup(row.connection, "inspect").catch(() => null);
|
|
26406
|
+
if (inspected) installations.set(hostId, inspected.state);
|
|
26407
|
+
else inspectFailures.set(hostId, Date.now());
|
|
26408
|
+
}
|
|
26409
|
+
if (signal.aborted || rows.get(hostId) !== row || probeTokens.get(hostId) !== token) return;
|
|
26410
|
+
row.probing = false;
|
|
26411
|
+
row.state = expectedGap ? "connecting" : state.state;
|
|
26412
|
+
row.stateError = expectedGap ? null : state.error;
|
|
26413
|
+
row.remote = remote;
|
|
26414
|
+
row.remoteIssue = remoteIssue;
|
|
26415
|
+
row.installation = installations.get(hostId) ?? "unknown";
|
|
26416
|
+
render();
|
|
26417
|
+
}
|
|
26418
|
+
async function refresh(actingHostId, wait = "acting") {
|
|
26419
|
+
if (signal.aborted) return;
|
|
26420
|
+
const localTask = control.runtime("local").catch(() => null).then((status) => {
|
|
26421
|
+
if (signal.aborted) return;
|
|
26422
|
+
local = status;
|
|
26423
|
+
localLoaded = true;
|
|
26424
|
+
render();
|
|
26425
|
+
});
|
|
26426
|
+
let connections;
|
|
26427
|
+
try {
|
|
26428
|
+
connections = await control.ssh.list(signal);
|
|
26429
|
+
} catch (error51) {
|
|
26430
|
+
if (signal.aborted) return;
|
|
26431
|
+
loadError = remoteErrorMessage(error51);
|
|
26432
|
+
render();
|
|
26433
|
+
return;
|
|
26434
|
+
}
|
|
26435
|
+
if (signal.aborted) return;
|
|
26436
|
+
loadError = null;
|
|
26437
|
+
loaded = true;
|
|
26438
|
+
order = connections.map((connection) => connection.hostId);
|
|
26439
|
+
for (const connection of connections) {
|
|
26440
|
+
const row = rows.get(connection.hostId);
|
|
26441
|
+
if (row) row.connection = connection;
|
|
26442
|
+
else
|
|
26443
|
+
rows.set(connection.hostId, {
|
|
26444
|
+
connection,
|
|
26445
|
+
probing: true,
|
|
26446
|
+
state: null,
|
|
26447
|
+
stateError: null,
|
|
26448
|
+
remote: null,
|
|
26449
|
+
remoteIssue: null,
|
|
26450
|
+
installation: null,
|
|
26451
|
+
pending: null,
|
|
26452
|
+
notice: null
|
|
26453
|
+
});
|
|
26454
|
+
}
|
|
26455
|
+
for (const hostId of [...rows.keys()]) {
|
|
26456
|
+
if (order.includes(hostId)) continue;
|
|
26457
|
+
rows.delete(hostId);
|
|
26458
|
+
installations.delete(hostId);
|
|
26459
|
+
probeTokens.delete(hostId);
|
|
26460
|
+
inspectFailures.delete(hostId);
|
|
26461
|
+
restarting.delete(hostId);
|
|
26462
|
+
}
|
|
26463
|
+
render();
|
|
26464
|
+
const probes = [...rows.values()].filter((row) => !row.pending || row.connection.hostId === actingHostId).map((row) => ({ hostId: row.connection.hostId, done: probe(row) }));
|
|
26465
|
+
const awaited = wait === "all" ? probes : probes.filter((p) => p.hostId === actingHostId);
|
|
26466
|
+
await Promise.all([localTask, ...awaited.map((p) => p.done)]);
|
|
26467
|
+
}
|
|
26468
|
+
async function act(row, action, label, operation) {
|
|
26469
|
+
const { hostId } = row.connection;
|
|
26470
|
+
row.pending = label;
|
|
26471
|
+
row.notice = null;
|
|
26472
|
+
render();
|
|
26473
|
+
try {
|
|
26474
|
+
const done = await operation();
|
|
26475
|
+
await refresh(hostId);
|
|
26476
|
+
if (typeof done === "string") {
|
|
26477
|
+
const notice = { tone: "success", text: done };
|
|
26478
|
+
row.notice = notice;
|
|
26479
|
+
setTimeout(() => {
|
|
26480
|
+
if (row.notice !== notice) return;
|
|
26481
|
+
row.notice = null;
|
|
26482
|
+
render();
|
|
26483
|
+
}, SUCCESS_NOTICE_MS);
|
|
26484
|
+
}
|
|
26485
|
+
} catch (error51) {
|
|
26486
|
+
row.notice = { tone: "danger", text: remoteErrorMessage(error51) };
|
|
26487
|
+
installations.delete(hostId);
|
|
26488
|
+
inspectFailures.delete(hostId);
|
|
26489
|
+
void refresh(hostId);
|
|
26490
|
+
} finally {
|
|
26491
|
+
row.pending = null;
|
|
26492
|
+
if (!signal.aborted) {
|
|
26493
|
+
render();
|
|
26494
|
+
const card = cards.get(hostId)?.element;
|
|
26495
|
+
if (card && !focusedElement()) focusAction(card, action);
|
|
26496
|
+
}
|
|
26497
|
+
}
|
|
26498
|
+
}
|
|
26499
|
+
function edit(previous) {
|
|
26500
|
+
openRemoteConnectionEditor({
|
|
26501
|
+
container: root,
|
|
26502
|
+
signal,
|
|
26503
|
+
t,
|
|
26504
|
+
previous,
|
|
26505
|
+
async save(draft) {
|
|
26506
|
+
await control.ssh.save(draft, previous, signal);
|
|
26507
|
+
if (previous) {
|
|
26508
|
+
installations.delete(previous.hostId);
|
|
26509
|
+
inspectFailures.delete(previous.hostId);
|
|
26510
|
+
restarting.delete(previous.hostId);
|
|
26511
|
+
}
|
|
26512
|
+
await refresh();
|
|
26513
|
+
}
|
|
26514
|
+
});
|
|
26515
|
+
}
|
|
26516
|
+
function handle(row, action) {
|
|
26517
|
+
if (row.pending) return;
|
|
26518
|
+
const { connection } = row;
|
|
26519
|
+
const { hostId } = connection;
|
|
26520
|
+
const setConnected = async (enabled) => {
|
|
26521
|
+
const request = control.ssh.connect(hostId, enabled, signal);
|
|
26522
|
+
request.catch(() => void 0);
|
|
26523
|
+
await Promise.race([
|
|
26524
|
+
request,
|
|
26525
|
+
new Promise((resolve) => setTimeout(resolve, CONNECT_REQUEST_WAIT_MS))
|
|
26526
|
+
]);
|
|
26527
|
+
};
|
|
26528
|
+
const reconnect = async () => {
|
|
26529
|
+
installations.delete(hostId);
|
|
26530
|
+
inspectFailures.delete(hostId);
|
|
26531
|
+
await setConnected(true);
|
|
26532
|
+
};
|
|
26533
|
+
switch (action) {
|
|
26534
|
+
case "edit":
|
|
26535
|
+
edit(connection);
|
|
26536
|
+
break;
|
|
26537
|
+
case "remove":
|
|
26538
|
+
openRemoteConnectionRemoval({
|
|
26539
|
+
container: root,
|
|
26540
|
+
signal,
|
|
26541
|
+
t,
|
|
26542
|
+
connection,
|
|
26543
|
+
async remove() {
|
|
26544
|
+
await control.ssh.remove(connection, signal);
|
|
26545
|
+
await refresh();
|
|
26546
|
+
}
|
|
26547
|
+
});
|
|
26548
|
+
break;
|
|
26549
|
+
case "toggle":
|
|
26550
|
+
void act(
|
|
26551
|
+
row,
|
|
26552
|
+
action,
|
|
26553
|
+
connection.autoConnect ? t("\u6B63\u5728\u65AD\u5F00\u2026", "Disconnecting\u2026") : t("\u6B63\u5728\u8FDE\u63A5\u2026", "Connecting\u2026"),
|
|
26554
|
+
() => setConnected(!connection.autoConnect)
|
|
26555
|
+
);
|
|
26556
|
+
break;
|
|
26557
|
+
case "reconnect":
|
|
26558
|
+
void act(row, action, t("\u6B63\u5728\u91CD\u65B0\u8FDE\u63A5\u2026", "Reconnecting\u2026"), async () => {
|
|
26559
|
+
await setConnected(false);
|
|
26560
|
+
await setConnected(true);
|
|
26561
|
+
});
|
|
26562
|
+
break;
|
|
26563
|
+
case "recheck":
|
|
26564
|
+
void act(row, action, t("\u6B63\u5728\u91CD\u65B0\u68C0\u6D4B\u2026", "Checking again\u2026"), async () => {
|
|
26565
|
+
installations.delete(hostId);
|
|
26566
|
+
inspectFailures.delete(hostId);
|
|
26567
|
+
});
|
|
26568
|
+
break;
|
|
26569
|
+
case "install": {
|
|
26570
|
+
const version2 = remoteInstallVersion(local);
|
|
26571
|
+
if (!version2) break;
|
|
26572
|
+
void act(
|
|
26573
|
+
row,
|
|
26574
|
+
action,
|
|
26575
|
+
t("\u6B63\u5728\u5B89\u88C5\u8FDC\u7A0B\u670D\u52A1\uFF0C\u8BF7\u7A0D\u5019\u2026", "Installing remote service, please wait\u2026"),
|
|
26576
|
+
async () => {
|
|
26577
|
+
await control.setup(connection, "install", version2);
|
|
26578
|
+
await reconnect();
|
|
26579
|
+
return t("\u8FDC\u7A0B\u670D\u52A1\u5DF2\u5B89\u88C5\uFF0C\u6B63\u5728\u8FDE\u63A5", "Remote service installed; connecting");
|
|
26580
|
+
}
|
|
26581
|
+
);
|
|
26582
|
+
break;
|
|
26583
|
+
}
|
|
26584
|
+
case "upgrade": {
|
|
26585
|
+
const version2 = remoteInstallVersion(local);
|
|
26586
|
+
if (!version2) break;
|
|
26587
|
+
void act(
|
|
26588
|
+
row,
|
|
26589
|
+
action,
|
|
26590
|
+
t("\u6B63\u5728\u66F4\u65B0\u8FDC\u7A0B\u670D\u52A1\uFF0C\u8BF7\u7A0D\u5019\u2026", "Updating remote service, please wait\u2026"),
|
|
26591
|
+
async () => {
|
|
26592
|
+
await control.setup(connection, "update", version2);
|
|
26593
|
+
await reconnect();
|
|
26594
|
+
return t("\u8FDC\u7A0B\u670D\u52A1\u5DF2\u66F4\u65B0\uFF0C\u6B63\u5728\u8FDE\u63A5", "Remote service updated; connecting");
|
|
26595
|
+
}
|
|
26596
|
+
);
|
|
26597
|
+
break;
|
|
26598
|
+
}
|
|
26599
|
+
case "repair":
|
|
26600
|
+
void act(
|
|
26601
|
+
row,
|
|
26602
|
+
action,
|
|
26603
|
+
t("\u6B63\u5728\u91CD\u65B0\u914D\u7F6E\u8FDC\u7A0B\u670D\u52A1\u2026", "Reconfiguring remote service\u2026"),
|
|
26604
|
+
async () => {
|
|
26605
|
+
await control.setup(connection, "repair");
|
|
26606
|
+
await reconnect();
|
|
26607
|
+
return t("\u8FDC\u7A0B\u670D\u52A1\u5DF2\u4FEE\u590D\uFF0C\u6B63\u5728\u8FDE\u63A5", "Remote service repaired; connecting");
|
|
26608
|
+
}
|
|
26609
|
+
);
|
|
26610
|
+
break;
|
|
26611
|
+
case "update": {
|
|
26612
|
+
const target = row.remote ? remoteMaintenanceTarget(local, row.remote) : null;
|
|
26613
|
+
if (!target) break;
|
|
26614
|
+
const restart = target === row.remote?.installedVersion;
|
|
26615
|
+
void act(
|
|
26616
|
+
row,
|
|
26617
|
+
action,
|
|
26618
|
+
restart ? t("\u6B63\u5728\u91CD\u542F\u8FDC\u7A0B\u670D\u52A1\u2026", "Restarting remote service\u2026") : t("\u6B63\u5728\u63D0\u4EA4\u66F4\u65B0\u2026", "Starting update\u2026"),
|
|
26619
|
+
async () => {
|
|
26620
|
+
await control.update(hostId, target);
|
|
26621
|
+
await setConnected(true);
|
|
26622
|
+
}
|
|
26623
|
+
);
|
|
26624
|
+
break;
|
|
26625
|
+
}
|
|
26626
|
+
}
|
|
26627
|
+
}
|
|
26628
|
+
const reload = () => {
|
|
26629
|
+
if (refreshButton.getAttribute("aria-busy") === "true") return;
|
|
26630
|
+
refreshButton.setAttribute("aria-busy", "true");
|
|
26631
|
+
installations.clear();
|
|
26632
|
+
inspectFailures.clear();
|
|
26633
|
+
void refresh(void 0, "all").finally(() => refreshButton.removeAttribute("aria-busy"));
|
|
26634
|
+
};
|
|
26635
|
+
refreshButton.addEventListener("click", reload);
|
|
26636
|
+
retry.addEventListener("click", reload);
|
|
26637
|
+
addButton.addEventListener("click", () => edit(null));
|
|
26638
|
+
render();
|
|
26639
|
+
void refresh();
|
|
26640
|
+
const timer = setInterval(() => {
|
|
26641
|
+
if (polling) return;
|
|
26642
|
+
polling = true;
|
|
26643
|
+
void refresh(void 0, "all").finally(() => {
|
|
26644
|
+
polling = false;
|
|
26645
|
+
});
|
|
26646
|
+
}, POLL_INTERVAL_MS);
|
|
26647
|
+
return () => clearInterval(timer);
|
|
26648
|
+
}
|
|
26649
|
+
});
|
|
26650
|
+
}
|
|
26651
|
+
|
|
25097
26652
|
// src/settings/core.ts
|
|
25098
26653
|
var SETTINGS_PAGE_ID_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/u;
|
|
25099
26654
|
var MAX_SETTINGS_PAGE_ID_LENGTH = 48;
|
|
@@ -25197,6 +26752,74 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
25197
26752
|
}
|
|
25198
26753
|
};
|
|
25199
26754
|
|
|
26755
|
+
// src/settings/horizontal-scroll-hint.ts
|
|
26756
|
+
function createHorizontalScrollHint(document2, scroller, className) {
|
|
26757
|
+
const element = document2.createElement("div");
|
|
26758
|
+
element.className = className;
|
|
26759
|
+
element.setAttribute("aria-hidden", "true");
|
|
26760
|
+
const thumb = document2.createElement("span");
|
|
26761
|
+
element.append(thumb);
|
|
26762
|
+
const limit = () => Math.max(0, scroller.scrollWidth - scroller.clientWidth);
|
|
26763
|
+
const scrollTo = (left) => {
|
|
26764
|
+
scroller.scrollLeft = Math.min(limit(), Math.max(0, left));
|
|
26765
|
+
update();
|
|
26766
|
+
};
|
|
26767
|
+
const update = () => {
|
|
26768
|
+
const { clientWidth, scrollLeft, scrollWidth } = scroller;
|
|
26769
|
+
const overflowing = scrollWidth > clientWidth + 1;
|
|
26770
|
+
element.dataset.overflowing = String(overflowing);
|
|
26771
|
+
if (!overflowing) return;
|
|
26772
|
+
thumb.style.width = `${clientWidth / scrollWidth * 100}%`;
|
|
26773
|
+
thumb.style.left = `${scrollLeft / scrollWidth * 100}%`;
|
|
26774
|
+
};
|
|
26775
|
+
scroller.addEventListener("scroll", update, { passive: true });
|
|
26776
|
+
scroller.addEventListener(
|
|
26777
|
+
"wheel",
|
|
26778
|
+
(event) => {
|
|
26779
|
+
if (event.deltaX !== 0 || event.deltaY === 0 || event.ctrlKey) return;
|
|
26780
|
+
const next = Math.min(limit(), Math.max(0, scroller.scrollLeft + event.deltaY));
|
|
26781
|
+
if (Math.abs(next - scroller.scrollLeft) < 1) return;
|
|
26782
|
+
event.preventDefault();
|
|
26783
|
+
scrollTo(next);
|
|
26784
|
+
},
|
|
26785
|
+
{ passive: false }
|
|
26786
|
+
);
|
|
26787
|
+
let drag = null;
|
|
26788
|
+
element.addEventListener("pointerdown", (event) => {
|
|
26789
|
+
if (event.button !== 0 || limit() <= 1) return;
|
|
26790
|
+
const track = element.getBoundingClientRect();
|
|
26791
|
+
if (track.width <= 0) return;
|
|
26792
|
+
if (event.target !== thumb) {
|
|
26793
|
+
const pointed = (event.clientX - track.left) / track.width * scroller.scrollWidth;
|
|
26794
|
+
scrollTo(pointed - scroller.clientWidth / 2);
|
|
26795
|
+
}
|
|
26796
|
+
drag = {
|
|
26797
|
+
pointerId: event.pointerId,
|
|
26798
|
+
startX: event.clientX,
|
|
26799
|
+
startLeft: scroller.scrollLeft,
|
|
26800
|
+
// One pixel along the line is this many pixels of row content.
|
|
26801
|
+
scale: scroller.scrollWidth / track.width
|
|
26802
|
+
};
|
|
26803
|
+
element.dataset.dragging = "true";
|
|
26804
|
+
element.setPointerCapture(event.pointerId);
|
|
26805
|
+
event.preventDefault();
|
|
26806
|
+
});
|
|
26807
|
+
element.addEventListener("pointermove", (event) => {
|
|
26808
|
+
if (drag?.pointerId !== event.pointerId) return;
|
|
26809
|
+
scrollTo(drag.startLeft + (event.clientX - drag.startX) * drag.scale);
|
|
26810
|
+
});
|
|
26811
|
+
const release = (event) => {
|
|
26812
|
+
if (drag?.pointerId !== event.pointerId) return;
|
|
26813
|
+
drag = null;
|
|
26814
|
+
delete element.dataset.dragging;
|
|
26815
|
+
};
|
|
26816
|
+
element.addEventListener("pointerup", release);
|
|
26817
|
+
element.addEventListener("pointercancel", release);
|
|
26818
|
+
const ResizeObserverClass = document2.defaultView?.ResizeObserver;
|
|
26819
|
+
if (ResizeObserverClass) new ResizeObserverClass(update).observe(scroller);
|
|
26820
|
+
return { element, update };
|
|
26821
|
+
}
|
|
26822
|
+
|
|
25200
26823
|
// src/settings/session-import-list-controls.ts
|
|
25201
26824
|
function createSessionImportListControls(document2, messages, onChange) {
|
|
25202
26825
|
let query = "";
|
|
@@ -25330,7 +26953,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
25330
26953
|
text.textContent = message;
|
|
25331
26954
|
return text;
|
|
25332
26955
|
}
|
|
25333
|
-
function createSessionImportSettingsPage(messages, getClient, openImportedThread) {
|
|
26956
|
+
function createSessionImportSettingsPage(messages, getClient, openImportedThread, getDiagnostics = () => null) {
|
|
25334
26957
|
return Object.freeze({
|
|
25335
26958
|
id: "session-import",
|
|
25336
26959
|
label: messages.pageLabels["session-import"],
|
|
@@ -25363,10 +26986,19 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
25363
26986
|
harnessOptions.dataset.sessionImportHarness = "selector";
|
|
25364
26987
|
harnessOptions.setAttribute("role", "group");
|
|
25365
26988
|
harnessOptions.setAttribute("aria-label", messages.sessionImportHarness);
|
|
26989
|
+
const harnessScroller = document2.createElement("div");
|
|
26990
|
+
harnessScroller.className = "settings-session-import-harness__scroller";
|
|
26991
|
+
const harnessHint = createHorizontalScrollHint(
|
|
26992
|
+
document2,
|
|
26993
|
+
harnessOptions,
|
|
26994
|
+
"settings-session-import-harness__indicator"
|
|
26995
|
+
);
|
|
26996
|
+
harnessScroller.append(harnessOptions, harnessHint.element);
|
|
25366
26997
|
let selectedHarness = null;
|
|
25367
26998
|
let sources = [];
|
|
25368
26999
|
const sourceButtons = [];
|
|
25369
27000
|
const renderHarnessOptions = () => {
|
|
27001
|
+
const scrolled = harnessOptions.scrollLeft;
|
|
25370
27002
|
harnessOptions.replaceChildren();
|
|
25371
27003
|
sourceButtons.length = 0;
|
|
25372
27004
|
for (const source of sources) {
|
|
@@ -25387,8 +27019,11 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
25387
27019
|
sourceButtons.push(option);
|
|
25388
27020
|
harnessOptions.append(option);
|
|
25389
27021
|
}
|
|
27022
|
+
harnessOptions.scrollLeft = scrolled;
|
|
27023
|
+
harnessOptions.querySelector('[aria-pressed="true"]')?.scrollIntoView?.({ block: "nearest", inline: "nearest" });
|
|
27024
|
+
harnessHint.update();
|
|
25390
27025
|
};
|
|
25391
|
-
harness.append(harnessLabel,
|
|
27026
|
+
harness.append(harnessLabel, harnessScroller);
|
|
25392
27027
|
const description = document2.createElement("p");
|
|
25393
27028
|
description.className = "settings-page-description";
|
|
25394
27029
|
description.textContent = messages.sessionImportDescription;
|
|
@@ -25677,10 +27312,15 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
25677
27312
|
const pageParams = listControls.params();
|
|
25678
27313
|
void context.runLatest(
|
|
25679
27314
|
async (signal) => {
|
|
25680
|
-
const
|
|
25681
|
-
|
|
27315
|
+
const missing = new Set(
|
|
27316
|
+
getDiagnostics()?.snapshot().hosts.find(({ hostId }) => hostId === "local")?.agents.filter(({ availability }) => availability === "notInstalled").map(({ agent }) => agent)
|
|
27317
|
+
);
|
|
27318
|
+
const harnesses = (await client.listSessionImportSources()).harnesses.filter(
|
|
27319
|
+
({ harnessId }) => !missing.has(harnessId)
|
|
27320
|
+
);
|
|
27321
|
+
const selected = harnesses.find(({ harnessId }) => harnessId === requestedHarness)?.harnessId ?? harnesses[0]?.harnessId ?? null;
|
|
25682
27322
|
if (signal.aborted) throw new Error("Session import selection changed");
|
|
25683
|
-
sources =
|
|
27323
|
+
sources = harnesses;
|
|
25684
27324
|
selectedHarness = selected;
|
|
25685
27325
|
if (selected !== requestedHarness) {
|
|
25686
27326
|
listControls.reset();
|
|
@@ -25821,104 +27461,6 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
25821
27461
|
};
|
|
25822
27462
|
}
|
|
25823
27463
|
|
|
25824
|
-
// src/settings/preference-ui.ts
|
|
25825
|
-
var nextPreferenceId = 0;
|
|
25826
|
-
function preferenceId(prefix) {
|
|
25827
|
-
nextPreferenceId += 1;
|
|
25828
|
-
return `codexhost-${prefix}-${nextPreferenceId}`;
|
|
25829
|
-
}
|
|
25830
|
-
function createPreferenceGroup(document2, title) {
|
|
25831
|
-
const group = document2.createElement("section");
|
|
25832
|
-
group.className = "mt-7 first-of-type:mt-0";
|
|
25833
|
-
const header = document2.createElement("div");
|
|
25834
|
-
header.className = "mb-2 flex min-h-6 items-center gap-2 px-1";
|
|
25835
|
-
const heading = document2.createElement("h3");
|
|
25836
|
-
heading.id = preferenceId("preference-group");
|
|
25837
|
-
heading.className = "m-0 text-[13px] leading-5 font-semibold text-settings-text";
|
|
25838
|
-
heading.textContent = title;
|
|
25839
|
-
header.append(heading);
|
|
25840
|
-
const card = document2.createElement("div");
|
|
25841
|
-
card.className = "rounded-[10px] border border-settings-border bg-settings-panel";
|
|
25842
|
-
group.setAttribute("aria-labelledby", heading.id);
|
|
25843
|
-
group.append(header, card);
|
|
25844
|
-
return { group, header, card };
|
|
25845
|
-
}
|
|
25846
|
-
function createPreferenceItem(document2, input) {
|
|
25847
|
-
const item = document2.createElement("div");
|
|
25848
|
-
item.className = "flex min-h-[60px] items-center justify-between gap-6 border-t border-settings-divider px-4 py-3 first:border-t-0";
|
|
25849
|
-
const copy = document2.createElement("div");
|
|
25850
|
-
copy.className = "flex min-w-0 flex-col gap-0.5";
|
|
25851
|
-
const heading = document2.createElement("div");
|
|
25852
|
-
heading.className = "flex items-center gap-1.5";
|
|
25853
|
-
const title = document2.createElement("label");
|
|
25854
|
-
title.htmlFor = input.controlId;
|
|
25855
|
-
title.className = "cursor-pointer text-[13px] leading-5 font-medium text-settings-text";
|
|
25856
|
-
title.textContent = input.title;
|
|
25857
|
-
heading.append(title);
|
|
25858
|
-
if (input.help) heading.append(createHelpTooltip(document2, input.help.label, input.help.lines));
|
|
25859
|
-
const description = document2.createElement("div");
|
|
25860
|
-
description.id = preferenceId("preference-description");
|
|
25861
|
-
description.className = "text-xs leading-[18px] text-settings-muted data-[invalid=true]:text-settings-danger";
|
|
25862
|
-
description.textContent = input.description;
|
|
25863
|
-
copy.append(heading, description);
|
|
25864
|
-
item.append(copy);
|
|
25865
|
-
return { item, description };
|
|
25866
|
-
}
|
|
25867
|
-
function createHelpTooltip(document2, label, lines) {
|
|
25868
|
-
const wrapper = document2.createElement("span");
|
|
25869
|
-
wrapper.className = "group relative inline-flex";
|
|
25870
|
-
const button = document2.createElement("button");
|
|
25871
|
-
button.type = "button";
|
|
25872
|
-
button.className = "inline-flex size-4 cursor-help items-center justify-center rounded-full border-0 bg-transparent p-0 text-settings-subtle transition-colors hover:text-settings-text focus-visible:text-settings-text focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-settings-focus";
|
|
25873
|
-
button.setAttribute("aria-label", label);
|
|
25874
|
-
button.append(createRendererSettingsIcon("help", 14));
|
|
25875
|
-
const tooltip = document2.createElement("div");
|
|
25876
|
-
tooltip.id = preferenceId("preference-tooltip");
|
|
25877
|
-
tooltip.setAttribute("role", "tooltip");
|
|
25878
|
-
tooltip.className = "pointer-events-none invisible absolute top-full left-0 z-20 mt-2 w-80 rounded-lg border border-settings-border bg-settings-panel px-3 py-2.5 text-xs leading-[18px] font-normal text-settings-text opacity-0 shadow-[0_10px_30px_rgb(0_0_0/0.22)] transition-opacity duration-150 group-hover:visible group-hover:opacity-100 group-focus-within:visible group-focus-within:opacity-100";
|
|
25879
|
-
const list = document2.createElement("ul");
|
|
25880
|
-
list.className = "m-0 grid list-disc gap-1 pl-4 marker:text-settings-subtle";
|
|
25881
|
-
for (const line of lines) {
|
|
25882
|
-
const item = document2.createElement("li");
|
|
25883
|
-
item.textContent = line;
|
|
25884
|
-
list.append(item);
|
|
25885
|
-
}
|
|
25886
|
-
tooltip.append(list);
|
|
25887
|
-
button.setAttribute("aria-describedby", tooltip.id);
|
|
25888
|
-
button.addEventListener("keydown", (event) => {
|
|
25889
|
-
if (event.key === "Escape") button.blur();
|
|
25890
|
-
});
|
|
25891
|
-
wrapper.append(button, tooltip);
|
|
25892
|
-
return wrapper;
|
|
25893
|
-
}
|
|
25894
|
-
function createPreferenceSwitch(document2, id, describedBy) {
|
|
25895
|
-
const input = document2.createElement("input");
|
|
25896
|
-
input.type = "checkbox";
|
|
25897
|
-
input.id = id;
|
|
25898
|
-
input.setAttribute("role", "switch");
|
|
25899
|
-
input.setAttribute("aria-describedby", describedBy);
|
|
25900
|
-
input.className = "relative m-0 h-5 w-9 shrink-0 cursor-pointer appearance-none rounded-full bg-settings-surface-hover ring-1 ring-settings-border transition-colors ring-inset before:absolute before:top-0.5 before:left-0.5 before:size-4 before:rounded-full before:bg-white before:shadow-[0_1px_2px_rgb(0_0_0/0.3)] before:transition-transform checked:bg-settings-focus checked:ring-transparent checked:before:translate-x-4 focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-settings-focus";
|
|
25901
|
-
return input;
|
|
25902
|
-
}
|
|
25903
|
-
function createNumberField(document2, input) {
|
|
25904
|
-
const field = document2.createElement("div");
|
|
25905
|
-
field.className = "flex h-8 shrink-0 items-center gap-1.5 rounded-md border border-settings-border bg-settings-surface px-2.5 transition-colors focus-within:border-settings-focus data-[invalid=true]:border-settings-danger";
|
|
25906
|
-
const control = document2.createElement("input");
|
|
25907
|
-
control.type = "number";
|
|
25908
|
-
control.id = input.id;
|
|
25909
|
-
control.min = String(input.min);
|
|
25910
|
-
control.max = String(input.max);
|
|
25911
|
-
control.step = "1";
|
|
25912
|
-
control.setAttribute("aria-describedby", input.describedBy);
|
|
25913
|
-
control.className = "w-14 border-0 bg-transparent p-0 text-right text-[13px] leading-5 text-settings-text tabular-nums outline-none";
|
|
25914
|
-
const unit = document2.createElement("span");
|
|
25915
|
-
unit.className = "text-xs text-settings-muted";
|
|
25916
|
-
unit.setAttribute("aria-hidden", "true");
|
|
25917
|
-
unit.textContent = input.unit;
|
|
25918
|
-
field.append(control, unit);
|
|
25919
|
-
return { field, control };
|
|
25920
|
-
}
|
|
25921
|
-
|
|
25922
27464
|
// src/settings/idle-release-controls.ts
|
|
25923
27465
|
function mountIdleReleaseControls(context, messages, getLoadedSessionsClient) {
|
|
25924
27466
|
const { content } = context;
|
|
@@ -26283,7 +27825,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
26283
27825
|
}
|
|
26284
27826
|
function defaultImportName(source, existing) {
|
|
26285
27827
|
const base = source.provider === "openai-codex" ? "codex" : "grok";
|
|
26286
|
-
const used = new Set(existing.map((
|
|
27828
|
+
const used = new Set(existing.map((record4) => record4.name));
|
|
26287
27829
|
const valid = (name) => credentialImportNameSchema.safeParse(name).success;
|
|
26288
27830
|
if (!used.has(base)) return base;
|
|
26289
27831
|
const local = source.label.includes("@") ? source.label.split("@")[0] ?? "" : "";
|
|
@@ -26303,7 +27845,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
26303
27845
|
let othersExpanded = false;
|
|
26304
27846
|
const targetButtons = /* @__PURE__ */ new Map();
|
|
26305
27847
|
const importedRecords = () => snapshot.targets.find((target) => target.harnessId === TARGET_HARNESS_ID)?.imports ?? [];
|
|
26306
|
-
const sourceOf = (
|
|
27848
|
+
const sourceOf = (record4) => snapshot.sources.find((source) => source.id === record4.source.id);
|
|
26307
27849
|
const section = document2.createElement("section");
|
|
26308
27850
|
section.className = "settings-pi-accounts";
|
|
26309
27851
|
section.hidden = true;
|
|
@@ -26352,33 +27894,33 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
26352
27894
|
mark.append(createRendererAgentIcon(agent ?? "pi", 26, document2));
|
|
26353
27895
|
return mark;
|
|
26354
27896
|
};
|
|
26355
|
-
const renderRow = (
|
|
27897
|
+
const renderRow = (record4) => {
|
|
26356
27898
|
const row = document2.createElement("div");
|
|
26357
27899
|
row.className = "settings-pi-accounts__row";
|
|
26358
27900
|
row.tabIndex = -1;
|
|
26359
|
-
row.dataset.importName =
|
|
26360
|
-
row.setAttribute("aria-label",
|
|
26361
|
-
const agent = KNOWN_RENDERER_AGENTS.find((candidate) => candidate ===
|
|
27901
|
+
row.dataset.importName = record4.name;
|
|
27902
|
+
row.setAttribute("aria-label", record4.source.label);
|
|
27903
|
+
const agent = KNOWN_RENDERER_AGENTS.find((candidate) => candidate === record4.source.harnessId);
|
|
26362
27904
|
const mark = createMark(agent);
|
|
26363
27905
|
const identity = document2.createElement("div");
|
|
26364
27906
|
identity.className = "settings-pi-accounts__identity";
|
|
26365
27907
|
const label = document2.createElement("strong");
|
|
26366
27908
|
label.className = "settings-account-email";
|
|
26367
|
-
label.textContent =
|
|
26368
|
-
label.title =
|
|
27909
|
+
label.textContent = record4.source.label;
|
|
27910
|
+
label.title = record4.source.label;
|
|
26369
27911
|
label.translate = false;
|
|
26370
27912
|
const meta3 = document2.createElement("div");
|
|
26371
27913
|
meta3.className = "settings-account-metadata";
|
|
26372
|
-
const source = sourceOf(
|
|
27914
|
+
const source = sourceOf(record4);
|
|
26373
27915
|
const parts = [
|
|
26374
27916
|
metaPart(
|
|
26375
|
-
agent && RENDERER_AGENT_LABELS[agent] ||
|
|
27917
|
+
agent && RENDERER_AGENT_LABELS[agent] || record4.source.harnessId,
|
|
26376
27918
|
"settings-pi-accounts__agent"
|
|
26377
27919
|
),
|
|
26378
|
-
metaPart(`${
|
|
27920
|
+
metaPart(`${record4.name}/\u2026`, void 0, true),
|
|
26379
27921
|
metaPart(messages.copied)
|
|
26380
27922
|
];
|
|
26381
|
-
const time3 = formatImportedAt(
|
|
27923
|
+
const time3 = formatImportedAt(record4.importedAt);
|
|
26382
27924
|
if (time3) parts.push(metaPart(time3));
|
|
26383
27925
|
parts.forEach((part, index) => {
|
|
26384
27926
|
if (index > 0) {
|
|
@@ -26395,23 +27937,23 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
26395
27937
|
reimport.type = "button";
|
|
26396
27938
|
reimport.className = "settings-account-action";
|
|
26397
27939
|
reimport.textContent = messages.rowReimport;
|
|
26398
|
-
reimport.setAttribute("aria-label", `${messages.reimport}: ${
|
|
27940
|
+
reimport.setAttribute("aria-label", `${messages.reimport}: ${record4.source.label}`);
|
|
26399
27941
|
reimport.disabled = busy || !source;
|
|
26400
27942
|
reimport.title = messages.reimport;
|
|
26401
27943
|
reimport.addEventListener("click", () => {
|
|
26402
|
-
if (source) openDialog("reimport", { source, record:
|
|
27944
|
+
if (source) openDialog("reimport", { source, record: record4 }, `row:${record4.name}`);
|
|
26403
27945
|
});
|
|
26404
27946
|
const remove = document2.createElement("button");
|
|
26405
27947
|
remove.type = "button";
|
|
26406
27948
|
remove.className = "settings-account-action settings-pi-accounts__remove";
|
|
26407
27949
|
remove.textContent = messages.rowRemove;
|
|
26408
|
-
remove.setAttribute("aria-label", `${messages.remove}: ${
|
|
27950
|
+
remove.setAttribute("aria-label", `${messages.remove}: ${record4.source.label}`);
|
|
26409
27951
|
remove.disabled = busy;
|
|
26410
|
-
remove.addEventListener("click", () => openDialog("remove", { record:
|
|
27952
|
+
remove.addEventListener("click", () => openDialog("remove", { record: record4 }, `row:${record4.name}`));
|
|
26411
27953
|
if (source) actions.append(reimport);
|
|
26412
27954
|
actions.append(remove);
|
|
26413
27955
|
row.append(mark, identity, actions);
|
|
26414
|
-
rows.set(
|
|
27956
|
+
rows.set(record4.name, row);
|
|
26415
27957
|
return row;
|
|
26416
27958
|
};
|
|
26417
27959
|
const loginTypeLabel = (type) => type === "oauth" ? messages.typeOauth : type === "api_key" ? messages.typeApiKey : messages.typeOther;
|
|
@@ -26558,7 +28100,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
26558
28100
|
const name = request.action === "list" ? void 0 : request.name;
|
|
26559
28101
|
state = {
|
|
26560
28102
|
source: state.source,
|
|
26561
|
-
record: importedRecords().find((
|
|
28103
|
+
record: importedRecords().find((record4) => record4.name === name) ?? state.record
|
|
26562
28104
|
};
|
|
26563
28105
|
show(next);
|
|
26564
28106
|
} else {
|
|
@@ -26571,20 +28113,20 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
26571
28113
|
nameInput = void 0;
|
|
26572
28114
|
body.replaceChildren();
|
|
26573
28115
|
controls.replaceChildren();
|
|
26574
|
-
const { source, record:
|
|
28116
|
+
const { source, record: record4 } = state;
|
|
26575
28117
|
const close = () => modal.close();
|
|
26576
28118
|
if (mode === "add" || mode === "reimport") {
|
|
26577
28119
|
title.textContent = mode === "add" ? messages.add : messages.reimport;
|
|
26578
28120
|
modal.setAttribute("aria-label", title.textContent);
|
|
26579
|
-
const active = source ??
|
|
28121
|
+
const active = source ?? record4?.source;
|
|
26580
28122
|
if (active) body.append(line(messages.source, active.label));
|
|
26581
28123
|
const input = document2.createElement("input");
|
|
26582
28124
|
input.type = "text";
|
|
26583
28125
|
input.maxLength = 48;
|
|
26584
28126
|
input.autocomplete = "off";
|
|
26585
28127
|
input.spellcheck = false;
|
|
26586
|
-
input.value =
|
|
26587
|
-
input.readOnly = Boolean(
|
|
28128
|
+
input.value = record4?.name ?? (source ? defaultImportName(source, importedRecords()) : "codex");
|
|
28129
|
+
input.readOnly = Boolean(record4);
|
|
26588
28130
|
nameInput = input;
|
|
26589
28131
|
const label = document2.createElement("label");
|
|
26590
28132
|
label.className = "settings-credential-dialog__field";
|
|
@@ -26613,7 +28155,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
26613
28155
|
{
|
|
26614
28156
|
action: mode === "reimport" ? "reimport" : "import",
|
|
26615
28157
|
sourceId: source.id,
|
|
26616
|
-
name:
|
|
28158
|
+
name: record4?.name ?? input.value,
|
|
26617
28159
|
confirmed: true
|
|
26618
28160
|
},
|
|
26619
28161
|
"done"
|
|
@@ -26623,16 +28165,16 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
26623
28165
|
)
|
|
26624
28166
|
);
|
|
26625
28167
|
(mode === "add" ? input : controls.children[0]).focus();
|
|
26626
|
-
} else if (mode === "remove" &&
|
|
28168
|
+
} else if (mode === "remove" && record4) {
|
|
26627
28169
|
title.textContent = messages.remove;
|
|
26628
28170
|
modal.setAttribute("aria-label", title.textContent);
|
|
26629
|
-
body.append(note(messages.removeWarning.replace("{name}",
|
|
28171
|
+
body.append(note(messages.removeWarning.replace("{name}", record4.name)));
|
|
26630
28172
|
const cancel = command(messages.cancel, close);
|
|
26631
28173
|
controls.append(
|
|
26632
28174
|
cancel,
|
|
26633
28175
|
command(
|
|
26634
28176
|
messages.remove,
|
|
26635
|
-
() => submit({ action: "remove", name:
|
|
28177
|
+
() => submit({ action: "remove", name: record4.name, confirmed: true }, null),
|
|
26636
28178
|
"danger"
|
|
26637
28179
|
)
|
|
26638
28180
|
);
|
|
@@ -26640,7 +28182,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
26640
28182
|
} else {
|
|
26641
28183
|
title.textContent = messages.doneTitle;
|
|
26642
28184
|
modal.setAttribute("aria-label", title.textContent);
|
|
26643
|
-
const name =
|
|
28185
|
+
const name = record4?.name;
|
|
26644
28186
|
if (name) body.append(line(messages.entry, `${name}/\u2026`, true));
|
|
26645
28187
|
body.append(note(messages.done));
|
|
26646
28188
|
const done = command(messages.close, close, "primary");
|
|
@@ -26681,25 +28223,25 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
26681
28223
|
(candidate) => candidate.harnessId === TARGET_HARNESS_ID && source && candidate.providers.includes(source.provider)
|
|
26682
28224
|
);
|
|
26683
28225
|
if (!source || !target) return null;
|
|
26684
|
-
const
|
|
28226
|
+
const record4 = target.imports.find((candidate) => candidate.source.id === source.id);
|
|
26685
28227
|
const key = `${harnessId}:${accountLabel}:import`;
|
|
26686
28228
|
const button = document2.createElement("button");
|
|
26687
28229
|
button.type = "button";
|
|
26688
28230
|
button.className = "settings-icon-button settings-account-harness-target";
|
|
26689
28231
|
button.dataset.accountFocus = key;
|
|
26690
28232
|
button.disabled = busy;
|
|
26691
|
-
if (
|
|
26692
|
-
const hint =
|
|
28233
|
+
if (record4) button.dataset.state = "imported";
|
|
28234
|
+
const hint = record4 ? messages.importedHint.replace("{name}", record4.name) : messages.add;
|
|
26693
28235
|
button.title = hint;
|
|
26694
28236
|
button.setAttribute("aria-label", hint);
|
|
26695
28237
|
button.setAttribute("aria-haspopup", "dialog");
|
|
26696
28238
|
button.append(createRendererAgentIcon("pi", 16, document2));
|
|
26697
28239
|
button.addEventListener("click", () => {
|
|
26698
|
-
if (!
|
|
28240
|
+
if (!record4) {
|
|
26699
28241
|
openDialog("add", { source }, key);
|
|
26700
28242
|
return;
|
|
26701
28243
|
}
|
|
26702
|
-
const row = rows.get(
|
|
28244
|
+
const row = rows.get(record4.name);
|
|
26703
28245
|
row?.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
26704
28246
|
row?.focus();
|
|
26705
28247
|
});
|
|
@@ -27425,7 +28967,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
27425
28967
|
}
|
|
27426
28968
|
|
|
27427
28969
|
// src/settings/accounts-page.ts
|
|
27428
|
-
function
|
|
28970
|
+
function errorMessage2(error51, fallback) {
|
|
27429
28971
|
return error51 instanceof Error && error51.message ? error51.message : fallback;
|
|
27430
28972
|
}
|
|
27431
28973
|
function createAccountsSettingsPage(messages, getClient) {
|
|
@@ -27667,7 +29209,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
27667
29209
|
refreshInBackground();
|
|
27668
29210
|
},
|
|
27669
29211
|
failure(error51) {
|
|
27670
|
-
loadMessage =
|
|
29212
|
+
loadMessage = errorMessage2(error51, messages.accountLoadFailed);
|
|
27671
29213
|
render();
|
|
27672
29214
|
}
|
|
27673
29215
|
});
|
|
@@ -28242,11 +29784,17 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
28242
29784
|
}
|
|
28243
29785
|
});
|
|
28244
29786
|
}
|
|
28245
|
-
function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getAccountClient = () => null, getSessionImportClient = () => null, openImportedThread = () => Promise.reject(new Error("Imported Thread navigation is unavailable")), getLoadedSessionsClient = () => null) {
|
|
29787
|
+
function createDefaultRendererSettingsPages(messages = DEFAULT_RENDERER_SETTINGS_MESSAGES, getUpdateClient = () => null, getDiagnostics = () => null, getAccountClient = () => null, getSessionImportClient = () => null, openImportedThread = () => Promise.reject(new Error("Imported Thread navigation is unavailable")), getLoadedSessionsClient = () => null, getRemoteConnections = () => null) {
|
|
28246
29788
|
return Object.freeze([
|
|
28247
29789
|
createConnectionsSettingsPage(messages, getDiagnostics),
|
|
29790
|
+
createRemoteConnectionsPage(messages, getRemoteConnections),
|
|
28248
29791
|
createAccountsSettingsPage(messages, getAccountClient),
|
|
28249
|
-
createSessionImportSettingsPage(
|
|
29792
|
+
createSessionImportSettingsPage(
|
|
29793
|
+
messages,
|
|
29794
|
+
getSessionImportClient,
|
|
29795
|
+
openImportedThread,
|
|
29796
|
+
getDiagnostics
|
|
29797
|
+
),
|
|
28250
29798
|
createAppearanceSettingsPage(messages, getLoadedSessionsClient),
|
|
28251
29799
|
updatesPage(messages, getUpdateClient),
|
|
28252
29800
|
aboutPage(messages, getUpdateClient)
|
|
@@ -28691,26 +30239,32 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
28691
30239
|
|
|
28692
30240
|
.settings-session-import-harness {
|
|
28693
30241
|
display: flex;
|
|
28694
|
-
|
|
30242
|
+
/* The label lines up with the options whether or not the scroll indicator is shown. */
|
|
30243
|
+
align-items: flex-start;
|
|
28695
30244
|
min-width: 0;
|
|
28696
30245
|
gap: 12px;
|
|
28697
|
-
margin: -12px 0
|
|
30246
|
+
margin: -12px 0 10px;
|
|
28698
30247
|
color: var(--settings-muted);
|
|
28699
30248
|
font-size: 13px;
|
|
28700
30249
|
}
|
|
28701
30250
|
|
|
28702
30251
|
.settings-session-import-harness > span {
|
|
28703
30252
|
flex: none;
|
|
30253
|
+
line-height: 32px;
|
|
30254
|
+
}
|
|
30255
|
+
|
|
30256
|
+
.settings-session-import-harness__scroller {
|
|
30257
|
+
min-width: 0;
|
|
30258
|
+
flex: 1;
|
|
28704
30259
|
}
|
|
28705
30260
|
|
|
28706
30261
|
.settings-session-import-harness__options {
|
|
28707
30262
|
display: flex;
|
|
28708
30263
|
align-items: center;
|
|
28709
|
-
min-width: 0;
|
|
28710
|
-
flex: 1;
|
|
28711
30264
|
gap: 6px;
|
|
28712
30265
|
overflow-x: auto;
|
|
28713
30266
|
overflow-y: hidden;
|
|
30267
|
+
/* Replaced by the hairline below: a native overlay scrollbar covers the options. */
|
|
28714
30268
|
scrollbar-width: none;
|
|
28715
30269
|
}
|
|
28716
30270
|
|
|
@@ -28718,6 +30272,59 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
28718
30272
|
display: none;
|
|
28719
30273
|
}
|
|
28720
30274
|
|
|
30275
|
+
/*
|
|
30276
|
+
* Always occupies 6px so the page does not shift; drawn only while the options overflow. The box
|
|
30277
|
+
* is taller than the 2px line it draws so the line can be grabbed with a mouse.
|
|
30278
|
+
*/
|
|
30279
|
+
.settings-session-import-harness__indicator {
|
|
30280
|
+
position: relative;
|
|
30281
|
+
height: 12px;
|
|
30282
|
+
margin-bottom: -6px;
|
|
30283
|
+
cursor: grab;
|
|
30284
|
+
touch-action: none;
|
|
30285
|
+
visibility: hidden;
|
|
30286
|
+
}
|
|
30287
|
+
|
|
30288
|
+
.settings-session-import-harness__indicator[data-overflowing="true"] {
|
|
30289
|
+
visibility: visible;
|
|
30290
|
+
}
|
|
30291
|
+
|
|
30292
|
+
.settings-session-import-harness__indicator[data-dragging="true"] {
|
|
30293
|
+
cursor: grabbing;
|
|
30294
|
+
}
|
|
30295
|
+
|
|
30296
|
+
.settings-session-import-harness__indicator::before,
|
|
30297
|
+
.settings-session-import-harness__indicator > span {
|
|
30298
|
+
position: absolute;
|
|
30299
|
+
top: 4px;
|
|
30300
|
+
height: 2px;
|
|
30301
|
+
border-radius: 1px;
|
|
30302
|
+
}
|
|
30303
|
+
|
|
30304
|
+
.settings-session-import-harness__indicator::before {
|
|
30305
|
+
right: 0;
|
|
30306
|
+
left: 0;
|
|
30307
|
+
background: var(--settings-divider);
|
|
30308
|
+
content: "";
|
|
30309
|
+
}
|
|
30310
|
+
|
|
30311
|
+
.settings-session-import-harness__indicator > span {
|
|
30312
|
+
/* Quieter than text: a hint that there is more, not a control competing with the options. */
|
|
30313
|
+
background: light-dark(rgb(13 13 13 / 24%), rgb(255 255 255 / 26%));
|
|
30314
|
+
}
|
|
30315
|
+
|
|
30316
|
+
/* The thumb takes the press across the whole grab area, not only on its 2px line. */
|
|
30317
|
+
.settings-session-import-harness__indicator > span::before {
|
|
30318
|
+
position: absolute;
|
|
30319
|
+
inset: -4px 0 -6px;
|
|
30320
|
+
content: "";
|
|
30321
|
+
}
|
|
30322
|
+
|
|
30323
|
+
.settings-session-import-harness__indicator:hover > span,
|
|
30324
|
+
.settings-session-import-harness__indicator[data-dragging="true"] > span {
|
|
30325
|
+
background: light-dark(rgb(13 13 13 / 42%), rgb(255 255 255 / 46%));
|
|
30326
|
+
}
|
|
30327
|
+
|
|
28721
30328
|
.settings-session-import-harness__option {
|
|
28722
30329
|
min-height: 32px;
|
|
28723
30330
|
flex: none;
|
|
@@ -29354,6 +30961,12 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
29354
30961
|
border-radius: 10px;
|
|
29355
30962
|
}
|
|
29356
30963
|
|
|
30964
|
+
.settings-harness-installation-actions {
|
|
30965
|
+
display: flex;
|
|
30966
|
+
flex-wrap: wrap;
|
|
30967
|
+
gap: 8px;
|
|
30968
|
+
}
|
|
30969
|
+
|
|
29357
30970
|
.settings-harness-installation-command pre {
|
|
29358
30971
|
white-space: pre-wrap;
|
|
29359
30972
|
overflow-wrap: anywhere;
|
|
@@ -29361,6 +30974,27 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
29361
30974
|
font-size: 12px;
|
|
29362
30975
|
}
|
|
29363
30976
|
|
|
30977
|
+
.settings-connection-website {
|
|
30978
|
+
display: inline-flex;
|
|
30979
|
+
align-items: center;
|
|
30980
|
+
justify-content: center;
|
|
30981
|
+
flex: none;
|
|
30982
|
+
width: 22px;
|
|
30983
|
+
height: 22px;
|
|
30984
|
+
color: var(--settings-muted);
|
|
30985
|
+
border-radius: 4px;
|
|
30986
|
+
}
|
|
30987
|
+
|
|
30988
|
+
.settings-connection-website:hover {
|
|
30989
|
+
color: var(--settings-focus);
|
|
30990
|
+
background: var(--settings-hover);
|
|
30991
|
+
}
|
|
30992
|
+
|
|
30993
|
+
.settings-connection-website:focus-visible {
|
|
30994
|
+
outline: 2px solid var(--settings-focus);
|
|
30995
|
+
outline-offset: 1px;
|
|
30996
|
+
}
|
|
30997
|
+
|
|
29364
30998
|
.settings-connection-install-link {
|
|
29365
30999
|
display: inline-flex;
|
|
29366
31000
|
align-items: center;
|
|
@@ -29372,13 +31006,11 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
29372
31006
|
background: transparent;
|
|
29373
31007
|
border: 1px solid transparent;
|
|
29374
31008
|
border-radius: 7px;
|
|
29375
|
-
opacity: 0;
|
|
29376
|
-
transition: opacity 120ms ease;
|
|
29377
31009
|
}
|
|
29378
31010
|
|
|
29379
|
-
.settings-connection-
|
|
29380
|
-
|
|
29381
|
-
|
|
31011
|
+
.settings-connection-install-link:disabled {
|
|
31012
|
+
opacity: 0.45;
|
|
31013
|
+
cursor: wait;
|
|
29382
31014
|
}
|
|
29383
31015
|
|
|
29384
31016
|
.settings-connection-install-link:hover {
|
|
@@ -29427,6 +31059,10 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
29427
31059
|
padding: 12px;
|
|
29428
31060
|
}
|
|
29429
31061
|
|
|
31062
|
+
.settings-connection-inspector__body:empty {
|
|
31063
|
+
display: none;
|
|
31064
|
+
}
|
|
31065
|
+
|
|
29430
31066
|
.settings-harness-version {
|
|
29431
31067
|
display: grid;
|
|
29432
31068
|
gap: 10px;
|
|
@@ -29551,33 +31187,6 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
29551
31187
|
border-radius: 10px;
|
|
29552
31188
|
}
|
|
29553
31189
|
|
|
29554
|
-
.settings-connection-error-metadata {
|
|
29555
|
-
display: grid;
|
|
29556
|
-
gap: 7px;
|
|
29557
|
-
padding: 12px;
|
|
29558
|
-
background: var(--settings-inset);
|
|
29559
|
-
border: 1px solid var(--settings-border);
|
|
29560
|
-
border-radius: 9px;
|
|
29561
|
-
}
|
|
29562
|
-
|
|
29563
|
-
.settings-connection-detail-line {
|
|
29564
|
-
display: grid;
|
|
29565
|
-
grid-template-columns: 92px minmax(0, 1fr);
|
|
29566
|
-
gap: 10px;
|
|
29567
|
-
min-width: 0;
|
|
29568
|
-
color: var(--settings-muted);
|
|
29569
|
-
font-size: 10px;
|
|
29570
|
-
line-height: 16px;
|
|
29571
|
-
}
|
|
29572
|
-
|
|
29573
|
-
.settings-connection-detail-line code {
|
|
29574
|
-
min-width: 0;
|
|
29575
|
-
overflow-wrap: anywhere;
|
|
29576
|
-
color: var(--settings-text);
|
|
29577
|
-
font-family: ui-monospace, "SFMono-Regular", Consolas, "Liberation Mono", monospace;
|
|
29578
|
-
white-space: pre-wrap;
|
|
29579
|
-
}
|
|
29580
|
-
|
|
29581
31190
|
.settings-connection-error-log-header {
|
|
29582
31191
|
display: flex;
|
|
29583
31192
|
align-items: center;
|
|
@@ -30394,6 +32003,336 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
30394
32003
|
transition-duration: 0s !important;
|
|
30395
32004
|
}
|
|
30396
32005
|
}
|
|
32006
|
+
|
|
32007
|
+
.settings-remote {
|
|
32008
|
+
display: grid;
|
|
32009
|
+
gap: 14px;
|
|
32010
|
+
min-width: 0;
|
|
32011
|
+
}
|
|
32012
|
+
|
|
32013
|
+
.settings-remote__header {
|
|
32014
|
+
display: flex;
|
|
32015
|
+
align-items: flex-start;
|
|
32016
|
+
justify-content: space-between;
|
|
32017
|
+
gap: 18px;
|
|
32018
|
+
margin-bottom: 4px;
|
|
32019
|
+
}
|
|
32020
|
+
|
|
32021
|
+
.settings-remote__header .settings-section-label {
|
|
32022
|
+
padding-bottom: 0;
|
|
32023
|
+
}
|
|
32024
|
+
|
|
32025
|
+
.settings-remote__header .settings-page-description {
|
|
32026
|
+
margin: 5px 0 0;
|
|
32027
|
+
}
|
|
32028
|
+
|
|
32029
|
+
.settings-remote__meta {
|
|
32030
|
+
margin: 2px 0 0;
|
|
32031
|
+
color: var(--settings-subtle);
|
|
32032
|
+
font-size: 12px;
|
|
32033
|
+
line-height: 18px;
|
|
32034
|
+
font-variant-numeric: tabular-nums;
|
|
32035
|
+
}
|
|
32036
|
+
|
|
32037
|
+
.settings-remote__meta:empty {
|
|
32038
|
+
display: none;
|
|
32039
|
+
}
|
|
32040
|
+
|
|
32041
|
+
.settings-remote__toolbar,
|
|
32042
|
+
.settings-remote-card__actions {
|
|
32043
|
+
display: flex;
|
|
32044
|
+
align-items: center;
|
|
32045
|
+
flex: none;
|
|
32046
|
+
gap: 6px;
|
|
32047
|
+
}
|
|
32048
|
+
|
|
32049
|
+
.settings-remote__toolbar {
|
|
32050
|
+
gap: 8px;
|
|
32051
|
+
}
|
|
32052
|
+
|
|
32053
|
+
.settings-remote__banner {
|
|
32054
|
+
display: flex;
|
|
32055
|
+
align-items: center;
|
|
32056
|
+
justify-content: space-between;
|
|
32057
|
+
gap: 12px;
|
|
32058
|
+
padding: 8px 8px 8px 12px;
|
|
32059
|
+
color: var(--settings-danger);
|
|
32060
|
+
font-size: 12px;
|
|
32061
|
+
line-height: 18px;
|
|
32062
|
+
overflow-wrap: anywhere;
|
|
32063
|
+
background: var(--settings-danger-bg);
|
|
32064
|
+
border: 1px solid var(--settings-danger-border);
|
|
32065
|
+
border-radius: 10px;
|
|
32066
|
+
}
|
|
32067
|
+
|
|
32068
|
+
.settings-remote__loading {
|
|
32069
|
+
display: flex;
|
|
32070
|
+
align-items: center;
|
|
32071
|
+
gap: 8px;
|
|
32072
|
+
margin: 0;
|
|
32073
|
+
padding: 16px 2px;
|
|
32074
|
+
color: var(--settings-muted);
|
|
32075
|
+
font-size: 12px;
|
|
32076
|
+
}
|
|
32077
|
+
|
|
32078
|
+
.settings-remote__empty {
|
|
32079
|
+
display: flex;
|
|
32080
|
+
align-items: center;
|
|
32081
|
+
justify-content: space-between;
|
|
32082
|
+
gap: 16px;
|
|
32083
|
+
padding: 16px;
|
|
32084
|
+
background: var(--settings-panel);
|
|
32085
|
+
border: 1px dashed var(--settings-border);
|
|
32086
|
+
border-radius: 10px;
|
|
32087
|
+
}
|
|
32088
|
+
|
|
32089
|
+
.settings-remote__empty > div {
|
|
32090
|
+
display: grid;
|
|
32091
|
+
min-width: 0;
|
|
32092
|
+
gap: 2px;
|
|
32093
|
+
}
|
|
32094
|
+
|
|
32095
|
+
.settings-remote__empty strong {
|
|
32096
|
+
color: var(--settings-text);
|
|
32097
|
+
font-size: 13px;
|
|
32098
|
+
font-weight: 500;
|
|
32099
|
+
line-height: 19px;
|
|
32100
|
+
}
|
|
32101
|
+
|
|
32102
|
+
.settings-remote__empty span {
|
|
32103
|
+
color: var(--settings-muted);
|
|
32104
|
+
font-size: 12px;
|
|
32105
|
+
line-height: 18px;
|
|
32106
|
+
}
|
|
32107
|
+
|
|
32108
|
+
.settings-remote__list {
|
|
32109
|
+
display: grid;
|
|
32110
|
+
gap: 12px;
|
|
32111
|
+
}
|
|
32112
|
+
|
|
32113
|
+
.settings-remote__placeholder:empty,
|
|
32114
|
+
.settings-remote__list:empty {
|
|
32115
|
+
display: none;
|
|
32116
|
+
}
|
|
32117
|
+
|
|
32118
|
+
.settings-remote-card {
|
|
32119
|
+
min-width: 0;
|
|
32120
|
+
overflow: hidden;
|
|
32121
|
+
background: var(--settings-panel);
|
|
32122
|
+
border: 1px solid var(--settings-border);
|
|
32123
|
+
border-radius: 10px;
|
|
32124
|
+
}
|
|
32125
|
+
|
|
32126
|
+
.settings-remote-card__head {
|
|
32127
|
+
display: flex;
|
|
32128
|
+
align-items: center;
|
|
32129
|
+
gap: 12px;
|
|
32130
|
+
padding: 12px 10px 12px 14px;
|
|
32131
|
+
}
|
|
32132
|
+
|
|
32133
|
+
.settings-remote-card__identity {
|
|
32134
|
+
display: grid;
|
|
32135
|
+
flex: 1;
|
|
32136
|
+
min-width: 0;
|
|
32137
|
+
gap: 2px;
|
|
32138
|
+
}
|
|
32139
|
+
|
|
32140
|
+
.settings-remote-card__title {
|
|
32141
|
+
display: flex;
|
|
32142
|
+
align-items: center;
|
|
32143
|
+
min-width: 0;
|
|
32144
|
+
gap: 10px;
|
|
32145
|
+
}
|
|
32146
|
+
|
|
32147
|
+
.settings-remote-card h3 {
|
|
32148
|
+
min-width: 0;
|
|
32149
|
+
margin: 0;
|
|
32150
|
+
overflow: hidden;
|
|
32151
|
+
color: var(--settings-text);
|
|
32152
|
+
font-size: 13px;
|
|
32153
|
+
font-weight: 600;
|
|
32154
|
+
line-height: 20px;
|
|
32155
|
+
text-overflow: ellipsis;
|
|
32156
|
+
white-space: nowrap;
|
|
32157
|
+
}
|
|
32158
|
+
|
|
32159
|
+
.settings-remote-card__state {
|
|
32160
|
+
display: inline-flex;
|
|
32161
|
+
align-items: center;
|
|
32162
|
+
flex: none;
|
|
32163
|
+
gap: 6px;
|
|
32164
|
+
color: var(--settings-muted);
|
|
32165
|
+
font-size: 12px;
|
|
32166
|
+
line-height: 18px;
|
|
32167
|
+
}
|
|
32168
|
+
|
|
32169
|
+
.settings-remote-card__state::before {
|
|
32170
|
+
width: 7px;
|
|
32171
|
+
height: 7px;
|
|
32172
|
+
content: "";
|
|
32173
|
+
background: var(--settings-subtle);
|
|
32174
|
+
border-radius: 50%;
|
|
32175
|
+
}
|
|
32176
|
+
|
|
32177
|
+
.settings-remote-card__state[data-tone="success"]::before {
|
|
32178
|
+
background: var(--settings-success);
|
|
32179
|
+
}
|
|
32180
|
+
|
|
32181
|
+
.settings-remote-card__state[data-tone="danger"]::before {
|
|
32182
|
+
background: var(--settings-danger);
|
|
32183
|
+
}
|
|
32184
|
+
|
|
32185
|
+
.settings-remote-card__state[data-tone="progress"]::before {
|
|
32186
|
+
animation: settings-remote-pulse 1.2s ease-in-out infinite;
|
|
32187
|
+
}
|
|
32188
|
+
|
|
32189
|
+
.settings-remote-card__address {
|
|
32190
|
+
display: flex;
|
|
32191
|
+
align-items: center;
|
|
32192
|
+
min-width: 0;
|
|
32193
|
+
gap: 8px;
|
|
32194
|
+
overflow: hidden;
|
|
32195
|
+
color: var(--settings-muted);
|
|
32196
|
+
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
32197
|
+
font-size: 12px;
|
|
32198
|
+
line-height: 18px;
|
|
32199
|
+
text-overflow: ellipsis;
|
|
32200
|
+
white-space: nowrap;
|
|
32201
|
+
}
|
|
32202
|
+
|
|
32203
|
+
.settings-remote-card__address .settings-status-badge {
|
|
32204
|
+
padding: 0 6px;
|
|
32205
|
+
font-family: system-ui, sans-serif;
|
|
32206
|
+
}
|
|
32207
|
+
|
|
32208
|
+
.settings-remote-card__actions {
|
|
32209
|
+
flex-wrap: wrap;
|
|
32210
|
+
justify-content: flex-end;
|
|
32211
|
+
}
|
|
32212
|
+
|
|
32213
|
+
.settings-remote-card__remove:hover:not(:disabled) {
|
|
32214
|
+
color: var(--settings-danger);
|
|
32215
|
+
background: var(--settings-danger-bg);
|
|
32216
|
+
}
|
|
32217
|
+
|
|
32218
|
+
.settings-remote .settings-icon-button:disabled {
|
|
32219
|
+
cursor: not-allowed;
|
|
32220
|
+
opacity: 0.55;
|
|
32221
|
+
}
|
|
32222
|
+
|
|
32223
|
+
.settings-remote-card__detail {
|
|
32224
|
+
margin: -4px 14px 12px;
|
|
32225
|
+
font-size: 12px;
|
|
32226
|
+
line-height: 18px;
|
|
32227
|
+
overflow-wrap: anywhere;
|
|
32228
|
+
}
|
|
32229
|
+
|
|
32230
|
+
.settings-remote-card__service {
|
|
32231
|
+
display: flex;
|
|
32232
|
+
align-items: center;
|
|
32233
|
+
justify-content: space-between;
|
|
32234
|
+
gap: 12px;
|
|
32235
|
+
padding: 10px 10px 10px 14px;
|
|
32236
|
+
background: var(--settings-surface);
|
|
32237
|
+
border-top: 1px solid var(--settings-divider);
|
|
32238
|
+
}
|
|
32239
|
+
|
|
32240
|
+
.settings-remote-card__service-copy {
|
|
32241
|
+
display: grid;
|
|
32242
|
+
min-width: 0;
|
|
32243
|
+
gap: 2px;
|
|
32244
|
+
font-size: 12px;
|
|
32245
|
+
line-height: 18px;
|
|
32246
|
+
}
|
|
32247
|
+
|
|
32248
|
+
.settings-remote-card__service-title {
|
|
32249
|
+
color: var(--settings-text);
|
|
32250
|
+
font-weight: 500;
|
|
32251
|
+
font-variant-numeric: tabular-nums;
|
|
32252
|
+
}
|
|
32253
|
+
|
|
32254
|
+
.settings-remote-card__hint {
|
|
32255
|
+
display: flex;
|
|
32256
|
+
align-items: center;
|
|
32257
|
+
gap: 6px;
|
|
32258
|
+
margin: 0;
|
|
32259
|
+
color: var(--settings-muted);
|
|
32260
|
+
overflow-wrap: anywhere;
|
|
32261
|
+
}
|
|
32262
|
+
|
|
32263
|
+
.settings-remote [data-tone="success"] {
|
|
32264
|
+
color: var(--settings-success);
|
|
32265
|
+
}
|
|
32266
|
+
|
|
32267
|
+
.settings-remote [data-tone="warning"] {
|
|
32268
|
+
color: var(--settings-warning);
|
|
32269
|
+
}
|
|
32270
|
+
|
|
32271
|
+
.settings-remote [data-tone="danger"] {
|
|
32272
|
+
color: var(--settings-danger);
|
|
32273
|
+
}
|
|
32274
|
+
|
|
32275
|
+
.settings-remote-spinner {
|
|
32276
|
+
width: 12px;
|
|
32277
|
+
height: 12px;
|
|
32278
|
+
flex: none;
|
|
32279
|
+
border: 1.5px solid var(--settings-border);
|
|
32280
|
+
border-top-color: var(--settings-muted);
|
|
32281
|
+
border-radius: 50%;
|
|
32282
|
+
animation: settings-remote-spin 0.8s linear infinite;
|
|
32283
|
+
}
|
|
32284
|
+
|
|
32285
|
+
.settings-remote__refresh[aria-busy="true"] svg {
|
|
32286
|
+
animation: settings-remote-spin 0.8s linear infinite;
|
|
32287
|
+
}
|
|
32288
|
+
|
|
32289
|
+
.settings-remote-dialog .settings-credential-dialog__field small {
|
|
32290
|
+
color: var(--settings-subtle);
|
|
32291
|
+
font-size: 11px;
|
|
32292
|
+
line-height: 16px;
|
|
32293
|
+
}
|
|
32294
|
+
|
|
32295
|
+
.settings-remote-dialog input:disabled {
|
|
32296
|
+
color: var(--settings-muted);
|
|
32297
|
+
cursor: not-allowed;
|
|
32298
|
+
}
|
|
32299
|
+
|
|
32300
|
+
.settings-remote-dialog input:focus-visible {
|
|
32301
|
+
border-color: var(--settings-focus);
|
|
32302
|
+
outline-offset: -1px;
|
|
32303
|
+
}
|
|
32304
|
+
|
|
32305
|
+
@keyframes settings-remote-spin {
|
|
32306
|
+
to {
|
|
32307
|
+
transform: rotate(360deg);
|
|
32308
|
+
}
|
|
32309
|
+
}
|
|
32310
|
+
|
|
32311
|
+
@keyframes settings-remote-pulse {
|
|
32312
|
+
50% {
|
|
32313
|
+
opacity: 0.3;
|
|
32314
|
+
}
|
|
32315
|
+
}
|
|
32316
|
+
|
|
32317
|
+
@container (max-width: 620px) {
|
|
32318
|
+
.settings-remote-card__head,
|
|
32319
|
+
.settings-remote-card__service {
|
|
32320
|
+
align-items: stretch;
|
|
32321
|
+
flex-direction: column;
|
|
32322
|
+
}
|
|
32323
|
+
|
|
32324
|
+
.settings-remote-card__actions {
|
|
32325
|
+
justify-content: flex-start;
|
|
32326
|
+
}
|
|
32327
|
+
}
|
|
32328
|
+
|
|
32329
|
+
@media (prefers-reduced-motion: reduce) {
|
|
32330
|
+
.settings-remote-spinner,
|
|
32331
|
+
.settings-remote__refresh svg,
|
|
32332
|
+
.settings-remote-card__state::before {
|
|
32333
|
+
animation: none !important;
|
|
32334
|
+
}
|
|
32335
|
+
}
|
|
30397
32336
|
`;
|
|
30398
32337
|
|
|
30399
32338
|
// src/settings/accounts.css
|
|
@@ -31139,7 +33078,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
31139
33078
|
`;
|
|
31140
33079
|
|
|
31141
33080
|
// src/settings/tailwind.css
|
|
31142
|
-
var tailwind_default = '@layer properties, theme, base, components, utilities;\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-content:"";--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}@layer theme{:root,:host{--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.relative{position:relative}.top-full{top:100%}.left-0{left:0}.z-20{z-index:20}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:0}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-7{margin-top:calc(var(--spacing) * 7)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-16{margin-top:calc(var(--spacing) * 16)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-1{margin-left:var(--spacing)}.ml-\\[45px\\]{margin-left:45px}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.list-item{display:list-item}.table{display:table}.size-1\\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-8{height:calc(var(--spacing) * 8)}.min-h-6{min-height:calc(var(--spacing) * 6)}.min-h-\\[60px\\]{min-height:60px}.w-9{width:calc(var(--spacing) * 9)}.w-14{width:calc(var(--spacing) * 14)}.w-80{width:calc(var(--spacing) * 80)}.w-full{width:100%}.w-px{width:1px}.max-w-64{max-width:calc(var(--spacing) * 64)}.min-w-0{min-width:0}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-help{cursor:help}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-disc{list-style-type:disc}.appearance-none{appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}.overflow-x-auto{overflow-x:auto}.rounded-\\[10px\\]{border-radius:10px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-settings-border{border-color:var(--settings-border)}.border-settings-divider{border-color:var(--settings-divider)}.bg-settings-panel{background-color:var(--settings-panel)}.bg-settings-subtle{background-color:var(--settings-subtle)}.bg-settings-surface{background-color:var(--settings-surface)}.bg-settings-surface-hover{background-color:var(--settings-surface-hover)}.bg-transparent{background-color:#0000}.p-0{padding:0}.p-4{padding:calc(var(--spacing) * 4)}.\\!px-0{padding-inline:0!important}.px-1{padding-inline:var(--spacing)}.px-2\\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pl-4{padding-left:calc(var(--spacing) * 4)}.\\!text-right{text-align:right!important}.text-left{text-align:left}.text-right{text-align:right}.align-top{vertical-align:top}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[11px\\]{font-size:11px}.text-\\[13px\\]{font-size:13px}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-7{--tw-leading:calc(var(--spacing) * 7);line-height:calc(var(--spacing) * 7)}.leading-\\[18px\\]{--tw-leading:18px;line-height:18px}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.text-wrap{text-wrap:wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-pre-wrap{white-space:pre-wrap}.text-settings-muted{color:var(--settings-muted)}.text-settings-subtle{color:var(--settings-subtle)}.text-settings-text{color:var(--settings-text)}.lowercase{text-transform:lowercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.opacity-0{opacity:0}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\\[0_10px_30px_rgb\\(0_0_0\\/0\\.22\\)\\]{--tw-shadow:0 10px 30px var(--tw-shadow-color,#00000038);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring,.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-settings-border{--tw-ring-color:var(--settings-border)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.outline-none{--tw-outline-style:none;outline-style:none}.ring-inset{--tw-ring-inset:inset}.group-focus-within\\:visible:is(:where(.group):focus-within *){visibility:visible}.group-focus-within\\:opacity-100:is(:where(.group):focus-within *){opacity:1}@media (hover:hover){.group-hover\\:visible:is(:where(.group):hover *){visibility:visible}.group-hover\\:opacity-100:is(:where(.group):hover *){opacity:1}}.group-data-\\[state\\=failed\\]\\/status\\:bg-settings-danger:is(:where(.group\\/status)[data-state=failed] *){background-color:var(--settings-danger)}.group-data-\\[state\\=unavailable\\]\\/status\\:bg-settings-warning:is(:where(.group\\/status)[data-state=unavailable] *){background-color:var(--settings-warning)}.marker\\:text-settings-subtle ::marker{color:var(--settings-subtle)}.marker\\:text-settings-subtle::marker{color:var(--settings-subtle)}.marker\\:text-settings-subtle ::-webkit-details-marker{color:var(--settings-subtle)}.marker\\:text-settings-subtle::-webkit-details-marker{color:var(--settings-subtle)}.before\\:absolute:before{content:var(--tw-content);position:absolute}.before\\:top-0\\.5:before{content:var(--tw-content);top:calc(var(--spacing) * .5)}.before\\:left-0\\.5:before{content:var(--tw-content);left:calc(var(--spacing) * .5)}.before\\:size-4:before{content:var(--tw-content);width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.before\\:rounded-full:before{content:var(--tw-content);border-radius:3.40282e38px}.before\\:bg-white:before{content:var(--tw-content);background-color:#fff}.before\\:shadow-\\[0_1px_2px_rgb\\(0_0_0\\/0\\.3\\)\\]:before{content:var(--tw-content);--tw-shadow:0 1px 2px var(--tw-shadow-color,#0000004d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.before\\:transition-transform:before{content:var(--tw-content);transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.first\\:border-t-0:first-child{border-top-style:var(--tw-border-style);border-top-width:0}.first-of-type\\:mt-0:first-of-type{margin-top:0}.checked\\:bg-settings-focus:checked{background-color:var(--settings-focus)}.checked\\:ring-transparent:checked{--tw-ring-color:transparent}.checked\\:before\\:translate-x-4:checked:before{content:var(--tw-content);--tw-translate-x:calc(var(--spacing) * 4);translate:var(--tw-translate-x) var(--tw-translate-y)}.focus-within\\:border-settings-focus:focus-within{border-color:var(--settings-focus)}@media (hover:hover){.hover\\:text-settings-text:hover{color:var(--settings-text)}}.focus-visible\\:text-settings-text:focus-visible{color:var(--settings-text)}.focus-visible\\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\\:outline-settings-focus:focus-visible{outline-color:var(--settings-focus)}.data-\\[invalid\\=true\\]\\:border-settings-danger[data-invalid=true]{border-color:var(--settings-danger)}.data-\\[invalid\\=true\\]\\:text-settings-danger[data-invalid=true],.data-\\[state\\=failed\\]\\:text-settings-danger[data-state=failed]{color:var(--settings-danger)}.data-\\[state\\=unavailable\\]\\:text-settings-warning[data-state=unavailable]{color:var(--settings-warning)}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@layer properties{\n *, ::before, ::after, ::backdrop{--tw-border-style:solid;--tw-shadow:0 0 #0000;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-alpha:100%;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-offset-width:0;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-drop-shadow-alpha:100%;--tw-content:"";--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}\n';
|
|
33081
|
+
var tailwind_default = '@layer properties, theme, base, components, utilities;\n/*! tailwindcss v4.3.3 | MIT License | https://tailwindcss.com */\n@layer properties{@supports (((-webkit-hyphens:none)) and (not (margin-trim:inline))) or ((-moz-orient:inline) and (not (color:rgb(from red r g b)))){*,:before,:after,::backdrop{--tw-rotate-x:initial;--tw-rotate-y:initial;--tw-rotate-z:initial;--tw-skew-x:initial;--tw-skew-y:initial;--tw-border-style:solid;--tw-leading:initial;--tw-font-weight:initial;--tw-tracking:initial;--tw-ordinal:initial;--tw-slashed-zero:initial;--tw-numeric-figure:initial;--tw-numeric-spacing:initial;--tw-numeric-fraction:initial;--tw-shadow:0 0 #0000;--tw-shadow-color:initial;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-color:initial;--tw-inset-shadow-alpha:100%;--tw-ring-color:initial;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-color:initial;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-inset:initial;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-blur:initial;--tw-brightness:initial;--tw-contrast:initial;--tw-grayscale:initial;--tw-hue-rotate:initial;--tw-invert:initial;--tw-opacity:initial;--tw-saturate:initial;--tw-sepia:initial;--tw-drop-shadow:initial;--tw-drop-shadow-color:initial;--tw-drop-shadow-alpha:100%;--tw-drop-shadow-size:initial;--tw-backdrop-blur:initial;--tw-backdrop-brightness:initial;--tw-backdrop-contrast:initial;--tw-backdrop-grayscale:initial;--tw-backdrop-hue-rotate:initial;--tw-backdrop-invert:initial;--tw-backdrop-opacity:initial;--tw-backdrop-saturate:initial;--tw-backdrop-sepia:initial;--tw-duration:initial;--tw-content:"";--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}}@layer theme{:root,:host{--spacing:.25rem;--text-xs:.75rem;--text-xs--line-height:calc(1 / .75);--text-sm:.875rem;--text-sm--line-height:calc(1.25 / .875);--text-base:1rem;--text-base--line-height:calc(1.5 / 1);--text-xl:1.25rem;--text-xl--line-height:calc(1.75 / 1.25);--font-weight-normal:400;--font-weight-medium:500;--font-weight-semibold:600;--tracking-tight:-.025em;--leading-relaxed:1.625;--radius-md:.375rem;--radius-lg:.5rem;--default-transition-duration:.15s;--default-transition-timing-function:cubic-bezier(.4, 0, .2, 1)}}@layer utilities{.pointer-events-none{pointer-events:none}.collapse{visibility:collapse}.invisible{visibility:hidden}.visible{visibility:visible}.sr-only{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.absolute{position:absolute}.fixed{position:fixed}.relative{position:relative}.top-full{top:100%}.left-0{left:0}.z-20{z-index:20}.container{width:100%}@media (min-width:40rem){.container{max-width:40rem}}@media (min-width:48rem){.container{max-width:48rem}}@media (min-width:64rem){.container{max-width:64rem}}@media (min-width:80rem){.container{max-width:80rem}}@media (min-width:96rem){.container{max-width:96rem}}.m-0{margin:0}.mx-2{margin-inline:calc(var(--spacing) * 2)}.mt-1{margin-top:var(--spacing)}.mt-2{margin-top:calc(var(--spacing) * 2)}.mt-3{margin-top:calc(var(--spacing) * 3)}.mt-4{margin-top:calc(var(--spacing) * 4)}.mt-5{margin-top:calc(var(--spacing) * 5)}.mt-7{margin-top:calc(var(--spacing) * 7)}.mt-8{margin-top:calc(var(--spacing) * 8)}.mt-16{margin-top:calc(var(--spacing) * 16)}.mb-2{margin-bottom:calc(var(--spacing) * 2)}.mb-3{margin-bottom:calc(var(--spacing) * 3)}.mb-4{margin-bottom:calc(var(--spacing) * 4)}.ml-1{margin-left:var(--spacing)}.ml-\\[45px\\]{margin-left:45px}.ml-auto{margin-left:auto}.block{display:block}.flex{display:flex}.grid{display:grid}.hidden{display:none}.inline{display:inline}.inline-flex{display:inline-flex}.list-item{display:list-item}.table{display:table}.size-1\\.5{width:calc(var(--spacing) * 1.5);height:calc(var(--spacing) * 1.5)}.size-4{width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.h-5{height:calc(var(--spacing) * 5)}.h-8{height:calc(var(--spacing) * 8)}.min-h-6{min-height:calc(var(--spacing) * 6)}.min-h-\\[60px\\]{min-height:60px}.w-9{width:calc(var(--spacing) * 9)}.w-14{width:calc(var(--spacing) * 14)}.w-80{width:calc(var(--spacing) * 80)}.w-full{width:100%}.w-px{width:1px}.max-w-64{max-width:calc(var(--spacing) * 64)}.min-w-0{min-width:0}.flex-shrink{flex-shrink:1}.shrink-0{flex-shrink:0}.border-collapse{border-collapse:collapse}.transform{transform:var(--tw-rotate-x,) var(--tw-rotate-y,) var(--tw-rotate-z,) var(--tw-skew-x,) var(--tw-skew-y,)}.cursor-help{cursor:help}.cursor-pointer{cursor:pointer}.resize{resize:both}.list-disc{list-style-type:disc}.appearance-none{appearance:none}.flex-col{flex-direction:column}.flex-wrap{flex-wrap:wrap}.items-center{align-items:center}.items-start{align-items:flex-start}.justify-between{justify-content:space-between}.justify-center{justify-content:center}.gap-0\\.5{gap:calc(var(--spacing) * .5)}.gap-1{gap:var(--spacing)}.gap-1\\.5{gap:calc(var(--spacing) * 1.5)}.gap-2{gap:calc(var(--spacing) * 2)}.gap-3{gap:calc(var(--spacing) * 3)}.gap-4{gap:calc(var(--spacing) * 4)}.gap-5{gap:calc(var(--spacing) * 5)}.gap-6{gap:calc(var(--spacing) * 6)}.overflow-x-auto{overflow-x:auto}.rounded-\\[10px\\]{border-radius:10px}.rounded-full{border-radius:3.40282e38px}.rounded-lg{border-radius:var(--radius-lg)}.rounded-md{border-radius:var(--radius-md)}.border{border-style:var(--tw-border-style);border-width:1px}.border-0{border-style:var(--tw-border-style);border-width:0}.border-t{border-top-style:var(--tw-border-style);border-top-width:1px}.border-b{border-bottom-style:var(--tw-border-style);border-bottom-width:1px}.border-settings-border{border-color:var(--settings-border)}.border-settings-divider{border-color:var(--settings-divider)}.bg-settings-panel{background-color:var(--settings-panel)}.bg-settings-subtle{background-color:var(--settings-subtle)}.bg-settings-surface{background-color:var(--settings-surface)}.bg-settings-surface-hover{background-color:var(--settings-surface-hover)}.bg-transparent{background-color:#0000}.p-0{padding:0}.p-4{padding:calc(var(--spacing) * 4)}.\\!px-0{padding-inline:0!important}.px-1{padding-inline:var(--spacing)}.px-2\\.5{padding-inline:calc(var(--spacing) * 2.5)}.px-3{padding-inline:calc(var(--spacing) * 3)}.px-4{padding-inline:calc(var(--spacing) * 4)}.py-2{padding-block:calc(var(--spacing) * 2)}.py-2\\.5{padding-block:calc(var(--spacing) * 2.5)}.py-3{padding-block:calc(var(--spacing) * 3)}.pt-4{padding-top:calc(var(--spacing) * 4)}.pl-4{padding-left:calc(var(--spacing) * 4)}.\\!text-right{text-align:right!important}.text-left{text-align:left}.text-right{text-align:right}.align-top{vertical-align:top}.text-base{font-size:var(--text-base);line-height:var(--tw-leading,var(--text-base--line-height))}.text-sm{font-size:var(--text-sm);line-height:var(--tw-leading,var(--text-sm--line-height))}.text-xl{font-size:var(--text-xl);line-height:var(--tw-leading,var(--text-xl--line-height))}.text-xs{font-size:var(--text-xs);line-height:var(--tw-leading,var(--text-xs--line-height))}.text-\\[11px\\]{font-size:11px}.text-\\[13px\\]{font-size:13px}.leading-5{--tw-leading:calc(var(--spacing) * 5);line-height:calc(var(--spacing) * 5)}.leading-7{--tw-leading:calc(var(--spacing) * 7);line-height:calc(var(--spacing) * 7)}.leading-\\[18px\\]{--tw-leading:18px;line-height:18px}.leading-relaxed{--tw-leading:var(--leading-relaxed);line-height:var(--leading-relaxed)}.font-medium{--tw-font-weight:var(--font-weight-medium);font-weight:var(--font-weight-medium)}.font-normal{--tw-font-weight:var(--font-weight-normal);font-weight:var(--font-weight-normal)}.font-semibold{--tw-font-weight:var(--font-weight-semibold);font-weight:var(--font-weight-semibold)}.tracking-tight{--tw-tracking:var(--tracking-tight);letter-spacing:var(--tracking-tight)}.text-wrap{text-wrap:wrap}.break-words{overflow-wrap:break-word}.break-all{word-break:break-all}.whitespace-pre-wrap{white-space:pre-wrap}.text-settings-muted{color:var(--settings-muted)}.text-settings-subtle{color:var(--settings-subtle)}.text-settings-text{color:var(--settings-text)}.lowercase{text-transform:lowercase}.tabular-nums{--tw-numeric-spacing:tabular-nums;font-variant-numeric:var(--tw-ordinal,) var(--tw-slashed-zero,) var(--tw-numeric-figure,) var(--tw-numeric-spacing,) var(--tw-numeric-fraction,)}.opacity-0{opacity:0}.shadow{--tw-shadow:0 1px 3px 0 var(--tw-shadow-color,#0000001a), 0 1px 2px -1px var(--tw-shadow-color,#0000001a);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.shadow-\\[0_10px_30px_rgb\\(0_0_0\\/0\\.22\\)\\]{--tw-shadow:0 10px 30px var(--tw-shadow-color,#00000038);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring,.ring-1{--tw-ring-shadow:var(--tw-ring-inset,) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.ring-settings-border{--tw-ring-color:var(--settings-border)}.outline{outline-style:var(--tw-outline-style);outline-width:1px}.filter{filter:var(--tw-blur,) var(--tw-brightness,) var(--tw-contrast,) var(--tw-grayscale,) var(--tw-hue-rotate,) var(--tw-invert,) var(--tw-saturate,) var(--tw-sepia,) var(--tw-drop-shadow,)}.backdrop-filter{-webkit-backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,);backdrop-filter:var(--tw-backdrop-blur,) var(--tw-backdrop-brightness,) var(--tw-backdrop-contrast,) var(--tw-backdrop-grayscale,) var(--tw-backdrop-hue-rotate,) var(--tw-backdrop-invert,) var(--tw-backdrop-opacity,) var(--tw-backdrop-saturate,) var(--tw-backdrop-sepia,)}.transition{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to,opacity,box-shadow,transform,translate,scale,rotate,filter,-webkit-backdrop-filter,backdrop-filter,display,content-visibility,overlay,pointer-events;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-colors{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.transition-opacity{transition-property:opacity;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.duration-150{--tw-duration:.15s;transition-duration:.15s}.outline-none{--tw-outline-style:none;outline-style:none}.ring-inset{--tw-ring-inset:inset}.group-focus-within\\:visible:is(:where(.group):focus-within *){visibility:visible}.group-focus-within\\:opacity-100:is(:where(.group):focus-within *){opacity:1}@media (hover:hover){.group-hover\\:visible:is(:where(.group):hover *){visibility:visible}.group-hover\\:opacity-100:is(:where(.group):hover *){opacity:1}}.group-data-\\[state\\=failed\\]\\/status\\:bg-settings-danger:is(:where(.group\\/status)[data-state=failed] *){background-color:var(--settings-danger)}.group-data-\\[state\\=unavailable\\]\\/status\\:bg-settings-warning:is(:where(.group\\/status)[data-state=unavailable] *){background-color:var(--settings-warning)}.marker\\:text-settings-subtle ::marker{color:var(--settings-subtle)}.marker\\:text-settings-subtle::marker{color:var(--settings-subtle)}.marker\\:text-settings-subtle ::-webkit-details-marker{color:var(--settings-subtle)}.marker\\:text-settings-subtle::-webkit-details-marker{color:var(--settings-subtle)}.before\\:absolute:before{content:var(--tw-content);position:absolute}.before\\:top-0\\.5:before{content:var(--tw-content);top:calc(var(--spacing) * .5)}.before\\:left-0\\.5:before{content:var(--tw-content);left:calc(var(--spacing) * .5)}.before\\:size-4:before{content:var(--tw-content);width:calc(var(--spacing) * 4);height:calc(var(--spacing) * 4)}.before\\:rounded-full:before{content:var(--tw-content);border-radius:3.40282e38px}.before\\:bg-white:before{content:var(--tw-content);background-color:#fff}.before\\:shadow-\\[0_1px_2px_rgb\\(0_0_0\\/0\\.3\\)\\]:before{content:var(--tw-content);--tw-shadow:0 1px 2px var(--tw-shadow-color,#0000004d);box-shadow:var(--tw-inset-shadow), var(--tw-inset-ring-shadow), var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow)}.before\\:transition-transform:before{content:var(--tw-content);transition-property:transform,translate,scale,rotate;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function));transition-duration:var(--tw-duration,var(--default-transition-duration))}.first\\:border-t-0:first-child{border-top-style:var(--tw-border-style);border-top-width:0}.first-of-type\\:mt-0:first-of-type{margin-top:0}.checked\\:bg-settings-focus:checked{background-color:var(--settings-focus)}.checked\\:ring-transparent:checked{--tw-ring-color:transparent}.checked\\:before\\:translate-x-4:checked:before{content:var(--tw-content);--tw-translate-x:calc(var(--spacing) * 4);translate:var(--tw-translate-x) var(--tw-translate-y)}.focus-within\\:border-settings-focus:focus-within{border-color:var(--settings-focus)}@media (hover:hover){.hover\\:text-settings-text:hover{color:var(--settings-text)}}.focus-visible\\:text-settings-text:focus-visible{color:var(--settings-text)}.focus-visible\\:outline-2:focus-visible{outline-style:var(--tw-outline-style);outline-width:2px}.focus-visible\\:outline-offset-2:focus-visible{outline-offset:2px}.focus-visible\\:outline-settings-focus:focus-visible{outline-color:var(--settings-focus)}.data-\\[invalid\\=true\\]\\:border-settings-danger[data-invalid=true]{border-color:var(--settings-danger)}.data-\\[invalid\\=true\\]\\:text-settings-danger[data-invalid=true],.data-\\[state\\=failed\\]\\:text-settings-danger[data-state=failed]{color:var(--settings-danger)}.data-\\[state\\=unavailable\\]\\:text-settings-warning[data-state=unavailable]{color:var(--settings-warning)}}@property --tw-rotate-x{syntax:"*";inherits:false}@property --tw-rotate-y{syntax:"*";inherits:false}@property --tw-rotate-z{syntax:"*";inherits:false}@property --tw-skew-x{syntax:"*";inherits:false}@property --tw-skew-y{syntax:"*";inherits:false}@property --tw-border-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-leading{syntax:"*";inherits:false}@property --tw-font-weight{syntax:"*";inherits:false}@property --tw-tracking{syntax:"*";inherits:false}@property --tw-ordinal{syntax:"*";inherits:false}@property --tw-slashed-zero{syntax:"*";inherits:false}@property --tw-numeric-figure{syntax:"*";inherits:false}@property --tw-numeric-spacing{syntax:"*";inherits:false}@property --tw-numeric-fraction{syntax:"*";inherits:false}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-outline-style{syntax:"*";inherits:false;initial-value:solid}@property --tw-blur{syntax:"*";inherits:false}@property --tw-brightness{syntax:"*";inherits:false}@property --tw-contrast{syntax:"*";inherits:false}@property --tw-grayscale{syntax:"*";inherits:false}@property --tw-hue-rotate{syntax:"*";inherits:false}@property --tw-invert{syntax:"*";inherits:false}@property --tw-opacity{syntax:"*";inherits:false}@property --tw-saturate{syntax:"*";inherits:false}@property --tw-sepia{syntax:"*";inherits:false}@property --tw-drop-shadow{syntax:"*";inherits:false}@property --tw-drop-shadow-color{syntax:"*";inherits:false}@property --tw-drop-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-drop-shadow-size{syntax:"*";inherits:false}@property --tw-backdrop-blur{syntax:"*";inherits:false}@property --tw-backdrop-brightness{syntax:"*";inherits:false}@property --tw-backdrop-contrast{syntax:"*";inherits:false}@property --tw-backdrop-grayscale{syntax:"*";inherits:false}@property --tw-backdrop-hue-rotate{syntax:"*";inherits:false}@property --tw-backdrop-invert{syntax:"*";inherits:false}@property --tw-backdrop-opacity{syntax:"*";inherits:false}@property --tw-backdrop-saturate{syntax:"*";inherits:false}@property --tw-backdrop-sepia{syntax:"*";inherits:false}@property --tw-duration{syntax:"*";inherits:false}@property --tw-content{syntax:"*";inherits:false;initial-value:""}@property --tw-translate-x{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-y{syntax:"*";inherits:false;initial-value:0}@property --tw-translate-z{syntax:"*";inherits:false;initial-value:0}@layer properties{\n *, ::before, ::after, ::backdrop{--tw-border-style:solid;--tw-shadow:0 0 #0000;--tw-shadow-alpha:100%;--tw-inset-shadow:0 0 #0000;--tw-inset-shadow-alpha:100%;--tw-ring-shadow:0 0 #0000;--tw-inset-ring-shadow:0 0 #0000;--tw-ring-offset-width:0;--tw-ring-offset-color:#fff;--tw-ring-offset-shadow:0 0 #0000;--tw-outline-style:solid;--tw-drop-shadow-alpha:100%;--tw-content:"";--tw-translate-x:0;--tw-translate-y:0;--tw-translate-z:0}}\n';
|
|
31143
33082
|
|
|
31144
33083
|
// src/settings/trigger.ts
|
|
31145
33084
|
var SETTINGS_TRIGGER_ATTRIBUTE = "data-codexhost-settings-trigger";
|
|
@@ -31717,7 +33656,8 @@ ${accounts_default}`;
|
|
|
31717
33656
|
await options.openImportedThread(threadId, signal);
|
|
31718
33657
|
if (!disposed && !signal.aborted) shell?.close();
|
|
31719
33658
|
},
|
|
31720
|
-
options.getLoadedSessionsClient ?? (() => null)
|
|
33659
|
+
options.getLoadedSessionsClient ?? (() => null),
|
|
33660
|
+
options.getRemoteConnections ?? (() => null)
|
|
31721
33661
|
);
|
|
31722
33662
|
const nextShell = installRendererSettingsShell(definitions, messages, ownerWindow.document, {
|
|
31723
33663
|
onOpenChange(open) {
|
|
@@ -32260,7 +34200,7 @@ ${accounts_default}`;
|
|
|
32260
34200
|
openedFor = { node: trigger.node, start: trigger.start };
|
|
32261
34201
|
options.onOpen?.(trigger.editor);
|
|
32262
34202
|
}
|
|
32263
|
-
const allTargets = options.readTargets();
|
|
34203
|
+
const allTargets = options.readTargets(trigger.editor);
|
|
32264
34204
|
syncChipStyle(ownerDocument, allTargets, iconCache);
|
|
32265
34205
|
const targets = filterDelegationTargets(allTargets, trigger.query);
|
|
32266
34206
|
const source = options.readCommands(trigger.editor);
|
|
@@ -32438,7 +34378,8 @@ ${accounts_default}`;
|
|
|
32438
34378
|
hermes: harnessIdSchema.parse("hermes"),
|
|
32439
34379
|
qoder: harnessIdSchema.parse("qoder"),
|
|
32440
34380
|
"qoder-cn": harnessIdSchema.parse("qoder-cn"),
|
|
32441
|
-
"kimi-code": harnessIdSchema.parse("kimi-code")
|
|
34381
|
+
"kimi-code": harnessIdSchema.parse("kimi-code"),
|
|
34382
|
+
zcode: harnessIdSchema.parse("zcode")
|
|
32442
34383
|
};
|
|
32443
34384
|
var externalAgents = [
|
|
32444
34385
|
"pi",
|
|
@@ -32455,7 +34396,8 @@ ${accounts_default}`;
|
|
|
32455
34396
|
"hermes",
|
|
32456
34397
|
"qoder",
|
|
32457
34398
|
"qoder-cn",
|
|
32458
|
-
"kimi-code"
|
|
34399
|
+
"kimi-code",
|
|
34400
|
+
"zcode"
|
|
32459
34401
|
];
|
|
32460
34402
|
function isRetryableHarnessAvailability(availability, error51) {
|
|
32461
34403
|
return availability !== void 0 && availability !== "ready" && availability !== "notInstalled" && error51?.retryable === true;
|
|
@@ -32477,8 +34419,13 @@ ${accounts_default}`;
|
|
|
32477
34419
|
return state === "ready";
|
|
32478
34420
|
}
|
|
32479
34421
|
var rendererUsageRefreshDelays = [250, 500, 1e3, 2e3, 4e3, 8e3];
|
|
32480
|
-
function refreshConnectionHosts(hostIds, refreshHost) {
|
|
32481
|
-
return Promise.all(
|
|
34422
|
+
function refreshConnectionHosts(hostIds, refreshHost, pendingHost) {
|
|
34423
|
+
return Promise.all(
|
|
34424
|
+
[...hostIds].map(async (hostId) => {
|
|
34425
|
+
if (pendingHost) await pendingHost(hostId)?.catch(() => void 0);
|
|
34426
|
+
await refreshHost(hostId);
|
|
34427
|
+
})
|
|
34428
|
+
).then(() => void 0);
|
|
32482
34429
|
}
|
|
32483
34430
|
function rendererUsageRefreshDelay(attempt) {
|
|
32484
34431
|
const index = Math.max(0, Math.min(Math.trunc(attempt), rendererUsageRefreshDelays.length - 1));
|
|
@@ -32663,10 +34610,10 @@ ${accounts_default}`;
|
|
|
32663
34610
|
...permissionModeId ? { permissionModeId } : {}
|
|
32664
34611
|
};
|
|
32665
34612
|
}
|
|
32666
|
-
if (inspection.harnessId === "kimi-code") {
|
|
34613
|
+
if (inspection.harnessId === "kimi-code" || inspection.harnessId === "zcode") {
|
|
32667
34614
|
const route = decodeHarnessPluginRoute(inspection.transportModelId);
|
|
32668
34615
|
if (!route || route.harnessId !== inspection.harnessId) {
|
|
32669
|
-
throw new Error(
|
|
34616
|
+
throw new Error(`${inspection.harnessId} Thread reported an incompatible transport Model`);
|
|
32670
34617
|
}
|
|
32671
34618
|
const model = inspection.effectiveModel ?? route.model;
|
|
32672
34619
|
const thinkingOptionId = inspection.availableThinkingOptions !== void 0 ? selectableThinkingOptionId(inspection) : inspection.effectiveThinkingOptionId ?? route.thinkingOptionId;
|
|
@@ -32772,19 +34719,23 @@ ${accounts_default}`;
|
|
|
32772
34719
|
let adapterDispose = null;
|
|
32773
34720
|
let applyAdapterAgent = null;
|
|
32774
34721
|
let modelControl = null;
|
|
32775
|
-
const activeModelHostId = () => {
|
|
34722
|
+
const activeModelHostId = (composer) => {
|
|
32776
34723
|
if (!modelControl) return null;
|
|
32777
|
-
return modelControl.currentHostId ? modelControl.currentHostId() : "local";
|
|
34724
|
+
return modelControl.currentHostId ? modelControl.currentHostId(composer) : "local";
|
|
32778
34725
|
};
|
|
32779
34726
|
const controllerTarget = (target, hostId) => scopedComposerTarget(target, hostId);
|
|
32780
|
-
|
|
34727
|
+
const usageSubscriptions = /* @__PURE__ */ new Map();
|
|
34728
|
+
const usageNotificationDispose = () => {
|
|
34729
|
+
for (const subscription of usageSubscriptions.values()) subscription.dispose();
|
|
34730
|
+
usageSubscriptions.clear();
|
|
34731
|
+
};
|
|
32781
34732
|
const localAgentForSidebarThread = (input) => {
|
|
32782
34733
|
for (const mounted of mountedByComposer.values()) {
|
|
32783
34734
|
const target = mounted.modelTarget;
|
|
32784
34735
|
const matchesDraft = target?.[0] === "default" && input.draftId !== null && target[1] === input.draftId;
|
|
32785
34736
|
const matchesConversation = target?.[0] === "conversation" && input.threadId !== null && target[1] === input.threadId && mounted.ownershipStatus === "ready";
|
|
32786
34737
|
if (!matchesDraft && !matchesConversation) continue;
|
|
32787
|
-
const mountedHostId =
|
|
34738
|
+
const mountedHostId = activeModelHostId(mounted.composer);
|
|
32788
34739
|
if (input.hostId !== mountedHostId) return null;
|
|
32789
34740
|
return controller.get(mounted.composer).agent;
|
|
32790
34741
|
}
|
|
@@ -32795,7 +34746,9 @@ ${accounts_default}`;
|
|
|
32795
34746
|
getLocalAgent: localAgentForSidebarThread
|
|
32796
34747
|
});
|
|
32797
34748
|
let connectionDiagnostics = null;
|
|
34749
|
+
const remoteConnections = createRemoteConnectionsControl(window, modelClientForHost);
|
|
32798
34750
|
const settingsLifecycle = installRendererSettingsLifecycle(window, {
|
|
34751
|
+
getRemoteConnections: () => remoteConnections,
|
|
32799
34752
|
getUpdateClient: () => modelControl,
|
|
32800
34753
|
getAccountClient: () => modelControl,
|
|
32801
34754
|
getConnectionDiagnostics: () => connectionDiagnostics,
|
|
@@ -32843,7 +34796,8 @@ ${accounts_default}`;
|
|
|
32843
34796
|
hermes: void 0,
|
|
32844
34797
|
qoder: void 0,
|
|
32845
34798
|
"qoder-cn": void 0,
|
|
32846
|
-
"kimi-code": void 0
|
|
34799
|
+
"kimi-code": void 0,
|
|
34800
|
+
zcode: void 0
|
|
32847
34801
|
},
|
|
32848
34802
|
webUi: Object.fromEntries(
|
|
32849
34803
|
externalAgents.map((agent) => [agent, false])
|
|
@@ -32924,6 +34878,9 @@ ${accounts_default}`;
|
|
|
32924
34878
|
const title = status === "unsupported" ? rendererHarnessMessages(settingsLifecycle.locale).codexUsageGateUnavailable : "";
|
|
32925
34879
|
if (mounted.control.root.title !== title) mounted.control.root.title = title;
|
|
32926
34880
|
};
|
|
34881
|
+
const composerClient = (mounted) => mounted.hostId ? modelClientForHost(mounted.hostId) : null;
|
|
34882
|
+
const composerAvailability = (mounted) => mounted.hostId ? hostHarnessAvailabilityState(mounted.hostId).availability : {};
|
|
34883
|
+
const composerAdapterState = (mounted) => composerClient(mounted) ? "ready" : "installing";
|
|
32927
34884
|
const renderMounted = (mounted) => {
|
|
32928
34885
|
const accounts = composerCodexAccounts(mounted.composer);
|
|
32929
34886
|
const currentCodexAccount = accounts?.accounts.find(
|
|
@@ -32932,9 +34889,9 @@ ${accounts_default}`;
|
|
|
32932
34889
|
const externalSubmissionReady = renderComposerAgentControl(
|
|
32933
34890
|
mounted.control,
|
|
32934
34891
|
controller.get(mounted.composer),
|
|
32935
|
-
|
|
34892
|
+
composerAdapterState(mounted),
|
|
32936
34893
|
controller.isSwitching(mounted.composer) || mounted.ownershipStatus === "loading",
|
|
32937
|
-
|
|
34894
|
+
composerAvailability(mounted),
|
|
32938
34895
|
mounted.modelView,
|
|
32939
34896
|
mounted.permissionModeView,
|
|
32940
34897
|
mounted.usage,
|
|
@@ -32967,7 +34924,7 @@ ${accounts_default}`;
|
|
|
32967
34924
|
const generation = ++mounted.commandRequestGeneration;
|
|
32968
34925
|
const agent = controller.get(mounted.composer).agent;
|
|
32969
34926
|
const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
|
|
32970
|
-
const hostId = threadId ? mounted.hostId : activeModelHostId();
|
|
34927
|
+
const hostId = threadId ? mounted.hostId : activeModelHostId(mounted.composer);
|
|
32971
34928
|
const requestControl = modelControl;
|
|
32972
34929
|
const client = modelClientForHostFrom(requestControl, hostId);
|
|
32973
34930
|
if (!keepCurrent || agent === "codex") mounted.control.harnessCommands.setCommands([]);
|
|
@@ -32977,7 +34934,7 @@ ${accounts_default}`;
|
|
|
32977
34934
|
harnessId: externalHarnessIds[agent],
|
|
32978
34935
|
...hostId && draftWorkspaces.has(hostId) ? { cwd: draftWorkspaces.get(hostId) } : {}
|
|
32979
34936
|
});
|
|
32980
|
-
if (disposed || mountedByComposer.get(mounted.composer) !== mounted || mounted.commandRequestGeneration !== generation || requestControl !== modelControl || (threadIdFromComposerModelTarget(mounted.modelTarget) ? mounted.hostId : activeModelHostId()) !== hostId || controller.get(mounted.composer).agent !== agent)
|
|
34937
|
+
if (disposed || mountedByComposer.get(mounted.composer) !== mounted || mounted.commandRequestGeneration !== generation || requestControl !== modelControl || (threadIdFromComposerModelTarget(mounted.modelTarget) ? mounted.hostId : activeModelHostId(mounted.composer)) !== hostId || controller.get(mounted.composer).agent !== agent)
|
|
32981
34938
|
return;
|
|
32982
34939
|
mounted.control.harnessCommands.setCommands(
|
|
32983
34940
|
catalog.commands,
|
|
@@ -32991,9 +34948,11 @@ ${accounts_default}`;
|
|
|
32991
34948
|
const executeCommand = async (mounted, command) => {
|
|
32992
34949
|
const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
|
|
32993
34950
|
if (!threadId || !modelControl || controller.get(mounted.composer).agent === "codex") return;
|
|
34951
|
+
const client = composerClient(mounted);
|
|
34952
|
+
if (!client) return;
|
|
32994
34953
|
mounted.control.harnessCommands.setExecuting(command.id);
|
|
32995
34954
|
try {
|
|
32996
|
-
await
|
|
34955
|
+
await client.executeThreadCommand({ threadId, commandId: command.id });
|
|
32997
34956
|
} catch (error51) {
|
|
32998
34957
|
console.error(
|
|
32999
34958
|
"codexhost Harness command failed",
|
|
@@ -33015,9 +34974,10 @@ ${accounts_default}`;
|
|
|
33015
34974
|
}
|
|
33016
34975
|
console.error("codexhost Harness command could not claim the current Composer editor");
|
|
33017
34976
|
};
|
|
33018
|
-
const applyThreadUsageUpdate = (update) => {
|
|
34977
|
+
const applyThreadUsageUpdate = (hostId, update) => {
|
|
33019
34978
|
for (const mounted of mountedByComposer.values()) {
|
|
33020
|
-
if (threadIdFromComposerModelTarget(mounted.modelTarget) !== update.threadId)
|
|
34979
|
+
if (mounted.hostId !== hostId || threadIdFromComposerModelTarget(mounted.modelTarget) !== update.threadId)
|
|
34980
|
+
continue;
|
|
33021
34981
|
mounted.usageRequestGeneration += 1;
|
|
33022
34982
|
mounted.usage = update.usage;
|
|
33023
34983
|
mounted.accountCredits = update.accountCredits ?? null;
|
|
@@ -33061,13 +35021,16 @@ ${accounts_default}`;
|
|
|
33061
35021
|
renderMounted(mounted);
|
|
33062
35022
|
return;
|
|
33063
35023
|
}
|
|
35024
|
+
const hostId = mounted.hostId;
|
|
35025
|
+
const client = composerClient(mounted);
|
|
35026
|
+
if (!client) return;
|
|
33064
35027
|
const generation = ++mounted.usageRequestGeneration;
|
|
33065
35028
|
try {
|
|
33066
|
-
const result = await
|
|
35029
|
+
const result = await client.inspectThreadUsage({
|
|
33067
35030
|
threadId,
|
|
33068
35031
|
...refresh ? { refresh } : {}
|
|
33069
35032
|
});
|
|
33070
|
-
if (disposed || mountedByComposer.get(mounted.composer) !== mounted || !mounted.composer.isConnected || mounted.usageRequestGeneration !== generation || threadIdFromComposerModelTarget(mounted.modelTarget) !== threadId || result.threadId !== threadId) {
|
|
35033
|
+
if (disposed || mountedByComposer.get(mounted.composer) !== mounted || !mounted.composer.isConnected || mounted.usageRequestGeneration !== generation || mounted.hostId !== hostId || composerClient(mounted) !== client || threadIdFromComposerModelTarget(mounted.modelTarget) !== threadId || result.threadId !== threadId) {
|
|
33071
35034
|
return;
|
|
33072
35035
|
}
|
|
33073
35036
|
mounted.usage = result.usage;
|
|
@@ -33136,7 +35099,7 @@ ${accounts_default}`;
|
|
|
33136
35099
|
return;
|
|
33137
35100
|
}
|
|
33138
35101
|
const requestModelControl = modelControl;
|
|
33139
|
-
const requestHostId = activeModelHostId();
|
|
35102
|
+
const requestHostId = activeModelHostId(mounted.composer);
|
|
33140
35103
|
const client = modelClientForHostFrom(requestModelControl, requestHostId);
|
|
33141
35104
|
const generation = controller.beginOwnershipRequest(mounted.composer);
|
|
33142
35105
|
const usageGeneration = mounted.usageRequestGeneration;
|
|
@@ -33146,7 +35109,7 @@ ${accounts_default}`;
|
|
|
33146
35109
|
if (!client || !requestHostId) throw new Error("Thread ownership control is unavailable");
|
|
33147
35110
|
mounted.hostId = requestHostId;
|
|
33148
35111
|
const inspection = await client.inspectThread({ threadId });
|
|
33149
|
-
if (!isCurrentOwnershipRequest(mounted, generation) || mountedByComposer.get(mounted.composer) !== mounted || threadIdFromComposerModelTarget(mounted.modelTarget) !== threadId || mounted.hostId !== requestHostId || modelControl !== requestModelControl || activeModelHostId() !== requestHostId) {
|
|
35112
|
+
if (!isCurrentOwnershipRequest(mounted, generation) || mountedByComposer.get(mounted.composer) !== mounted || threadIdFromComposerModelTarget(mounted.modelTarget) !== threadId || mounted.hostId !== requestHostId || modelControl !== requestModelControl || activeModelHostId(mounted.composer) !== requestHostId) {
|
|
33150
35113
|
return;
|
|
33151
35114
|
}
|
|
33152
35115
|
const { agent, model, thinkingOptionId, permissionModeId } = restoredThreadOwnership(inspection);
|
|
@@ -33212,7 +35175,7 @@ ${accounts_default}`;
|
|
|
33212
35175
|
);
|
|
33213
35176
|
if (resolution === "none") return false;
|
|
33214
35177
|
const previousTarget = mounted.modelTarget;
|
|
33215
|
-
const nextHostId = activeModelHostId(
|
|
35178
|
+
const nextHostId = activeModelHostId(mounted.composer);
|
|
33216
35179
|
const nextControllerTarget = controllerTarget(currentTarget, nextHostId);
|
|
33217
35180
|
mounted.modelTarget = currentTarget;
|
|
33218
35181
|
mounted.hostId = nextHostId;
|
|
@@ -33251,7 +35214,7 @@ ${accounts_default}`;
|
|
|
33251
35214
|
const agent = state.agent;
|
|
33252
35215
|
const requestModelControl = modelControl;
|
|
33253
35216
|
const isDraft = !threadIdFromComposerModelTarget(mounted.modelTarget);
|
|
33254
|
-
const requestHostId = isDraft ? activeModelHostId() : mounted.hostId;
|
|
35217
|
+
const requestHostId = isDraft ? activeModelHostId(mounted.composer) : mounted.hostId;
|
|
33255
35218
|
if (!requestHostId) {
|
|
33256
35219
|
mounted.modelView = {
|
|
33257
35220
|
status: "waitingForAdapter",
|
|
@@ -33265,7 +35228,7 @@ ${accounts_default}`;
|
|
|
33265
35228
|
const availability = hostHarnessAvailabilityState(requestHostId).availability[agent];
|
|
33266
35229
|
if (availability !== "ready" && availability !== "checking") {
|
|
33267
35230
|
mounted.modelView = {
|
|
33268
|
-
status:
|
|
35231
|
+
status: composerAdapterState(mounted) === "ready" ? "error" : "waitingForAdapter",
|
|
33269
35232
|
thinkingSelectionSupported: false,
|
|
33270
35233
|
...availability ? { error: `${agent} runtime is ${availability}` } : {}
|
|
33271
35234
|
};
|
|
@@ -33274,12 +35237,12 @@ ${accounts_default}`;
|
|
|
33274
35237
|
return;
|
|
33275
35238
|
}
|
|
33276
35239
|
mounted.modelView = {
|
|
33277
|
-
status:
|
|
35240
|
+
status: composerAdapterState(mounted) === "ready" ? "loading" : "waitingForAdapter",
|
|
33278
35241
|
thinkingSelectionSupported: false
|
|
33279
35242
|
};
|
|
33280
35243
|
mounted.permissionModeView = { status: "idle" };
|
|
33281
35244
|
renderMounted(mounted);
|
|
33282
|
-
if (
|
|
35245
|
+
if (!composerClient(mounted)) return;
|
|
33283
35246
|
const generation = controller.beginModelRequest(mounted.composer);
|
|
33284
35247
|
let catalogRequest;
|
|
33285
35248
|
try {
|
|
@@ -33295,7 +35258,7 @@ ${accounts_default}`;
|
|
|
33295
35258
|
const inspection = await client.inspectHarness({
|
|
33296
35259
|
harnessId: externalHarnessIds[agent]
|
|
33297
35260
|
});
|
|
33298
|
-
if (!isCurrentModelRequest(mounted, generation) || controller.get(mounted.composer).agent !== agent || mounted.hostId !== requestHostId || modelControl !== requestModelControl || modelClientForHostFrom(requestModelControl, requestHostId) !== client || activeModelHostId() !== requestHostId) {
|
|
35261
|
+
if (!isCurrentModelRequest(mounted, generation) || controller.get(mounted.composer).agent !== agent || mounted.hostId !== requestHostId || modelControl !== requestModelControl || modelClientForHostFrom(requestModelControl, requestHostId) !== client || activeModelHostId(mounted.composer) !== requestHostId) {
|
|
33299
35262
|
return;
|
|
33300
35263
|
}
|
|
33301
35264
|
if (inspection.status !== "ready") throw new Error(inspection.error.message);
|
|
@@ -33524,7 +35487,10 @@ ${accounts_default}`;
|
|
|
33524
35487
|
if (!threadId) {
|
|
33525
35488
|
throw new Error("External Thread identity is unavailable for Model selection");
|
|
33526
35489
|
}
|
|
33527
|
-
const
|
|
35490
|
+
const client = composerClient(mounted);
|
|
35491
|
+
if (!client) throw new Error("Thread Host is unavailable");
|
|
35492
|
+
const state = await client.selectThreadModel({ threadId, model: selected });
|
|
35493
|
+
if (composerClient(mounted) !== client) return;
|
|
33528
35494
|
if (!isCurrentModelRequest(mounted, generation) || controller.get(mounted.composer).agent !== agent) {
|
|
33529
35495
|
return;
|
|
33530
35496
|
}
|
|
@@ -33648,10 +35614,13 @@ ${accounts_default}`;
|
|
|
33648
35614
|
if (!threadId) {
|
|
33649
35615
|
throw new Error("External Thread identity is unavailable for Permission Mode selection");
|
|
33650
35616
|
}
|
|
33651
|
-
const
|
|
35617
|
+
const client = composerClient(mounted);
|
|
35618
|
+
if (!client) throw new Error("Thread Host is unavailable");
|
|
35619
|
+
const state = await client.selectThreadPermissionMode({
|
|
33652
35620
|
threadId,
|
|
33653
35621
|
permissionModeId: selectedPermissionModeId
|
|
33654
35622
|
});
|
|
35623
|
+
if (composerClient(mounted) !== client) return;
|
|
33655
35624
|
if (!isCurrentModelRequest(mounted, generation) || controller.get(mounted.composer).agent !== agent) {
|
|
33656
35625
|
return;
|
|
33657
35626
|
}
|
|
@@ -33762,10 +35731,13 @@ ${accounts_default}`;
|
|
|
33762
35731
|
if (!threadId || !modelControl) {
|
|
33763
35732
|
throw new Error("External Thread identity is unavailable for Thinking selection");
|
|
33764
35733
|
}
|
|
33765
|
-
const
|
|
35734
|
+
const client = composerClient(mounted);
|
|
35735
|
+
if (!client) throw new Error("Thread Host is unavailable");
|
|
35736
|
+
const state = await client.selectThreadThinking({
|
|
33766
35737
|
threadId,
|
|
33767
35738
|
thinkingOptionId: selectedThinkingOptionId
|
|
33768
35739
|
});
|
|
35740
|
+
if (composerClient(mounted) !== client) return;
|
|
33769
35741
|
if (!isCurrentModelRequest(mounted, generation) || controller.get(mounted.composer).agent !== agent) {
|
|
33770
35742
|
return;
|
|
33771
35743
|
}
|
|
@@ -33825,7 +35797,7 @@ ${accounts_default}`;
|
|
|
33825
35797
|
}
|
|
33826
35798
|
};
|
|
33827
35799
|
const switchComposerAgent = async (mounted, agent) => {
|
|
33828
|
-
if (agent !== "codex" &&
|
|
35800
|
+
if (agent !== "codex" && composerAvailability(mounted)[agent] !== "ready") {
|
|
33829
35801
|
return false;
|
|
33830
35802
|
}
|
|
33831
35803
|
controller.clearPendingSubmission(mounted.composer);
|
|
@@ -33862,16 +35834,20 @@ ${accounts_default}`;
|
|
|
33862
35834
|
}
|
|
33863
35835
|
};
|
|
33864
35836
|
const loadCodexAccounts = async () => {
|
|
33865
|
-
const
|
|
33866
|
-
|
|
33867
|
-
|
|
33868
|
-
|
|
33869
|
-
|
|
33870
|
-
|
|
33871
|
-
|
|
33872
|
-
|
|
33873
|
-
|
|
33874
|
-
|
|
35837
|
+
const hostIds = new Set([...mountedByComposer.values()].map((mounted) => mounted.hostId));
|
|
35838
|
+
await Promise.all(
|
|
35839
|
+
[...hostIds].map(async (hostId) => {
|
|
35840
|
+
const accounts = codexAccountsForHost(hostId);
|
|
35841
|
+
if (!accounts) return;
|
|
35842
|
+
await accounts.refresh();
|
|
35843
|
+
if (disposed || codexAccountsForHost(hostId) !== accounts) return;
|
|
35844
|
+
for (const mounted of mountedByComposer.values()) {
|
|
35845
|
+
if (mounted.hostId !== hostId) continue;
|
|
35846
|
+
renderMounted(mounted);
|
|
35847
|
+
void refreshDraftCodexUsage(mounted);
|
|
35848
|
+
}
|
|
35849
|
+
})
|
|
35850
|
+
);
|
|
33875
35851
|
};
|
|
33876
35852
|
const openInstallPage = (agent) => {
|
|
33877
35853
|
const url2 = RENDERER_AGENT_INSTALL_URLS[agent];
|
|
@@ -33915,7 +35891,7 @@ ${accounts_default}`;
|
|
|
33915
35891
|
state.requestGeneration += 1;
|
|
33916
35892
|
state.request = null;
|
|
33917
35893
|
}
|
|
33918
|
-
if (force ||
|
|
35894
|
+
if (force || [...mountedByComposer.values()].some((mounted) => mounted.hostId === hostId)) {
|
|
33919
35895
|
for (const agent of externalAgents) {
|
|
33920
35896
|
state.availability[agent] = "error";
|
|
33921
35897
|
state.errors[agent] = {
|
|
@@ -33989,17 +35965,15 @@ ${accounts_default}`;
|
|
|
33989
35965
|
state.errors[agent] = nextError;
|
|
33990
35966
|
state.availability = { ...state.availability, [agent]: status };
|
|
33991
35967
|
state.webUi = { ...state.webUi, [agent]: webUiAvailable };
|
|
33992
|
-
if (hostId !== activeAvailabilityHostId) {
|
|
33993
|
-
publishConnectionStatus();
|
|
33994
|
-
return;
|
|
33995
|
-
}
|
|
33996
35968
|
for (const mounted of mountedByComposer.values()) {
|
|
35969
|
+
if (mounted.hostId !== hostId) continue;
|
|
33997
35970
|
const composerState = controller.get(mounted.composer);
|
|
33998
|
-
if (
|
|
35971
|
+
if (composerAdapterState(mounted) === "ready" && composerState.phase === "draft" && composerState.agent === agent && status !== "ready") {
|
|
33999
35972
|
await switchComposerAgent(mounted, "codex");
|
|
34000
35973
|
}
|
|
34001
35974
|
}
|
|
34002
35975
|
for (const mounted of mountedByComposer.values()) {
|
|
35976
|
+
if (mounted.hostId !== hostId) continue;
|
|
34003
35977
|
const composerState = controller.get(mounted.composer);
|
|
34004
35978
|
const pendingCatalog = catalogRequests.get(mounted);
|
|
34005
35979
|
const loadingCurrentCatalog = pendingCatalog?.client === client && pendingCatalog.hostId === hostId && pendingCatalog.agent === agent && isCurrentModelRequest(mounted, pendingCatalog.generation);
|
|
@@ -34035,9 +36009,10 @@ ${accounts_default}`;
|
|
|
34035
36009
|
);
|
|
34036
36010
|
return promise2;
|
|
34037
36011
|
}
|
|
34038
|
-
const reloadMountedOwnershipForHost = (
|
|
36012
|
+
const reloadMountedOwnershipForHost = () => {
|
|
34039
36013
|
for (const mounted of mountedByComposer.values()) {
|
|
34040
|
-
|
|
36014
|
+
const hostId = activeModelHostId(mounted.composer);
|
|
36015
|
+
if (!hostId || mounted.hostId === hostId) continue;
|
|
34041
36016
|
if (!threadIdFromComposerModelTarget(mounted.modelTarget)) {
|
|
34042
36017
|
controller.clearPendingSubmission(mounted.composer);
|
|
34043
36018
|
controller.beginModelRequest(mounted.composer);
|
|
@@ -34081,19 +36056,46 @@ ${accounts_default}`;
|
|
|
34081
36056
|
sidebarAgentIcons.refresh();
|
|
34082
36057
|
};
|
|
34083
36058
|
function reconcileHarnessAvailabilityHost() {
|
|
36059
|
+
for (const hostId2 of modelControl?.knownHostIds?.() ?? []) {
|
|
36060
|
+
hostHarnessAvailabilityState(hostId2);
|
|
36061
|
+
}
|
|
36062
|
+
reloadMountedOwnershipForHost();
|
|
36063
|
+
for (const target of new Set([...mountedByComposer.values()].map((m) => m.hostId))) {
|
|
36064
|
+
if (!target) continue;
|
|
36065
|
+
const client = modelClientForHost(target);
|
|
36066
|
+
const previous = usageSubscriptions.get(target);
|
|
36067
|
+
if (previous?.client === client) continue;
|
|
36068
|
+
previous?.dispose();
|
|
36069
|
+
usageSubscriptions.delete(target);
|
|
36070
|
+
if (!client?.subscribeThreadUsage) continue;
|
|
36071
|
+
try {
|
|
36072
|
+
const dispose = client.subscribeThreadUsage((update) => {
|
|
36073
|
+
if (usageSubscriptions.get(target)?.client !== client) return;
|
|
36074
|
+
if (modelClientForHost(target) !== client) return;
|
|
36075
|
+
applyThreadUsageUpdate(target, update);
|
|
36076
|
+
});
|
|
36077
|
+
usageSubscriptions.set(target, { client, dispose });
|
|
36078
|
+
} catch {
|
|
36079
|
+
}
|
|
36080
|
+
}
|
|
34084
36081
|
const hostId = activeModelHostId();
|
|
34085
36082
|
if (!hostId || hostId === activeAvailabilityHostId && [...mountedByComposer.values()].every((mounted) => mounted.hostId !== null))
|
|
34086
36083
|
return;
|
|
34087
36084
|
activeAvailabilityHostId = hostId;
|
|
34088
36085
|
hostHarnessAvailabilityState(hostId);
|
|
34089
|
-
reloadMountedOwnershipForHost(hostId);
|
|
34090
36086
|
publishConnectionStatus();
|
|
34091
36087
|
for (const mounted of mountedByComposer.values()) renderMounted(mounted);
|
|
34092
36088
|
void refreshHarnessAvailabilityForHost(hostId);
|
|
34093
36089
|
}
|
|
34094
|
-
const refreshHarnessAvailability = (refresh = false) => {
|
|
36090
|
+
const refreshHarnessAvailability = async (refresh = false) => {
|
|
34095
36091
|
reconcileHarnessAvailabilityHost();
|
|
34096
|
-
|
|
36092
|
+
const hostIds = /* @__PURE__ */ new Set([activeAvailabilityHostId]);
|
|
36093
|
+
for (const mounted of mountedByComposer.values()) {
|
|
36094
|
+
if (mounted.hostId) hostIds.add(mounted.hostId);
|
|
36095
|
+
}
|
|
36096
|
+
await Promise.all(
|
|
36097
|
+
[...hostIds].map((hostId) => refreshHarnessAvailabilityForHost(hostId, refresh))
|
|
36098
|
+
);
|
|
34097
36099
|
};
|
|
34098
36100
|
connectionDiagnostics = {
|
|
34099
36101
|
snapshot() {
|
|
@@ -34118,11 +36120,18 @@ ${accounts_default}`;
|
|
|
34118
36120
|
})
|
|
34119
36121
|
};
|
|
34120
36122
|
},
|
|
34121
|
-
refresh() {
|
|
36123
|
+
refresh(hostId) {
|
|
36124
|
+
if (hostId !== void 0) {
|
|
36125
|
+
return refreshConnectionHosts(
|
|
36126
|
+
[hostId],
|
|
36127
|
+
(target) => refreshHarnessAvailabilityForHost(target, true, false, true),
|
|
36128
|
+
(target) => hostHarnessAvailabilityState(target).request?.promise
|
|
36129
|
+
);
|
|
36130
|
+
}
|
|
34122
36131
|
reconcileHarnessAvailabilityHost();
|
|
34123
36132
|
return refreshConnectionHosts(
|
|
34124
36133
|
harnessAvailabilityByHost.keys(),
|
|
34125
|
-
(
|
|
36134
|
+
(target) => refreshHarnessAvailabilityForHost(target, true, false, true)
|
|
34126
36135
|
);
|
|
34127
36136
|
},
|
|
34128
36137
|
async installation(hostId, agent, action) {
|
|
@@ -34169,7 +36178,7 @@ ${accounts_default}`;
|
|
|
34169
36178
|
const sendButton = sendButtonWithin(composer) ?? allButtons.at(-1) ?? null;
|
|
34170
36179
|
if (!sendButton) return;
|
|
34171
36180
|
const modelTarget = findComposerModelTarget(composer);
|
|
34172
|
-
const hostId = activeModelHostId();
|
|
36181
|
+
const hostId = activeModelHostId(composer);
|
|
34173
36182
|
const editor = composer.querySelector(EDITOR_SELECTOR);
|
|
34174
36183
|
if (!editor) return;
|
|
34175
36184
|
const state = controller.mount(
|
|
@@ -34253,7 +36262,7 @@ ${accounts_default}`;
|
|
|
34253
36262
|
for (const [target, replacement] of pendingReplacements) {
|
|
34254
36263
|
const sourceState = controller.get(replacement.source.composer);
|
|
34255
36264
|
const replacementTarget = findComposerModelTarget(target);
|
|
34256
|
-
const replacementHostId = activeModelHostId()
|
|
36265
|
+
const replacementHostId = activeModelHostId(target);
|
|
34257
36266
|
if (!shouldTransferComposerState(
|
|
34258
36267
|
replacement.sourceModelTarget,
|
|
34259
36268
|
replacementTarget,
|
|
@@ -34296,8 +36305,8 @@ ${accounts_default}`;
|
|
|
34296
36305
|
void refreshHarnessAvailabilityForHost("local");
|
|
34297
36306
|
}
|
|
34298
36307
|
reconcileHarnessAvailabilityHost();
|
|
34299
|
-
if (
|
|
34300
|
-
(agent) =>
|
|
36308
|
+
if ([...mountedByComposer.values()].some(
|
|
36309
|
+
(mounted) => externalAgents.some((agent) => composerAvailability(mounted)[agent] === "checking")
|
|
34301
36310
|
)) {
|
|
34302
36311
|
void refreshHarnessAvailability();
|
|
34303
36312
|
}
|
|
@@ -34449,8 +36458,8 @@ ${accounts_default}`;
|
|
|
34449
36458
|
scheduleScan(relevant.some(mutationMayChangeComposerTarget));
|
|
34450
36459
|
});
|
|
34451
36460
|
const onHostRouteChange = () => {
|
|
34452
|
-
const hostId = activeModelHostId();
|
|
34453
36461
|
for (const mounted of mountedByComposer.values()) {
|
|
36462
|
+
const hostId = activeModelHostId(mounted.composer);
|
|
34454
36463
|
if (hostId && mounted.hostId === hostId && !threadIdFromComposerModelTarget(mounted.modelTarget) && controller.get(mounted.composer).agent !== "codex" && !controller.isSwitching(mounted.composer) && isExternalConfigurationStable(mounted.modelView, mounted.permissionModeView)) {
|
|
34455
36464
|
applyComposerAgent(mounted.composer);
|
|
34456
36465
|
}
|
|
@@ -34473,14 +36482,14 @@ ${accounts_default}`;
|
|
|
34473
36482
|
sidebarAgentIcons.refresh();
|
|
34474
36483
|
void refreshHarnessAvailabilityForHost("local");
|
|
34475
36484
|
void refreshHarnessAvailability();
|
|
34476
|
-
|
|
34477
|
-
|
|
34478
|
-
|
|
34479
|
-
|
|
34480
|
-
|
|
36485
|
+
}
|
|
36486
|
+
for (const mounted of mountedByComposer.values()) {
|
|
36487
|
+
if (mounted.modelView.status === "waitingForAdapter" && mounted.composer.isConnected && composerClient(mounted)) {
|
|
36488
|
+
applyComposerAgent(mounted.composer);
|
|
36489
|
+
void loadExternalCatalog(mounted);
|
|
34481
36490
|
}
|
|
36491
|
+
renderMounted(mounted);
|
|
34482
36492
|
}
|
|
34483
|
-
for (const mounted of mountedByComposer.values()) renderMounted(mounted);
|
|
34484
36493
|
};
|
|
34485
36494
|
mutationObserver.observe(document.documentElement, {
|
|
34486
36495
|
attributes: true,
|
|
@@ -34497,7 +36506,7 @@ ${accounts_default}`;
|
|
|
34497
36506
|
reconcileHarnessAvailabilityHost();
|
|
34498
36507
|
void loadCodexAccounts();
|
|
34499
36508
|
for (const mounted of mountedByComposer.values()) {
|
|
34500
|
-
if (mounted.hostId === activeModelHostId() && mounted.ownershipStatus === "error") {
|
|
36509
|
+
if (mounted.hostId === activeModelHostId(mounted.composer) && mounted.ownershipStatus === "error") {
|
|
34501
36510
|
void loadThreadOwnership(mounted);
|
|
34502
36511
|
}
|
|
34503
36512
|
}
|
|
@@ -34505,8 +36514,9 @@ ${accounts_default}`;
|
|
|
34505
36514
|
if (externalAgents.some((agent) => local.availability[agent] !== "ready")) {
|
|
34506
36515
|
void refreshHarnessAvailabilityForHost("local", true);
|
|
34507
36516
|
}
|
|
34508
|
-
|
|
34509
|
-
|
|
36517
|
+
if ([...mountedByComposer.values()].some(
|
|
36518
|
+
(mounted) => externalAgents.some((agent) => composerAvailability(mounted)[agent] !== "ready")
|
|
36519
|
+
)) {
|
|
34510
36520
|
void refreshHarnessAvailability(true);
|
|
34511
36521
|
}
|
|
34512
36522
|
};
|
|
@@ -34517,7 +36527,7 @@ ${accounts_default}`;
|
|
|
34517
36527
|
if (typeof hostId !== "string" || typeof cwd !== "string" || cwd.length === 0) return;
|
|
34518
36528
|
draftWorkspaces.set(hostId, cwd);
|
|
34519
36529
|
for (const mounted of mountedByComposer.values()) {
|
|
34520
|
-
if (!threadIdFromComposerModelTarget(mounted.modelTarget) && activeModelHostId() === hostId && controller.get(mounted.composer).agent !== "codex") {
|
|
36530
|
+
if (!threadIdFromComposerModelTarget(mounted.modelTarget) && activeModelHostId(mounted.composer) === hostId && controller.get(mounted.composer).agent !== "codex") {
|
|
34521
36531
|
void refreshCommands(mounted, { keepCurrent: true });
|
|
34522
36532
|
}
|
|
34523
36533
|
}
|
|
@@ -34534,8 +36544,10 @@ ${accounts_default}`;
|
|
|
34534
36544
|
void refreshCommands(mounted, { keepCurrent: true });
|
|
34535
36545
|
}
|
|
34536
36546
|
},
|
|
34537
|
-
readTargets: () => {
|
|
34538
|
-
const
|
|
36547
|
+
readTargets: (editor) => {
|
|
36548
|
+
const composer = composerForElement(editor);
|
|
36549
|
+
const mounted = composer ? mountedByComposer.get(composer) : void 0;
|
|
36550
|
+
const availability = mounted ? composerAvailability(mounted) : {};
|
|
34539
36551
|
return enabledAgents.filter((agent) => agent === "codex" || availability[agent] === "ready").map((agent) => ({ agent, label: RENDERER_AGENT_LABELS[agent] }));
|
|
34540
36552
|
},
|
|
34541
36553
|
isComposerEditor: (editor) => {
|
|
@@ -34571,6 +36583,10 @@ ${accounts_default}`;
|
|
|
34571
36583
|
(mounted) => mounted.composer.isConnected && mounted.control.root.isConnected
|
|
34572
36584
|
);
|
|
34573
36585
|
const api = {
|
|
36586
|
+
currentThreadId() {
|
|
36587
|
+
const mounted = connectedComposers();
|
|
36588
|
+
return mounted.length === 1 && mounted[0] ? threadIdFromComposerModelTarget(mounted[0].modelTarget) ?? null : null;
|
|
36589
|
+
},
|
|
34574
36590
|
status() {
|
|
34575
36591
|
const selections = connectedComposers().map((mounted) => ({
|
|
34576
36592
|
composerId: mounted.composerId,
|
|
@@ -34604,17 +36620,11 @@ ${accounts_default}`;
|
|
|
34604
36620
|
};
|
|
34605
36621
|
},
|
|
34606
36622
|
setAdapter(status, dispose, applyAgent, nextModelControl) {
|
|
34607
|
-
usageNotificationDispose
|
|
34608
|
-
usageNotificationDispose = null;
|
|
36623
|
+
usageNotificationDispose();
|
|
34609
36624
|
adapterDispose?.();
|
|
34610
36625
|
adapterDispose = dispose ?? null;
|
|
34611
36626
|
applyAdapterAgent = applyAgent ?? null;
|
|
34612
36627
|
modelControl = nextModelControl ?? null;
|
|
34613
|
-
try {
|
|
34614
|
-
usageNotificationDispose = modelControl?.subscribeThreadUsage?.(applyThreadUsageUpdate) ?? null;
|
|
34615
|
-
} catch {
|
|
34616
|
-
usageNotificationDispose = null;
|
|
34617
|
-
}
|
|
34618
36628
|
adapterStatus = status;
|
|
34619
36629
|
publishConnectionStatus();
|
|
34620
36630
|
const installedModelControl = modelControl;
|
|
@@ -34643,7 +36653,7 @@ ${accounts_default}`;
|
|
|
34643
36653
|
if (mounted) {
|
|
34644
36654
|
const state = controller.get(mounted.composer);
|
|
34645
36655
|
if (!threadIdFromComposerModelTarget(mounted.modelTarget)) {
|
|
34646
|
-
mounted.hostId = activeModelHostId();
|
|
36656
|
+
mounted.hostId = activeModelHostId(mounted.composer);
|
|
34647
36657
|
}
|
|
34648
36658
|
if (threadIdFromComposerModelTarget(mounted.modelTarget) && mounted.ownershipStatus !== "ready") {
|
|
34649
36659
|
void loadThreadOwnership(mounted);
|
|
@@ -34662,8 +36672,7 @@ ${accounts_default}`;
|
|
|
34662
36672
|
dispose() {
|
|
34663
36673
|
if (disposed) return;
|
|
34664
36674
|
disposed = true;
|
|
34665
|
-
usageNotificationDispose
|
|
34666
|
-
usageNotificationDispose = null;
|
|
36675
|
+
usageNotificationDispose();
|
|
34667
36676
|
adapterDispose?.();
|
|
34668
36677
|
adapterDispose = null;
|
|
34669
36678
|
applyAdapterAgent = null;
|