0sec-cli 0.22.0 → 0.22.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (107) hide show
  1. package/0.js +56 -45
  2. package/README.md +12 -0
  3. package/chunks/{adapt-loop-7I57LXXR.js → adapt-loop-3CCOWE43.js} +4 -4
  4. package/chunks/{artifact-scraper-PYZ3RU3O.js → artifact-scraper-Z4UUIOH3.js} +2 -2
  5. package/chunks/{assumption-mining-MFLF43IR.js → assumption-mining-2UAKQB6V.js} +18 -14
  6. package/chunks/{chunk-RE5EZDG2.js → chunk-2WWAPKAW.js} +126 -1089
  7. package/chunks/{chunk-LPTRPRZR.js → chunk-3BPX75OR.js} +1 -1
  8. package/chunks/chunk-4ZYYX5GY.js +74 -0
  9. package/chunks/{chunk-RSIUX3RW.js → chunk-5JNTMWPK.js} +2 -2
  10. package/chunks/{chunk-RRD4XXPU.js → chunk-5WAJGLCW.js} +3 -3
  11. package/chunks/{chunk-76KSBWOQ.js → chunk-6KFB6AYN.js} +515 -20
  12. package/chunks/{chunk-HR2TU42B.js → chunk-6WQDXWQC.js} +169 -15
  13. package/chunks/chunk-6YZE552K.js +5603 -0
  14. package/chunks/chunk-BGX53365.js +309 -0
  15. package/chunks/{chunk-7DEHG7YT.js → chunk-C6JPA32H.js} +1 -1
  16. package/chunks/chunk-CF3MNS3O.js +990 -0
  17. package/chunks/{chunk-4VGLO2YS.js → chunk-CPCHLL6A.js} +5 -2
  18. package/chunks/{chunk-DM5C5L5D.js → chunk-DPUXXMJW.js} +1 -1
  19. package/chunks/{chunk-LYUAM3TG.js → chunk-E3OOBVOK.js} +30 -12
  20. package/chunks/{chunk-HUNAPTKV.js → chunk-E74LXQFY.js} +1 -1
  21. package/chunks/{chunk-UU7PQP6N.js → chunk-ELI3BVIK.js} +3 -3
  22. package/chunks/chunk-FFHRANYC.js +547 -0
  23. package/chunks/{chunk-IO7R7WBM.js → chunk-G2BE2FC7.js} +1 -1
  24. package/chunks/chunk-GQ3DGHWE.js +1659 -0
  25. package/chunks/{chunk-V36HVTUL.js → chunk-GVY3S5E5.js} +21 -18
  26. package/chunks/{chunk-UV5QWZGE.js → chunk-H4DH7COV.js} +192 -40
  27. package/chunks/{chunk-SJBCK2EI.js → chunk-H6Q2QAIY.js} +23475 -22747
  28. package/chunks/{chunk-VMRRNRMR.js → chunk-IHPTOTLL.js} +1 -1
  29. package/chunks/chunk-IXAHQICR.js +31 -0
  30. package/chunks/{chunk-TH2LW437.js → chunk-KCA35IL3.js} +2 -190
  31. package/chunks/{chunk-VNRY6AWF.js → chunk-L2CCO4KE.js} +282 -34
  32. package/chunks/{chunk-6YNKRUMC.js → chunk-NJLKFC66.js} +321 -5
  33. package/chunks/{chunk-W6UWZFKL.js → chunk-O6KPVYOI.js} +100 -5
  34. package/chunks/{chunk-EGZGZFAH.js → chunk-OAS5SAVZ.js} +6768 -2100
  35. package/chunks/chunk-PS5E7LUQ.js +277 -0
  36. package/chunks/{chunk-2GV4HQKE.js → chunk-QVIRWJ45.js} +257 -145
  37. package/chunks/{chunk-OWLJYJ5O.js → chunk-QWK4R3DB.js} +9 -9
  38. package/chunks/{chunk-XFCTUKXR.js → chunk-RCRTSKQN.js} +1 -1
  39. package/chunks/chunk-RS4MAN3Q.js +73 -0
  40. package/chunks/{chunk-7UFUALR2.js → chunk-RTBZ36BD.js} +8 -274
  41. package/chunks/{chunk-TZFIAMWZ.js → chunk-SCWWLABR.js} +1 -1
  42. package/chunks/chunk-VDOWARMJ.js +63 -0
  43. package/chunks/{chunk-5MWAG3FT.js → chunk-WBRGXCU2.js} +79 -18
  44. package/chunks/{chunk-LCRTAQN2.js → chunk-WHUAUFSX.js} +1 -1
  45. package/chunks/{chunk-YIQSGNAA.js → chunk-XODDLNBI.js} +1535 -1306
  46. package/chunks/chunk-YAZARMJY.js +355 -0
  47. package/chunks/{chunk-OAYUPGF6.js → chunk-YED25PA4.js} +1 -1
  48. package/chunks/{codex-models-7TLJSY3L.js → codex-models-Z43V3427.js} +9 -3
  49. package/chunks/{commands-NEI7L3QA.js → commands-EUGF4FUZ.js} +5844 -4095
  50. package/chunks/{db-5AP3JB4W.js → db-NVAW4WWR.js} +3 -3
  51. package/chunks/{dist-3FNZIBB4.js → dist-27BNG6WD.js} +195 -112
  52. package/chunks/{dist-5YHYNLI3.js → dist-7RUOKPRJ.js} +12 -2
  53. package/chunks/{dist-KEULE5IQ.js → dist-LNXGATR2.js} +2 -2
  54. package/chunks/{dist-XZB53PS5.js → dist-M2X367VW.js} +2 -2
  55. package/chunks/{dist-DD4H6HMQ.js → dist-NG2HT5XU.js} +27 -1
  56. package/chunks/{eval-runner-43BO2C4T.js → eval-runner-6Q3H52SP.js} +13 -9
  57. package/chunks/{exploit-agent-N4A5ELBK.js → exploit-agent-FCCR2HYX.js} +1 -1
  58. package/chunks/{exploit-autoclimb-N7P6KIF5.js → exploit-autoclimb-X5ZS5FAO.js} +1 -1
  59. package/chunks/{exploit-climb-WNEJUB5W.js → exploit-climb-3JHGEO36.js} +2 -2
  60. package/chunks/{fix-Z452M4EC.js → fix-NSNPU33B.js} +12 -6
  61. package/chunks/{harness-QJJJVSG4.js → harness-KXQOVIDQ.js} +3 -3
  62. package/chunks/{hunt-scan-K6D2V3PX.js → hunt-scan-ELTKGKC4.js} +16 -12
  63. package/chunks/{kernel-primitive-TKUACPKD.js → kernel-primitive-MT7YZSIG.js} +2 -2
  64. package/chunks/{kernel-vm-runner-RAAO2PGT.js → kernel-vm-runner-YFRHYC6G.js} +2 -2
  65. package/chunks/{native-loop-2ZRJENZ3.js → native-loop-OFJDRHPI.js} +18 -8
  66. package/chunks/orchestrate-DRZ2SVCP.js +62 -0
  67. package/chunks/{prepare-KYHGFWCJ.js → prepare-72GWTRVI.js} +6 -2
  68. package/chunks/{process-N245QIQG.js → process-MJYJ2K5E.js} +2 -1
  69. package/chunks/{run-U3XU4CTC.js → run-WTJCZZHV.js} +3091 -6037
  70. package/chunks/{runtime-G75TEWQY.js → runtime-FCKOUB7V.js} +10 -4
  71. package/chunks/{runtime-XFWJTBUO.js → runtime-LCJ4XSKE.js} +5 -1
  72. package/chunks/{scan-stream-BMOCPKQX.js → scan-stream-GT6GKQ3U.js} +7 -1
  73. package/chunks/{scope-WXI46UHJ.js → scope-E5QZUOOH.js} +2 -2
  74. package/chunks/service-plugins-MSK2EQP6.js +62 -0
  75. package/chunks/{session-store-27L3ZU73.js → session-store-H3Q7KCYG.js} +6 -4
  76. package/chunks/{variant-candidates-YWZORZMK.js → variant-candidates-SZKDCOLK.js} +9 -3
  77. package/chunks/{web-recon-prepass-YVMFXCIK.js → web-recon-prepass-IO3GXQMW.js} +11 -6
  78. package/dashboard/apple-touch-icon.png +0 -0
  79. package/dashboard/assets/operations-BvB5Qpmk.css +1 -0
  80. package/dashboard/assets/operations-D8Ii01SV.js +114 -0
  81. package/dashboard/assets/zero-peek-Dzm3MT3X.png +0 -0
  82. package/dashboard/favicon.ico +0 -0
  83. package/dashboard/favicon.svg +10 -0
  84. package/dashboard/index.html +5 -3
  85. package/package.json +1 -1
  86. package/chunks/chunk-6GHSR47F.js +0 -147
  87. package/chunks/chunk-CAYANSH6.js +0 -3524
  88. package/chunks/chunk-GHWODZMR.js +0 -16
  89. package/chunks/chunk-MICHDTBK.js +0 -193
  90. package/chunks/orchestrate-2GWGNTBF.js +0 -58
  91. package/dashboard/assets/bot-Bg1Tp9_d.js +0 -1
  92. package/dashboard/assets/dist-B_dDCPbu.js +0 -1
  93. package/dashboard/assets/findings-page-mayGhNx6.js +0 -5
  94. package/dashboard/assets/format--susmHX7.js +0 -1
  95. package/dashboard/assets/input-TuVPR3Zl.js +0 -1
  96. package/dashboard/assets/jsx-runtime-MGseXjj5.js +0 -3
  97. package/dashboard/assets/live-page-HWWHX99U.js +0 -1
  98. package/dashboard/assets/meta-tile-ckHo-w7k.js +0 -1
  99. package/dashboard/assets/operations-BxZ0OoXO.js +0 -10
  100. package/dashboard/assets/operations-CMFVrXEe.css +0 -2
  101. package/dashboard/assets/operations-app-D3d35rgo.js +0 -46
  102. package/dashboard/assets/overview-page-W_4IteEr.js +0 -1
  103. package/dashboard/assets/page-header-Bw9AJgBV.js +0 -1
  104. package/dashboard/assets/scans-page-CgzVXHnn.js +0 -1
  105. package/dashboard/assets/siren-KQj8QAnJ.js +0 -1
  106. package/dashboard/assets/table-8EDklulN.js +0 -1
  107. package/dashboard/assets/tabs-CFHPOwg8.js +0 -1
