@codexhost/cli-darwin-x64 0.16.0 → 0.17.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 +2 -2
- package/THIRD_PARTY_NOTICES.txt +6 -2
- package/app/codexhost-distribution.json +1 -1
- package/app/console-server.mjs +59 -21
- package/app/console-web.js +49 -18
- package/app/desktop-controller.mjs +554 -34
- package/app/host-runtime.mjs +3436 -1846
- package/app/plugins/antigravity/plugin.mjs +39 -3
- package/app/plugins/claude-code/plugin.mjs +16 -7
- package/app/plugins/codebuddy/plugin.mjs +14 -1
- package/app/plugins/codex-usage/plugin.mjs +4 -1
- package/app/plugins/copilot/plugin.mjs +4 -1
- package/app/plugins/cursor-cli/plugin.mjs +13 -6
- package/app/plugins/deepseek-harness/plugin.mjs +463 -47
- package/app/plugins/devin/assets/icon.svg +1 -0
- package/app/plugins/devin/manifest.json +30 -0
- package/app/plugins/devin/plugin.mjs +23363 -0
- package/app/plugins/enabled.json +2 -0
- package/app/plugins/grok/plugin.mjs +476 -392
- package/app/plugins/hermes/plugin.mjs +457 -197
- package/app/plugins/kimi-code/plugin.mjs +4 -1
- package/app/plugins/kiro-cli/plugin.mjs +4 -1
- package/app/plugins/omp/plugin.mjs +4 -1
- package/app/plugins/opencode/plugin.mjs +4 -1
- package/app/plugins/pi/plugin.mjs +1464 -412
- package/app/plugins/qoder/plugin.mjs +9528 -8655
- package/app/plugins/qoder-cn/plugin.mjs +9528 -8655
- package/app/plugins/qwen-code/assets/icon.svg +1 -0
- package/app/plugins/qwen-code/manifest.json +29 -0
- package/app/plugins/qwen-code/plugin.mjs +29298 -0
- package/app/plugins/workbuddy/plugin.mjs +14 -1
- package/app/plugins/zcode/plugin.mjs +4 -1
- package/app/renderer-extension.js +510 -114
- package/bin/codexhost +0 -0
- package/libexec/codexhost-shim +0 -0
- package/libexec/codexhost-updater +0 -0
- package/licenses/Qwen-Code-SDK-LICENSE.txt +203 -0
- package/package.json +2 -2
|
@@ -15858,7 +15858,10 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
15858
15858
|
harnessId: harnessPluginIdSchema,
|
|
15859
15859
|
model: harnessModelRefSchema.optional(),
|
|
15860
15860
|
thinkingOptionId: harnessThinkingOptionIdSchema.optional(),
|
|
15861
|
-
permissionModeId: harnessPermissionModeIdSchema.optional()
|
|
15861
|
+
permissionModeId: harnessPermissionModeIdSchema.optional(),
|
|
15862
|
+
/** A draft prewarm create: stays unsubmitted until the user's first Turn.
|
|
15863
|
+
* Desktop forwards only the Model of a main-process prewarm to thread/start. */
|
|
15864
|
+
prewarm: external_exports.literal(true).optional()
|
|
15862
15865
|
}).strict();
|
|
15863
15866
|
function encodeHarnessPluginRoute(route) {
|
|
15864
15867
|
const parsed = harnessPluginRouteSchema.parse(route);
|
|
@@ -16260,6 +16263,19 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16260
16263
|
return `${HARNESS_COMMAND_MENTION_PATH_PREFIX}${encodeURIComponent(name).replace(/[()]/gu, (character) => `%${character.charCodeAt(0).toString(16).toUpperCase()}`)}`;
|
|
16261
16264
|
}
|
|
16262
16265
|
|
|
16266
|
+
// ../shared-contracts/dist/desktop-attachments.js
|
|
16267
|
+
var ATTACHED_FILES_HEADING = /^\s*# Files mentioned by the user:[ \t]*(?:\r?\n|$)/u;
|
|
16268
|
+
var REQUEST_HEADING = /(?:^|\n)## My request:[ \t]*(?:\r?\n|$)/u;
|
|
16269
|
+
var IMAGE_ATTACHMENT_PATTERN = /(?:^|\n)## [^\r\n]+: ((?:\/|[A-Za-z]:[\\/]|\\\\)[^\r\n]+)\r?\nImage attachment: true(?=\r?\n|$)/gu;
|
|
16270
|
+
var CONTROL_CHARACTER_PATTERN = /[\u0000-\u001f\u007f]/u;
|
|
16271
|
+
function desktopImageAttachmentPaths(text) {
|
|
16272
|
+
const end = text.search(REQUEST_HEADING);
|
|
16273
|
+
const context = end < 0 ? text : text.slice(0, end);
|
|
16274
|
+
if (!ATTACHED_FILES_HEADING.test(context))
|
|
16275
|
+
return [];
|
|
16276
|
+
return [...context.matchAll(IMAGE_ATTACHMENT_PATTERN)].map((match) => match[1] ?? "").filter((path) => path.length > 0 && !CONTROL_CHARACTER_PATTERN.test(path));
|
|
16277
|
+
}
|
|
16278
|
+
|
|
16263
16279
|
// ../shared-contracts/dist/remote-runtime.js
|
|
16264
16280
|
var RUNTIME_STATUS_METHOD = "codexhost/runtime/status";
|
|
16265
16281
|
var REMOTE_UPDATE_METHOD = "codexhost/remote/update";
|
|
@@ -16350,8 +16366,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16350
16366
|
if (!ownerWindow.document || !ownerWindow.location) return null;
|
|
16351
16367
|
const page = new URL(ownerWindow.location.href);
|
|
16352
16368
|
const urls = /* @__PURE__ */ new Set();
|
|
16353
|
-
|
|
16354
|
-
|
|
16369
|
+
const catalog = Reflect.get(ownerWindow, "__codexhostLoadedModulesV1");
|
|
16370
|
+
let sources;
|
|
16371
|
+
if (catalog !== void 0) {
|
|
16372
|
+
if (typeof catalog !== "object" || catalog === null || !("complete" in catalog) || catalog.complete !== true || !("documentUrl" in catalog) || catalog.documentUrl !== page.href || !("urls" in catalog) || !Array.isArray(catalog.urls) || catalog.urls.length > 4096 || catalog.urls.some((url2) => typeof url2 !== "string"))
|
|
16373
|
+
throw new Error("Codex loaded module catalog is unavailable in this window");
|
|
16374
|
+
sources = catalog.urls;
|
|
16375
|
+
} else {
|
|
16376
|
+
sources = [...ownerWindow.document.querySelectorAll('link[rel="modulepreload"][href]')].map(
|
|
16377
|
+
(link) => link.getAttribute("href") ?? ""
|
|
16378
|
+
);
|
|
16379
|
+
}
|
|
16380
|
+
for (const source of sources) {
|
|
16381
|
+
let url2;
|
|
16382
|
+
try {
|
|
16383
|
+
url2 = new URL(source, page);
|
|
16384
|
+
} catch {
|
|
16385
|
+
continue;
|
|
16386
|
+
}
|
|
16355
16387
|
if (url2.protocol === page.protocol && url2.host === page.host && url2.pathname.endsWith(".js") && !url2.search && !url2.hash)
|
|
16356
16388
|
urls.add(url2.href);
|
|
16357
16389
|
}
|
|
@@ -16369,6 +16401,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
16369
16401
|
for (const value of Object.values(module).filter(matchesServices)) matches.add(value);
|
|
16370
16402
|
if (matches.size > 1) throw new Error("Codex native services are unavailable in this window");
|
|
16371
16403
|
}
|
|
16404
|
+
if (catalog !== void 0 && Reflect.get(ownerWindow, "__codexhostLoadedModulesV1") !== catalog)
|
|
16405
|
+
throw new Error("Codex loaded module catalog changed during discovery. Try again once ready.");
|
|
16372
16406
|
return [...matches][0] ?? null;
|
|
16373
16407
|
}
|
|
16374
16408
|
|
|
@@ -17350,12 +17384,15 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17350
17384
|
if (!entry)
|
|
17351
17385
|
return;
|
|
17352
17386
|
entry.update((current) => {
|
|
17387
|
+
const { original } = entry;
|
|
17388
|
+
if (!original)
|
|
17389
|
+
return current;
|
|
17353
17390
|
const settings = current.modelSettings;
|
|
17354
17391
|
return settings?.model === entry.model && current.modelSettingsPersistAsDefault === false ? {
|
|
17355
17392
|
...current,
|
|
17356
|
-
modelSettings:
|
|
17357
|
-
modelSettingsPersistAsDefault:
|
|
17358
|
-
isManuallyChanged:
|
|
17393
|
+
modelSettings: original.modelSettings,
|
|
17394
|
+
modelSettingsPersistAsDefault: original.modelSettingsPersistAsDefault,
|
|
17395
|
+
isManuallyChanged: original.isManuallyChanged
|
|
17359
17396
|
} : current;
|
|
17360
17397
|
});
|
|
17361
17398
|
captured.delete(key);
|
|
@@ -17364,15 +17401,20 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17364
17401
|
has(key) {
|
|
17365
17402
|
return captured.has(key);
|
|
17366
17403
|
},
|
|
17404
|
+
/** The carrier last written to this draft, or null while it keeps its native setting. */
|
|
17405
|
+
model(key) {
|
|
17406
|
+
return captured.get(key)?.model ?? null;
|
|
17407
|
+
},
|
|
17367
17408
|
apply(key, binding, model2) {
|
|
17368
17409
|
if (model2 === null) {
|
|
17369
17410
|
restore(key);
|
|
17370
17411
|
return;
|
|
17371
17412
|
}
|
|
17372
17413
|
const { update, usesAccountPreferences } = binding;
|
|
17414
|
+
const previous = captured.get(key);
|
|
17415
|
+
const entry = { update, model: model2 };
|
|
17373
17416
|
update((current) => {
|
|
17374
|
-
|
|
17375
|
-
captured.set(key, { update, original: previous?.original ?? current, model: model2 });
|
|
17417
|
+
entry.original ??= previous?.original ?? current;
|
|
17376
17418
|
const settings = current.modelSettings;
|
|
17377
17419
|
if (settings?.model === model2 && settings.usesAccountPreferences === usesAccountPreferences && current.modelSettingsPersistAsDefault === false)
|
|
17378
17420
|
return current;
|
|
@@ -17389,6 +17431,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17389
17431
|
}
|
|
17390
17432
|
};
|
|
17391
17433
|
});
|
|
17434
|
+
captured.set(key, entry);
|
|
17392
17435
|
},
|
|
17393
17436
|
dispose() {
|
|
17394
17437
|
for (const key of captured.keys())
|
|
@@ -17463,14 +17506,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17463
17506
|
|
|
17464
17507
|
// ../desktop-control/dist/renderer-host-discovery.js
|
|
17465
17508
|
function requestManagerFromHookState(value, hostId2) {
|
|
17466
|
-
const
|
|
17509
|
+
const record10 = (candidate) => typeof candidate === "object" && candidate !== null;
|
|
17467
17510
|
const manager = (candidate) => {
|
|
17468
|
-
if (!
|
|
17511
|
+
if (!record10(candidate) || !record10(candidate.requestClient) || !record10(candidate.prewarmedThreadManager))
|
|
17469
17512
|
return null;
|
|
17470
17513
|
const bridge = candidate.requestClient;
|
|
17471
17514
|
return typeof candidate.sendRequest === "function" && typeof bridge.sendRequest === "function" && typeof bridge.prewarmThreadStart === "function" && typeof bridge.enqueueRequest === "function" && typeof candidate.prewarmedThreadManager.discardAllPrewarmedThreads === "function" ? candidate : null;
|
|
17472
17515
|
};
|
|
17473
|
-
if (!
|
|
17516
|
+
if (!record10(value))
|
|
17474
17517
|
return null;
|
|
17475
17518
|
const direct = manager(value) ?? manager(value.manager);
|
|
17476
17519
|
if (direct)
|
|
@@ -17531,14 +17574,197 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17531
17574
|
};
|
|
17532
17575
|
}
|
|
17533
17576
|
|
|
17534
|
-
// ../desktop-control/dist/renderer-
|
|
17577
|
+
// ../desktop-control/dist/renderer-host-rpc-discovery.js
|
|
17578
|
+
function findRendererHostRpcFamily(store) {
|
|
17579
|
+
const record10 = (value) => typeof value === "object" && value !== null;
|
|
17580
|
+
const families = /* @__PURE__ */ new Set();
|
|
17581
|
+
for (const [definition, members] of store.familyBindings) {
|
|
17582
|
+
if (!record10(definition) || definition.kind !== "signal-family")
|
|
17583
|
+
continue;
|
|
17584
|
+
if (!record10(members) || typeof members.get !== "function")
|
|
17585
|
+
continue;
|
|
17586
|
+
for (const [hostId2, member] of members) {
|
|
17587
|
+
if (typeof hostId2 !== "string" || !record10(member))
|
|
17588
|
+
continue;
|
|
17589
|
+
const signal = member.value;
|
|
17590
|
+
if (!record10(signal) || typeof signal.get !== "function")
|
|
17591
|
+
continue;
|
|
17592
|
+
let value;
|
|
17593
|
+
try {
|
|
17594
|
+
value = signal.get();
|
|
17595
|
+
} catch {
|
|
17596
|
+
continue;
|
|
17597
|
+
}
|
|
17598
|
+
if (record10(value) && Object.keys(value).length === 2 && typeof value.status === "string" && record10(value.client) && value.client.hostId === hostId2 && "rpc" in value.client) {
|
|
17599
|
+
families.add(members);
|
|
17600
|
+
break;
|
|
17601
|
+
}
|
|
17602
|
+
}
|
|
17603
|
+
}
|
|
17604
|
+
if (families.size !== 1)
|
|
17605
|
+
return null;
|
|
17606
|
+
return { store, family: families.values().next().value };
|
|
17607
|
+
}
|
|
17608
|
+
function resolveRendererHostRpc(discovery, hostId2) {
|
|
17609
|
+
const record10 = (value2) => typeof value2 === "object" && value2 !== null;
|
|
17610
|
+
const signal = discovery.family.get(hostId2)?.value;
|
|
17611
|
+
if (!record10(signal) || typeof signal.get !== "function")
|
|
17612
|
+
return null;
|
|
17613
|
+
let value;
|
|
17614
|
+
try {
|
|
17615
|
+
value = signal.get();
|
|
17616
|
+
} catch {
|
|
17617
|
+
return null;
|
|
17618
|
+
}
|
|
17619
|
+
if (!record10(value) || value.status !== "ready" || !record10(value.client) || value.client.hostId !== hostId2)
|
|
17620
|
+
return null;
|
|
17621
|
+
const rpc = value.client.rpc;
|
|
17622
|
+
return typeof rpc === "function" || record10(rpc) ? rpc : null;
|
|
17623
|
+
}
|
|
17624
|
+
|
|
17625
|
+
// ../desktop-control/dist/renderer-schedule-workspace-rpc.js
|
|
17535
17626
|
var record5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17627
|
+
function localAppScope(root) {
|
|
17628
|
+
const scopes = /* @__PURE__ */ new Map();
|
|
17629
|
+
const seen = /* @__PURE__ */ new Set();
|
|
17630
|
+
for (const main of root.querySelectorAll("main")) {
|
|
17631
|
+
const keys = Object.getOwnPropertyNames(main).filter((key2) => key2.startsWith("__reactFiber$"));
|
|
17632
|
+
const key = keys[0];
|
|
17633
|
+
if (keys.length !== 1 || !key)
|
|
17634
|
+
continue;
|
|
17635
|
+
for (const fiber of committedReactAncestors(Reflect.get(main, key))) {
|
|
17636
|
+
if (seen.has(fiber))
|
|
17637
|
+
break;
|
|
17638
|
+
seen.add(fiber);
|
|
17639
|
+
let hook = fiber.memoizedState;
|
|
17640
|
+
for (let n = 0; record5(hook) && "next" in hook && n < 150; n++, hook = hook.next) {
|
|
17641
|
+
const handle = record5(hook.memoizedState) ? hook.memoizedState.current : null;
|
|
17642
|
+
if (!record5(handle) || !record5(handle.node) || handle.node.parent != null || !("chain" in handle) || !("scope" in handle) || typeof handle.get !== "function" || typeof handle.set !== "function" || typeof handle.watch !== "function" || !(handle.node.familyBindings instanceof Map))
|
|
17643
|
+
continue;
|
|
17644
|
+
scopes.set(handle.node, { handle, store: handle.node });
|
|
17645
|
+
}
|
|
17646
|
+
}
|
|
17647
|
+
}
|
|
17648
|
+
const scope = scopes.values().next().value;
|
|
17649
|
+
if (scopes.size !== 1 || !scope)
|
|
17650
|
+
throw new Error("Native local app scope is missing or ambiguous");
|
|
17651
|
+
const discovery = findRendererHostRpcFamily(scope.store);
|
|
17652
|
+
const rpc = discovery && resolveRendererHostRpc(discovery, "local");
|
|
17653
|
+
if (!discovery || !rpc)
|
|
17654
|
+
throw new Error("Native local app RPC is unavailable");
|
|
17655
|
+
return { ...scope, discovery, rpc };
|
|
17656
|
+
}
|
|
17657
|
+
async function createRpcScheduleWorkspaceThread(root, routing, route, createThread, input, signal) {
|
|
17658
|
+
if (!route.policy.scopedCreation)
|
|
17659
|
+
throw new Error("Native local chat creation is unavailable");
|
|
17660
|
+
const scope = localAppScope(root);
|
|
17661
|
+
const assertConnection = () => {
|
|
17662
|
+
if (routing.forHost("local")?.manager !== route.manager || resolveRendererHostRpc(scope.discovery, "local") !== scope.rpc)
|
|
17663
|
+
throw new Error("The local connection changed. Reopen the task dialog.");
|
|
17664
|
+
};
|
|
17665
|
+
const assertCurrent = () => {
|
|
17666
|
+
signal.throwIfAborted();
|
|
17667
|
+
assertConnection();
|
|
17668
|
+
};
|
|
17669
|
+
const request = async (method, params) => {
|
|
17670
|
+
assertConnection();
|
|
17671
|
+
return route.manager.sendRequest(method, params);
|
|
17672
|
+
};
|
|
17673
|
+
const readEmpty = async (threadId) => {
|
|
17674
|
+
const read = await request("thread/read", { threadId, includeTurns: false });
|
|
17675
|
+
if (!record5(read) || !record5(read.thread) || read.thread.id !== threadId || !record5(read.thread.status))
|
|
17676
|
+
throw new Error("The created chat could not be read");
|
|
17677
|
+
const turns = await request("thread/turns/list", { threadId, cursor: null, limit: 1 });
|
|
17678
|
+
const queue = await request("thread/queue/list", { threadId, cursor: null, limit: 1 });
|
|
17679
|
+
if (!record5(turns) || !Array.isArray(turns.data) || !("nextCursor" in turns) || !record5(queue) || !Array.isArray(queue.data) || !("nextCursor" in queue))
|
|
17680
|
+
throw new Error("The created chat's history or queue could not be confirmed");
|
|
17681
|
+
return {
|
|
17682
|
+
thread: read.thread,
|
|
17683
|
+
empty: read.thread.status.type === "idle" && turns.data.length === 0 && turns.nextCursor === null && queue.data.length === 0 && queue.nextCursor === null
|
|
17684
|
+
};
|
|
17685
|
+
};
|
|
17686
|
+
assertCurrent();
|
|
17687
|
+
let createdId = null;
|
|
17688
|
+
let retained = false;
|
|
17689
|
+
let failed = false;
|
|
17690
|
+
let cleanup;
|
|
17691
|
+
const discard = () => {
|
|
17692
|
+
if (!createdId || retained)
|
|
17693
|
+
return Promise.resolve();
|
|
17694
|
+
const threadId = createdId;
|
|
17695
|
+
return cleanup ??= (async () => {
|
|
17696
|
+
const { empty } = await readEmpty(threadId);
|
|
17697
|
+
if (!empty || retained)
|
|
17698
|
+
return;
|
|
17699
|
+
await request("thread/archive", { threadId });
|
|
17700
|
+
})();
|
|
17701
|
+
};
|
|
17702
|
+
const discardAfterDismissal = () => {
|
|
17703
|
+
void discard().catch((error51) => {
|
|
17704
|
+
console.error("Could not discard the unsubmitted schedule chat. Check the chat list.", error51);
|
|
17705
|
+
});
|
|
17706
|
+
};
|
|
17707
|
+
signal.addEventListener("abort", discardAfterDismissal, { once: true });
|
|
17708
|
+
const remember = (result) => {
|
|
17709
|
+
if (!record5(result) || result.status !== "created")
|
|
17710
|
+
return;
|
|
17711
|
+
const id = hostThreadIdSchema.safeParse(result.conversationId);
|
|
17712
|
+
if (!id.success)
|
|
17713
|
+
return;
|
|
17714
|
+
if (createdId && createdId !== id.data)
|
|
17715
|
+
throw new Error("Chat creation returned conflicting identities");
|
|
17716
|
+
createdId = id.data;
|
|
17717
|
+
if (signal.aborted || failed)
|
|
17718
|
+
discardAfterDismissal();
|
|
17719
|
+
};
|
|
17720
|
+
try {
|
|
17721
|
+
const output = await createThread({
|
|
17722
|
+
scope: scope.handle,
|
|
17723
|
+
target: { type: "project", projectId: input.workspace.id, environment: { type: "local" } },
|
|
17724
|
+
model: input.model,
|
|
17725
|
+
title: input.title,
|
|
17726
|
+
prompt: "",
|
|
17727
|
+
startWithoutFirstTurn: true,
|
|
17728
|
+
assertRequestCurrent: assertCurrent,
|
|
17729
|
+
onSettled: remember
|
|
17730
|
+
});
|
|
17731
|
+
const result = record5(output) && output.kind === "creation" ? output.result : null;
|
|
17732
|
+
remember(result);
|
|
17733
|
+
assertCurrent();
|
|
17734
|
+
if (!record5(result) || result.status !== "created" || !createdId || !record5(result.firstTurn) || result.firstTurn.status !== "not-requested")
|
|
17735
|
+
throw new Error("Chat creation was not confirmed. Check the chat list before creating another task.");
|
|
17736
|
+
const { thread, empty } = await readEmpty(createdId);
|
|
17737
|
+
const inspection = threadInspectionSchema.parse(await request("codexhost/thread/inspect", { threadId: createdId }));
|
|
17738
|
+
assertCurrent();
|
|
17739
|
+
if (!empty || thread.cwd !== input.workspace.cwd || inspection.owner !== "external" || inspection.transportModelId !== input.model)
|
|
17740
|
+
throw new Error("The created chat's workspace, Model or empty state could not be confirmed");
|
|
17741
|
+
return {
|
|
17742
|
+
threadId: createdId,
|
|
17743
|
+
discard,
|
|
17744
|
+
retain() {
|
|
17745
|
+
retained = true;
|
|
17746
|
+
signal.removeEventListener("abort", discardAfterDismissal);
|
|
17747
|
+
}
|
|
17748
|
+
};
|
|
17749
|
+
} catch (error51) {
|
|
17750
|
+
failed = true;
|
|
17751
|
+
try {
|
|
17752
|
+
await discard();
|
|
17753
|
+
} catch (cleanupError) {
|
|
17754
|
+
throw new Error(`${error51 instanceof Error ? error51.message : String(error51)}; Chat cleanup failed: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}. Check the chat list.`);
|
|
17755
|
+
}
|
|
17756
|
+
throw error51;
|
|
17757
|
+
}
|
|
17758
|
+
}
|
|
17759
|
+
|
|
17760
|
+
// ../desktop-control/dist/renderer-schedule-workspace.js
|
|
17761
|
+
var record6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
17536
17762
|
function readNativeScheduleWorkspaces(root) {
|
|
17537
17763
|
const projects = /* @__PURE__ */ new Map();
|
|
17538
17764
|
const ambiguous = /* @__PURE__ */ new Set();
|
|
17539
17765
|
const seen = /* @__PURE__ */ new Set();
|
|
17540
17766
|
const add = (value) => {
|
|
17541
|
-
if (!
|
|
17767
|
+
if (!record6(value) || value.source !== "codex" || !record6(value.group))
|
|
17542
17768
|
return;
|
|
17543
17769
|
const group = value.group;
|
|
17544
17770
|
if (group.projectKind !== "local" || group.hostId != null && group.hostId !== "local" || typeof group.projectId !== "string" || !group.projectId || typeof group.label !== "string" || typeof group.path !== "string" || !Array.isArray(group.rootPaths) || !group.rootPaths.includes(group.path) || !/^(?:\/|[A-Za-z]:[\\/]|\\\\)/u.test(group.path) || group.path.includes("\0"))
|
|
@@ -17560,7 +17786,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17560
17786
|
break;
|
|
17561
17787
|
seen.add(fiber);
|
|
17562
17788
|
const props = fiber.memoizedProps;
|
|
17563
|
-
if (!
|
|
17789
|
+
if (!record6(props))
|
|
17564
17790
|
continue;
|
|
17565
17791
|
add(props.project);
|
|
17566
17792
|
if (props.projectByKey instanceof Map)
|
|
@@ -17571,15 +17797,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17571
17797
|
return [...projects.values()].filter(({ id }) => !ambiguous.has(id));
|
|
17572
17798
|
}
|
|
17573
17799
|
function isNativeProjectThreadCreator(value) {
|
|
17574
|
-
|
|
17800
|
+
try {
|
|
17801
|
+
if (typeof value !== "function" || value.length !== 1)
|
|
17802
|
+
return false;
|
|
17803
|
+
const source = Function.prototype.toString.call(value);
|
|
17804
|
+
return /^async function/u.test(source) && source.includes("startWithoutFirstTurn:") && source.includes("onSettled:") && source.includes("createThread config is not supported for delegated thread creation") && source.includes("createThread serviceName is only supported for local Electron root threads outside worktrees");
|
|
17805
|
+
} catch {
|
|
17575
17806
|
return false;
|
|
17576
|
-
|
|
17577
|
-
return /^async function/u.test(source) && source.includes("startWithoutFirstTurn:") && source.includes("onSettled:") && source.includes("createThread config is not supported for delegated thread creation") && source.includes("createThread serviceName is only supported for local Electron root threads outside worktrees");
|
|
17807
|
+
}
|
|
17578
17808
|
}
|
|
17579
17809
|
async function createNativeScheduleWorkspaceThread(root, routing, createThread, input, signal) {
|
|
17580
17810
|
if (!decodeHarnessPluginRoute(input.model))
|
|
17581
17811
|
throw new Error("An external Harness is required");
|
|
17582
17812
|
const route = routing.forHost("local");
|
|
17813
|
+
if (route && Reflect.get(route.manager, "kind") === "main-process-rpc") {
|
|
17814
|
+
if (!readNativeScheduleWorkspaces(root).some(({ id, cwd }) => id === input.workspace.id && cwd === input.workspace.cwd))
|
|
17815
|
+
throw new Error("The selected workspace is no longer available");
|
|
17816
|
+
return createRpcScheduleWorkspaceThread(root, routing, route, createThread, input, signal);
|
|
17817
|
+
}
|
|
17583
17818
|
const manager = route?.manager;
|
|
17584
17819
|
if (!route?.policy.scopedCreation || !manager || typeof manager.getConversation !== "function" || typeof manager.archiveConversation !== "function")
|
|
17585
17820
|
throw new Error("Native local chat creation is unavailable");
|
|
@@ -17594,7 +17829,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17594
17829
|
}
|
|
17595
17830
|
}));
|
|
17596
17831
|
const scope = scopes.values().next().value;
|
|
17597
|
-
if (scopes.size !== 1 || !
|
|
17832
|
+
if (scopes.size !== 1 || !record6(scope) || typeof scope.get !== "function")
|
|
17598
17833
|
throw new Error("Native local chat scope is missing or ambiguous");
|
|
17599
17834
|
if (!readNativeScheduleWorkspaces(root).some(({ id, cwd }) => id === input.workspace.id && cwd === input.workspace.cwd))
|
|
17600
17835
|
throw new Error("The selected workspace is no longer available");
|
|
@@ -17607,7 +17842,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17607
17842
|
const id = createdId;
|
|
17608
17843
|
released = true;
|
|
17609
17844
|
const conversation2 = manager.getConversation(id);
|
|
17610
|
-
if (!
|
|
17845
|
+
if (!record6(conversation2) || !Array.isArray(conversation2.turns) || conversation2.turns.length || Array.isArray(conversation2.requests) && conversation2.requests.length > 0 || conversation2.pendingRequest != null)
|
|
17611
17846
|
return;
|
|
17612
17847
|
void Promise.resolve().then(() => manager.archiveConversation(id, {
|
|
17613
17848
|
useAppServerPins: false,
|
|
@@ -17616,7 +17851,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17616
17851
|
};
|
|
17617
17852
|
signal.addEventListener("abort", discard, { once: true });
|
|
17618
17853
|
const remember = (result2) => {
|
|
17619
|
-
if (!
|
|
17854
|
+
if (!record6(result2) || result2.status !== "created")
|
|
17620
17855
|
return;
|
|
17621
17856
|
const id = hostThreadIdSchema.safeParse(result2.conversationId);
|
|
17622
17857
|
if (id.success)
|
|
@@ -17633,16 +17868,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
17633
17868
|
startWithoutFirstTurn: true,
|
|
17634
17869
|
onSettled: remember
|
|
17635
17870
|
});
|
|
17636
|
-
const result =
|
|
17871
|
+
const result = record6(output) && output.kind === "creation" ? output.result : null;
|
|
17637
17872
|
remember(result);
|
|
17638
17873
|
signal.throwIfAborted();
|
|
17639
|
-
if (!
|
|
17874
|
+
if (!record6(result) || result.status !== "created" || !createdId || !record6(result.firstTurn) || result.firstTurn.status !== "not-requested")
|
|
17640
17875
|
throw new Error("Chat creation was not confirmed. Check the chat list before creating another task.");
|
|
17641
17876
|
if (routing.forHost("local")?.manager !== route.manager)
|
|
17642
17877
|
throw new Error("The local connection changed. Reopen the task dialog.");
|
|
17643
17878
|
const conversation = manager.getConversation(createdId);
|
|
17644
|
-
const mode =
|
|
17645
|
-
if (!
|
|
17879
|
+
const mode = record6(conversation) ? conversation.latestCollaborationMode : null;
|
|
17880
|
+
if (!record6(conversation) || conversation.cwd !== input.workspace.cwd || !record6(mode) || !record6(mode.settings) || mode.settings.model !== input.model)
|
|
17646
17881
|
throw new Error("The created chat's workspace or Model could not be confirmed");
|
|
17647
17882
|
return {
|
|
17648
17883
|
threadId: createdId,
|
|
@@ -18450,6 +18685,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
|
|
|
18450
18685
|
loaded = true;
|
|
18451
18686
|
show(value);
|
|
18452
18687
|
}).catch(() => {
|
|
18688
|
+
loaded = true;
|
|
18453
18689
|
status.textContent = messages.launchPathLoadError;
|
|
18454
18690
|
}).finally(() => {
|
|
18455
18691
|
busy = false;
|
|
@@ -20029,7 +20265,7 @@ ${messages.harnessVersionLatest}: ${harnessVersionLabel(version2.state, messages
|
|
|
20029
20265
|
launchPathAutomatic: "No saved override. Uses environment configuration, then automatic discovery.",
|
|
20030
20266
|
launchPathSaving: "Saving\u2026",
|
|
20031
20267
|
launchPathLoading: "Loading launch settings\u2026",
|
|
20032
|
-
launchPathLoadError: "Could not load launch settings.
|
|
20268
|
+
launchPathLoadError: "Could not load launch settings. Save an installation directory or reset to automatic discovery to replace them.",
|
|
20033
20269
|
launchPathSaveError: "Could not save. Enter an existing absolute installation folder on this Host and check configuration permissions.",
|
|
20034
20270
|
connectionOfficialWebsite: "Visit official website",
|
|
20035
20271
|
connectionOpenHarnessWeb: "Open DeepSeek Harness Web",
|
|
@@ -20308,7 +20544,7 @@ ${messages.harnessVersionLatest}: ${harnessVersionLabel(version2.state, messages
|
|
|
20308
20544
|
launchPathAutomatic: "\u672A\u8BBE\u7F6E\u81EA\u5B9A\u4E49\u8DEF\u5F84\uFF0C\u4F7F\u7528\u73AF\u5883\u53D8\u91CF\u914D\u7F6E\u6216\u81EA\u52A8\u53D1\u73B0\u3002",
|
|
20309
20545
|
launchPathSaving: "\u6B63\u5728\u4FDD\u5B58\u2026",
|
|
20310
20546
|
launchPathLoading: "\u6B63\u5728\u8BFB\u53D6\u542F\u52A8\u8BBE\u7F6E\u2026",
|
|
20311
|
-
launchPathLoadError: "\u65E0\u6CD5\u8BFB\u53D6\u542F\u52A8\u8BBE\u7F6E\
|
|
20547
|
+
launchPathLoadError: "\u65E0\u6CD5\u8BFB\u53D6\u542F\u52A8\u8BBE\u7F6E\u3002\u4FDD\u5B58\u5B89\u88C5\u76EE\u5F55\u6216\u6062\u590D\u81EA\u52A8\u53D1\u73B0\u5373\u53EF\u66FF\u6362\u3002",
|
|
20312
20548
|
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",
|
|
20313
20549
|
connectionOfficialWebsite: "\u8BBF\u95EE\u5B98\u7F51",
|
|
20314
20550
|
connectionOpenHarnessWeb: "\u6253\u5F00 DeepSeek Harness Web",
|
|
@@ -25553,10 +25789,16 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
25553
25789
|
const currentRole = manager.getStreamRole?.(threadId);
|
|
25554
25790
|
if (isRecord7(currentRole) && currentRole.role === "follower")
|
|
25555
25791
|
return originalSteer.apply(manager, args);
|
|
25556
|
-
if (!Array.isArray(input) || input.length === 0 || input.some(
|
|
25557
|
-
(
|
|
25558
|
-
|
|
25559
|
-
|
|
25792
|
+
if (!Array.isArray(input) || input.length === 0 || input.some((item) => {
|
|
25793
|
+
if (!isRecord7(item)) return true;
|
|
25794
|
+
if (item.type === "text") return typeof item.text !== "string";
|
|
25795
|
+
if (item.type === "localImage") return typeof item.path !== "string" || !item.path;
|
|
25796
|
+
if (item.type === "image") return typeof item.url !== "string" || !item.url;
|
|
25797
|
+
return true;
|
|
25798
|
+
}) || !input.some(
|
|
25799
|
+
(item) => isRecord7(item) && (item.type !== "text" || typeof item.text === "string" && item.text.trim())
|
|
25800
|
+
)) {
|
|
25801
|
+
throw new Error("External steering requires non-empty text or image input");
|
|
25560
25802
|
}
|
|
25561
25803
|
if (toolOutput != null) throw new Error("External steering cannot replace a tool response");
|
|
25562
25804
|
if (!isRecord7(restoreMessage) || !isRecord7(restoreMessage.context)) {
|
|
@@ -25677,16 +25919,6 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
25677
25919
|
for (let index = 0; index < decoded.length; index += 1) bytes[index] = decoded.charCodeAt(index);
|
|
25678
25920
|
return { contents: new Blob([bytes], { type: mimeType }), extension };
|
|
25679
25921
|
}
|
|
25680
|
-
function nativeImagePaths(text) {
|
|
25681
|
-
const context = text.split("## My request:")[0] ?? "";
|
|
25682
|
-
const start = context.indexOf("# Files mentioned by the user:");
|
|
25683
|
-
if (start < 0) return [];
|
|
25684
|
-
return [
|
|
25685
|
-
...context.slice(start).matchAll(
|
|
25686
|
-
/(?:^|\n)## [^\r\n]+: ((?:\/|[A-Za-z]:[\\/]|\\\\)[^\r\n]+)\r?\nImage attachment: true(?=\r?\n|$)/gu
|
|
25687
|
-
)
|
|
25688
|
-
].map((match) => match[1]).filter(filePath);
|
|
25689
|
-
}
|
|
25690
25922
|
function createRemoteAttachmentSender(target, hostId2, isCurrent) {
|
|
25691
25923
|
const prepared = /* @__PURE__ */ new WeakMap();
|
|
25692
25924
|
return (params, send) => {
|
|
@@ -25711,7 +25943,7 @@ Codex Fast mode prioritizes requests and may increase usage.`
|
|
|
25711
25943
|
if (cached2) return cached2.then(dispatch);
|
|
25712
25944
|
const input = params.input;
|
|
25713
25945
|
const text = input.filter((item) => isRecord8(item) && item.type === "text").map((item) => isRecord8(item) && typeof item.text === "string" ? item.text : "").join("\n");
|
|
25714
|
-
const existingPaths =
|
|
25946
|
+
const existingPaths = desktopImageAttachmentPaths(text);
|
|
25715
25947
|
const prepare = async () => {
|
|
25716
25948
|
if (existingPaths.length === images.length) return params;
|
|
25717
25949
|
if (images.length > 20) throw new Error("Too many remote image attachments (maximum 20)");
|
|
@@ -25792,10 +26024,72 @@ ${text.includes("## My request:") ? "" : "\n## My request:\n"}`,
|
|
|
25792
26024
|
};
|
|
25793
26025
|
}
|
|
25794
26026
|
|
|
26027
|
+
// src/renderer-thread-reference-persistence.ts
|
|
26028
|
+
var record7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
26029
|
+
var SYNC_TIMEOUT_MS = 2e3;
|
|
26030
|
+
function restoreRpcThreadReferenceCapability(client, messages, isCurrent) {
|
|
26031
|
+
if (!record7(messages) || !record7(messages.electronBridge)) return client;
|
|
26032
|
+
const bridge = messages.electronBridge;
|
|
26033
|
+
const send = bridge.sendMessageFromView;
|
|
26034
|
+
if (typeof send !== "function") return client;
|
|
26035
|
+
const inspect = client.inspectThread.bind(client);
|
|
26036
|
+
const checked = /* @__PURE__ */ new Set();
|
|
26037
|
+
const isMissing = (key) => new Promise((resolve) => {
|
|
26038
|
+
const finish = (missing) => {
|
|
26039
|
+
clearTimeout(timer);
|
|
26040
|
+
messages.removeEventListener("message", listener);
|
|
26041
|
+
resolve(missing);
|
|
26042
|
+
};
|
|
26043
|
+
const listener = (event) => {
|
|
26044
|
+
if (event.source != null && event.source !== messages) return;
|
|
26045
|
+
const message2 = event.data;
|
|
26046
|
+
if (!record7(message2) || message2.type !== "persisted-atom-sync" || !record7(message2.state))
|
|
26047
|
+
return;
|
|
26048
|
+
finish(!Object.hasOwn(message2.state, key));
|
|
26049
|
+
};
|
|
26050
|
+
const timer = setTimeout(() => finish(false), SYNC_TIMEOUT_MS);
|
|
26051
|
+
messages.addEventListener("message", listener);
|
|
26052
|
+
try {
|
|
26053
|
+
Promise.resolve(
|
|
26054
|
+
send.call(bridge, { type: "persisted-atom-sync-request", responsePriority: "critical" })
|
|
26055
|
+
).catch(() => finish(false));
|
|
26056
|
+
} catch {
|
|
26057
|
+
finish(false);
|
|
26058
|
+
}
|
|
26059
|
+
});
|
|
26060
|
+
const inspectThread = async (input) => {
|
|
26061
|
+
if (!isCurrent() || checked.has(input.threadId)) return inspect(input);
|
|
26062
|
+
checked.add(input.threadId);
|
|
26063
|
+
const key = `thread-reference-capability:${input.threadId}`;
|
|
26064
|
+
if (!await isMissing(key) || !isCurrent()) return inspect(input);
|
|
26065
|
+
let proven = true;
|
|
26066
|
+
const result = await inspect({ ...input, includeReferenceCapability: true }).catch(() => {
|
|
26067
|
+
proven = false;
|
|
26068
|
+
return inspect(input);
|
|
26069
|
+
});
|
|
26070
|
+
if (proven && result.owner === "codex" && result.supportsThreadReferences === true && isCurrent() && await isMissing(key) && isCurrent()) {
|
|
26071
|
+
try {
|
|
26072
|
+
await send.call(bridge, {
|
|
26073
|
+
type: "persisted-atom-update",
|
|
26074
|
+
key,
|
|
26075
|
+
value: true,
|
|
26076
|
+
deleted: false
|
|
26077
|
+
});
|
|
26078
|
+
} catch {
|
|
26079
|
+
}
|
|
26080
|
+
}
|
|
26081
|
+
return result;
|
|
26082
|
+
};
|
|
26083
|
+
return Object.freeze({ ...client, inspectThread });
|
|
26084
|
+
}
|
|
26085
|
+
|
|
25795
26086
|
// src/renderer-thread-reference-capability.ts
|
|
25796
|
-
var
|
|
25797
|
-
function restoreThreadReferenceCapability(client, manager, isCurrent) {
|
|
25798
|
-
if (
|
|
26087
|
+
var record8 = (value) => typeof value === "object" && value !== null;
|
|
26088
|
+
function restoreThreadReferenceCapability(client, manager, isCurrent, messages = null) {
|
|
26089
|
+
if (record8(manager) && manager.kind === "main-process-rpc") {
|
|
26090
|
+
return restoreRpcThreadReferenceCapability(client, messages, isCurrent);
|
|
26091
|
+
}
|
|
26092
|
+
if (!record8(manager) || !record8(manager.storage)) return client;
|
|
25799
26093
|
const storage = manager.storage;
|
|
25800
26094
|
const read = storage.readValue;
|
|
25801
26095
|
const write = storage.writeValue;
|
|
@@ -25830,14 +26124,14 @@ ${text.includes("## My request:") ? "" : "\n## My request:\n"}`,
|
|
|
25830
26124
|
}
|
|
25831
26125
|
|
|
25832
26126
|
// src/renderer-thread-reference-context.ts
|
|
25833
|
-
var
|
|
26127
|
+
var record9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
25834
26128
|
function createThreadReferenceContext(manager, hostId2, isCurrent) {
|
|
25835
26129
|
const prepared = /* @__PURE__ */ new WeakMap();
|
|
25836
26130
|
return (params) => {
|
|
25837
|
-
if (hostId2 === "local" || !
|
|
26131
|
+
if (hostId2 === "local" || !record9(manager) || typeof manager.getConversation !== "function" || !record9(params) || typeof params.threadId !== "string")
|
|
25838
26132
|
return params;
|
|
25839
26133
|
const conversation = manager.getConversation.call(manager, params.threadId);
|
|
25840
|
-
if (!
|
|
26134
|
+
if (!record9(conversation) || conversation.id !== params.threadId || conversation.modelProvider !== "codexhost")
|
|
25841
26135
|
return params;
|
|
25842
26136
|
if (!isCurrent()) throw new Error("Thread reference connection is no longer available");
|
|
25843
26137
|
const cached2 = prepared.get(params);
|
|
@@ -25943,7 +26237,8 @@ ${text.includes("## My request:") ? "" : "\n## My request:\n"}`,
|
|
|
25943
26237
|
const client = restoreThreadReferenceCapability(
|
|
25944
26238
|
nativeClient,
|
|
25945
26239
|
target,
|
|
25946
|
-
() => !disposed && readRouting()?.forHost(route.hostId) === route
|
|
26240
|
+
() => !disposed && readRouting()?.forHost(route.hostId) === route,
|
|
26241
|
+
messages
|
|
25947
26242
|
);
|
|
25948
26243
|
entries.set(route.hostId, { route, client, cleanups });
|
|
25949
26244
|
try {
|
|
@@ -27157,8 +27452,18 @@ ${text.includes("## My request:") ? "" : "\n## My request:\n"}`,
|
|
|
27157
27452
|
const draftKey = target[1];
|
|
27158
27453
|
if (!binding || !route.policy.scopedCreation)
|
|
27159
27454
|
return agent === "codex" && !draftModels.has(draftKey);
|
|
27160
|
-
draftModels.
|
|
27161
|
-
|
|
27455
|
+
const previous = draftModels.model(draftKey);
|
|
27456
|
+
const policyChanged = route.policy.select(carrier ?? null, draftKey, binding.creationModes);
|
|
27457
|
+
try {
|
|
27458
|
+
draftModels.apply(draftKey, binding, carrier ?? null);
|
|
27459
|
+
} catch (error51) {
|
|
27460
|
+
try {
|
|
27461
|
+
route.policy.select(previous, draftKey, binding.creationModes);
|
|
27462
|
+
} catch {
|
|
27463
|
+
}
|
|
27464
|
+
throw error51;
|
|
27465
|
+
}
|
|
27466
|
+
if (policyChanged) {
|
|
27162
27467
|
modelUpdates += 1;
|
|
27163
27468
|
liveStatus.modelUpdates = modelUpdates;
|
|
27164
27469
|
}
|
|
@@ -30363,7 +30668,7 @@ ${detail}` : ""}`
|
|
|
30363
30668
|
"codexhost was not detected over SSH. Install it on the remote computer or add it to the login shell PATH, then retry": "\u901A\u8FC7 SSH \u672A\u68C0\u6D4B\u5230 codexhost\u3002\u8BF7\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u5B89\u88C5\uFF0C\u6216\u5C06\u5DF2\u5B89\u88C5\u7684 codexhost \u52A0\u5165\u767B\u5F55 shell \u7684 PATH \u540E\u91CD\u8BD5",
|
|
30364
30669
|
"The active codexhost does not match the global npm installation. Uninstall only the remote service, or remove the package manually on the remote computer": "\u5F53\u524D codexhost \u4E0E npm \u5168\u5C40\u5B89\u88C5\u4F4D\u7F6E\u4E0D\u5339\u914D\u3002\u8BF7\u9009\u62E9\u4EC5\u5378\u8F7D\u8FDC\u7A0B\u670D\u52A1\uFF0C\u6216\u5728\u8FDC\u7A0B\u7535\u8111\u4E0A\u624B\u52A8\u5378\u8F7D\u8F6F\u4EF6\u5305",
|
|
30365
30670
|
"The remote service was uninstalled, but removing the codexhost package failed. Check npm permissions on the remote computer and retry": "\u8FDC\u7A0B\u670D\u52A1\u5DF2\u5378\u8F7D\uFF0C\u4F46 codexhost \u8F6F\u4EF6\u5305\u5378\u8F7D\u5931\u8D25\u3002\u8BF7\u68C0\u67E5\u8FDC\u7A0B\u7535\u8111\u4E0A\u7684 npm \u6743\u9650\u540E\u91CD\u8BD5",
|
|
30366
|
-
"Remote Node.js is unsupported. Select Node.js 22.19 or later
|
|
30671
|
+
"Remote Node.js is unsupported. Select Node.js 22.19 or later, except 23.x": "\u8FDC\u7A0B Node.js \u7248\u672C\u4E0D\u53D7\u652F\u6301\uFF0C\u8BF7\u9009\u62E9 Node.js 22.19 \u53CA\u4EE5\u4E0A\u7248\u672C\uFF0C\u4F46\u4E0D\u5305\u62EC 23.x",
|
|
30367
30672
|
"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",
|
|
30368
30673
|
"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",
|
|
30369
30674
|
"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",
|
|
@@ -31795,6 +32100,30 @@ ${detail}` : ""}`
|
|
|
31795
32100
|
};
|
|
31796
32101
|
}
|
|
31797
32102
|
|
|
32103
|
+
// src/settings/session-import-sources.ts
|
|
32104
|
+
async function loadSessionImportSources(client, diagnostics, signal, refresh) {
|
|
32105
|
+
const { harnesses } = await client.listSessionImportSources();
|
|
32106
|
+
signal.throwIfAborted();
|
|
32107
|
+
if (!diagnostics || harnesses.length === 0) return harnesses;
|
|
32108
|
+
const hostId2 = client.hostId ?? "local";
|
|
32109
|
+
const readHost = () => diagnostics.snapshot().hosts.find((host2) => host2.hostId === hostId2);
|
|
32110
|
+
let host = readHost();
|
|
32111
|
+
const incomplete = () => !host || Boolean(host.directoryError) || harnesses.some(({ harnessId }) => {
|
|
32112
|
+
const status = host?.agents.find(({ agent }) => agent === harnessId)?.availability;
|
|
32113
|
+
return status === void 0 || status === "checking";
|
|
32114
|
+
});
|
|
32115
|
+
if (refresh || incomplete()) {
|
|
32116
|
+
await diagnostics.refresh(hostId2);
|
|
32117
|
+
signal.throwIfAborted();
|
|
32118
|
+
host = readHost();
|
|
32119
|
+
}
|
|
32120
|
+
if (incomplete()) throw new Error("Harness installation diagnostics are incomplete");
|
|
32121
|
+
const missing = new Set(
|
|
32122
|
+
host?.agents.filter(({ availability }) => availability === "notInstalled").map(({ agent }) => agent)
|
|
32123
|
+
);
|
|
32124
|
+
return harnesses.filter(({ harnessId }) => !missing.has(harnessId));
|
|
32125
|
+
}
|
|
32126
|
+
|
|
31798
32127
|
// src/settings/session-import-page.ts
|
|
31799
32128
|
function shortSessionId(value) {
|
|
31800
32129
|
return value.length <= 18 ? value : `${value.slice(0, 10)}\u2026${value.slice(-6)}`;
|
|
@@ -31864,7 +32193,7 @@ ${detail}` : ""}`
|
|
|
31864
32193
|
...getDiagnostics()?.snapshot().hosts.map(({ hostId: hostId2 }) => hostId2) ?? [],
|
|
31865
32194
|
...current ? [current] : []
|
|
31866
32195
|
])
|
|
31867
|
-
];
|
|
32196
|
+
].filter((hostId2) => hostId2 !== "durable");
|
|
31868
32197
|
displayedHostId = current;
|
|
31869
32198
|
const scrollLeft = hostOptions.scrollLeft;
|
|
31870
32199
|
hostOptions.replaceChildren();
|
|
@@ -32208,10 +32537,14 @@ ${detail}` : ""}`
|
|
|
32208
32537
|
content.append(list);
|
|
32209
32538
|
updateImportActions();
|
|
32210
32539
|
};
|
|
32211
|
-
const load = () => {
|
|
32540
|
+
const load = (refreshDiagnostics = false) => {
|
|
32212
32541
|
if (importingId !== null || context.signal.aborted) return;
|
|
32213
32542
|
loadedClient = null;
|
|
32214
|
-
|
|
32543
|
+
let client = getClient(selectedHostId);
|
|
32544
|
+
if (client?.hostId === "durable") {
|
|
32545
|
+
selectedHostId = "local";
|
|
32546
|
+
client = getClient(selectedHostId);
|
|
32547
|
+
}
|
|
32215
32548
|
renderHosts(client);
|
|
32216
32549
|
listControls.setBusy(client !== null);
|
|
32217
32550
|
refresh.disabled = client !== null;
|
|
@@ -32224,11 +32557,11 @@ ${detail}` : ""}`
|
|
|
32224
32557
|
void context.runLatest(
|
|
32225
32558
|
async (signal) => {
|
|
32226
32559
|
if (!client) throw new RendererSessionImportUnavailableError();
|
|
32227
|
-
const
|
|
32228
|
-
|
|
32229
|
-
|
|
32230
|
-
|
|
32231
|
-
|
|
32560
|
+
const harnesses = await loadSessionImportSources(
|
|
32561
|
+
client,
|
|
32562
|
+
getDiagnostics(),
|
|
32563
|
+
signal,
|
|
32564
|
+
refreshDiagnostics
|
|
32232
32565
|
);
|
|
32233
32566
|
const selected = harnesses.find(({ harnessId }) => harnessId === requestedHarness)?.harnessId ?? harnesses[0]?.harnessId ?? null;
|
|
32234
32567
|
if (signal.aborted) throw new Error("Session import selection changed");
|
|
@@ -32279,7 +32612,7 @@ ${detail}` : ""}`
|
|
|
32279
32612
|
load();
|
|
32280
32613
|
hostButtons.find((button2) => button2.dataset.sessionImportHost === hostId2)?.focus();
|
|
32281
32614
|
};
|
|
32282
|
-
refresh.addEventListener("click", load);
|
|
32615
|
+
refresh.addEventListener("click", () => load(true));
|
|
32283
32616
|
load();
|
|
32284
32617
|
return void 0;
|
|
32285
32618
|
}
|
|
@@ -32772,7 +33105,7 @@ ${detail}` : ""}`
|
|
|
32772
33105
|
}
|
|
32773
33106
|
function defaultImportName(source, existing) {
|
|
32774
33107
|
const base = source.provider === "openai-codex" ? "codex" : "grok";
|
|
32775
|
-
const used = new Set(existing.map((
|
|
33108
|
+
const used = new Set(existing.map((record10) => record10.name));
|
|
32776
33109
|
const valid = (name) => credentialImportNameSchema.safeParse(name).success;
|
|
32777
33110
|
if (!used.has(base)) return base;
|
|
32778
33111
|
const local = source.label.includes("@") ? source.label.split("@")[0] ?? "" : "";
|
|
@@ -32795,7 +33128,7 @@ ${detail}` : ""}`
|
|
|
32795
33128
|
const shown = (text) => accountDisplayText(text, hideEmails);
|
|
32796
33129
|
const targetButtons = /* @__PURE__ */ new Map();
|
|
32797
33130
|
const importedRecords = () => snapshot.targets.find((target) => target.harnessId === TARGET_HARNESS_ID)?.imports ?? [];
|
|
32798
|
-
const sourceOf = (
|
|
33131
|
+
const sourceOf = (record10) => snapshot.sources.find((source) => source.id === record10.source.id);
|
|
32799
33132
|
const piTarget = () => snapshot.targets.find((candidate) => candidate.harnessId === TARGET_HARNESS_ID);
|
|
32800
33133
|
const compatibleSources = () => {
|
|
32801
33134
|
const target = piTarget();
|
|
@@ -32833,7 +33166,7 @@ ${detail}` : ""}`
|
|
|
32833
33166
|
sectionImport.addEventListener("click", () => {
|
|
32834
33167
|
const sources = compatibleSources();
|
|
32835
33168
|
const free = sources.find(
|
|
32836
|
-
(source2) => !importedRecords().some((
|
|
33169
|
+
(source2) => !importedRecords().some((record10) => record10.source.id === source2.id)
|
|
32837
33170
|
);
|
|
32838
33171
|
const source = free ?? sources[0];
|
|
32839
33172
|
if (source) openDialog("add", { source, choose: true }, SECTION_IMPORT_KEY);
|
|
@@ -32883,30 +33216,30 @@ ${detail}` : ""}`
|
|
|
32883
33216
|
mark.append(createRendererAgentIcon(agent ?? "pi", 26, document2, pluginFor(agent ?? "pi")));
|
|
32884
33217
|
return mark;
|
|
32885
33218
|
};
|
|
32886
|
-
const renderRow = (
|
|
33219
|
+
const renderRow = (record10) => {
|
|
32887
33220
|
const row = document2.createElement("div");
|
|
32888
33221
|
row.className = "settings-pi-accounts__row";
|
|
32889
33222
|
row.tabIndex = -1;
|
|
32890
|
-
row.dataset.importName =
|
|
32891
|
-
row.setAttribute("aria-label", shown(
|
|
32892
|
-
const agent =
|
|
33223
|
+
row.dataset.importName = record10.name;
|
|
33224
|
+
row.setAttribute("aria-label", shown(record10.source.label));
|
|
33225
|
+
const agent = record10.source.harnessId;
|
|
32893
33226
|
const mark = createMark(agent);
|
|
32894
33227
|
const identity = document2.createElement("div");
|
|
32895
33228
|
identity.className = "settings-pi-accounts__identity";
|
|
32896
33229
|
const label = document2.createElement("strong");
|
|
32897
33230
|
label.className = "settings-account-email";
|
|
32898
|
-
label.textContent = shown(
|
|
33231
|
+
label.textContent = shown(record10.source.label);
|
|
32899
33232
|
label.title = label.textContent;
|
|
32900
33233
|
label.translate = false;
|
|
32901
33234
|
const meta3 = document2.createElement("div");
|
|
32902
33235
|
meta3.className = "settings-account-metadata";
|
|
32903
|
-
const source = sourceOf(
|
|
33236
|
+
const source = sourceOf(record10);
|
|
32904
33237
|
const parts = [
|
|
32905
33238
|
metaPart(rendererAgentLabel(agent, pluginFor(agent)), "settings-pi-accounts__agent"),
|
|
32906
|
-
metaPart(`${
|
|
33239
|
+
metaPart(`${record10.name}/\u2026`, void 0, true),
|
|
32907
33240
|
metaPart(messages.copied)
|
|
32908
33241
|
];
|
|
32909
|
-
const time3 = formatImportedAt(
|
|
33242
|
+
const time3 = formatImportedAt(record10.importedAt);
|
|
32910
33243
|
if (time3) parts.push(metaPart(time3));
|
|
32911
33244
|
parts.forEach((part, index) => {
|
|
32912
33245
|
if (index > 0) {
|
|
@@ -32923,23 +33256,23 @@ ${detail}` : ""}`
|
|
|
32923
33256
|
reimport.type = "button";
|
|
32924
33257
|
reimport.className = "settings-account-action";
|
|
32925
33258
|
reimport.textContent = messages.rowReimport;
|
|
32926
|
-
reimport.setAttribute("aria-label", `${messages.reimport}: ${shown(
|
|
33259
|
+
reimport.setAttribute("aria-label", `${messages.reimport}: ${shown(record10.source.label)}`);
|
|
32927
33260
|
reimport.disabled = busy || !source;
|
|
32928
33261
|
reimport.title = messages.reimport;
|
|
32929
33262
|
reimport.addEventListener("click", () => {
|
|
32930
|
-
if (source) openDialog("reimport", { source, record:
|
|
33263
|
+
if (source) openDialog("reimport", { source, record: record10 }, `row:${record10.name}`);
|
|
32931
33264
|
});
|
|
32932
33265
|
const remove = document2.createElement("button");
|
|
32933
33266
|
remove.type = "button";
|
|
32934
33267
|
remove.className = "settings-account-action settings-pi-accounts__remove";
|
|
32935
33268
|
remove.textContent = messages.rowRemove;
|
|
32936
|
-
remove.setAttribute("aria-label", `${messages.remove}: ${shown(
|
|
33269
|
+
remove.setAttribute("aria-label", `${messages.remove}: ${shown(record10.source.label)}`);
|
|
32937
33270
|
remove.disabled = busy;
|
|
32938
|
-
remove.addEventListener("click", () => openDialog("remove", { record:
|
|
33271
|
+
remove.addEventListener("click", () => openDialog("remove", { record: record10 }, `row:${record10.name}`));
|
|
32939
33272
|
if (source) actions.append(reimport);
|
|
32940
33273
|
actions.append(remove);
|
|
32941
33274
|
row.append(mark, identity, actions);
|
|
32942
|
-
rows.set(
|
|
33275
|
+
rows.set(record10.name, row);
|
|
32943
33276
|
return row;
|
|
32944
33277
|
};
|
|
32945
33278
|
const loginTypeLabel = (type) => type === "oauth" ? messages.typeOauth : type === "api_key" ? messages.typeApiKey : messages.typeOther;
|
|
@@ -33092,7 +33425,7 @@ ${detail}` : ""}`
|
|
|
33092
33425
|
const label = document2.createElement("strong");
|
|
33093
33426
|
label.textContent = shown(choice.label);
|
|
33094
33427
|
label.translate = false;
|
|
33095
|
-
const existing = importedRecords().find((
|
|
33428
|
+
const existing = importedRecords().find((record10) => record10.source.id === choice.id);
|
|
33096
33429
|
const agent = choice.harnessId;
|
|
33097
33430
|
const detail = document2.createElement("span");
|
|
33098
33431
|
detail.textContent = [
|
|
@@ -33133,7 +33466,7 @@ ${detail}` : ""}`
|
|
|
33133
33466
|
const name = request.action === "list" ? void 0 : request.name;
|
|
33134
33467
|
state = {
|
|
33135
33468
|
source: state.source,
|
|
33136
|
-
record: importedRecords().find((
|
|
33469
|
+
record: importedRecords().find((record10) => record10.name === name) ?? state.record
|
|
33137
33470
|
};
|
|
33138
33471
|
show(next);
|
|
33139
33472
|
} else {
|
|
@@ -33147,12 +33480,12 @@ ${detail}` : ""}`
|
|
|
33147
33480
|
sourceRadios = [];
|
|
33148
33481
|
body.replaceChildren();
|
|
33149
33482
|
controls.replaceChildren();
|
|
33150
|
-
const { source, record:
|
|
33483
|
+
const { source, record: record10 } = state;
|
|
33151
33484
|
const close = () => modal.close();
|
|
33152
33485
|
if (mode === "add" || mode === "reimport") {
|
|
33153
33486
|
title.textContent = mode === "add" ? messages.add : messages.reimport;
|
|
33154
33487
|
modal.setAttribute("aria-label", title.textContent);
|
|
33155
|
-
const active = source ??
|
|
33488
|
+
const active = source ?? record10?.source;
|
|
33156
33489
|
const choices = mode === "add" && state.choose ? compatibleSources() : [];
|
|
33157
33490
|
if (choices.length > 1) body.append(sourcePicker(choices));
|
|
33158
33491
|
else if (active) body.append(line(messages.source, shown(active.label)));
|
|
@@ -33161,8 +33494,8 @@ ${detail}` : ""}`
|
|
|
33161
33494
|
input.maxLength = 48;
|
|
33162
33495
|
input.autocomplete = "off";
|
|
33163
33496
|
input.spellcheck = false;
|
|
33164
|
-
input.value =
|
|
33165
|
-
input.readOnly = Boolean(
|
|
33497
|
+
input.value = record10?.name ?? (source ? defaultImportName(source, importedRecords()) : "codex");
|
|
33498
|
+
input.readOnly = Boolean(record10);
|
|
33166
33499
|
input.addEventListener("input", () => {
|
|
33167
33500
|
nameEdited = true;
|
|
33168
33501
|
});
|
|
@@ -33196,7 +33529,7 @@ ${detail}` : ""}`
|
|
|
33196
33529
|
{
|
|
33197
33530
|
action: mode === "reimport" ? "reimport" : "import",
|
|
33198
33531
|
sourceId: source2.id,
|
|
33199
|
-
name:
|
|
33532
|
+
name: record10?.name ?? input.value,
|
|
33200
33533
|
confirmed: true
|
|
33201
33534
|
},
|
|
33202
33535
|
"done"
|
|
@@ -33206,16 +33539,16 @@ ${detail}` : ""}`
|
|
|
33206
33539
|
)
|
|
33207
33540
|
);
|
|
33208
33541
|
(mode === "add" ? input : controls.children[0]).focus();
|
|
33209
|
-
} else if (mode === "remove" &&
|
|
33542
|
+
} else if (mode === "remove" && record10) {
|
|
33210
33543
|
title.textContent = messages.remove;
|
|
33211
33544
|
modal.setAttribute("aria-label", title.textContent);
|
|
33212
|
-
body.append(note(messages.removeWarning.replace("{name}",
|
|
33545
|
+
body.append(note(messages.removeWarning.replace("{name}", record10.name)));
|
|
33213
33546
|
const cancel = command(messages.cancel, close);
|
|
33214
33547
|
controls.append(
|
|
33215
33548
|
cancel,
|
|
33216
33549
|
command(
|
|
33217
33550
|
messages.remove,
|
|
33218
|
-
() => submit({ action: "remove", name:
|
|
33551
|
+
() => submit({ action: "remove", name: record10.name, confirmed: true }, null),
|
|
33219
33552
|
"danger"
|
|
33220
33553
|
)
|
|
33221
33554
|
);
|
|
@@ -33223,7 +33556,7 @@ ${detail}` : ""}`
|
|
|
33223
33556
|
} else {
|
|
33224
33557
|
title.textContent = messages.doneTitle;
|
|
33225
33558
|
modal.setAttribute("aria-label", title.textContent);
|
|
33226
|
-
const name =
|
|
33559
|
+
const name = record10?.name;
|
|
33227
33560
|
if (name) body.append(line(messages.entry, `${name}/\u2026`, true));
|
|
33228
33561
|
body.append(note(messages.done));
|
|
33229
33562
|
const done = command(messages.close, close, "primary");
|
|
@@ -33270,21 +33603,21 @@ ${detail}` : ""}`
|
|
|
33270
33603
|
(candidate) => candidate.harnessId === TARGET_HARNESS_ID && source && candidate.providers.includes(source.provider)
|
|
33271
33604
|
);
|
|
33272
33605
|
if (!source || !target) return null;
|
|
33273
|
-
const
|
|
33606
|
+
const record10 = target.imports.find((candidate) => candidate.source.id === source.id);
|
|
33274
33607
|
const key = `${harnessId}:${accountLabel}:import`;
|
|
33275
33608
|
const button2 = document2.createElement("button");
|
|
33276
33609
|
button2.type = "button";
|
|
33277
33610
|
button2.className = "settings-account-pi-import";
|
|
33278
33611
|
button2.dataset.accountFocus = key;
|
|
33279
33612
|
button2.disabled = busy;
|
|
33280
|
-
const hint =
|
|
33613
|
+
const hint = record10 ? messages.importedHint.replace("{name}", record10.name) : messages.add;
|
|
33281
33614
|
button2.title = hint;
|
|
33282
33615
|
button2.setAttribute("aria-label", hint);
|
|
33283
33616
|
button2.append(createRendererAgentIcon("pi", 12, document2, pluginFor("pi")));
|
|
33284
|
-
if (
|
|
33617
|
+
if (record10) {
|
|
33285
33618
|
button2.dataset.state = "imported";
|
|
33286
33619
|
const name = document2.createElement("code");
|
|
33287
|
-
name.textContent = `${
|
|
33620
|
+
name.textContent = `${record10.name}/\u2026`;
|
|
33288
33621
|
name.translate = false;
|
|
33289
33622
|
button2.append(name, createRendererSettingsIcon("check", 12));
|
|
33290
33623
|
} else {
|
|
@@ -33292,7 +33625,7 @@ ${detail}` : ""}`
|
|
|
33292
33625
|
button2.append(messages.add);
|
|
33293
33626
|
}
|
|
33294
33627
|
button2.addEventListener("click", () => {
|
|
33295
|
-
if (!
|
|
33628
|
+
if (!record10) {
|
|
33296
33629
|
openDialog("add", { source }, key);
|
|
33297
33630
|
return;
|
|
33298
33631
|
}
|
|
@@ -33301,7 +33634,7 @@ ${detail}` : ""}`
|
|
|
33301
33634
|
renderSection();
|
|
33302
33635
|
sectionToggle.setAttribute("aria-expanded", "true");
|
|
33303
33636
|
}
|
|
33304
|
-
const row = rows.get(
|
|
33637
|
+
const row = rows.get(record10.name);
|
|
33305
33638
|
row?.scrollIntoView({ block: "nearest", behavior: "smooth" });
|
|
33306
33639
|
row?.focus();
|
|
33307
33640
|
});
|
|
@@ -41619,7 +41952,19 @@ ${usage_default}`;
|
|
|
41619
41952
|
update();
|
|
41620
41953
|
form.requestSubmit();
|
|
41621
41954
|
} catch (cause) {
|
|
41622
|
-
|
|
41955
|
+
let cleanupError = "";
|
|
41956
|
+
if (attempt.thread?.discard) {
|
|
41957
|
+
if (readNativeScheduleForm(form)?.targetThreadId === attempt.thread.threadId)
|
|
41958
|
+
attempt.thread.retain();
|
|
41959
|
+
else {
|
|
41960
|
+
try {
|
|
41961
|
+
await attempt.thread.discard();
|
|
41962
|
+
} catch (error52) {
|
|
41963
|
+
cleanupError = ` ${text("\u4F1A\u8BDD\u6E05\u7406\u5931\u8D25\uFF1A", "Chat cleanup failed:")} ${error52 instanceof Error ? error52.message : String(error52)}`;
|
|
41964
|
+
}
|
|
41965
|
+
}
|
|
41966
|
+
}
|
|
41967
|
+
attempt.error = `${cause instanceof Error ? cause.message : text("\u4F1A\u8BDD\u521B\u5EFA\u5931\u8D25\u3002", "Chat creation failed.")}${cleanupError} ${text("\u8BF7\u5148\u68C0\u67E5\u4F1A\u8BDD\u5217\u8868\uFF0C\u52FF\u91CD\u590D\u521B\u5EFA\u3002", "Check the chat list before creating another task.")}`;
|
|
41623
41968
|
} finally {
|
|
41624
41969
|
attempt.pending = false;
|
|
41625
41970
|
if (!retired) update();
|
|
@@ -42037,6 +42382,7 @@ ${usage_default}`;
|
|
|
42037
42382
|
});
|
|
42038
42383
|
const mountedByComposer = /* @__PURE__ */ new Map();
|
|
42039
42384
|
const catalogRequests = /* @__PURE__ */ new WeakMap();
|
|
42385
|
+
const draftUsageRequests = /* @__PURE__ */ new WeakMap();
|
|
42040
42386
|
const pendingReplacements = /* @__PURE__ */ new Map();
|
|
42041
42387
|
let disposed = false;
|
|
42042
42388
|
const disposeReasoningSoftWrap = installReasoningTranscriptSoftWrap(document);
|
|
@@ -42163,7 +42509,7 @@ ${usage_default}`;
|
|
|
42163
42509
|
for (const mounted of mountedByComposer.values()) {
|
|
42164
42510
|
if (mounted.hostId !== hostId2) continue;
|
|
42165
42511
|
renderMounted(mounted);
|
|
42166
|
-
void
|
|
42512
|
+
if (controller.get(mounted.composer).agent === "codex") void refreshDraftUsage(mounted);
|
|
42167
42513
|
}
|
|
42168
42514
|
});
|
|
42169
42515
|
});
|
|
@@ -42346,36 +42692,59 @@ ${usage_default}`;
|
|
|
42346
42692
|
renderMounted(mounted);
|
|
42347
42693
|
}
|
|
42348
42694
|
};
|
|
42349
|
-
const
|
|
42695
|
+
const refreshDraftUsage = async (mounted) => {
|
|
42350
42696
|
const state = controller.get(mounted.composer);
|
|
42351
|
-
if (state.
|
|
42697
|
+
if (state.phase !== "draft" || controller.isSwitching(mounted.composer) || controller.isSubmissionPending(mounted.composer) || threadIdFromComposerModelTarget(mounted.modelTarget))
|
|
42352
42698
|
return;
|
|
42353
|
-
const
|
|
42354
|
-
const
|
|
42699
|
+
const agent = state.agent;
|
|
42700
|
+
const accounts = agent === "codex" ? composerCodexAccounts(mounted.composer) : null;
|
|
42355
42701
|
const accountId = accounts?.readyAccountId;
|
|
42702
|
+
const client = composerClient(mounted);
|
|
42356
42703
|
const hostId2 = mounted.hostId;
|
|
42704
|
+
const previous = draftUsageRequests.get(mounted);
|
|
42705
|
+
if (agent !== "codex" && previous?.pending && previous.client === client && previous.generation === mounted.usageRequestGeneration)
|
|
42706
|
+
return;
|
|
42357
42707
|
const generation = ++mounted.usageRequestGeneration;
|
|
42708
|
+
const request = { client, generation, pending: true };
|
|
42709
|
+
draftUsageRequests.set(mounted, request);
|
|
42710
|
+
mounted.draftUsageClient = null;
|
|
42358
42711
|
mounted.usage = null;
|
|
42359
42712
|
mounted.accountCredits = null;
|
|
42713
|
+
mounted.accountCreditsSupported = false;
|
|
42360
42714
|
renderMounted(mounted);
|
|
42361
|
-
|
|
42715
|
+
const isCurrent = () => !disposed && mounted.hostId === hostId2 && composerClient(mounted) === client && mounted.composer.isConnected && mountedByComposer.get(mounted.composer) === mounted && mounted.usageRequestGeneration === generation && controller.get(mounted.composer).agent === agent && controller.get(mounted.composer).phase === "draft" && !controller.isSwitching(mounted.composer) && !controller.isSubmissionPending(mounted.composer) && !threadIdFromComposerModelTarget(mounted.modelTarget);
|
|
42362
42716
|
try {
|
|
42363
|
-
|
|
42364
|
-
if (
|
|
42365
|
-
return;
|
|
42366
|
-
|
|
42367
|
-
|
|
42717
|
+
if (!client) return;
|
|
42718
|
+
if (agent === "codex") {
|
|
42719
|
+
if (!accountId || !client.inspectCodexAccountUsage) return;
|
|
42720
|
+
const result = await client.inspectCodexAccountUsage({ accountId });
|
|
42721
|
+
if (!isCurrent() || composerCodexAccounts(mounted.composer) !== accounts || accounts?.readyAccountId !== accountId || result.accountId !== accountId)
|
|
42722
|
+
return;
|
|
42723
|
+
mounted.usage = result.usage;
|
|
42724
|
+
mounted.accountCredits = result.accountCredits ?? null;
|
|
42725
|
+
} else {
|
|
42726
|
+
if (!client.inspectHarnessAccount) return;
|
|
42727
|
+
const result = await client.inspectHarnessAccount({
|
|
42728
|
+
harnessId: harnessIdSchema.parse(agent),
|
|
42729
|
+
refresh: true
|
|
42730
|
+
});
|
|
42731
|
+
if (!isCurrent() || result.harnessId !== agent) return;
|
|
42732
|
+
mounted.accountCredits = result.account?.credits ?? null;
|
|
42733
|
+
}
|
|
42734
|
+
mounted.draftUsageClient = client;
|
|
42368
42735
|
renderMounted(mounted);
|
|
42369
42736
|
} catch {
|
|
42737
|
+
} finally {
|
|
42738
|
+
request.pending = false;
|
|
42370
42739
|
}
|
|
42371
42740
|
};
|
|
42372
42741
|
const refreshThreadUsage = async (mounted, refresh) => {
|
|
42373
42742
|
const threadId = threadIdFromComposerModelTarget(mounted.modelTarget);
|
|
42374
|
-
if (!threadId
|
|
42375
|
-
await
|
|
42743
|
+
if (!threadId) {
|
|
42744
|
+
await refreshDraftUsage(mounted);
|
|
42376
42745
|
return;
|
|
42377
42746
|
}
|
|
42378
|
-
if (!
|
|
42747
|
+
if (!modelControl) {
|
|
42379
42748
|
mounted.usage = null;
|
|
42380
42749
|
mounted.accountCredits = null;
|
|
42381
42750
|
usageRefreshAttempts.delete(mounted.composer);
|
|
@@ -43170,8 +43539,23 @@ ${usage_default}`;
|
|
|
43170
43539
|
if (agent !== "codex" && composerAvailability(mounted)[agent] !== "ready") {
|
|
43171
43540
|
return false;
|
|
43172
43541
|
}
|
|
43542
|
+
const state = controller.get(mounted.composer);
|
|
43543
|
+
if (state.phase !== "draft" || controller.isSwitching(mounted.composer)) return false;
|
|
43173
43544
|
controller.clearPendingSubmission(mounted.composer);
|
|
43174
|
-
const composerId =
|
|
43545
|
+
const composerId = state.composerId;
|
|
43546
|
+
for (const candidate of mountedByComposer.values()) {
|
|
43547
|
+
if (controller.get(candidate.composer).composerId !== composerId) continue;
|
|
43548
|
+
candidate.usageRequestGeneration += 1;
|
|
43549
|
+
candidate.usage = null;
|
|
43550
|
+
candidate.accountCredits = null;
|
|
43551
|
+
candidate.accountCreditsSupported = false;
|
|
43552
|
+
usageRefreshAttempts.delete(candidate.composer);
|
|
43553
|
+
const timer = usageRefreshTimers.get(candidate.composer);
|
|
43554
|
+
if (timer !== void 0) {
|
|
43555
|
+
window.clearTimeout(timer);
|
|
43556
|
+
usageRefreshTimers.delete(candidate.composer);
|
|
43557
|
+
}
|
|
43558
|
+
}
|
|
43175
43559
|
controller.invalidateModelRequests(mounted.composer);
|
|
43176
43560
|
const switching = controller.switchAgent(mounted.composer, agent, {
|
|
43177
43561
|
applyAgent: (nextAgent) => applyDraftAgentCarrier(mounted.composer, nextAgent),
|
|
@@ -43199,7 +43583,9 @@ ${usage_default}`;
|
|
|
43199
43583
|
return false;
|
|
43200
43584
|
} finally {
|
|
43201
43585
|
for (const candidate of mountedByComposer.values()) {
|
|
43202
|
-
if (controller.get(candidate.composer).composerId
|
|
43586
|
+
if (controller.get(candidate.composer).composerId !== composerId) continue;
|
|
43587
|
+
renderMounted(candidate);
|
|
43588
|
+
void refreshDraftUsage(candidate);
|
|
43203
43589
|
}
|
|
43204
43590
|
}
|
|
43205
43591
|
};
|
|
@@ -43214,7 +43600,7 @@ ${usage_default}`;
|
|
|
43214
43600
|
for (const mounted of mountedByComposer.values()) {
|
|
43215
43601
|
if (mounted.hostId !== hostId2) continue;
|
|
43216
43602
|
renderMounted(mounted);
|
|
43217
|
-
void
|
|
43603
|
+
if (controller.get(mounted.composer).agent === "codex") void refreshDraftUsage(mounted);
|
|
43218
43604
|
}
|
|
43219
43605
|
})
|
|
43220
43606
|
);
|
|
@@ -43428,6 +43814,7 @@ ${usage_default}`;
|
|
|
43428
43814
|
void clearDraftPrewarm(mounted.composer).catch(() => void 0);
|
|
43429
43815
|
}
|
|
43430
43816
|
void loadExternalCatalog(mounted);
|
|
43817
|
+
void refreshDraftUsage(mounted);
|
|
43431
43818
|
continue;
|
|
43432
43819
|
}
|
|
43433
43820
|
const target = controllerTarget(mounted.modelTarget, hostId2);
|
|
@@ -43456,11 +43843,18 @@ ${usage_default}`;
|
|
|
43456
43843
|
}
|
|
43457
43844
|
if (changed) sidebarAgentIcons.refresh();
|
|
43458
43845
|
};
|
|
43459
|
-
function reconcileHarnessAvailabilityHost() {
|
|
43846
|
+
function reconcileHarnessAvailabilityHost(retryDraftUsage = false) {
|
|
43460
43847
|
for (const hostId3 of modelControl?.knownHostIds?.() ?? []) {
|
|
43461
43848
|
hostHarnessAvailabilityState(hostId3);
|
|
43462
43849
|
}
|
|
43463
43850
|
reloadMountedOwnershipForHost();
|
|
43851
|
+
for (const mounted of mountedByComposer.values()) {
|
|
43852
|
+
const client = composerClient(mounted);
|
|
43853
|
+
const request = draftUsageRequests.get(mounted);
|
|
43854
|
+
if (controller.get(mounted.composer).agent !== "codex" && mounted.draftUsageClient !== client && (!request || request.client !== client || request.generation !== mounted.usageRequestGeneration || retryDraftUsage && !request.pending)) {
|
|
43855
|
+
void refreshDraftUsage(mounted);
|
|
43856
|
+
}
|
|
43857
|
+
}
|
|
43464
43858
|
let connectionsChanged = false;
|
|
43465
43859
|
for (const target of new Set([...mountedByComposer.values()].map((m) => m.hostId))) {
|
|
43466
43860
|
if (!target) continue;
|
|
@@ -43667,6 +44061,7 @@ ${usage_default}`;
|
|
|
43667
44061
|
accountCreditsSupported: inherited?.accountCreditsSupported ?? false,
|
|
43668
44062
|
hostId: inherited?.hostId ?? hostId2,
|
|
43669
44063
|
usageRequestGeneration: 0,
|
|
44064
|
+
draftUsageClient: null,
|
|
43670
44065
|
commandRequestGeneration: 0
|
|
43671
44066
|
};
|
|
43672
44067
|
mountedByComposer.set(composer, mounted);
|
|
@@ -43686,7 +44081,7 @@ ${usage_default}`;
|
|
|
43686
44081
|
} else if (state.agent !== "codex" && !isExternalConfigurationStable(mounted.modelView, mounted.permissionModeView)) {
|
|
43687
44082
|
void loadExternalCatalog(mounted);
|
|
43688
44083
|
}
|
|
43689
|
-
if (!threadIdFromComposerModelTarget(modelTarget)) void
|
|
44084
|
+
if (!threadIdFromComposerModelTarget(modelTarget)) void refreshDraftUsage(mounted);
|
|
43690
44085
|
void refreshCommands(mounted);
|
|
43691
44086
|
};
|
|
43692
44087
|
const scan = () => {
|
|
@@ -43966,7 +44361,7 @@ ${usage_default}`;
|
|
|
43966
44361
|
document.addEventListener("keydown", onKeyDown, true);
|
|
43967
44362
|
document.addEventListener("click", onClick, true);
|
|
43968
44363
|
const onWindowFocus = () => {
|
|
43969
|
-
reconcileHarnessAvailabilityHost();
|
|
44364
|
+
reconcileHarnessAvailabilityHost(true);
|
|
43970
44365
|
void loadCodexAccounts();
|
|
43971
44366
|
for (const mounted of mountedByComposer.values()) {
|
|
43972
44367
|
if (mounted.hostId === activeModelHostId(mounted.composer) && mounted.ownershipStatus === "error") {
|
|
@@ -44150,6 +44545,7 @@ ${usage_default}`;
|
|
|
44150
44545
|
for (const mounted of mountedByComposer.values()) {
|
|
44151
44546
|
renderMounted(mounted);
|
|
44152
44547
|
void refreshCommands(mounted);
|
|
44548
|
+
if (controller.get(mounted.composer).agent !== "codex") void refreshDraftUsage(mounted);
|
|
44153
44549
|
}
|
|
44154
44550
|
},
|
|
44155
44551
|
dispose() {
|