@openclaw/codex 2026.7.2-beta.5 → 2026.8.1-beta.2

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.
Files changed (59) hide show
  1. package/README.md +2 -0
  2. package/dist/{app-server-policy-BmDgseo_.js → app-server-policy-zcBDc1JU.js} +1 -1
  3. package/dist/attempt-client-cleanup-DMLXUfa8.js +735 -0
  4. package/dist/binding-connection-I5Bo-AsX.js +33 -0
  5. package/dist/{bounded-turn-FEbUXoYT.js → bounded-turn-qgZmzy_4.js} +71 -63
  6. package/dist/{capabilities-BHRSI6Cn.js → capabilities-CybGI1oz.js} +8 -2
  7. package/dist/cli-metadata.js +1 -1
  8. package/dist/{command-formatters-ico4ZFnk.js → command-formatters-B1AEz8ZA.js} +18 -18
  9. package/dist/{command-handlers-CRmnwI2N.js → command-handlers-Db8pu_ds.js} +484 -95
  10. package/dist/{compact-dEN49UH6.js → compact-LspQaGfl.js} +213 -199
  11. package/dist/{conversation-binding-data-BHRpYbX3.js → conversation-binding-data-CW2GuupV.js} +6 -10
  12. package/dist/doctor-contract-api.js +40 -43
  13. package/dist/{dynamic-tools-LIt9ojep.js → dynamic-tools-BVdyWkUD.js} +2984 -1221
  14. package/dist/effective-mcp-catalog-DIIhAtOZ.js +119 -0
  15. package/dist/{event-projector-assistant-message-DTgnPPVF.js → event-projector-assistant-message-BwxV4d6N.js} +11 -23
  16. package/dist/{attempt-notifications-CMR2_fmR.js → event-projector-usage-e5huIQWu.js} +113 -29
  17. package/dist/harness.js +83 -13
  18. package/dist/image-payload-sanitizer-CnfoUPCE.js +65 -0
  19. package/dist/index.js +703 -329
  20. package/dist/isolated-completion-C58NbL40.js +75 -0
  21. package/dist/local-runtime-attribution-B_2mnqhb.js +19 -0
  22. package/dist/media-understanding-provider.js +5 -5
  23. package/dist/{models-BA01NEez.js → models-BFlpn1Ex.js} +12 -17
  24. package/dist/native-subagent-monitor-DyTGmTUx.js +3111 -0
  25. package/dist/{plugin-app-cache-key-DSXX-rXO.js → plugin-app-cache-key-C3H2CVp6.js} +135 -42
  26. package/dist/plugin-marketplace-discovery-CzrGJdCR.js +385 -0
  27. package/dist/{computer-use-BjGylO-E.js → plugin-metadata-cache-CNJPj4_b.js} +211 -113
  28. package/dist/protocol-validators-B4F7L8Rf.js +2346 -0
  29. package/dist/{rate-limits-S_PXs0ul.js → rate-limits-DZXmOL8-.js} +17 -35
  30. package/dist/{request-CXpPennK.js → request-BRl5_UfX.js} +4 -4
  31. package/dist/{run-attempt-C5GTPJOE.js → run-attempt-P8BdxC1I.js} +1996 -5728
  32. package/dist/{runtime-artifact-C2ITXdhM.js → runtime-artifact-BVSPdd6g.js} +91 -40
  33. package/dist/{sandbox-guard-D1Wky__S.js → sandbox-guard-Cmwc9eIk.js} +10 -13
  34. package/dist/{session-binding-DlVQ-Pxs.js → session-binding-DPxIvMgE.js} +305 -271
  35. package/dist/{session-catalog-CP2oCcEb.js → session-catalog-xwNi_SDM.js} +418 -144
  36. package/dist/{session-cli-CqZ0Fp2a.js → session-cli-7hgXZDV7.js} +1 -1
  37. package/dist/session-retirement-DoMMJFKm.js +36 -0
  38. package/dist/{session-upstream-marker-QE-m5QFG.js → session-upstream-marker-CrIFX06J.js} +1 -1
  39. package/dist/{settled-turn-finalizer-CA_2QXIE.js → settled-turn-finalizer-BRWBO4MO.js} +36 -15
  40. package/dist/{shared-client-BVKE40c-.js → shared-client-kIBbGjk4.js} +721 -240
  41. package/dist/{side-question-CO12sHxo.js → side-question-9HAL26l9.js} +102 -53
  42. package/dist/{thread-lifecycle-DRg_FdzC.js → thread-lifecycle-Bu1BTDXr.js} +1355 -660
  43. package/dist/thread-ownership-6kOQHlyC.js +92 -0
  44. package/dist/thread-resume-CPrJNQVM.js +30 -0
  45. package/dist/{transcript-mirror-uKA-A4tB.js → transcript-mirror-B9gGgnJS.js} +202 -182
  46. package/dist/{transport-stdio-DXgGZ7Ib.js → transport-stdio-DIImwDVS.js} +11 -0
  47. package/dist/upstream-prompt-provenance-ClRBije0.js +41 -0
  48. package/dist/{upstream-session-fork-_Vrz4WJr.js → upstream-session-fork-CE-_LdnP.js} +5 -5
  49. package/dist/{usage-UpVbdX5G.js → usage-CHlV0e-o.js} +3 -3
  50. package/dist/{web-search-provider.runtime-CaQMYDbp.js → web-search-provider.runtime-DRw2Vl42.js} +8 -9
  51. package/openclaw.plugin.json +18 -3
  52. package/package.json +6 -7
  53. package/dist/attempt-client-cleanup-Ia52yRWc.js +0 -127
  54. package/dist/conversation-control-DE7d9DOj.js +0 -287
  55. package/dist/event-projector-usage-tvgb1NCX.js +0 -69
  56. package/dist/notification-correlation-Bj_Ak_jI.js +0 -67
  57. package/dist/protocol-validators-Dm4eXZmt.js +0 -6337
  58. package/dist/realtime-voice-api-BPcA1uN9.js +0 -494
  59. package/dist/realtime-voice-api.js +0 -2
