@codexhost/cli-darwin-x64 0.16.0 → 0.16.1

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.
@@ -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);
@@ -16350,8 +16353,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16350
16353
  if (!ownerWindow.document || !ownerWindow.location) return null;
16351
16354
  const page = new URL(ownerWindow.location.href);
16352
16355
  const urls = /* @__PURE__ */ new Set();
16353
- for (const link of ownerWindow.document.querySelectorAll('link[rel="modulepreload"][href]')) {
16354
- const url2 = new URL(link.getAttribute("href") ?? "", page);
16356
+ const catalog = Reflect.get(ownerWindow, "__codexhostLoadedModulesV1");
16357
+ let sources;
16358
+ if (catalog !== void 0) {
16359
+ 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"))
16360
+ throw new Error("Codex loaded module catalog is unavailable in this window");
16361
+ sources = catalog.urls;
16362
+ } else {
16363
+ sources = [...ownerWindow.document.querySelectorAll('link[rel="modulepreload"][href]')].map(
16364
+ (link) => link.getAttribute("href") ?? ""
16365
+ );
16366
+ }
16367
+ for (const source of sources) {
16368
+ let url2;
16369
+ try {
16370
+ url2 = new URL(source, page);
16371
+ } catch {
16372
+ continue;
16373
+ }
16355
16374
  if (url2.protocol === page.protocol && url2.host === page.host && url2.pathname.endsWith(".js") && !url2.search && !url2.hash)
16356
16375
  urls.add(url2.href);
16357
16376
  }
@@ -16369,6 +16388,8 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
16369
16388
  for (const value of Object.values(module).filter(matchesServices)) matches.add(value);
16370
16389
  if (matches.size > 1) throw new Error("Codex native services are unavailable in this window");
16371
16390
  }
16391
+ if (catalog !== void 0 && Reflect.get(ownerWindow, "__codexhostLoadedModulesV1") !== catalog)
16392
+ throw new Error("Codex loaded module catalog changed during discovery. Try again once ready.");
16372
16393
  return [...matches][0] ?? null;
16373
16394
  }
16374
16395
 
@@ -17463,14 +17484,14 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17463
17484
 
17464
17485
  // ../desktop-control/dist/renderer-host-discovery.js
17465
17486
  function requestManagerFromHookState(value, hostId2) {
17466
- const record8 = (candidate) => typeof candidate === "object" && candidate !== null;
17487
+ const record10 = (candidate) => typeof candidate === "object" && candidate !== null;
17467
17488
  const manager = (candidate) => {
17468
- if (!record8(candidate) || !record8(candidate.requestClient) || !record8(candidate.prewarmedThreadManager))
17489
+ if (!record10(candidate) || !record10(candidate.requestClient) || !record10(candidate.prewarmedThreadManager))
17469
17490
  return null;
17470
17491
  const bridge = candidate.requestClient;
17471
17492
  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
17493
  };
17473
- if (!record8(value))
17494
+ if (!record10(value))
17474
17495
  return null;
17475
17496
  const direct = manager(value) ?? manager(value.manager);
17476
17497
  if (direct)
@@ -17531,14 +17552,197 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17531
17552
  };
17532
17553
  }
17533
17554
 
17534
- // ../desktop-control/dist/renderer-schedule-workspace.js
17555
+ // ../desktop-control/dist/renderer-host-rpc-discovery.js
17556
+ function findRendererHostRpcFamily(store) {
17557
+ const record10 = (value) => typeof value === "object" && value !== null;
17558
+ const families = /* @__PURE__ */ new Set();
17559
+ for (const [definition, members] of store.familyBindings) {
17560
+ if (!record10(definition) || definition.kind !== "signal-family")
17561
+ continue;
17562
+ if (!record10(members) || typeof members.get !== "function")
17563
+ continue;
17564
+ for (const [hostId2, member] of members) {
17565
+ if (typeof hostId2 !== "string" || !record10(member))
17566
+ continue;
17567
+ const signal = member.value;
17568
+ if (!record10(signal) || typeof signal.get !== "function")
17569
+ continue;
17570
+ let value;
17571
+ try {
17572
+ value = signal.get();
17573
+ } catch {
17574
+ continue;
17575
+ }
17576
+ if (record10(value) && Object.keys(value).length === 2 && typeof value.status === "string" && record10(value.client) && value.client.hostId === hostId2 && "rpc" in value.client) {
17577
+ families.add(members);
17578
+ break;
17579
+ }
17580
+ }
17581
+ }
17582
+ if (families.size !== 1)
17583
+ return null;
17584
+ return { store, family: families.values().next().value };
17585
+ }
17586
+ function resolveRendererHostRpc(discovery, hostId2) {
17587
+ const record10 = (value2) => typeof value2 === "object" && value2 !== null;
17588
+ const signal = discovery.family.get(hostId2)?.value;
17589
+ if (!record10(signal) || typeof signal.get !== "function")
17590
+ return null;
17591
+ let value;
17592
+ try {
17593
+ value = signal.get();
17594
+ } catch {
17595
+ return null;
17596
+ }
17597
+ if (!record10(value) || value.status !== "ready" || !record10(value.client) || value.client.hostId !== hostId2)
17598
+ return null;
17599
+ const rpc = value.client.rpc;
17600
+ return typeof rpc === "function" || record10(rpc) ? rpc : null;
17601
+ }
17602
+
17603
+ // ../desktop-control/dist/renderer-schedule-workspace-rpc.js
17535
17604
  var record5 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