@@ -1,9 +1,19 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire as __0CreateRequire } from "node:module";
3
3
  const require = __0CreateRequire(import.meta.url);
4
+ import {
5
+ isAdmittedSmolvmWorkbench
6
+ } from "./chunk-2WWAPKAW.js";
7
+ import {
8
+ MESSAGE_CACHE_BREAKPOINTS,
9
+ planMessageBreakpoints,
10
+ providerSupportsPromptCache,
11
+ readCacheUsage,
12
+ withCacheControl
13
+ } from "./chunk-RS4MAN3Q.js";
4
14
  import {
5
15
  VERSION
6
- } from "./chunk-76KSBWOQ.js";
16
+ } from "./chunk-6KFB6AYN.js";
7
17
 
8
18
  // packages/core/dist/agent/feature-presets.js
9
19
  var FP_MOAT_FLAGS = [
@@ -1029,66 +1039,25 @@ import { appendFileSync, existsSync, readFileSync, renameSync, writeFileSync } f
1029
1039
  import { homedir } from "node:os";
1030
1040
  import { join } from "node:path";
1031
1041
 
1032
- // packages/core/dist/runtime/prompt-cache.js
1033
- var MAX_CACHE_BREAKPOINTS = 4;
1034
- var MESSAGE_CACHE_BREAKPOINTS = MAX_CACHE_BREAKPOINTS - 1;
1035
- var BREAKPOINT_SPACING_BLOCKS = 15;
1036
- var NATIVE_CACHE_PROVIDERS = /* @__PURE__ */ new Set(["anthropic"]);
1037
- var OPT_IN_CACHE_PROVIDERS = /* @__PURE__ */ new Set(["z-ai", "kimi"]);
1038
- function providerSupportsPromptCache(provider) {
1039
- if (NATIVE_CACHE_PROVIDERS.has(provider))
1040
- return true;
1041
- if (!OPT_IN_CACHE_PROVIDERS.has(provider))
1042
- return false;
1043
- return readExtraCacheProviders().has(provider);
1044
- }
1045
- function readExtraCacheProviders() {
1046
- const raw = process.env["ZERO_PROMPT_CACHE_EXTRA_PROVIDERS"];
1042
+ // packages/core/dist/runtime/workbench-provider-proxy.js
1043
+ function resolveWorkbenchProviderProxy(env2) {
1044
+ const raw = env2.ZERO_WORKBENCH_PROVIDER_PROXY;
1047
1045
  if (!raw)
1048
- return /* @__PURE__ */ new Set();
1049
- return new Set(raw.split(",").map((entry) => entry.trim().toLowerCase()).filter((entry) => entry.length > 0));
1050
- }
1051
- function planMessageBreakpoints(messages, budget = MESSAGE_CACHE_BREAKPOINTS) {
1052
- if (messages.length === 0 || budget <= 0)
1053
- return [];
1054
- const lastIndex = messages.length - 1;
1055
- const picks = /* @__PURE__ */ new Set([lastIndex]);
1056
- const rollingBudget = Math.max(1, budget - 1);
1057
- let blocksSincePick = blockCount(messages[lastIndex]);
1058
- for (let i = lastIndex - 1; i >= 0 && picks.size < rollingBudget; i--) {
1059
- if (blocksSincePick >= BREAKPOINT_SPACING_BLOCKS) {
1060
- picks.add(i);
1061
- blocksSincePick = 0;
1062
- }
1063
- blocksSincePick += blockCount(messages[i]);
1064
- }
1065
- if (picks.size < budget)
1066
- picks.add(0);
1067
- return [...picks].sort((a, b) => a - b).slice(0, budget);
1068
- }
1069
- function blockCount(message) {
1070
- return message?.content.length ?? 0;
1071
- }
1072
- function withCacheControl(block) {
1073
- return { ...block, cache_control: { type: "ephemeral" } };
1074
- }
1075
- function readCacheUsage(raw) {
1076
- if (typeof raw !== "object" || raw === null)
1077
1046
  return void 0;
1078
- const usage = raw;
1079
- const uncachedInput = numberOr(usage.input_tokens, 0);
1080
- const outputTokens = numberOr(usage.output_tokens, 0);
1081
- const cacheRead = numberOr(usage.cache_read_input_tokens, void 0);
1082
- const cacheWrite = numberOr(usage.cache_creation_input_tokens, void 0);
1083
- return {
1084
- inputTokens: uncachedInput + (cacheRead ?? 0) + (cacheWrite ?? 0),
1085
- outputTokens,
1086
- ...cacheRead !== void 0 ? { cachedInputTokens: cacheRead } : {},
1087
- ...cacheWrite !== void 0 ? { cacheWriteTokens: cacheWrite } : {}
1088
- };
1089
- }
1090
- function numberOr(value, fallback) {
1091
- return typeof value === "number" && Number.isFinite(value) ? value : fallback;
1047
+ if (!isAdmittedSmolvmWorkbench())
1048
+ throw new Error("Provider proxy requires authenticated SmolVM workbench admission");
1049
+ let url;
1050
+ try {
1051
+ url = new URL(raw);
1052
+ } catch {
1053
+ throw new Error("Invalid guest provider proxy address");
1054
+ }
1055
+ if (url.protocol !== "http:" || url.hostname !== "127.0.0.1" || !url.port || url.pathname !== "/provider/request" || url.username || url.password || url.search || url.hash)
1056
+ throw new Error("Provider proxy must be the fixed guest loopback route");
1057
+ const model = env2.ZERO_WORKBENCH_PROVIDER_MODEL;
1058
+ if (!model || !/^[A-Za-z0-9._-]{1,128}$/.test(model))
1059
+ throw new Error("Missing exact workbench provider model");
1060
+ return { url: url.href, model };
1092
1061
  }
1093
1062
 
1094
1063
  // packages/core/dist/runtime/llm-api.js
@@ -1098,6 +1067,31 @@ function readResponsesCachedTokens(usage) {
1098
1067
  const cached = Number(details?.cached_tokens ?? 0);
1099
1068
  return Number.isFinite(cached) && cached > 0 ? { cachedInputTokens: cached } : {};
1100
1069
  }
1070
+ function readChatUsage(raw) {
1071
+ if (!raw || typeof raw !== "object")
1072
+ return void 0;
1073
+ const usage = raw;
1074
+ if (usage.prompt_tokens === void 0 && usage.completion_tokens === void 0)
1075
+ return void 0;
1076
+ return {
1077
+ inputTokens: Number(usage.prompt_tokens ?? 0),
1078
+ outputTokens: Number(usage.completion_tokens ?? 0),
1079
+ ...readResponsesCachedTokens({ input_tokens_details: usage.prompt_tokens_details })
1080
+ };
1081
+ }
1082
+ function readGoogleUsage(raw) {
1083
+ if (!raw || typeof raw !== "object")
1084
+ return void 0;
1085
+ const usage = raw;
1086
+ if (usage.promptTokenCount === void 0 && usage.candidatesTokenCount === void 0)
1087
+ return void 0;
1088
+ const cached = Number(usage.cachedContentTokenCount ?? 0);
1089
+ return {
1090
+ inputTokens: Number(usage.promptTokenCount ?? 0),
1091
+ outputTokens: Number(usage.candidatesTokenCount ?? 0) + Number(usage.thoughtsTokenCount ?? 0),
1092
+ ...cached > 0 ? { cachedInputTokens: cached } : {}
1093
+ };
1094
+ }
1101
1095
  function safeParseJson(raw) {
1102
1096
  if (!raw)
1103
1097
  return {};
@@ -1107,6 +1101,18 @@ function safeParseJson(raw) {
1107
1101
  return { _raw: raw };
1108
1102
  }
1109
1103
  }
1104
+ function parseResponsesFunctionCall(item) {
1105
+ if (item.status !== void 0 && item.status !== "completed" || typeof item.call_id !== "string" || !item.call_id.trim() || typeof item.name !== "string" || !item.name.trim() || typeof item.arguments !== "string")
1106
+ return void 0;
1107
+ try {
1108
+ const input = JSON.parse(item.arguments);
1109
+ if (!input || typeof input !== "object" || Array.isArray(input))
1110
+ return void 0;
1111
+ return { type: "tool_use", id: item.call_id, name: item.name, input };
1112
+ } catch {
1113
+ return void 0;
1114
+ }
1115
+ }
1110
1116
  function isWireBlockArray(blocks) {
1111
1117
  return blocks.every((block) => block !== null && typeof block === "object" && !Array.isArray(block) && typeof block.type === "string");
1112
1118
  }
@@ -2187,6 +2193,13 @@ var DEFAULT_PROVIDER_MODELS = {
2187
2193
  };
2188
2194
  var AUTO_MODEL_SENTINEL = "auto";
2189
2195
  function detectProvider(configApiKey, preferredModel, env2, configProvider) {
2196
+ const proxy = resolveWorkbenchProviderProxy(env2);
2197
+ if (proxy) {
2198
+ if ([configProvider, env2.ZERO_SELECTED_PROVIDER, env2.ZERO_FORCE_PROVIDER].some((provider) => provider && provider !== "chatgpt-codex")) {
2199
+ throw new Error("Workbench provider broker supports chatgpt-codex only; no fallback is permitted");
2200
+ }
2201
+ return { provider: "chatgpt-codex", apiKey: "", baseUrl: proxy.url, defaultModel: proxy.model, wireApi: "responses" };
2202
+ }
2190
2203
  if (configProvider !== void 0 && !Object.hasOwn(DEFAULT_PROVIDER_MODELS, configProvider)) {
2191
2204
  throw new Error(`RuntimeConfig.provider is unsupported: ${configProvider}`);
2192
2205
  }
@@ -2204,8 +2217,10 @@ function detectProvider(configApiKey, preferredModel, env2, configProvider) {
2204
2217
  throw new Error(`${source} is unsupported: ${pinnedProviderRaw}`);
2205
2218
  }
2206
2219
  const provider = pinnedProviderRaw;
2207
- const model = preferredModel ?? env2["ZERO_MODEL"] ?? (configProvider !== void 0 ? DEFAULT_PROVIDER_MODELS[provider] : void 0);
2220
+ const model = preferredModel ?? env2["ZERO_MODEL"] ?? (provider === "azure" ? env2.AZURE_OPENAI_MODEL ?? parseCodexAzureConfig(env2).model : void 0) ?? (configProvider !== void 0 ? DEFAULT_PROVIDER_MODELS[provider] : void 0);
2208
2221
  if (model === void 0 || model === "") {
2222
+ if (provider === "azure")
2223
+ throw new Error("Choose an Azure deployment model in Connections to finish setup.");
2209
2224
  throw new Error(`${source} requires an explicit model`);
2210
2225
  }
2211
2226
  if (configApiKey && provider === "chatgpt-codex") {
@@ -2520,6 +2535,7 @@ var LlmApiRuntime = class _LlmApiRuntime {
2520
2535
  // Not readonly: a live provider switch re-freezes env from the new account.
2521
2536
  env;
2522
2537
  codexAuthState;
2538
+ workbenchProviderProxy;
2523
2539
  geminiAuthState;
2524
2540
  provider;
2525
2541
  apiKey;
@@ -2552,6 +2568,7 @@ var LlmApiRuntime = class _LlmApiRuntime {
2552
2568
  timeout: Math.min(timeout, inherited.config.timeout || 12e4)
2553
2569
  };
2554
2570
  this.env = inherited.env;
2571
+ this.workbenchProviderProxy = inherited.workbenchProviderProxy;
2555
2572
  this.provider = inherited.provider;
2556
2573
  this.apiKey = inherited.apiKey;
2557
2574
  this.baseUrl = inherited.baseUrl;
@@ -2591,8 +2608,9 @@ var LlmApiRuntime = class _LlmApiRuntime {
2591
2608
  ...config.agentModels ? { agentModels: Object.freeze({ ...config.agentModels }) } : {}
2592
2609
  };
2593
2610
  this.env = Object.freeze({ ...process.env, ...config.env });
2611
+ this.workbenchProviderProxy = resolveWorkbenchProviderProxy(this.env);
2594
2612
  this.azureConfig = parseCodexAzureConfig(this.env);
2595
- this.fallbackChain = getFallbackChain(this.env).map((entry) => ({
2613
+ this.fallbackChain = (this.workbenchProviderProxy ? [] : getFallbackChain(this.env)).map((entry) => ({
2596
2614
  ...entry,
2597
2615
  credentials: resolveFailoverProvider(entry.provider, entry.model, this.env)
2598
2616
  }));
@@ -2603,7 +2621,7 @@ var LlmApiRuntime = class _LlmApiRuntime {
2603
2621
  this.baseUrl = detected.baseUrl;
2604
2622
  this.wireApi = detected.wireApi;
2605
2623
  this.codexAuthState = void 0;
2606
- if (this.provider === "chatgpt-codex" || this.fallbackChain.some((entry) => entry.provider === "chatgpt-codex")) {
2624
+ if (!this.workbenchProviderProxy && (this.provider === "chatgpt-codex" || this.fallbackChain.some((entry) => entry.provider === "chatgpt-codex"))) {
2607
2625
  if (readChatGptCodexEnv(this.env) || readChatGptCodexAuthFile(this.env)) {
2608
2626
  this.codexAuthState = resolveChatGptCodexAuthState(this.env);
2609
2627
  }
@@ -2661,14 +2679,50 @@ var LlmApiRuntime = class _LlmApiRuntime {
2661
2679
  }
2662
2680
  return createHash("sha256").update(JSON.stringify(identity)).digest("hex");
2663
2681
  }
2682
+ /** Documented effort controls only on routes which send Responses reasoning. */
2683
+ reasoningConfiguration() {
2684
+ if (this.wireApi !== "responses" || !["openai", "azure", "chatgpt-codex"].includes(this.provider))
2685
+ return null;
2686
+ const model = this.model.replace(/^openai\//, "");
2687
+ let options;
2688
+ if (/^gpt-(?:6-astra|6\.1-sol)(?:-20\d\d-\d\d-\d\d)?$/.test(model))
2689
+ options = ["low", "medium", "high", "xhigh", "max"];
2690
+ else if (/^gpt-(?:6-sol|6-luna|5\.6(?:-sol|-terra|-luna)?)(?:-20\d\d-\d\d-\d\d)?$/.test(model))
2691
+ options = ["none", "low", "medium", "high", "xhigh", "max"];
2692
+ else
2693
+ return null;
2694
+ const effort = this.reasoningEffort ?? defaultReasoningEffort(this.model) ?? "medium";
2695
+ return options.includes(effort) ? { effort, options } : null;
2696
+ }
2697
+ /** Apply an effort for subsequent requests and same-model worker forks. */
2698
+ setReasoningEffort(effort) {
2699
+ const configuration = this.reasoningConfiguration();
2700
+ if (!configuration || !configuration.options.includes(effort))
2701
+ throw new Error("This reasoning effort is not supported by the selected model and connection.");
2702
+ this.reasoningEffort = effort;
2703
+ }
2664
2704
  /** Discover models using this runtime's captured account, including after a separate login changes. */
2665
2705
  async codexModelCatalog(signal) {
2706
+ if (this.workbenchProviderProxy) {
2707
+ signal?.throwIfAborted();
2708
+ return [{ id: this.workbenchProviderProxy.model }];
2709
+ }
2666
2710
  const state = this.codexAuthState;
2667
2711
  if (this.provider !== "chatgpt-codex" || !state)
2668
2712
  throw new Error("No active Codex subscription");
2669
- const { loadCodexModelCatalog } = await import("./codex-models-7TLJSY3L.js");
2713
+ const { loadCodexModelCatalog } = await import("./codex-models-Z43V3427.js");
2670
2714
  return loadCodexModelCatalog({ signal, resolveCredentials: () => refreshChatGptCodexAuthState(state) });
2671
2715
  }
2716
+ /** Host-only inference grant bound to this captured account, including after
2717
+ * later logins or runtime reconfiguration. Never serialize the closure or
2718
+ * its result into guest admission, workspace files or environment. */
2719
+ workbenchCredentialResolver() {
2720
+ const state = this.codexAuthState;
2721
+ if (this.workbenchProviderProxy || this.provider !== "chatgpt-codex" || !state) {
2722
+ throw new Error("Host workbench credential broker requires a captured chatgpt-codex account");
2723
+ }
2724
+ return () => refreshChatGptCodexAuthState(state);
2725
+ }
2672
2726
  /**
2673
2727
  * Mutate the live selection in place so the NEXT turn (the engine reads
2674
2728
  * `config.runtime` per turn) and the NEXT `forkForSubagent` pick up the new
@@ -2685,6 +2739,7 @@ var LlmApiRuntime = class _LlmApiRuntime {
2685
2739
  model: sel.model,
2686
2740
  ...sel.agentModels !== void 0 ? { agentModels: sel.agentModels } : {},
2687
2741
  ...sel.singleModel !== void 0 ? { singleModel: sel.singleModel } : {},
2742
+ ...sel.autoRoute !== void 0 ? { autoRoute: sel.autoRoute } : {},
2688
2743
  ...sel.env !== void 0 ? { env: sel.env } : {}
2689
2744
  };
2690
2745
  this.applyConfiguration(merged);
@@ -2696,6 +2751,9 @@ var LlmApiRuntime = class _LlmApiRuntime {
2696
2751
  if (sel.singleModel !== void 0) {
2697
2752
  this.config = { ...this.config, singleModel: sel.singleModel };
2698
2753
  }
2754
+ if (sel.autoRoute !== void 0) {
2755
+ this.config = { ...this.config, autoRoute: sel.autoRoute };
2756
+ }
2699
2757
  if (sel.model !== void 0) {
2700
2758
  const model = this.provider === "opencode" ? opencodeModelId(sel.model) : this.provider === "copilot" ? copilotModelId(sel.model) : sel.model;
2701
2759
  if (model !== this.model) {
@@ -2727,6 +2785,8 @@ var LlmApiRuntime = class _LlmApiRuntime {
2727
2785
  * failover chain uses — including auth-only providers (chatgpt-codex OAuth).
2728
2786
  */
2729
2787
  accessibleProviders() {
2788
+ if (this.workbenchProviderProxy)
2789
+ return ["chatgpt-codex"];
2730
2790
  const out = [];
2731
2791
  for (const provider of Object.keys(DEFAULT_PROVIDER_MODELS)) {
2732
2792
  const probeModel = DEFAULT_PROVIDER_MODELS[provider] || "probe";
@@ -2743,6 +2803,8 @@ var LlmApiRuntime = class _LlmApiRuntime {
2743
2803
  * provider has creds, so this is a helpful starting set, not the whole bound.
2744
2804
  */
2745
2805
  accessibleModels() {
2806
+ if (this.workbenchProviderProxy)
2807
+ return [this.workbenchProviderProxy.model];
2746
2808
  const models = /* @__PURE__ */ new Set();
2747
2809
  if (this.model)
2748
2810
  models.add(this.model);
@@ -2760,6 +2822,8 @@ var LlmApiRuntime = class _LlmApiRuntime {
2760
2822
  * accessible defaults as a fallback for ids the router does not pattern-match.
2761
2823
  */
2762
2824
  isModelAccessible(model) {
2825
+ if (this.workbenchProviderProxy)
2826
+ return this.accessibleModels().includes(model);
2763
2827
  if (providerForModel(model, this.env) !== void 0)
2764
2828
  return true;
2765
2829
  return this.accessibleModels().includes(model);
@@ -2849,6 +2913,17 @@ var LlmApiRuntime = class _LlmApiRuntime {
2849
2913
  resolvedModel() {
2850
2914
  return this.model;
2851
2915
  }
2916
+ /** JSON-safe routing policy, not the runtime's private environment or configuration. */
2917
+ modelSelection() {
2918
+ return {
2919
+ agentModels: { ...this.config.agentModels },
2920
+ singleModel: this.config.singleModel === true,
2921
+ autoRoute: this.config.autoRoute === true
2922
+ };
2923
+ }
2924
+ resolvedProvider() {
2925
+ return this.provider;
2926
+ }
2852
2927
  /** Price discovered IDs on their actual route without changing the wire model. */
2853
2928
  resolvedPricingModel() {
2854
2929
  if (this.provider === "chatgpt-codex" || this.provider === "copilot" || this.provider === "google")
@@ -3252,7 +3327,13 @@ Missing: ${missing.join("; ")}
3252
3327
  abort?.throwIfCancelled();
3253
3328
  let res;
3254
3329
  try {
3255
- res = await fetch(this.buildUrl(), {
3330
+ res = this.workbenchProviderProxy ? await fetch(this.workbenchProviderProxy.url, {
3331
+ method: "POST",
3332
+ redirect: "error",
3333
+ headers: { "Content-Type": "application/json" },
3334
+ body: JSON.stringify({ provider: this.provider, model: this.model, body: bodyFactory() }),
3335
+ signal
3336
+ }) : await fetch(this.buildUrl(), {
3256
3337
  method: "POST",
3257
3338
  headers: await this.ensureFreshHeaders(),
3258
3339
  body: bodyFactory(),
@@ -3377,6 +3458,22 @@ Missing: ${missing.join("; ")}
3377
3458
  // ── Legacy Runtime interface (single-prompt) ──
3378
3459
  async execute(prompt, context) {
3379
3460
  const start = Date.now();
3461
+ if (context?.signal?.aborted) {
3462
+ return { output: "", exitCode: null, timedOut: false, durationMs: 0, error: "API execution cancelled." };
3463
+ }
3464
+ if (this.workbenchProviderProxy) {
3465
+ const result = await this.executeNative(context?.systemPrompt ?? "", [
3466
+ { role: "user", content: [{ type: "text", text: prompt }] }
3467
+ ], [], void 0, context?.signal);
3468
+ return {
3469
+ output: result.content.filter((block) => block.type === "text").map((block) => block.text).join("\n"),
3470
+ exitCode: result.cancelled ? null : result.stopReason === "error" ? 1 : 0,
3471
+ timedOut: false,
3472
+ durationMs: Date.now() - start,
3473
+ usage: result.usage,
3474
+ error: result.error
3475
+ };
3476
+ }
3380
3477
  if (!this.apiKey && this.provider !== "chatgpt-codex" && this.provider !== "google") {
3381
3478
  return {
3382
3479
  output: "",
@@ -3389,9 +3486,11 @@ Missing: ${missing.join("; ")}
3389
3486
  const systemPrompt = context?.systemPrompt ?? "";
3390
3487
  const controller = new AbortController();
3391
3488
  const timer = setTimeout(() => controller.abort(), this.config.timeout || 12e4);
3489
+ const abort = composeCallAbort(controller.signal, context?.signal);
3392
3490
  try {
3393
3491
  let res;
3394
3492
  do {
3493
+ abort.throwIfCancelled();
3395
3494
  if (this.isOpenAICompat && this.wireApi === "chat_completions") {
3396
3495
  const messages = [];
3397
3496
  if (systemPrompt) {
@@ -3404,7 +3503,7 @@ Missing: ${missing.join("; ")}
3404
3503
  messages,
3405
3504
  // See executeNative: explicit reasoning_effort passthrough only.
3406
3505
  ...this.reasoningEffort ? { reasoning_effort: this.reasoningEffort } : {}
3407
- }), controller.signal);
3506
+ }), abort.signal, abort);
3408
3507
  } else if (this.isOpenAICompat && this.wireApi === "responses") {
3409
3508
  const input = [];
3410
3509
  if (systemPrompt) {
@@ -3422,7 +3521,7 @@ Missing: ${missing.join("; ")}
3422
3521
  model: this.model,
3423
3522
  input,
3424
3523
  ...isCodex ? { store: false } : { max_output_tokens: NATIVE_COMPLETION_TOKEN_LIMIT }
3425
- }), controller.signal);
3524
+ }), abort.signal, abort);
3426
3525
  } else if (this.isGeminiCodeAssist) {
3427
3526
  const request = {
3428
3527
  ...systemPrompt ? { systemInstruction: { parts: [{ text: systemPrompt }] } } : {},
@@ -3430,13 +3529,13 @@ Missing: ${missing.join("; ")}
3430
3529
  generationConfig: { maxOutputTokens: NATIVE_COMPLETION_TOKEN_LIMIT }
3431
3530
  };
3432
3531
  const geminiBody = await this.wrapGeminiCodeAssistBody(request);
3433
- res = await this.postWithRetry(() => JSON.stringify(geminiBody), controller.signal);
3532
+ res = await this.postWithRetry(() => JSON.stringify(geminiBody), abort.signal, abort);
3434
3533
  } else if (this.isGoogleWire) {
3435
3534
  res = await this.postWithRetry(() => JSON.stringify({
3436
3535
  ...systemPrompt ? { systemInstruction: { parts: [{ text: systemPrompt }] } } : {},
3437
3536
  contents: [{ role: "user", parts: [{ text: prompt }] }],
3438
3537
  generationConfig: { maxOutputTokens: NATIVE_COMPLETION_TOKEN_LIMIT }
3439
- }), controller.signal);
3538
+ }), abort.signal, abort);
3440
3539
  } else if (this.isAnthropicWire) {
3441
3540
  res = await this.postWithRetry(() => JSON.stringify({
3442
3541
  model: this.model,
@@ -3444,12 +3543,11 @@ Missing: ${missing.join("; ")}
3444
3543
  ...this.anthropicThinkingField(),
3445
3544
  ...systemPrompt ? { system: systemPrompt } : {},
3446
3545
  messages: [{ role: "user", content: prompt }]
3447
- }), controller.signal);
3546
+ }), abort.signal, abort);
3448
3547
  } else {
3449
3548
  throw new Error(`execute: provider ${this.provider} is not mapped to a wire`);
3450
3549
  }
3451
3550
  } while (!res);
3452
- clearTimeout(timer);
3453
3551
  const body = await res.text();
3454
3552
  if (!res.ok) {
3455
3553
  appendNativeTrace({
@@ -3483,12 +3581,9 @@ Missing: ${missing.join("; ")}
3483
3581
  if (this.isAnthropicWire) {
3484
3582
  usage = readCacheUsage(json.usage);
3485
3583
  } else if ((this.isGoogleWire || this.isGeminiCodeAssist) && json.usageMetadata) {
3486
- usage = {
3487
- inputTokens: json.usageMetadata.promptTokenCount ?? 0,
3488
- outputTokens: json.usageMetadata.candidatesTokenCount ?? 0
3489
- };
3584
+ usage = readGoogleUsage(json.usageMetadata);
3490
3585
  } else if (this.isOpenAICompat && json.usage) {
3491
- usage = this.wireApi === "chat_completions" ? { inputTokens: json.usage.prompt_tokens ?? 0, outputTokens: json.usage.completion_tokens ?? 0 } : { inputTokens: json.usage.input_tokens ?? 0, outputTokens: json.usage.output_tokens ?? 0 };
3586
+ usage = this.wireApi === "chat_completions" ? readChatUsage(json.usage) : { inputTokens: json.usage.input_tokens ?? 0, outputTokens: json.usage.output_tokens ?? 0, ...readResponsesCachedTokens(json.usage) };
3492
3587
  }
3493
3588
  return {
3494
3589
  output: text,
@@ -3499,6 +3594,9 @@ Missing: ${missing.join("; ")}
3499
3594
  };
3500
3595
  } catch (err) {
3501
3596
  clearTimeout(timer);
3597
+ if (abort.operatorAborted()) {
3598
+ return { output: "", exitCode: null, timedOut: false, durationMs: Date.now() - start, error: "API execution cancelled." };
3599
+ }
3502
3600
  if (err instanceof QuotaExhaustedError) {
3503
3601
  return {
3504
3602
  output: "",
@@ -3517,6 +3615,9 @@ Missing: ${missing.join("; ")}
3517
3615
  durationMs: Date.now() - start,
3518
3616
  error: timedOut ? `${this.providerLabel} API request timed out` : `${this.providerLabel} API error: ${msg}`
3519
3617
  };
3618
+ } finally {
3619
+ clearTimeout(timer);
3620
+ abort.dispose();
3520
3621
  }
3521
3622
  }
3522
3623
  // ── Native Runtime interface (structured messages + tool_use) ──
@@ -3903,62 +4004,7 @@ Missing: ${missing.join("; ")}
3903
4004
  const finishReason = choice?.finish_reason;
3904
4005
  stopReason = finishReason === "tool_calls" || finishReason === "function_call" ? "tool_use" : finishReason === "length" ? "max_tokens" : "end_turn";
3905
4006
  if (json.usage) {
3906
- usage = {
3907
- inputTokens: json.usage.prompt_tokens ?? 0,
3908
- outputTokens: json.usage.completion_tokens ?? 0
3909
- };
3910
- }
3911
- } else if (this.isOpenAICompat && this.wireApi === "responses") {
3912
- content = [];
3913
- const reasoningSummaries = [];
3914
- const rawOutput = json.output ?? [];
3915
- if (rawOutput.length > 0) {
3916
- providerRaw = {
3917
- provider: this.provider,
3918
- model: this.model,
3919
- wireApi: this.wireApi,
3920
- output: rawOutput
3921
- };
3922
- }
3923
- for (const item of json.output ?? []) {
3924
- if (item.type === "function_call") {
3925
- content.push({
3926
- type: "tool_use",
3927
- id: item.call_id,
3928
- name: item.name,
3929
- input: safeParseJson(item.arguments)
3930
- });
3931
- continue;
3932
- }
3933
- if (item.type === "reasoning") {
3934
- const summaryParts = Array.isArray(item.summary) ? item.summary.map((block) => typeof block.text === "string" ? block.text : "").filter((text) => text.trim().length > 0) : [];
3935
- const reasoningText = summaryParts.join("\n").trim();
3936
- if (reasoningText)
3937
- reasoningSummaries.push(reasoningText);
3938
- continue;
3939
- }
3940
- for (const block of item.content ?? []) {
3941
- if (block.type === "output_text") {
3942
- content.push({ type: "text", text: block.text });
3943
- } else if (block.type === "summary_text" || block.type === "reasoning_text") {
3944
- const text = typeof block.text === "string" ? block.text : "";
3945
- if (text.trim())
3946
- reasoningSummaries.push(text);
3947
- }
3948
- }
3949
- }
3950
- if (callbacks?.onThinking && reasoningSummaries.length > 0) {
3951
- callbacks.onThinking(reasoningSummaries.join("\n"));
3952
- }
3953
- stopReason = content.some((block) => block.type === "tool_use") ? "tool_use" : "end_turn";
3954
- if (json.usage) {
3955
- usage = {
3956
- inputTokens: json.usage.input_tokens ?? 0,
3957
- outputTokens: json.usage.output_tokens ?? 0,
3958
- // Responses `input_tokens` already includes the cached span, so
3959
- // this is instrumentation only — see the streaming path.
3960
- ...readResponsesCachedTokens(json.usage)
3961
- };
4007
+ usage = readChatUsage(json.usage);
3962
4008
  }
3963
4009
  } else if (this.isGoogleWire || this.isGeminiCodeAssist) {
3964
4010
  const candidate = json.candidates?.[0];
@@ -3990,10 +4036,7 @@ Missing: ${missing.join("; ")}
3990
4036
  const finishReason = String(candidate?.finishReason ?? "").toUpperCase();
3991
4037
  stopReason = content.some((block) => block.type === "tool_use") ? "tool_use" : finishReason === "MAX_TOKENS" ? "max_tokens" : "end_turn";
3992
4038
  if (json.usageMetadata) {
3993
- usage = {
3994
- inputTokens: json.usageMetadata.promptTokenCount ?? 0,
3995
- outputTokens: json.usageMetadata.candidatesTokenCount ?? 0
3996
- };
4039
+ usage = readGoogleUsage(json.usageMetadata);
3997
4040
  }
3998
4041
  } else {
3999
4042
  const rawBlocks = json.content ?? [];
@@ -4135,6 +4178,9 @@ Missing: ${missing.join("; ")}
4135
4178
  const eventTypes = /* @__PURE__ */ new Set();
4136
4179
  const identifier = (value) => typeof value === "string" && /^[A-Za-z0-9_.:-]{1,96}$/.test(value) ? value : null;
4137
4180
  let completedResponse = null;
4181
+ let outputCapResponse;
4182
+ let assistantText = "";
4183
+ const pendingFunctionCalls = /* @__PURE__ */ new Set();
4138
4184
  let streamFailure;
4139
4185
  let responseUsage;
4140
4186
  const streamedOutputItems = [];
@@ -4239,9 +4285,13 @@ Missing: ${missing.join("; ")}
4239
4285
  };
4240
4286
  callbacks?.onUsage?.(responseUsage);
4241
4287
  }
4288
+ const incomplete = response?.incomplete_details;
4289
+ if (type === "response.incomplete" && response?.status === "incomplete" && incomplete?.reason === "max_output_tokens" && response.error == null && event.error == null && event.code == null && !completedResponse && malformedEvents === 0) {
4290
+ outputCapResponse = response;
4291
+ break responses;
4292
+ }
4242
4293
  if (!terminal || !response || response.error != null || (type === "response.done" || response.status !== void 0) && response.status !== "completed") {
4243
4294
  const error = response?.error ?? event.error;
4244
- const incomplete = response?.incomplete_details;
4245
4295
  streamFailure = {
4246
4296
  event: type,
4247
4297
  status: identifier(response?.status),
@@ -4257,6 +4307,7 @@ Missing: ${missing.join("; ")}
4257
4307
  if (type === "response.output_text.delta" || this.provider === "openrouter" && type === "response.content_part.delta") {
4258
4308
  const delta = typeof event.delta === "string" ? event.delta : "";
4259
4309
  if (delta) {
4310
+ assistantText += delta;
4260
4311
  callbacks?.onDelta?.("assistant_response", delta);
4261
4312
  }
4262
4313
  continue;
@@ -4278,9 +4329,18 @@ Missing: ${missing.join("; ")}
4278
4329
  }
4279
4330
  continue;
4280
4331
  }
4332
+ if (type === "response.output_item.added") {
4333
+ const item = event.item;
4334
+ if (item?.type === "function_call") {
4335
+ pendingFunctionCalls.add(String(item.id ?? item.call_id ?? event.output_index ?? pendingFunctionCalls.size));
4336
+ }
4337
+ continue;
4338
+ }
4281
4339
  if (type === "response.output_item.done") {
4282
4340
  const item = event.item;
4283
4341
  if (item && typeof item.type === "string") {
4342
+ if (item.type === "function_call")
4343
+ pendingFunctionCalls.add(String(item.id ?? item.call_id ?? event.output_index ?? pendingFunctionCalls.size));
4284
4344
  streamedOutputItems.push(item);
4285
4345
  }
4286
4346
  continue;
@@ -4288,6 +4348,46 @@ Missing: ${missing.join("; ")}
4288
4348
  }
4289
4349
  }
4290
4350
  emitThinking(true);
4351
+ if (outputCapResponse) {
4352
+ void reader.cancel().catch(() => {
4353
+ });
4354
+ const finalOutput = Array.isArray(outputCapResponse.output) ? outputCapResponse.output : [];
4355
+ const output = finalOutput.length > 0 ? finalOutput : streamedOutputItems;
4356
+ let finalText = "";
4357
+ for (const item of output) {
4358
+ if (item.type === "function_call")
4359
+ pendingFunctionCalls.add(String(item.id ?? item.call_id ?? pendingFunctionCalls.size));
4360
+ if (!Array.isArray(item.content))
4361
+ continue;
4362
+ for (const block of item.content) {
4363
+ if (block.type === "output_text" && typeof block.text === "string")
4364
+ finalText += block.text;
4365
+ }
4366
+ }
4367
+ const text = finalText.startsWith(assistantText) ? finalText : assistantText || finalText;
4368
+ if (operatorSignal?.aborted) {
4369
+ return { ...this.cancelledResult(start), content: [{ type: "text", text }], usage: responseUsage };
4370
+ }
4371
+ const checkpoint = {
4372
+ reason: "max_output_tokens",
4373
+ ...identifier(outputCapResponse.id) ? { responseId: String(outputCapResponse.id) } : {},
4374
+ discardedToolCalls: pendingFunctionCalls.size
4375
+ };
4376
+ appendNativeTrace({
4377
+ kind: "native-response-checkpoint",
4378
+ provider: this.providerLabel,
4379
+ wireApi: this.wireApi,
4380
+ checkpoint,
4381
+ usage: responseUsage ?? null
4382
+ });
4383
+ return {
4384
+ content: [{ type: "text", text }],
4385
+ stopReason: "max_tokens",
4386
+ checkpoint,
4387
+ usage: responseUsage,
4388
+ durationMs: Date.now() - start
4389
+ };
4390
+ }
4291
4391
  if (!completedResponse || streamFailure) {
4292
4392
  if (streamFailure) {
4293
4393
  void reader.cancel().catch(() => {
@@ -4333,18 +4433,25 @@ Missing: ${missing.join("; ")}
4333
4433
  })),
4334
4434
  topLevelKeys: Object.keys(completedResponse)
4335
4435
  });
4336
- const completedOutput = completedResponse.output ?? [];
4337
- const outputItems = streamedOutputItems.length > 0 ? streamedOutputItems : completedOutput;
4436
+ const completedOutput = Array.isArray(completedResponse.output) ? completedResponse.output : [];
4437
+ const outputItems = completedOutput.length > 0 ? completedOutput : streamedOutputItems;
4338
4438
  const content = [];
4339
4439
  const reasoningSummaries = [];
4440
+ const callIds = /* @__PURE__ */ new Set();
4340
4441
  for (const item of outputItems) {
4341
4442
  if (item.type === "function_call") {
4342
- content.push({
4343
- type: "tool_use",
4344
- id: String(item.call_id),
4345
- name: String(item.name),
4346
- input: safeParseJson(String(item.arguments ?? "{}"))
4347
- });
4443
+ const call = parseResponsesFunctionCall(item);
4444
+ if (!call || callIds.has(call.id) || malformedEvents > 0) {
4445
+ return {
4446
+ content: [{ type: "text", text: assistantText }],
4447
+ stopReason: "error",
4448
+ usage: responseUsage,
4449
+ durationMs: Date.now() - start,
4450
+ error: `${this.providerLabel} API error: Responses completed with an incomplete or malformed function call`
4451
+ };
4452
+ }
4453
+ callIds.add(call.id);
4454
+ content.push(call);
4348
4455
  continue;
4349
4456
  }
4350
4457
  if (item.type === "reasoning") {
@@ -4360,6 +4467,9 @@ Missing: ${missing.join("; ")}
4360
4467
  }
4361
4468
  }
4362
4469
  }
4470
+ const observedTextFallback = !!assistantText && !content.some((block) => block.type === "text");
4471
+ if (observedTextFallback)
4472
+ content.unshift({ type: "text", text: assistantText });
4363
4473
  if (lastThinkingEmit === 0 && reasoningSummaries.length > 0) {
4364
4474
  thinkingText = reasoningSummaries.join("\n");
4365
4475
  emitThinking(true);
@@ -4373,7 +4483,7 @@ Missing: ${missing.join("; ")}
4373
4483
  // reasoning items with their `encrypted_content` still attached, each
4374
4484
  // immediately followed by the item it produced. Handing it back lets the
4375
4485
  // next turn replay it verbatim instead of re-deriving the reasoning.
4376
- ...outputItems.length > 0 ? {
4486
+ ...!observedTextFallback && outputItems.length > 0 ? {
4377
4487
  providerRaw: {
4378
4488
  provider: this.provider,
4379
4489
  model: this.model,
@@ -4384,6 +4494,8 @@ Missing: ${missing.join("; ")}
4384
4494
  };
4385
4495
  }
4386
4496
  async isAvailable() {
4497
+ if (this.workbenchProviderProxy)
4498
+ return true;
4387
4499
  if (this.provider === "chatgpt-codex") {
4388
4500
  return this.codexAuthState !== void 0;
4389
4501
  }