@@ -1,9 +1,91 @@
1
- import { C as isCodexAppServerIndeterminateTransportError, H as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, S as isCodexAppServerIndeterminateRequestCancellationError, a as getLeasedSharedCodexAppServerClient, g as acquireCodexNativeConfigFence, l as releaseLeasedSharedCodexAppServerClient, u as resolveCodexNativeConfigFenceKey, x as isCodexAppServerConnectionClosedError } from "./shared-client-BVKE40c-.js";
2
- import { h as resolveCodexComputerUseConfig, p as resolveCodexAppServerRuntimeOptions } from "./session-binding-DlVQ-Pxs.js";
3
- import { n as describeControlFailure } from "./capabilities-BHRSI6Cn.js";
4
- import { r as requestCodexAppServerJson } from "./request-CXpPennK.js";
1
+ import { g as resolveCodexAppServerRuntimeOptions, v as resolveCodexComputerUseConfig } from "./session-binding-DPxIvMgE.js";
2
+ import { M as isCodexAppServerConnectionClosedError, N as isCodexAppServerIndeterminateRequestCancellationError, P as isCodexAppServerIndeterminateTransportError, a as getLeasedSharedCodexAppServerClient, l as releaseLeasedSharedCodexAppServerClient, lt as resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath, u as resolveCodexNativeConfigFenceKey, v as acquireCodexNativeConfigFence } from "./shared-client-kIBbGjk4.js";
3
+ import { n as describeControlFailure } from "./capabilities-CybGI1oz.js";
4
+ import { r as requestCodexAppServerJson } from "./request-BRl5_UfX.js";
5
5
  import { existsSync } from "node:fs";
6
6
  import { runExec } from "openclaw/plugin-sdk/process-runtime";