17605
+ function localAppScope(root) {
17606
+ const scopes = /* @__PURE__ */ new Map();
17607
+ const seen = /* @__PURE__ */ new Set();
17608
+ for (const main of root.querySelectorAll("main")) {
17609
+ const keys = Object.getOwnPropertyNames(main).filter((key2) => key2.startsWith("__reactFiber$"));
17610
+ const key = keys[0];
17611
+ if (keys.length !== 1 || !key)
17612
+ continue;
17613
+ for (const fiber of committedReactAncestors(Reflect.get(main, key))) {
17614
+ if (seen.has(fiber))
17615
+ break;
17616
+ seen.add(fiber);
17617
+ let hook = fiber.memoizedState;
17618
+ for (let n = 0; record5(hook) && "next" in hook && n < 150; n++, hook = hook.next) {
17619
+ const handle = record5(hook.memoizedState) ? hook.memoizedState.current : null;
17620
+ 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))
17621
+ continue;
17622
+ scopes.set(handle.node, { handle, store: handle.node });
17623
+ }
17624
+ }
17625
+ }
17626
+ const scope = scopes.values().next().value;
17627
+ if (scopes.size !== 1 || !scope)
17628
+ throw new Error("Native local app scope is missing or ambiguous");
17629
+ const discovery = findRendererHostRpcFamily(scope.store);
17630
+ const rpc = discovery && resolveRendererHostRpc(discovery, "local");
17631
+ if (!discovery || !rpc)
17632
+ throw new Error("Native local app RPC is unavailable");
17633
+ return { ...scope, discovery, rpc };
17634
+ }
17635
+ async function createRpcScheduleWorkspaceThread(root, routing, route, createThread, input, signal) {
17636
+ if (!route.policy.scopedCreation)
17637
+ throw new Error("Native local chat creation is unavailable");
17638
+ const scope = localAppScope(root);
17639
+ const assertConnection = () => {
17640
+ if (routing.forHost("local")?.manager !== route.manager || resolveRendererHostRpc(scope.discovery, "local") !== scope.rpc)
17641
+ throw new Error("The local connection changed. Reopen the task dialog.");
17642
+ };
17643
+ const assertCurrent = () => {
17644
+ signal.throwIfAborted();
17645
+ assertConnection();
17646
+ };
17647
+ const request = async (method, params) => {
17648
+ assertConnection();
17649
+ return route.manager.sendRequest(method, params);
17650
+ };
17651
+ const readEmpty = async (threadId) => {
17652
+ const read = await request("thread/read", { threadId, includeTurns: false });
17653
+ if (!record5(read) || !record5(read.thread) || read.thread.id !== threadId || !record5(read.thread.status))
17654
+ throw new Error("The created chat could not be read");
17655
+ const turns = await request("thread/turns/list", { threadId, cursor: null, limit: 1 });
17656
+ const queue = await request("thread/queue/list", { threadId, cursor: null, limit: 1 });
17657
+ if (!record5(turns) || !Array.isArray(turns.data) || !("nextCursor" in turns) || !record5(queue) || !Array.isArray(queue.data) || !("nextCursor" in queue))
17658
+ throw new Error("The created chat's history or queue could not be confirmed");
17659
+ return {
17660
+ thread: read.thread,
17661
+ empty: read.thread.status.type === "idle" && turns.data.length === 0 && turns.nextCursor === null && queue.data.length === 0 && queue.nextCursor === null
17662
+ };
17663
+ };
17664
+ assertCurrent();
17665
+ let createdId = null;
17666
+ let retained = false;
17667
+ let failed = false;
17668
+ let cleanup;
17669
+ const discard = () => {
17670
+ if (!createdId || retained)
17671
+ return Promise.resolve();
17672
+ const threadId = createdId;
17673
+ return cleanup ??= (async () => {
17674
+ const { empty } = await readEmpty(threadId);
17675
+ if (!empty || retained)
17676
+ return;
17677
+ await request("thread/archive", { threadId });
17678
+ })();
17679
+ };
17680
+ const discardAfterDismissal = () => {
17681
+ void discard().catch((error51) => {
17682
+ console.error("Could not discard the unsubmitted schedule chat. Check the chat list.", error51);
17683
+ });
17684
+ };
17685
+ signal.addEventListener("abort", discardAfterDismissal, { once: true });
17686
+ const remember = (result) => {
17687
+ if (!record5(result) || result.status !== "created")
17688
+ return;
17689
+ const id = hostThreadIdSchema.safeParse(result.conversationId);
17690
+ if (!id.success)
17691
+ return;
17692
+ if (createdId && createdId !== id.data)
17693
+ throw new Error("Chat creation returned conflicting identities");
17694
+ createdId = id.data;
17695
+ if (signal.aborted || failed)
17696
+ discardAfterDismissal();
17697
+ };
17698
+ try {
17699
+ const output = await createThread({
17700
+ scope: scope.handle,
17701
+ target: { type: "project", projectId: input.workspace.id, environment: { type: "local" } },
17702
+ model: input.model,
17703
+ title: input.title,
17704
+ prompt: "",
17705
+ startWithoutFirstTurn: true,
17706
+ assertRequestCurrent: assertCurrent,
17707
+ onSettled: remember
17708
+ });
17709
+ const result = record5(output) && output.kind === "creation" ? output.result : null;
17710
+ remember(result);
17711
+ assertCurrent();
17712
+ if (!record5(result) || result.status !== "created" || !createdId || !record5(result.firstTurn) || result.firstTurn.status !== "not-requested")
17713
+ throw new Error("Chat creation was not confirmed. Check the chat list before creating another task.");
17714
+ const { thread, empty } = await readEmpty(createdId);
17715
+ const inspection = threadInspectionSchema.parse(await request("codexhost/thread/inspect", { threadId: createdId }));
17716
+ assertCurrent();
17717
+ if (!empty || thread.cwd !== input.workspace.cwd || inspection.owner !== "external" || inspection.transportModelId !== input.model)
17718
+ throw new Error("The created chat's workspace, Model or empty state could not be confirmed");
17719
+ return {
17720
+ threadId: createdId,
17721
+ discard,
17722
+ retain() {
17723
+ retained = true;
17724
+ signal.removeEventListener("abort", discardAfterDismissal);
17725
+ }
17726
+ };
17727
+ } catch (error51) {
17728
+ failed = true;
17729
+ try {
17730
+ await discard();
17731
+ } catch (cleanupError) {
17732
+ throw new Error(`${error51 instanceof Error ? error51.message : String(error51)}; Chat cleanup failed: ${cleanupError instanceof Error ? cleanupError.message : String(cleanupError)}. Check the chat list.`);
17733
+ }
17734
+ throw error51;
17735
+ }
17736
+ }
17737
+
17738
+ // ../desktop-control/dist/renderer-schedule-workspace.js
17739
+ var record6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
17536
17740
  function readNativeScheduleWorkspaces(root) {
17537
17741
  const projects = /* @__PURE__ */ new Map();
17538
17742
  const ambiguous = /* @__PURE__ */ new Set();
17539
17743
  const seen = /* @__PURE__ */ new Set();
17540
17744
  const add = (value) => {
17541
- if (!record5(value) || value.source !== "codex" || !record5(value.group))
17745
+ if (!record6(value) || value.source !== "codex" || !record6(value.group))
17542
17746
  return;
17543
17747
  const group = value.group;
17544
17748
  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 +17764,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17560
17764
  break;
17561
17765
  seen.add(fiber);
17562
17766
  const props = fiber.memoizedProps;
17563
- if (!record5(props))
17767
+ if (!record6(props))
17564
17768
  continue;
17565
17769
  add(props.project);
17566
17770
  if (props.projectByKey instanceof Map)
@@ -17571,15 +17775,24 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17571
17775
  return [...projects.values()].filter(({ id }) => !ambiguous.has(id));
17572
17776
  }
17573
17777
  function isNativeProjectThreadCreator(value) {
17574
- if (typeof value !== "function" || value.length !== 1)
17778
+ try {
17779
+ if (typeof value !== "function" || value.length !== 1)
17780
+ return false;
17781
+ const source = Function.prototype.toString.call(value);
17782
+ 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");
17783
+ } catch {
17575
17784
  return false;
17576
- const source = Function.prototype.toString.call(value);
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");
17785
+ }
17578
17786
  }
17579
17787
  async function createNativeScheduleWorkspaceThread(root, routing, createThread, input, signal) {
17580
17788
  if (!decodeHarnessPluginRoute(input.model))
17581
17789
  throw new Error("An external Harness is required");
17582
17790
  const route = routing.forHost("local");
17791
+ if (route && Reflect.get(route.manager, "kind") === "main-process-rpc") {
17792
+ if (!readNativeScheduleWorkspaces(root).some(({ id, cwd }) => id === input.workspace.id && cwd === input.workspace.cwd))
17793
+ throw new Error("The selected workspace is no longer available");
17794
+ return createRpcScheduleWorkspaceThread(root, routing, route, createThread, input, signal);
17795
+ }
17583
17796
  const manager = route?.manager;
17584
17797
  if (!route?.policy.scopedCreation || !manager || typeof manager.getConversation !== "function" || typeof manager.archiveConversation !== "function")
17585
17798
  throw new Error("Native local chat creation is unavailable");
@@ -17594,7 +17807,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17594
17807
  }
17595
17808
  }));