7
+ //#region extensions/codex/src/app-server/computer-use-process-repair.ts
8
+ const COMPUTER_USE_PROCESS_LIST_TIMEOUT_MS = 2e3;
9
+ const COMPUTER_USE_PROCESS_LIST_MAX_BUFFER_BYTES = 5 * 1024 * 1024;
10
+ function scopedRepairUnavailableStatus() {
11
+ return {
12
+ attempted: false,
13
+ killedPids: [],
14
+ warnings: ["Computer Use auto-repair skipped because no scoped Codex app-server process was available."],
15
+ message: "Computer Use stale child repair requires a scoped local app-server PID."
16
+ };
17
+ }
18
+ async function killStaleComputerUseMcpChildren(options = {}) {
19
+ if (process.platform !== "darwin") return {
20
+ attempted: true,
21
+ killedPids: [],
22
+ warnings: [`Computer Use stale child repair is currently macOS-only, not ${process.platform}.`],
23
+ message: "Computer Use stale child repair skipped on this platform."
24
+ };
25
+ if (!options.ancestorPid || !Number.isSafeInteger(options.ancestorPid) || options.ancestorPid <= 0) return scopedRepairUnavailableStatus();
26
+ let stdout;
27
+ try {
28
+ stdout = (await runExec("/bin/ps", ["-axo", "pid=,ppid=,command="], {
29
+ logOutput: false,
30
+ maxBuffer: COMPUTER_USE_PROCESS_LIST_MAX_BUFFER_BYTES,
31
+ timeoutMs: COMPUTER_USE_PROCESS_LIST_TIMEOUT_MS
32
+ })).stdout;
33
+ } catch (error) {
34
+ return {
35
+ attempted: true,
36
+ killedPids: [],
37
+ warnings: [`Could not list processes for Computer Use repair: ${describeControlFailure(error)}`],
38
+ message: "Computer Use stale child repair could not inspect running processes."
39
+ };
40
+ }
41
+ const killedPids = [];
42
+ const warnings = [];
43
+ const processInfos = parsePsOutput(stdout);
44
+ for (const processInfo of processInfos) {
45
+ if (!isStaleComputerUseMcpChild(processInfo.command)) continue;
46
+ if (!isDescendantOfPid(processInfo.pid, options.ancestorPid, processInfos)) continue;
47
+ try {
48
+ process.kill(processInfo.pid, "SIGTERM");
49
+ killedPids.push(processInfo.pid);
50
+ } catch (error) {
51
+ warnings.push(`Could not terminate stale Computer Use MCP child pid ${processInfo.pid}: ${describeControlFailure(error)}`);
52
+ }
53
+ }
54
+ return {
55
+ attempted: true,
56
+ killedPids,
57
+ warnings,
58
+ message: killedPids.length === 0 ? "No stale Computer Use MCP children were found under the scoped Codex app-server process." : `Terminated ${killedPids.length} stale Computer Use MCP child process${killedPids.length === 1 ? "" : "es"} under the scoped Codex app-server process.`
59
+ };
60
+ }
61
+ function parsePsOutput(stdout) {
62
+ return stdout.split(/\r?\n/u).flatMap((line) => {
63
+ const match = /^\s*(\d+)\s+(\d+)\s+(.+)$/u.exec(line);
64
+ if (!match) return [];
65
+ return [{
66
+ pid: Number(match[1]),
67
+ ppid: Number(match[2]),
68
+ command: match[3] ?? ""
69
+ }];
70
+ }).filter((processInfo) => Number.isSafeInteger(processInfo.pid) && processInfo.pid > 0 && Number.isSafeInteger(processInfo.ppid) && processInfo.ppid >= 0);
71
+ }
72
+ function isStaleComputerUseMcpChild(command) {
73
+ return command.includes("SkyComputerUseClient") && /(?:^|\s)mcp(?:\s|$)/u.test(command);
74
+ }
75
+ function isDescendantOfPid(pid, ancestorPid, processInfos) {
76
+ const parents = new Map(processInfos.map((processInfo) => [processInfo.pid, processInfo.ppid]));
77
+ const seen = /* @__PURE__ */ new Set();
78
+ let current = pid;
79
+ while (!seen.has(current)) {
80
+ seen.add(current);
81
+ const parent = parents.get(current);
82
+ if (!parent || parent <= 0) return false;
83
+ if (parent === ancestorPid) return true;
84
+ current = parent;
85
+ }
86
+ return false;
87
+ }
88
+ //#endregion
7
89
  //#region extensions/codex/src/app-server/computer-use.ts
8
90
  /**
9
91
  * Computer Use plugin/MCP readiness checks and optional install flow for Codex
@@ -20,6 +102,8 @@ const CURATED_MARKETPLACE_POLL_INTERVAL_MS = 2e3;
20
102
  const COMPUTER_USE_MARKETPLACE_NAME_PRIORITY = [
21
103
  "openai-bundled",
22
104
  "openai-curated",
105
+ "openai-api-curated",
106
+ "openai-curated-remote",
23
107
  "local"
24
108
  ];
25
109
  const COMPUTER_USE_LIVE_TEST_RETRY_COUNT = 1;
@@ -179,18 +263,8 @@ async function ensureComputerUsePlugin(params) {
179
263
  config: params.config,
180
264
  plugin,
181
265
  tools: [],
182
- reason: pluginSetupReason(plugin, params.marketplace),
183
- message: pluginSetupMessage(params.config, plugin, params.marketplace)
184
- })
185
- };
186
- if (params.marketplace.kind === "remote") return {
187
- ok: false,
188
- status: statusFromPlugin({
189
- config: params.config,
190
- plugin,
191
- tools: [],
192
- reason: "remote_install_unsupported",
193
- message: remoteInstallUnsupportedMessage(plugin, params.marketplace)
266
+ reason: pluginSetupReason(plugin),
267
+ message: pluginSetupMessage(params.config, plugin)
194
268
  })
195
269
  };
196
270
  await params.request("plugin/install", pluginRequestParams(params.marketplace, params.config.pluginName));
@@ -203,8 +277,8 @@ async function ensureComputerUsePlugin(params) {
203
277
  config: params.config,
204
278
  plugin,
205
279
  tools: [],
206
- reason: pluginSetupReason(plugin, params.marketplace),
207
- message: pluginSetupMessage(params.config, plugin, params.marketplace)
280
+ reason: pluginSetupReason(plugin),
281
+ message: pluginSetupMessage(params.config, plugin)
208
282
  })
209
283
  };
210
284
  return {
@@ -326,14 +400,6 @@ async function runCodexComputerUseLiveTest(params) {
326
400
  async function cleanupComputerUseProbeThread(request, threadId, config) {
327
401
  await Promise.allSettled([request("thread/unsubscribe", { threadId }, { timeoutMs: config.liveTestTimeoutMs }), request("thread/archive", { threadId }, { timeoutMs: config.liveTestTimeoutMs })]);
328
402
  }
329
- function scopedRepairUnavailableStatus() {
330
- return {
331
- attempted: false,
332
- killedPids: [],
333
- warnings: ["Computer Use auto-repair skipped because no scoped Codex app-server process was available."],
334
- message: "Computer Use stale child repair requires a scoped local app-server PID."
335
- };
336
- }
337
403
  async function resolveMarketplaceRef(params) {
338
404
  let preferredMarketplaceName = params.config.marketplaceName;
339
405
  if (params.config.marketplaceSource && params.allowAdd) {
@@ -390,17 +456,22 @@ function resolveBundledComputerUseMarketplacePath(params) {
390
456
  return resolveFirstExistingMacOSDesktopCodexBundledMarketplacePath({ candidates: params.defaultBundledMarketplacePathCandidates });
391
457
  }
392
458
  function findComputerUseMarketplaces(listed, pluginName) {
393
- return listed.marketplaces.filter((marketplace) => marketplace.plugins.some((plugin) => plugin.name === pluginName || plugin.id === pluginName || plugin.id === `${pluginName}@${marketplace.name}`)).map((marketplace) => {
394
- if (marketplace.path) return {
459
+ return listed.marketplaces.flatMap((marketplace) => {
460
+ const plugin = marketplace.plugins.find((candidate) => candidate.name === pluginName || candidate.id === pluginName || candidate.id === `${pluginName}@${marketplace.name}`);
461
+ if (!plugin) return [];
462
+ if (marketplace.path) return [{
395
463
  kind: "local",
396
464
  name: marketplace.name,
397
465
  path: marketplace.path
398
- };
399
- return {
466
+ }];
467
+ const remotePluginId = plugin.remotePluginId?.trim();
468
+ if (!remotePluginId) return [];
469
+ return [{
400
470
  kind: "remote",
401
471
  name: marketplace.name,
402
- remoteMarketplaceName: marketplace.name
403
- };
472
+ remoteMarketplaceName: marketplace.name,
473
+ remotePluginId
474
+ }];
404
475
  });
405
476
  }
406
477
  function chooseKnownComputerUseMarketplace(candidates) {
@@ -452,25 +523,21 @@ async function reloadMcpServers(request) {
452
523
  await request("config/mcpServer/reload", void 0);
453
524
  }
454
525
  function pluginRequestParams(marketplace, pluginName) {
455
- return {
456
- ...marketplace.kind === "local" ? { marketplacePath: marketplace.path } : {},
457
- ...marketplace.kind === "remote" ? { remoteMarketplaceName: marketplace.remoteMarketplaceName } : {},
526
+ return marketplace.kind === "local" ? {
527
+ marketplacePath: marketplace.path,
458
528
  pluginName
529
+ } : {
530
+ remoteMarketplaceName: marketplace.remoteMarketplaceName,
531
+ pluginName: marketplace.remotePluginId
459
532
  };
460
533
  }
461
- function pluginSetupReason(plugin, marketplace) {
462
- if (marketplace.kind === "remote") return "remote_install_unsupported";
534
+ function pluginSetupReason(plugin) {
463
535
  return plugin.summary.installed ? "plugin_disabled" : "plugin_not_installed";
464
536
  }
465
- function pluginSetupMessage(config, plugin, marketplace) {
466
- if (marketplace.kind === "remote") return remoteInstallUnsupportedMessage(plugin, marketplace);
537
+ function pluginSetupMessage(config, plugin) {
467
538
  if (!plugin.summary.installed) return "Computer Use is available but not installed. Run /codex computer-use install or enable computerUse.autoInstall.";
468
539
  return `Computer Use is installed, but the ${config.pluginName} plugin is disabled. Run /codex computer-use install or enable computerUse.autoInstall to re-enable it.`;
469
540
  }
470
- function remoteInstallUnsupportedMessage(plugin, marketplace) {
471
- const marketplaceName = marketplace.name ?? plugin.marketplaceName;
472
- return `Computer Use is ${plugin.summary.installed ? "installed but disabled" : "available"} in remote Codex marketplace ${marketplaceName}, but Codex app-server does not support remote plugin install yet. Configure computerUse.marketplaceSource or computerUse.marketplacePath for a local marketplace, then run /codex computer-use install.`;
473
- }
474
541
  function statusFromPlugin(params) {
475
542
  return {
476
543
  enabled: true,
@@ -592,75 +659,6 @@ function pluginWarnings(plugin) {
592
659
  if (source && typeof source === "object" && "type" in source && source.type === "remote") warnings.push("Computer Use plugin is resolved from a remote marketplace; live local bundles are preferred.");
593
660
  return warnings;
594
661
  }
595
- async function killStaleComputerUseMcpChildren(options = {}) {
596
- if (process.platform !== "darwin") return {
597
- attempted: true,
598
- killedPids: [],
599
- warnings: [`Computer Use stale child repair is currently macOS-only, not ${process.platform}.`],
600
- message: "Computer Use stale child repair skipped on this platform."
601
- };
602
- if (!options.ancestorPid || !Number.isSafeInteger(options.ancestorPid) || options.ancestorPid <= 0) return scopedRepairUnavailableStatus();
603
- let stdout;
604
- try {
605
- stdout = (await runExec("/bin/ps", ["-axo", "pid=,ppid=,command="], {
606
- logOutput: false,
607
- maxBuffer: 5 * 1024 * 1024
608
- })).stdout;
609
- } catch (error) {
610
- return {
611
- attempted: true,
612
- killedPids: [],
613
- warnings: [`Could not list processes for Computer Use repair: ${describeControlFailure(error)}`],
614
- message: "Computer Use stale child repair could not inspect running processes."
615
- };
616
- }
617
- const killedPids = [];
618
- const warnings = [];
619
- const processInfos = parsePsOutput(stdout);
620
- for (const processInfo of processInfos) {
621
- if (!isStaleComputerUseMcpChild(processInfo.command)) continue;
622
- if (!isDescendantOfPid(processInfo.pid, options.ancestorPid, processInfos)) continue;
623
- try {
624
- process.kill(processInfo.pid, "SIGTERM");
625
- killedPids.push(processInfo.pid);
626
- } catch (error) {
627
- warnings.push(`Could not terminate stale Computer Use MCP child pid ${processInfo.pid}: ${describeControlFailure(error)}`);
628
- }
629
- }
630
- return {
631
- attempted: true,
632
- killedPids,
633
- warnings,
634
- message: killedPids.length === 0 ? "No stale Computer Use MCP children were found under the scoped Codex app-server process." : `Terminated ${killedPids.length} stale Computer Use MCP child process${killedPids.length === 1 ? "" : "es"} under the scoped Codex app-server process.`
635
- };
636
- }
637
- function parsePsOutput(stdout) {
638
- return stdout.split(/\r?\n/u).flatMap((line) => {
639
- const match = /^\s*(\d+)\s+(\d+)\s+(.+)$/u.exec(line);
640
- if (!match) return [];
641
- return [{
642
- pid: Number(match[1]),
643
- ppid: Number(match[2]),
644
- command: match[3] ?? ""
645
- }];
646
- }).filter((processInfo) => Number.isSafeInteger(processInfo.pid) && processInfo.pid > 0 && Number.isSafeInteger(processInfo.ppid) && processInfo.ppid >= 0);
647
- }
648
- function isStaleComputerUseMcpChild(command) {
649
- return command.includes("SkyComputerUseClient") && /(?:^|\s)mcp(?:\s|$)/u.test(command);
650
- }
651
- function isDescendantOfPid(pid, ancestorPid, processInfos) {
652
- const parents = new Map(processInfos.map((processInfo) => [processInfo.pid, processInfo.ppid]));
653
- const seen = /* @__PURE__ */ new Set();
654
- let current = pid;
655
- while (!seen.has(current)) {
656
- seen.add(current);
657
- const parent = parents.get(current);
658
- if (!parent || parent <= 0) return false;
659
- if (parent === ancestorPid) return true;
660
- current = parent;
661
- }
662
- return false;
663
- }
664
662
  function createComputerUseRequest(params) {
665
663
  if (params.request) return params.request;
666
664
  if (params.client) return async (method, requestParams, options) => await params.client.request(method, requestParams, {
@@ -692,4 +690,104 @@ function resolveComputerUseConfig(params) {
692
690
  });
693
691
  }
694
692
  //#endregion
695
- export { runCodexComputerUseLiveTest as a, readCodexComputerUseStatus as i, installCodexComputerUse as n, killStaleComputerUseMcpChildren as r, ensureCodexComputerUse as t };
693
+ //#region extensions/codex/src/app-server/plugin-metadata-cache.ts
694
+ const CODEX_PLUGIN_METADATA_CACHE_TTL_MS = 3600 * 1e3;
695
+ /** Process-local plugin metadata cache with coalesced loads per query. */
696
+ var CodexPluginMetadataCache = class {
697
+ constructor(nowMs = Date.now) {
698
+ this.nowMs = nowMs;
699
+ this.entries = /* @__PURE__ */ new Map();
700
+ this.inFlight = /* @__PURE__ */ new Map();
701
+ this.generations = /* @__PURE__ */ new Map();
702
+ this.clearGeneration = 0;
703
+ }
704
+ /** Returns a fresh cached snapshot without issuing a request. */
705
+ read(appCacheKey, queryKind, requestParams, catalogScope) {
706
+ const entryKey = buildMetadataCacheEntryKey(appCacheKey, queryKind, requestParams, catalogScope);
707
+ const entry = this.entries.get(entryKey);
708
+ if (!entry) return;
709
+ if (entry.expiresAtMs <= this.nowMs()) {
710
+ this.entries.delete(entryKey);
711
+ return;
712
+ }
713
+ return entry.snapshot;
714
+ }
715
+ /** Returns a fresh snapshot or coalesces one catalog or installed-plugin request. */
716
+ async load(params) {
717
+ const entryKey = buildMetadataCacheEntryKey(params.appCacheKey, params.queryKind, params.requestParams, params.catalogScope);
718
+ const cached = this.read(params.appCacheKey, params.queryKind, params.requestParams, params.catalogScope);
719
+ if (cached) return cached;
720
+ const pending = this.inFlight.get(entryKey);
721
+ if (pending) try {
722
+ return await pending.promise;
723
+ } catch {
724
+ if (this.inFlight.get(entryKey) === pending) this.inFlight.delete(entryKey);
725
+ return await this.load(params);
726
+ }
727
+ const generation = this.generations.get(params.appCacheKey) ?? 0;
728
+ const clearGeneration = this.clearGeneration;
729
+ const promise = (async () => {
730
+ const method = params.queryKind === "installed" ? "plugin/installed" : "plugin/list";
731
+ const response = await params.request(method, params.requestParams);
732
+ const snapshot = {
733
+ appCacheKey: params.appCacheKey,
734
+ queryKind: params.queryKind,
735
+ response
736
+ };
737
+ if (generation === (this.generations.get(params.appCacheKey) ?? 0) && clearGeneration === this.clearGeneration && !hasMarketplaceLoadErrors(response) && (params.cacheable?.(response) ?? true)) this.entries.set(entryKey, {
738
+ snapshot,
739
+ expiresAtMs: this.nowMs() + CODEX_PLUGIN_METADATA_CACHE_TTL_MS
740
+ });
741
+ return snapshot;
742
+ })();
743
+ this.inFlight.set(entryKey, {
744
+ appCacheKey: params.appCacheKey,
745
+ promise
746
+ });
747
+ try {
748
+ return await promise;
749
+ } finally {
750
+ if (this.inFlight.get(entryKey)?.promise === promise) this.inFlight.delete(entryKey);
751
+ }
752
+ }
753
+ /** Invalidates all plugin metadata queries for one app-server runtime. */
754
+ invalidate(appCacheKey) {
755
+ this.generations.set(appCacheKey, (this.generations.get(appCacheKey) ?? 0) + 1);
756
+ for (const [entryKey, entry] of this.entries) if (entry.snapshot.appCacheKey === appCacheKey) this.entries.delete(entryKey);
757
+ for (const [entryKey, pending] of this.inFlight) if (pending.appCacheKey === appCacheKey) this.inFlight.delete(entryKey);
758
+ }
759
+ /** Clears snapshots and prevents late in-flight loads from repopulating them. */
760
+ clear() {
761
+ this.clearGeneration += 1;
762
+ this.generations.clear();
763
+ this.entries.clear();
764
+ this.inFlight.clear();
765
+ }
766
+ };
767
+ /** Shared plugin metadata cache used by Codex app-server runtime paths. */
768
+ const defaultCodexPluginMetadataCache = new CodexPluginMetadataCache();
769
+ function hasMarketplaceLoadErrors(response) {
770
+ return response.marketplaceLoadErrors.length > 0;
771
+ }
772
+ function buildMetadataCacheEntryKey(appCacheKey, queryKind, requestParams, catalogScope) {
773
+ if (queryKind !== "installed") {
774
+ const listParams = requestParams;
775
+ const entry = [
776
+ appCacheKey,
777
+ queryKind,
778
+ listParams?.cwds ?? [],
779
+ Array.from(new Set(listParams?.marketplaceKinds ?? [])).toSorted(),
780
+ ...catalogScope ? [catalogScope] : []
781
+ ];
782
+ return JSON.stringify(entry);
783
+ }
784
+ const installedParams = requestParams;
785
+ return JSON.stringify([
786
+ appCacheKey,
787
+ queryKind,
788
+ installedParams?.cwds ?? [],
789
+ Array.from(new Set(installedParams?.installSuggestionPluginNames ?? [])).toSorted()
790
+ ]);
791
+ }
792
+ //#endregion
793
+ export { runCodexComputerUseLiveTest as a, readCodexComputerUseStatus as i, ensureCodexComputerUse as n, killStaleComputerUseMcpChildren as o, installCodexComputerUse as r, defaultCodexPluginMetadataCache as t };