17596
17809
  const scope = scopes.values().next().value;
17597
- if (scopes.size !== 1 || !record5(scope) || typeof scope.get !== "function")
17810
+ if (scopes.size !== 1 || !record6(scope) || typeof scope.get !== "function")
17598
17811
  throw new Error("Native local chat scope is missing or ambiguous");
17599
17812
  if (!readNativeScheduleWorkspaces(root).some(({ id, cwd }) => id === input.workspace.id && cwd === input.workspace.cwd))
17600
17813
  throw new Error("The selected workspace is no longer available");
@@ -17607,7 +17820,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17607
17820
  const id = createdId;
17608
17821
  released = true;
17609
17822
  const conversation2 = manager.getConversation(id);
17610
- if (!record5(conversation2) || !Array.isArray(conversation2.turns) || conversation2.turns.length || Array.isArray(conversation2.requests) && conversation2.requests.length > 0 || conversation2.pendingRequest != null)
17823
+ if (!record6(conversation2) || !Array.isArray(conversation2.turns) || conversation2.turns.length || Array.isArray(conversation2.requests) && conversation2.requests.length > 0 || conversation2.pendingRequest != null)
17611
17824
  return;
17612
17825
  void Promise.resolve().then(() => manager.archiveConversation(id, {
17613
17826
  useAppServerPins: false,
@@ -17616,7 +17829,7 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17616
17829
  };
17617
17830
  signal.addEventListener("abort", discard, { once: true });
17618
17831
  const remember = (result2) => {
17619
- if (!record5(result2) || result2.status !== "created")
17832
+ if (!record6(result2) || result2.status !== "created")
17620
17833
  return;
17621
17834
  const id = hostThreadIdSchema.safeParse(result2.conversationId);
17622
17835
  if (id.success)
@@ -17633,16 +17846,16 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
17633
17846
  startWithoutFirstTurn: true,
17634
17847
  onSettled: remember
17635
17848
  });
17636
- const result = record5(output) && output.kind === "creation" ? output.result : null;
17849
+ const result = record6(output) && output.kind === "creation" ? output.result : null;
17637
17850
  remember(result);
17638
17851
  signal.throwIfAborted();
17639
- if (!record5(result) || result.status !== "created" || !createdId || !record5(result.firstTurn) || result.firstTurn.status !== "not-requested")
17852
+ if (!record6(result) || result.status !== "created" || !createdId || !record6(result.firstTurn) || result.firstTurn.status !== "not-requested")
17640
17853
  throw new Error("Chat creation was not confirmed. Check the chat list before creating another task.");
17641
17854
  if (routing.forHost("local")?.manager !== route.manager)
17642
17855
  throw new Error("The local connection changed. Reopen the task dialog.");
17643
17856
  const conversation = manager.getConversation(createdId);
17644
- const mode = record5(conversation) ? conversation.latestCollaborationMode : null;
17645
- if (!record5(conversation) || conversation.cwd !== input.workspace.cwd || !record5(mode) || !record5(mode.settings) || mode.settings.model !== input.model)
17857
+ const mode = record6(conversation) ? conversation.latestCollaborationMode : null;
17858
+ if (!record6(conversation) || conversation.cwd !== input.workspace.cwd || !record6(mode) || !record6(mode.settings) || mode.settings.model !== input.model)
17646
17859
  throw new Error("The created chat's workspace or Model could not be confirmed");
17647
17860
  return {
17648
17861
  threadId: createdId,
@@ -25792,10 +26005,72 @@ ${text.includes("## My request:") ? "" : "\n## My request:\n"}`,
25792
26005
  };
25793
26006
  }
25794
26007
 
26008
+ // src/renderer-thread-reference-persistence.ts
26009
+ var record7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
26010
+ var SYNC_TIMEOUT_MS = 2e3;
26011
+ function restoreRpcThreadReferenceCapability(client, messages, isCurrent) {
26012
+ if (!record7(messages) || !record7(messages.electronBridge)) return client;
26013
+ const bridge = messages.electronBridge;
26014
+ const send = bridge.sendMessageFromView;
26015
+ if (typeof send !== "function") return client;
26016
+ const inspect = client.inspectThread.bind(client);
26017
+ const checked = /* @__PURE__ */ new Set();
26018
+ const isMissing = (key) => new Promise((resolve) => {
26019
+ const finish = (missing) => {
26020
+ clearTimeout(timer);
26021
+ messages.removeEventListener("message", listener);
26022
+ resolve(missing);
26023
+ };
26024
+ const listener = (event) => {
26025
+ if (event.source != null && event.source !== messages) return;
26026
+ const message2 = event.data;
26027
+ if (!record7(message2) || message2.type !== "persisted-atom-sync" || !record7(message2.state))
26028
+ return;
26029
+ finish(!Object.hasOwn(message2.state, key));
26030
+ };
26031
+ const timer = setTimeout(() => finish(false), SYNC_TIMEOUT_MS);
26032
+ messages.addEventListener("message", listener);
26033
+ try {
26034
+ Promise.resolve(
26035
+ send.call(bridge, { type: "persisted-atom-sync-request", responsePriority: "critical" })
26036
+ ).catch(() => finish(false));
26037
+ } catch {
26038
+ finish(false);
26039
+ }
26040
+ });
26041
+ const inspectThread = async (input) => {
26042
+ if (!isCurrent() || checked.has(input.threadId)) return inspect(input);
26043
+ checked.add(input.threadId);
26044
+ const key = `thread-reference-capability:${input.threadId}`;
26045
+ if (!await isMissing(key) || !isCurrent()) return inspect(input);
26046
+ let proven = true;
26047
+ const result = await inspect({ ...input, includeReferenceCapability: true }).catch(() => {
26048
+ proven = false;
26049
+ return inspect(input);
26050
+ });
26051
+ if (proven && result.owner === "codex" && result.supportsThreadReferences === true && isCurrent() && await isMissing(key) && isCurrent()) {
26052
+ try {
26053
+ await send.call(bridge, {
26054
+ type: "persisted-atom-update",
26055
+ key,
26056
+ value: true,
26057
+ deleted: false
26058
+ });
26059
+ } catch {
26060
+ }
26061
+ }
26062
+ return result;
26063
+ };
26064
+ return Object.freeze({ ...client, inspectThread });
26065
+ }
26066
+
25795
26067
  // src/renderer-thread-reference-capability.ts
25796
- var record6 = (value) => typeof value === "object" && value !== null;
25797
- function restoreThreadReferenceCapability(client, manager, isCurrent) {
25798
- if (!record6(manager) || !record6(manager.storage)) return client;
26068
+ var record8 = (value) => typeof value === "object" && value !== null;
26069
+ function restoreThreadReferenceCapability(client, manager, isCurrent, messages = null) {
26070
+ if (record8(manager) && manager.kind === "main-process-rpc") {
26071
+ return restoreRpcThreadReferenceCapability(client, messages, isCurrent);
26072
+ }
26073
+ if (!record8(manager) || !record8(manager.storage)) return client;
25799
26074
  const storage = manager.storage;
25800
26075
  const read = storage.readValue;
25801
26076
  const write = storage.writeValue;
@@ -25830,14 +26105,14 @@ ${text.includes("## My request:") ? "" : "\n## My request:\n"}`,
25830
26105
  }
25831
26106
 
25832
26107
  // src/renderer-thread-reference-context.ts
25833
- var record7 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
26108
+ var record9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
25834
26109
  function createThreadReferenceContext(manager, hostId2, isCurrent) {
25835
26110
  const prepared = /* @__PURE__ */ new WeakMap();
25836
26111
  return (params) => {
25837
- if (hostId2 === "local" || !record7(manager) || typeof manager.getConversation !== "function" || !record7(params) || typeof params.threadId !== "string")
26112
+ if (hostId2 === "local" || !record9(manager) || typeof manager.getConversation !== "function" || !record9(params) || typeof params.threadId !== "string")
25838
26113
  return params;
25839
26114
  const conversation = manager.getConversation.call(manager, params.threadId);
25840
- if (!record7(conversation) || conversation.id !== params.threadId || conversation.modelProvider !== "codexhost")
26115
+ if (!record9(conversation) || conversation.id !== params.threadId || conversation.modelProvider !== "codexhost")
25841
26116
  return params;
25842
26117
  if (!isCurrent()) throw new Error("Thread reference connection is no longer available");
25843
26118
  const cached2 = prepared.get(params);
@@ -25943,7 +26218,8 @@ ${text.includes("## My request:") ? "" : "\n## My request:\n"}`,
25943
26218
  const client = restoreThreadReferenceCapability(
25944
26219
  nativeClient,
25945
26220
  target,
25946
- () => !disposed && readRouting()?.forHost(route.hostId) === route
26221
+ () => !disposed && readRouting()?.forHost(route.hostId) === route,
26222
+ messages
25947
26223
  );
25948
26224
  entries.set(route.hostId, { route, client, cleanups });
25949
26225
  try {
@@ -32772,7 +33048,7 @@ ${detail}` : ""}`
32772
33048
  }
32773
33049
  function defaultImportName(source, existing) {
32774
33050
  const base = source.provider === "openai-codex" ? "codex" : "grok";
32775
- const used = new Set(existing.map((record8) => record8.name));
33051
+ const used = new Set(existing.map((record10) => record10.name));
32776
33052
  const valid = (name) => credentialImportNameSchema.safeParse(name).success;
32777
33053
  if (!used.has(base)) return base;
32778
33054
  const local = source.label.includes("@") ? source.label.split("@")[0] ?? "" : "";
@@ -32795,7 +33071,7 @@ ${detail}` : ""}`
32795
33071
  const shown = (text) => accountDisplayText(text, hideEmails);
32796
33072
  const targetButtons = /* @__PURE__ */ new Map();
32797
33073
  const importedRecords = () => snapshot.targets.find((target) => target.harnessId === TARGET_HARNESS_ID)?.imports ?? [];
32798
- const sourceOf = (record8) => snapshot.sources.find((source) => source.id === record8.source.id);
33074
+ const sourceOf = (record10) => snapshot.sources.find((source) => source.id === record10.source.id);
32799
33075
  const piTarget = () => snapshot.targets.find((candidate) => candidate.harnessId === TARGET_HARNESS_ID);
32800
33076
  const compatibleSources = () => {
32801
33077
  const target = piTarget();
@@ -32833,7 +33109,7 @@ ${detail}` : ""}`
32833
33109
  sectionImport.addEventListener("click", () => {
32834
33110
  const sources = compatibleSources();
32835
33111
  const free = sources.find(
32836
- (source2) => !importedRecords().some((record8) => record8.source.id === source2.id)
33112
+ (source2) => !importedRecords().some((record10) => record10.source.id === source2.id)
32837
33113
  );
32838
33114
  const source = free ?? sources[0];
32839
33115
  if (source) openDialog("add", { source, choose: true }, SECTION_IMPORT_KEY);
@@ -32883,30 +33159,30 @@ ${detail}` : ""}`
32883
33159
  mark.append(createRendererAgentIcon(agent ?? "pi", 26, document2, pluginFor(agent ?? "pi")));
32884
33160
  return mark;
32885
33161
  };
32886
- const renderRow = (record8) => {
33162
+ const renderRow = (record10) => {
32887
33163
  const row = document2.createElement("div");
32888
33164
  row.className = "settings-pi-accounts__row";
32889
33165
  row.tabIndex = -1;
32890
- row.dataset.importName = record8.name;
32891
- row.setAttribute("aria-label", shown(record8.source.label));
32892
- const agent = record8.source.harnessId;
33166
+ row.dataset.importName = record10.name;
33167
+ row.setAttribute("aria-label", shown(record10.source.label));
33168
+ const agent = record10.source.harnessId;
32893
33169
  const mark = createMark(agent);
32894
33170
  const identity = document2.createElement("div");
32895
33171
  identity.className = "settings-pi-accounts__identity";
32896
33172
  const label = document2.createElement("strong");
32897
33173
  label.className = "settings-account-email";
32898
- label.textContent = shown(record8.source.label);
33174
+ label.textContent = shown(record10.source.label);
32899
33175
  label.title = label.textContent;
32900
33176
  label.translate = false;
32901
33177
  const meta3 = document2.createElement("div");
32902
33178
  meta3.className = "settings-account-metadata";
32903
- const source = sourceOf(record8);
33179
+ const source = sourceOf(record10);
32904
33180
  const parts = [
32905
33181
  metaPart(rendererAgentLabel(agent, pluginFor(agent)), "settings-pi-accounts__agent"),
32906
- metaPart(`${record8.name}/\u2026`, void 0, true),
33182
+ metaPart(`${record10.name}/\u2026`, void 0, true),
32907
33183
  metaPart(messages.copied)
32908
33184
  ];
32909
- const time3 = formatImportedAt(record8.importedAt);
33185
+ const time3 = formatImportedAt(record10.importedAt);
32910
33186
  if (time3) parts.push(metaPart(time3));
32911
33187
  parts.forEach((part, index) => {
32912
33188
  if (index > 0) {
@@ -32923,23 +33199,23 @@ ${detail}` : ""}`
32923
33199
  reimport.type = "button";
32924
33200
  reimport.className = "settings-account-action";
32925
33201
  reimport.textContent = messages.rowReimport;
32926
- reimport.setAttribute("aria-label", `${messages.reimport}: ${shown(record8.source.label)}`);
33202
+ reimport.setAttribute("aria-label", `${messages.reimport}: ${shown(record10.source.label)}`);
32927
33203
  reimport.disabled = busy || !source;
32928
33204
  reimport.title = messages.reimport;
32929
33205
  reimport.addEventListener("click", () => {
32930
- if (source) openDialog("reimport", { source, record: record8 }, `row:${record8.name}`);
33206
+ if (source) openDialog("reimport", { source, record: record10 }, `row:${record10.name}`);
32931
33207
  });
32932
33208
  const remove = document2.createElement("button");
32933
33209
  remove.type = "button";
32934
33210
  remove.className = "settings-account-action settings-pi-accounts__remove";
32935
33211
  remove.textContent = messages.rowRemove;
32936
- remove.setAttribute("aria-label", `${messages.remove}: ${shown(record8.source.label)}`);
33212
+ remove.setAttribute("aria-label", `${messages.remove}: ${shown(record10.source.label)}`);
32937
33213
  remove.disabled = busy;
32938
- remove.addEventListener("click", () => openDialog("remove", { record: record8 }, `row:${record8.name}`));
33214
+ remove.addEventListener("click", () => openDialog("remove", { record: record10 }, `row:${record10.name}`));
32939
33215
  if (source) actions.append(reimport);
32940
33216
  actions.append(remove);
32941
33217
  row.append(mark, identity, actions);
32942
- rows.set(record8.name, row);
33218
+ rows.set(record10.name, row);
32943
33219
  return row;
32944
33220
  };
32945
33221
  const loginTypeLabel = (type) => type === "oauth" ? messages.typeOauth : type === "api_key" ? messages.typeApiKey : messages.typeOther;
@@ -33092,7 +33368,7 @@ ${detail}` : ""}`
33092
33368
  const label = document2.createElement("strong");
33093
33369
  label.textContent = shown(choice.label);
33094
33370
  label.translate = false;
33095
- const existing = importedRecords().find((record8) => record8.source.id === choice.id);
33371
+ const existing = importedRecords().find((record10) => record10.source.id === choice.id);
33096
33372
  const agent = choice.harnessId;
33097
33373
  const detail = document2.createElement("span");
33098
33374
  detail.textContent = [
@@ -33133,7 +33409,7 @@ ${detail}` : ""}`
33133
33409
  const name = request.action === "list" ? void 0 : request.name;
33134
33410
  state = {
33135
33411
  source: state.source,
33136
- record: importedRecords().find((record8) => record8.name === name) ?? state.record
33412
+ record: importedRecords().find((record10) => record10.name === name) ?? state.record
33137
33413
  };
33138
33414
  show(next);
33139
33415
  } else {
@@ -33147,12 +33423,12 @@ ${detail}` : ""}`
33147
33423
  sourceRadios = [];
33148
33424
  body.replaceChildren();
33149
33425
  controls.replaceChildren();
33150
- const { source, record: record8 } = state;
33426
+ const { source, record: record10 } = state;
33151
33427
  const close = () => modal.close();
33152
33428
  if (mode === "add" || mode === "reimport") {
33153
33429
  title.textContent = mode === "add" ? messages.add : messages.reimport;
33154
33430
  modal.setAttribute("aria-label", title.textContent);
33155
- const active = source ?? record8?.source;
33431
+ const active = source ?? record10?.source;
33156
33432
  const choices = mode === "add" && state.choose ? compatibleSources() : [];
33157
33433
  if (choices.length > 1) body.append(sourcePicker(choices));
33158
33434
  else if (active) body.append(line(messages.source, shown(active.label)));
@@ -33161,8 +33437,8 @@ ${detail}` : ""}`
33161
33437
  input.maxLength = 48;
33162
33438
  input.autocomplete = "off";
33163
33439
  input.spellcheck = false;
33164
- input.value = record8?.name ?? (source ? defaultImportName(source, importedRecords()) : "codex");
33165
- input.readOnly = Boolean(record8);
33440
+ input.value = record10?.name ?? (source ? defaultImportName(source, importedRecords()) : "codex");
33441
+ input.readOnly = Boolean(record10);
33166
33442
  input.addEventListener("input", () => {
33167
33443
  nameEdited = true;
33168
33444
  });
@@ -33196,7 +33472,7 @@ ${detail}` : ""}`
33196
33472
  {
33197
33473
  action: mode === "reimport" ? "reimport" : "import",
33198
33474
  sourceId: source2.id,
33199
- name: record8?.name ?? input.value,
33475
+ name: record10?.name ?? input.value,
33200
33476
  confirmed: true
33201
33477
  },
33202
33478
  "done"
@@ -33206,16 +33482,16 @@ ${detail}` : ""}`
33206
33482
  )
33207
33483
  );
33208
33484
  (mode === "add" ? input : controls.children[0]).focus();
33209
- } else if (mode === "remove" && record8) {
33485
+ } else if (mode === "remove" && record10) {
33210
33486
  title.textContent = messages.remove;
33211
33487
  modal.setAttribute("aria-label", title.textContent);
33212
- body.append(note(messages.removeWarning.replace("{name}", record8.name)));
33488
+ body.append(note(messages.removeWarning.replace("{name}", record10.name)));
33213
33489
  const cancel = command(messages.cancel, close);
33214
33490
  controls.append(
33215
33491
  cancel,
33216
33492
  command(
33217
33493
  messages.remove,
33218
- () => submit({ action: "remove", name: record8.name, confirmed: true }, null),
33494
+ () => submit({ action: "remove", name: record10.name, confirmed: true }, null),
33219
33495
  "danger"
33220
33496
  )
33221
33497
  );
@@ -33223,7 +33499,7 @@ ${detail}` : ""}`
33223
33499
  } else {
33224
33500
  title.textContent = messages.doneTitle;
33225
33501
  modal.setAttribute("aria-label", title.textContent);
33226
- const name = record8?.name;
33502
+ const name = record10?.name;
33227
33503
  if (name) body.append(line(messages.entry, `${name}/\u2026`, true));
33228
33504
  body.append(note(messages.done));
33229
33505
  const done = command(messages.close, close, "primary");
@@ -33270,21 +33546,21 @@ ${detail}` : ""}`
33270
33546
  (candidate) => candidate.harnessId === TARGET_HARNESS_ID && source && candidate.providers.includes(source.provider)
33271
33547
  );
33272
33548
  if (!source || !target) return null;
33273
- const record8 = target.imports.find((candidate) => candidate.source.id === source.id);
33549
+ const record10 = target.imports.find((candidate) => candidate.source.id === source.id);
33274
33550
  const key = `${harnessId}:${accountLabel}:import`;
33275
33551
  const button2 = document2.createElement("button");
33276
33552
  button2.type = "button";
33277
33553
  button2.className = "settings-account-pi-import";
33278
33554
  button2.dataset.accountFocus = key;
33279
33555
  button2.disabled = busy;
33280
- const hint = record8 ? messages.importedHint.replace("{name}", record8.name) : messages.add;
33556
+ const hint = record10 ? messages.importedHint.replace("{name}", record10.name) : messages.add;
33281
33557
  button2.title = hint;
33282
33558
  button2.setAttribute("aria-label", hint);
33283
33559
  button2.append(createRendererAgentIcon("pi", 12, document2, pluginFor("pi")));
33284
- if (record8) {
33560
+ if (record10) {
33285
33561
  button2.dataset.state = "imported";
33286
33562
  const name = document2.createElement("code");
33287
- name.textContent = `${record8.name}/\u2026`;
33563
+ name.textContent = `${record10.name}/\u2026`;
33288
33564
  name.translate = false;
33289
33565
  button2.append(name, createRendererSettingsIcon("check", 12));
33290
33566
  } else {
@@ -33292,7 +33568,7 @@ ${detail}` : ""}`
33292
33568
  button2.append(messages.add);
33293
33569
  }
33294
33570
  button2.addEventListener("click", () => {
33295
- if (!record8) {
33571
+ if (!record10) {
33296
33572
  openDialog("add", { source }, key);
33297
33573
  return;
33298
33574
  }
@@ -33301,7 +33577,7 @@ ${detail}` : ""}`
33301
33577
  renderSection();
33302
33578
  sectionToggle.setAttribute("aria-expanded", "true");
33303
33579
  }
33304
- const row = rows.get(record8.name);
33580
+ const row = rows.get(record10.name);
33305
33581
  row?.scrollIntoView({ block: "nearest", behavior: "smooth" });
33306
33582
  row?.focus();
33307
33583
  });
@@ -41619,7 +41895,19 @@ ${usage_default}`;
41619
41895
  update();
41620
41896
  form.requestSubmit();
41621
41897
  } catch (cause) {
41622
- attempt.error = `${cause instanceof Error ? cause.message : text("\u4F1A\u8BDD\u521B\u5EFA\u5931\u8D25\u3002", "Chat creation failed.")} ${text("\u8BF7\u5148\u68C0\u67E5\u4F1A\u8BDD\u5217\u8868\uFF0C\u52FF\u91CD\u590D\u521B\u5EFA\u3002", "Check the chat list before creating another task.")}`;
41898
+ let cleanupError = "";
41899
+ if (attempt.thread?.discard) {
41900
+ if (readNativeScheduleForm(form)?.targetThreadId === attempt.thread.threadId)
41901
+ attempt.thread.retain();
41902
+ else {
41903
+ try {
41904
+ await attempt.thread.discard();
41905
+ } catch (error52) {
41906
+ cleanupError = ` ${text("\u4F1A\u8BDD\u6E05\u7406\u5931\u8D25\uFF1A", "Chat cleanup failed:")} ${error52 instanceof Error ? error52.message : String(error52)}`;
41907
+ }
41908
+ }
41909
+ }
41910
+ 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
41911
  } finally {
41624
41912
  attempt.pending = false;
41625
41913
  if (!retired) update();