0sec-cli 0.21.4 → 0.22.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.
- package/0.js +56 -56
- package/README.md +48 -63
- package/chunks/{adapt-loop-IGBRQAXO.js → adapt-loop-J6QCZZTB.js} +4 -4
- package/chunks/{artifact-scraper-LNQJUORS.js → artifact-scraper-MFKT6OI4.js} +2 -2
- package/chunks/{assumption-mining-4MJTP6H5.js → assumption-mining-646LYSJY.js} +16 -16
- package/chunks/{chunk-Z3IKZX3X.js → chunk-23DG5YKS.js} +1 -1
- package/chunks/{chunk-2WSXFFJZ.js → chunk-3E2KALZ5.js} +2 -2
- package/chunks/{chunk-TF46UWFU.js → chunk-4G7OVYJX.js} +1 -1
- package/chunks/{chunk-E2UOY5PJ.js → chunk-5BTJMINS.js} +12 -70
- package/chunks/{chunk-QZVG3BG4.js → chunk-5IBCBQEH.js} +1 -2
- package/chunks/{chunk-YA4PUM4H.js → chunk-7XCKYNLO.js} +1 -1
- package/chunks/{chunk-BACXRTQ4.js → chunk-AV2LG2L7.js} +87 -767
- package/chunks/{chunk-IMGWPNQM.js → chunk-BCSRRQG5.js} +76 -593
- package/chunks/{chunk-NOPBXZUV.js → chunk-BOUGKEKA.js} +1 -1
- package/chunks/{chunk-RF5QGKLR.js → chunk-CPWA6RWE.js} +3 -3
- package/chunks/{chunk-P6YG6TEZ.js → chunk-DKSCN2AB.js} +1 -1
- package/chunks/{chunk-YPOA3W4O.js → chunk-GOEA3NW6.js} +877 -110
- package/chunks/{chunk-ANDKY54G.js → chunk-HHPWRY2M.js} +4019 -7299
- package/chunks/{chunk-NDJU5ZZ7.js → chunk-IFME676H.js} +3 -3
- package/chunks/{chunk-HBKCGJAV.js → chunk-IVQV574Y.js} +1 -1
- package/chunks/{chunk-W4JOXE4N.js → chunk-IXT64DV5.js} +709 -1929
- package/chunks/{chunk-PC6RCKQV.js → chunk-KAU6NLGP.js} +59 -26
- package/chunks/{chunk-FAH6V4QM.js → chunk-LGCASF2C.js} +1117 -2291
- package/chunks/{chunk-CAJJRUTV.js → chunk-NLH4LMWH.js} +1 -1
- package/chunks/chunk-OHHCGDJ2.js +5523 -0
- package/chunks/{chunk-YHWWF4QY.js → chunk-OSBPGWTE.js} +3 -3
- package/chunks/{chunk-G34QP2XW.js → chunk-TM74SSHC.js} +1 -1
- package/chunks/{chunk-VOAXLO4A.js → chunk-TO35Y326.js} +5 -721
- package/chunks/{chunk-FWAYJ2IV.js → chunk-TV27OWIW.js} +8 -8
- package/chunks/chunk-UELXHK2Y.js +1950 -0
- package/chunks/{chunk-CL5KAUM6.js → chunk-V6GHX34G.js} +274 -8
- package/chunks/{chunk-WZISK5VC.js → chunk-VWITLWXB.js} +53 -7
- package/chunks/{chunk-ER3SUMYJ.js → chunk-W6UWZFKL.js} +0 -195
- package/chunks/chunk-WSDDGFA6.js +114 -0
- package/chunks/{chunk-5T6D5BVY.js → chunk-WZRVS7SB.js} +1 -1
- package/chunks/chunk-X7LAEEUW.js +2143 -0
- package/chunks/chunk-XA2O4WXA.js +1228 -0
- package/chunks/{chunk-Y5H6E24H.js → chunk-XCISCI4T.js} +1 -1
- package/chunks/{chunk-WPQLBN4S.js → chunk-XDKB2P5X.js} +1 -1
- package/chunks/{chunk-SBMB4OL3.js → chunk-YL6YAGLL.js} +62 -8
- package/chunks/{chunk-O6SD4A36.js → chunk-ZKQ2I3S2.js} +1 -1
- package/chunks/{codex-models-TYYV4JNN.js → codex-models-NHQW45SO.js} +5 -3
- package/chunks/{commands-WF5RG4I2.js → commands-N6GN5SBF.js} +2152 -3643
- package/chunks/{db-U3WQZVAO.js → db-5IWEJUYV.js} +3 -3
- package/chunks/{disclose-67GZCDBO.js → disclose-LDNKAVRH.js} +10 -8
- package/chunks/{dist-ACC3DZUZ.js → dist-BS4CY4RG.js} +3 -1
- package/chunks/{dist-EVTN3UTT.js → dist-FSS7MBDF.js} +2 -2
- package/chunks/{dist-F6X62TQK.js → dist-L3XJWWZ6.js} +225 -192
- package/chunks/{eval-runner-SA6OUGHZ.js → eval-runner-EMEGF24P.js} +11 -11
- package/chunks/{exploit-agent-36Q7XQFP.js → exploit-agent-KW4EB7BE.js} +1 -1
- package/chunks/{exploit-autoclimb-J4OTSTZ6.js → exploit-autoclimb-CXJ2ERRO.js} +1 -1
- package/chunks/{exploit-climb-PYEJDIC4.js → exploit-climb-TJWLY4XC.js} +2 -2
- package/chunks/fix-UUKPXCFB.js +26 -0
- package/chunks/{harness-GDUMKGSE.js → harness-C5HOKIEV.js} +3 -3
- package/chunks/{hunt-scan-UDJSCISU.js → hunt-scan-KZZ444V2.js} +14 -14
- package/chunks/{identity-JTIVJSV7.js → identity-62SVRW4H.js} +1 -1
- package/chunks/{kernel-primitive-F2IXUFAX.js → kernel-primitive-Z77IR7YS.js} +2 -2
- package/chunks/{kernel-vm-runner-276LHIOV.js → kernel-vm-runner-JW77P276.js} +2 -2
- package/chunks/{memsafety-scan-NHUOGTEX.js → memsafety-scan-FCPAXIZE.js} +2 -2
- package/chunks/{native-loop-3BSYVDUI.js → native-loop-P6P5GYVJ.js} +10 -10
- package/chunks/{npm-detectors-VIYJXKFQ.js → npm-detectors-Z2ZIQCN4.js} +2 -2
- package/chunks/orchestrate-DWWUT5RC.js +58 -0
- package/chunks/{process-PNMC36JI.js → process-N245QIQG.js} +1 -4
- package/chunks/{run-CBGE6DRQ.js → run-GAFKBCTN.js} +14935 -17598
- package/chunks/{runtime-PXO5G6UV.js → runtime-H7YBR5IZ.js} +4 -5
- package/chunks/{scope-NJHIDDTN.js → scope-QWY4VQZ7.js} +4 -1
- package/chunks/{session-store-46WBZM22.js → session-store-XIDFGG7K.js} +2 -2
- package/chunks/{variant-candidates-UH2WC2HA.js → variant-candidates-7D4F5E4H.js} +3 -3
- package/chunks/{web-recon-prepass-SFXU44SS.js → web-recon-prepass-VXXBPDAV.js} +3 -3
- package/cli-path-traversal-fixture.js +352 -0
- package/dashboard/assets/bot-Bg1Tp9_d.js +1 -0
- package/dashboard/assets/dist-B_dDCPbu.js +1 -0
- package/dashboard/assets/findings-page-mayGhNx6.js +5 -0
- package/dashboard/assets/format--susmHX7.js +1 -0
- package/dashboard/assets/input-TuVPR3Zl.js +1 -0
- package/dashboard/assets/jsx-runtime-MGseXjj5.js +3 -0
- package/dashboard/assets/live-page-HWWHX99U.js +1 -0
- package/dashboard/assets/meta-tile-ckHo-w7k.js +1 -0
- package/dashboard/assets/operations-BxZ0OoXO.js +10 -0
- package/dashboard/assets/operations-app-D3d35rgo.js +46 -0
- package/dashboard/assets/overview-page-W_4IteEr.js +1 -0
- package/dashboard/assets/page-header-Bw9AJgBV.js +1 -0
- package/dashboard/assets/scans-page-CgzVXHnn.js +1 -0
- package/dashboard/assets/siren-KQj8QAnJ.js +1 -0
- package/dashboard/assets/table-8EDklulN.js +1 -0
- package/dashboard/assets/tabs-CFHPOwg8.js +1 -0
- package/dashboard/index.html +2 -3
- package/node_modules/node-addon-api/LICENSE.md +9 -0
- package/node_modules/node-addon-api/README.md +95 -0
- package/node_modules/node-addon-api/common.gypi +21 -0
- package/node_modules/node-addon-api/except.gypi +25 -0
- package/node_modules/node-addon-api/index.js +14 -0
- package/node_modules/node-addon-api/napi-inl.deprecated.h +186 -0
- package/node_modules/node-addon-api/napi-inl.h +7250 -0
- package/node_modules/node-addon-api/napi.h +3463 -0
- package/node_modules/node-addon-api/node_addon_api.gyp +42 -0
- package/node_modules/node-addon-api/node_api.gyp +9 -0
- package/node_modules/node-addon-api/noexcept.gypi +26 -0
- package/node_modules/node-addon-api/nothing.c +0 -0
- package/node_modules/node-addon-api/package-support.json +21 -0
- package/node_modules/node-addon-api/package.json +481 -0
- package/node_modules/node-addon-api/tools/README.md +73 -0
- package/node_modules/node-addon-api/tools/check-napi.js +99 -0
- package/node_modules/node-addon-api/tools/clang-format.js +71 -0
- package/node_modules/node-addon-api/tools/conversion.js +301 -0
- package/node_modules/node-gyp-build/LICENSE +21 -0
- package/node_modules/node-gyp-build/README.md +58 -0
- package/node_modules/node-gyp-build/SECURITY.md +5 -0
- package/node_modules/node-gyp-build/bin.js +84 -0
- package/node_modules/node-gyp-build/build-test.js +19 -0
- package/node_modules/node-gyp-build/index.js +6 -0
- package/node_modules/node-gyp-build/node-gyp-build.js +207 -0
- package/node_modules/node-gyp-build/optional.js +7 -0
- package/node_modules/node-gyp-build/package.json +43 -0
- package/node_modules/tree-sitter/LICENSE +21 -0
- package/node_modules/tree-sitter/README.md +90 -0
- package/node_modules/tree-sitter/binding.gyp +76 -0
- package/node_modules/tree-sitter/index.js +895 -0
- package/node_modules/tree-sitter/package.json +62 -0
- package/node_modules/tree-sitter/prebuilds/darwin-arm64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/darwin-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/linux-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/prebuilds/win32-x64/tree-sitter.node +0 -0
- package/node_modules/tree-sitter/src/addon_data.h +47 -0
- package/node_modules/tree-sitter/src/binding.cc +35 -0
- package/node_modules/tree-sitter/src/conversions.cc +140 -0
- package/node_modules/tree-sitter/src/conversions.h +22 -0
- package/node_modules/tree-sitter/src/language.cc +106 -0
- package/node_modules/tree-sitter/src/language.h +17 -0
- package/node_modules/tree-sitter/src/logger.cc +70 -0
- package/node_modules/tree-sitter/src/logger.h +19 -0
- package/node_modules/tree-sitter/src/lookaheaditerator.cc +122 -0
- package/node_modules/tree-sitter/src/lookaheaditerator.h +33 -0
- package/node_modules/tree-sitter/src/node.cc +1056 -0
- package/node_modules/tree-sitter/src/node.h +30 -0
- package/node_modules/tree-sitter/src/parser.cc +298 -0
- package/node_modules/tree-sitter/src/parser.h +35 -0
- package/node_modules/tree-sitter/src/query.cc +383 -0
- package/node_modules/tree-sitter/src/query.h +39 -0
- package/node_modules/tree-sitter/src/tree.cc +307 -0
- package/node_modules/tree-sitter/src/tree.h +45 -0
- package/node_modules/tree-sitter/src/tree_cursor.cc +213 -0
- package/node_modules/tree-sitter/src/tree_cursor.h +52 -0
- package/node_modules/tree-sitter/tree-sitter.d.ts +211 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/LICENSE +21 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/README.md +21 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/README.md +6 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/include/tree_sitter/api.h +1266 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.c +48 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/alloc.h +41 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/array.h +290 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/atomic.h +68 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/clock.h +146 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/error_costs.h +11 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.c +501 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/get_changed_ranges.h +36 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/host.h +21 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.c +221 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/language.h +299 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/length.h +52 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.c +419 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lexer.h +49 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/lib.c +14 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/node.c +774 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.c +2151 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/parser.h +230 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/point.h +62 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/query.c +4134 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reduce_action.h +34 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/reusable_node.h +95 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.c +899 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/stack.h +133 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.c +1060 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/subtree.h +382 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.c +165 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree.h +31 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.c +714 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/tree_cursor.h +48 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ICU_SHA +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/LICENSE +414 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/README.md +29 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/ptypes.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/umachine.h +448 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/urename.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf.h +1 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf16.h +733 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode/utf8.h +881 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/unicode.h +50 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib-symbols.txt +23 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/stdlib.c +109 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm/wasm-stdlib.h +1294 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.c +1823 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/lib/src/wasm_store.h +31 -0
- package/node_modules/tree-sitter/vendor/tree-sitter/test/fixtures/grammars/.gitkeep +0 -0
- package/node_modules/tree-sitter-c/LICENSE +21 -0
- package/node_modules/tree-sitter-c/README.md +18 -0
- package/node_modules/tree-sitter-c/binding.gyp +20 -0
- package/node_modules/tree-sitter-c/bindings/node/binding.cc +20 -0
- package/node_modules/tree-sitter-c/bindings/node/index.d.ts +28 -0
- package/node_modules/tree-sitter-c/bindings/node/index.js +7 -0
- package/node_modules/tree-sitter-c/grammar.js +1463 -0
- package/node_modules/tree-sitter-c/package.json +108 -0
- package/node_modules/tree-sitter-c/prebuilds/darwin-arm64/tree-sitter-c.node +0 -0
- package/node_modules/tree-sitter-c/prebuilds/darwin-x64/tree-sitter-c.node +0 -0
- package/node_modules/tree-sitter-c/prebuilds/linux-x64/tree-sitter-c.node +0 -0
- package/node_modules/tree-sitter-c/prebuilds/win32-x64/tree-sitter-c.node +0 -0
- package/node_modules/tree-sitter-c/queries/highlights.scm +81 -0
- package/node_modules/tree-sitter-c/queries/tags.scm +9 -0
- package/node_modules/tree-sitter-c/src/grammar.json +9682 -0
- package/node_modules/tree-sitter-c/src/node-types.json +4556 -0
- package/node_modules/tree-sitter-c/src/parser.c +113852 -0
- package/node_modules/tree-sitter-c/src/tree_sitter/alloc.h +54 -0
- package/node_modules/tree-sitter-c/src/tree_sitter/array.h +290 -0
- package/node_modules/tree-sitter-c/src/tree_sitter/parser.h +265 -0
- package/package.json +10 -3
- package/vendor/tree-sitter-0.21.1-node24.json +16 -0
- package/vendor/tree-sitter-0.21.1-node24.tgz +0 -0
- package/chunks/chunk-CGHCEN7W.js +0 -169
- package/chunks/chunk-CXKDWFNO.js +0 -102
- package/chunks/chunk-GIQKESMN.js +0 -687
- package/chunks/chunk-HPQZHOIU.js +0 -67
- package/chunks/chunk-PD2BBBKT.js +0 -245
- package/chunks/chunk-WF5W75WY.js +0 -1070
- package/chunks/fix-J2KBRJDV.js +0 -12
- package/chunks/orchestrate-DHBFRTSI.js +0 -59
- package/chunks/replay-runner-LK2XFIVG.js +0 -39
- package/dashboard/assets/bot-yILPnRgD.js +0 -1
- package/dashboard/assets/chevron-down-BeDJ-Vka.js +0 -1
- package/dashboard/assets/circle-alert-BEnMBMT-.js +0 -1
- package/dashboard/assets/client-DRYsuOGl.js +0 -9
- package/dashboard/assets/copy-Bi5vzoF9.js +0 -1
- package/dashboard/assets/desktop-BT7RkC4q.js +0 -32
- package/dashboard/assets/desktop-OaBI0E0e.css +0 -1
- package/dashboard/assets/dist-CmX-h7a4.js +0 -1
- package/dashboard/assets/dist-DAwYQmf_.js +0 -45
- package/dashboard/assets/findings-page-B4rwF6fZ.js +0 -5
- package/dashboard/assets/format-LNQSSpn6.js +0 -1
- package/dashboard/assets/jsx-runtime-C7oxC63R.js +0 -1
- package/dashboard/assets/live-page-DoNwpPAO.js +0 -1
- package/dashboard/assets/meta-tile-BMtBC-Qq.js +0 -1
- package/dashboard/assets/operations-app-ER0gg7GN.js +0 -2
- package/dashboard/assets/operations-e2CGYKB1.js +0 -4
- package/dashboard/assets/overview-page-CmeWH17A.js +0 -1
- package/dashboard/assets/page-header-CIJyycfz.js +0 -1
- package/dashboard/assets/play-Dwo-9xt6.js +0 -1
- package/dashboard/assets/scans-page-CuhzWhHx.js +0 -1
- package/dashboard/assets/search-CiooTLck.js +0 -1
- package/dashboard/assets/siren-CCBwTSuk.js +0 -1
- package/dashboard/assets/table-BgsSBdke.js +0 -1
- package/dashboard/assets/tabs-vn6v7Bk6.js +0 -1
- package/dashboard/desktop.html +0 -21
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
import { createRequire as __0CreateRequire } from "node:module";
|
|
3
3
|
const require = __0CreateRequire(import.meta.url);
|
|
4
4
|
import {
|
|
5
|
-
VERSION
|
|
6
|
-
|
|
7
|
-
} from "./chunk-PC6RCKQV.js";
|
|
5
|
+
VERSION
|
|
6
|
+
} from "./chunk-KAU6NLGP.js";
|
|
8
7
|
|
|
9
8
|
// packages/core/dist/agent/feature-presets.js
|
|
10
9
|
var FP_MOAT_FLAGS = [
|
|
@@ -309,18 +308,6 @@ var features = {
|
|
|
309
308
|
get cloudSurface() {
|
|
310
309
|
return env("ZERO_FEATURE_CLOUD_SURFACE", false);
|
|
311
310
|
},
|
|
312
|
-
/**
|
|
313
|
-
* #978 (ADR-060) — agent fan-out. When ON, the agent gets the `start_scan`
|
|
314
|
-
* tool: it can dispatch CHILD scans (via the same POST /scans the UI uses)
|
|
315
|
-
* that run independently and report up the scan tree — the recursive
|
|
316
|
-
* sub-agent orchestration. Default OFF: fan-out multiplies scans/cost, so it
|
|
317
|
-
* stays opt-in even though the orchestrator enforces budget + a tree-level
|
|
318
|
-
* cap (max children/depth). Enable with ZERO_FEATURE_AGENT_FANOUT=1.
|
|
319
|
-
* Getter so the CLI `--features` flag is honored at dispatch time.
|
|
320
|
-
*/
|
|
321
|
-
get agentFanout() {
|
|
322
|
-
return env("ZERO_FEATURE_AGENT_FANOUT", false);
|
|
323
|
-
},
|
|
324
311
|
// ── Phase-2 offensive-engine feature flags (dev-live-engine-recovery) ──
|
|
325
312
|
// Each gates a tool that RUNS/BUILDS untrusted code or WEAPONIZES. They are
|
|
326
313
|
// deny-by-default and mirror `cloudSurface` exactly: the env flag is only one
|
|
@@ -448,20 +435,6 @@ var features = {
|
|
|
448
435
|
get dynamicTriageRouting() {
|
|
449
436
|
return env("ZERO_FEATURE_DYNAMIC_TRIAGE", false);
|
|
450
437
|
},
|
|
451
|
-
/**
|
|
452
|
-
* Opt-in cloud-sink webhook integration (`packages/core/src/cloud-sink.ts`).
|
|
453
|
-
* When enabled AND the user has set ZERO_CLOUD_SINK + ZERO_CLOUD_SCAN_ID,
|
|
454
|
-
* every finding and the final scan report are POSTed to the configured
|
|
455
|
-
* remote endpoint in real time.
|
|
456
|
-
*
|
|
457
|
-
* Default ON so the env-var trio is sufficient to enable streaming, but the
|
|
458
|
-
* flag exists so operators can force-disable the integration in environments
|
|
459
|
-
* where outbound HTTP from the scanner is not desired (e.g. air-gapped CI).
|
|
460
|
-
* Disable via ZERO_FEATURE_CLOUD_SINK=0.
|
|
461
|
-
*/
|
|
462
|
-
get cloudSink() {
|
|
463
|
-
return env("ZERO_FEATURE_CLOUD_SINK", true);
|
|
464
|
-
},
|
|
465
438
|
/**
|
|
466
439
|
* Pre-recon CVE check (`packages/core/src/pre-recon-cve.ts`).
|
|
467
440
|
* In white-box mode (`--repo` set), runs `npm audit` / `pip-audit`
|
|
@@ -1050,514 +1023,11 @@ function _resetDiagnosticsForTests() {
|
|
|
1050
1023
|
diag.resetForTests();
|
|
1051
1024
|
}
|
|
1052
1025
|
|
|
1053
|
-
// packages/core/dist/cloud/credentials.js
|
|
1054
|
-
import { readFileSync, statSync } from "node:fs";
|
|
1055
|
-
import { join } from "node:path";
|
|
1056
|
-
var DEFAULT_CLOUD_HOST = "https://cloud.0.security";
|
|
1057
|
-
var CloudAuthMissingError = class extends Error {
|
|
1058
|
-
constructor(message) {
|
|
1059
|
-
super(message);
|
|
1060
|
-
this.name = "CloudAuthMissingError";
|
|
1061
|
-
}
|
|
1062
|
-
};
|
|
1063
|
-
var CloudAuthError = class extends Error {
|
|
1064
|
-
status;
|
|
1065
|
-
constructor(message, status) {
|
|
1066
|
-
super(message);
|
|
1067
|
-
this.status = status;
|
|
1068
|
-
this.name = "CloudAuthError";
|
|
1069
|
-
}
|
|
1070
|
-
};
|
|
1071
|
-
function loadCloudCredentials(opts = {}) {
|
|
1072
|
-
const env2 = opts.env ?? process.env;
|
|
1073
|
-
const warn = opts.warn ?? ((m) => process.stderr.write(`${m}
|
|
1074
|
-
`));
|
|
1075
|
-
const envTok = env2["ZERO_CLOUD_TOKEN"]?.trim() || env2["0SEC_CLOUD_TOKEN"]?.trim();
|
|
1076
|
-
if (envTok) {
|
|
1077
|
-
const envHost = normaliseHost(env2["ZERO_CLOUD_HOST"]?.trim() ?? env2["0SEC_CLOUD_HOST"]?.trim() ?? DEFAULT_CLOUD_HOST);
|
|
1078
|
-
if (!env2["ZERO_CLOUD_TOKEN"]?.trim()) {
|
|
1079
|
-
warn("[0 cloud] using legacy 0SEC_CLOUD_* credentials; re-run `0 auth login` to migrate to ZERO_CLOUD_*.");
|
|
1080
|
-
}
|
|
1081
|
-
return { host: envHost, token: envTok, source: "env" };
|
|
1082
|
-
}
|
|
1083
|
-
const path = join(cloudStateDir(opts.homeDir, env2), "cloud.env");
|
|
1084
|
-
let raw;
|
|
1085
|
-
try {
|
|
1086
|
-
raw = readFileSync(path, "utf-8");
|
|
1087
|
-
} catch (err) {
|
|
1088
|
-
const code = err.code;
|
|
1089
|
-
if (code === "ENOENT") {
|
|
1090
|
-
throw new CloudAuthMissingError(`0-cloud credentials not found. Run \`${env2["ZERO_DEV_SOURCE_ROOT"]?.trim() ? "0dev" : "0"} auth login\`.`);
|
|
1091
|
-
}
|
|
1092
|
-
throw err;
|
|
1093
|
-
}
|
|
1094
|
-
try {
|
|
1095
|
-
const st = statSync(path);
|
|
1096
|
-
const mode = st.mode & 511;
|
|
1097
|
-
if (mode !== 384) {
|
|
1098
|
-
warn(`[0 cloud] WARNING: ${path} mode is ${mode.toString(8).padStart(3, "0")} (expected 600). Run: chmod 600 ${path}`);
|
|
1099
|
-
}
|
|
1100
|
-
} catch {
|
|
1101
|
-
}
|
|
1102
|
-
const parsed = parseEnvFile(raw);
|
|
1103
|
-
const fileTok = parsed["ZERO_CLOUD_TOKEN"]?.trim() || parsed["0SEC_CLOUD_TOKEN"]?.trim();
|
|
1104
|
-
if (!fileTok) {
|
|
1105
|
-
throw new CloudAuthMissingError(`0-cloud credentials in ${path} are incomplete: ZERO_CLOUD_TOKEN is required.`);
|
|
1106
|
-
}
|
|
1107
|
-
if (!parsed["ZERO_CLOUD_TOKEN"]?.trim()) {
|
|
1108
|
-
warn("[0 cloud] using legacy 0SEC_CLOUD_* credentials; re-run `0 auth login` to migrate to ZERO_CLOUD_*.");
|
|
1109
|
-
}
|
|
1110
|
-
const fileHost = normaliseHost(parsed["ZERO_CLOUD_HOST"]?.trim() ?? parsed["0SEC_CLOUD_HOST"]?.trim() ?? env2["ZERO_CLOUD_HOST"]?.trim() ?? env2["0SEC_CLOUD_HOST"]?.trim() ?? DEFAULT_CLOUD_HOST);
|
|
1111
|
-
return { host: fileHost, token: fileTok, source: "file" };
|
|
1112
|
-
}
|
|
1113
|
-
function normaliseHost(host) {
|
|
1114
|
-
let h = host;
|
|
1115
|
-
if (!/^https?:\/\//.test(h)) {
|
|
1116
|
-
throw new CloudAuthMissingError(`ZERO_CLOUD_HOST must be an http(s) URL (got ${JSON.stringify(host)}).`);
|
|
1117
|
-
}
|
|
1118
|
-
while (h.endsWith("/"))
|
|
1119
|
-
h = h.slice(0, -1);
|
|
1120
|
-
return h;
|
|
1121
|
-
}
|
|
1122
|
-
function parseEnvFile(raw) {
|
|
1123
|
-
const out = {};
|
|
1124
|
-
const lines = raw.split(/\r?\n/);
|
|
1125
|
-
for (let i = 0; i < lines.length; i++) {
|
|
1126
|
-
const line = lines[i];
|
|
1127
|
-
const trimmed = line.trim();
|
|
1128
|
-
if (trimmed.length === 0)
|
|
1129
|
-
continue;
|
|
1130
|
-
if (trimmed.startsWith("#"))
|
|
1131
|
-
continue;
|
|
1132
|
-
const eq = trimmed.indexOf("=");
|
|
1133
|
-
if (eq <= 0) {
|
|
1134
|
-
throw new CloudAuthMissingError(`Malformed cloud.env at line ${i + 1}: expected KEY=VALUE, got ${JSON.stringify(line)}`);
|
|
1135
|
-
}
|
|
1136
|
-
const key = trimmed.slice(0, eq).trim();
|
|
1137
|
-
const value = trimmed.slice(eq + 1).trim();
|
|
1138
|
-
if (!/^[A-Z0-9_]+$/.test(key)) {
|
|
1139
|
-
throw new CloudAuthMissingError(`Malformed cloud.env at line ${i + 1}: invalid key ${JSON.stringify(key)}`);
|
|
1140
|
-
}
|
|
1141
|
-
out[key] = value;
|
|
1142
|
-
}
|
|
1143
|
-
return out;
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
// packages/core/dist/cloud/client.js
|
|
1147
|
-
var CloudError = class extends Error {
|
|
1148
|
-
status;
|
|
1149
|
-
path;
|
|
1150
|
-
code;
|
|
1151
|
-
constructor(message, status, path, code) {
|
|
1152
|
-
super(message);
|
|
1153
|
-
this.status = status;
|
|
1154
|
-
this.path = path;
|
|
1155
|
-
this.code = code;
|
|
1156
|
-
this.name = "CloudError";
|
|
1157
|
-
}
|
|
1158
|
-
};
|
|
1159
|
-
var CloudUnauthorizedError = class extends CloudError {
|
|
1160
|
-
constructor(path) {
|
|
1161
|
-
super(`0-cloud auth rejected (HTTP 401) on ${path}. Run \`0 auth login\` to refresh.`, 401, path);
|
|
1162
|
-
this.name = "CloudUnauthorizedError";
|
|
1163
|
-
}
|
|
1164
|
-
};
|
|
1165
|
-
var CloudForbiddenError = class extends CloudError {
|
|
1166
|
-
constructor(path) {
|
|
1167
|
-
super(`0-cloud forbidden (HTTP 403) on ${path}. Token lacks scope for this resource.`, 403, path);
|
|
1168
|
-
this.name = "CloudForbiddenError";
|
|
1169
|
-
}
|
|
1170
|
-
};
|
|
1171
|
-
var CloudNetworkError = class extends CloudError {
|
|
1172
|
-
constructor(message, path) {
|
|
1173
|
-
super(`0-cloud network error on ${path}: ${message}`, void 0, path);
|
|
1174
|
-
this.name = "CloudNetworkError";
|
|
1175
|
-
}
|
|
1176
|
-
};
|
|
1177
|
-
function isUsageAccount(raw) {
|
|
1178
|
-
if (!raw || typeof raw !== "object")
|
|
1179
|
-
return false;
|
|
1180
|
-
const obj = raw;
|
|
1181
|
-
if (obj.schemaVersion !== "usage-v2")
|
|
1182
|
-
return false;
|
|
1183
|
-
if (!isUtcDate(obj.snapshotAt))
|
|
1184
|
-
return false;
|
|
1185
|
-
if (!obj.scope || typeof obj.scope !== "object")
|
|
1186
|
-
return false;
|
|
1187
|
-
if (typeof obj.scope.orgId !== "string")
|
|
1188
|
-
return false;
|
|
1189
|
-
if (typeof obj.state !== "string")
|
|
1190
|
-
return false;
|
|
1191
|
-
if (!["ready", "disabled", "unavailable", "restricted"].includes(obj.state))
|
|
1192
|
-
return false;
|
|
1193
|
-
if (obj.reason !== null && typeof obj.reason !== "string")
|
|
1194
|
-
return false;
|
|
1195
|
-
const plan = obj.plan;
|
|
1196
|
-
if (!plan || typeof plan !== "object")
|
|
1197
|
-
return false;
|
|
1198
|
-
if (typeof plan.id !== "string" && plan.id !== null)
|
|
1199
|
-
return false;
|
|
1200
|
-
if (plan.id !== null && !["pro", "gold", "enterprise"].includes(plan.id))
|
|
1201
|
-
return false;
|
|
1202
|
-
if (typeof plan.name !== "string" && plan.name !== null)
|
|
1203
|
-
return false;
|
|
1204
|
-
if (!isUsd(plan.monthlyPriceUsd))
|
|
1205
|
-
return false;
|
|
1206
|
-
const included = obj.included;
|
|
1207
|
-
if (!included || typeof included !== "object")
|
|
1208
|
-
return false;
|
|
1209
|
-
if (typeof included.state !== "string")
|
|
1210
|
-
return false;
|
|
1211
|
-
if (!["active", "exhausted", "none", "unavailable"].includes(included.state))
|
|
1212
|
-
return false;
|
|
1213
|
-
if (included.usedPercent !== null && typeof included.usedPercent !== "number")
|
|
1214
|
-
return false;
|
|
1215
|
-
if (included.usedPercent !== null && (!Number.isFinite(included.usedPercent) || included.usedPercent < 0 || included.usedPercent > 100))
|
|
1216
|
-
return false;
|
|
1217
|
-
if (included.resetsAt !== null && !isUtcDate(included.resetsAt))
|
|
1218
|
-
return false;
|
|
1219
|
-
const prepaid = obj.prepaid;
|
|
1220
|
-
if (!prepaid || typeof prepaid !== "object")
|
|
1221
|
-
return false;
|
|
1222
|
-
if (!isUsd(prepaid.balanceUsd))
|
|
1223
|
-
return false;
|
|
1224
|
-
if (typeof prepaid.fallbackEnabled !== "boolean")
|
|
1225
|
-
return false;
|
|
1226
|
-
if (typeof obj.canManageBilling !== "boolean")
|
|
1227
|
-
return false;
|
|
1228
|
-
const admission = obj.admission;
|
|
1229
|
-
if (!admission || typeof admission !== "object")
|
|
1230
|
-
return false;
|
|
1231
|
-
if (typeof admission.eligible !== "boolean")
|
|
1232
|
-
return false;
|
|
1233
|
-
if (admission.reason !== null && typeof admission.reason !== "string")
|
|
1234
|
-
return false;
|
|
1235
|
-
return true;
|
|
1236
|
-
}
|
|
1237
|
-
function isUsd(value) {
|
|
1238
|
-
return value === null || typeof value === "string" && /^\d+(?:\.\d{1,9})?$/.test(value);
|
|
1239
|
-
}
|
|
1240
|
-
function isUtcDate(value) {
|
|
1241
|
-
return typeof value === "string" && /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?Z$/.test(value) && Number.isFinite(Date.parse(value));
|
|
1242
|
-
}
|
|
1243
|
-
function healthPath(host) {
|
|
1244
|
-
try {
|
|
1245
|
-
const hostname = new URL(host).hostname.toLowerCase();
|
|
1246
|
-
if (hostname === "cloud.0.ai" || hostname === "cloud.0.security") {
|
|
1247
|
-
return "/api/health";
|
|
1248
|
-
}
|
|
1249
|
-
} catch {
|
|
1250
|
-
}
|
|
1251
|
-
return "/health";
|
|
1252
|
-
}
|
|
1253
|
-
var CloudClient = class {
|
|
1254
|
-
host;
|
|
1255
|
-
token;
|
|
1256
|
-
fetchImpl;
|
|
1257
|
-
constructor(opts) {
|
|
1258
|
-
this.host = opts.host;
|
|
1259
|
-
this.token = opts.token;
|
|
1260
|
-
this.fetchImpl = opts.fetchImpl ?? fetch;
|
|
1261
|
-
}
|
|
1262
|
-
/**
|
|
1263
|
-
* Verify cloud reachability through its health route. The hosted dashboard
|
|
1264
|
-
* uses `/api/health`; a self-hosted receiver uses `/health`.
|
|
1265
|
-
*/
|
|
1266
|
-
async pingHealth() {
|
|
1267
|
-
return this.getJson(healthPath(this.host));
|
|
1268
|
-
}
|
|
1269
|
-
/**
|
|
1270
|
-
* Fetch the hosted inference model catalog — available models, pricing,
|
|
1271
|
-
* wire API protocol, and context limits. Used at runtime for model
|
|
1272
|
-
* selection and by the hosted provider to determine per-model capabilities.
|
|
1273
|
-
* Returns the raw list response; the caller caches/filters as needed.
|
|
1274
|
-
*/
|
|
1275
|
-
async getInferenceModels() {
|
|
1276
|
-
return this.getJson("/api/inference/v1/models");
|
|
1277
|
-
}
|
|
1278
|
-
/**
|
|
1279
|
-
* Fetch the organization's credit account — usage-v2 shape including
|
|
1280
|
-
* plan, included allowance, prepaid balance, and admission status.
|
|
1281
|
-
*
|
|
1282
|
-
* Returns `null` when the response is a recognised HTTP 200 (customer is
|
|
1283
|
-
* authenticated) but the payload is missing, legacy, or structurally
|
|
1284
|
-
* unrecognised — not an auth failure. HTTP 401/403 still throw the
|
|
1285
|
-
* existing typed errors so the caller can distinguish a credential
|
|
1286
|
-
* problem from unsupported credit data.
|
|
1287
|
-
*
|
|
1288
|
-
* Monetary amounts are decimal strings (no Number coercion); the
|
|
1289
|
-
* caller preserves them for exact display.
|
|
1290
|
-
*/
|
|
1291
|
-
async getInferenceAccount() {
|
|
1292
|
-
const raw = await this.getJson("/api/inference/account");
|
|
1293
|
-
if (!isUsageAccount(raw))
|
|
1294
|
-
return null;
|
|
1295
|
-
const { plan, included, prepaid, admission } = raw;
|
|
1296
|
-
return {
|
|
1297
|
-
schemaVersion: raw.schemaVersion,
|
|
1298
|
-
snapshotAt: raw.snapshotAt,
|
|
1299
|
-
scope: { orgId: raw.scope.orgId },
|
|
1300
|
-
state: raw.state,
|
|
1301
|
-
reason: raw.reason,
|
|
1302
|
-
plan: {
|
|
1303
|
-
id: plan.id,
|
|
1304
|
-
name: plan.name,
|
|
1305
|
-
monthlyPriceUsd: plan.monthlyPriceUsd
|
|
1306
|
-
},
|
|
1307
|
-
included: {
|
|
1308
|
-
state: included.state,
|
|
1309
|
-
usedPercent: included.usedPercent,
|
|
1310
|
-
resetsAt: included.resetsAt
|
|
1311
|
-
},
|
|
1312
|
-
prepaid: {
|
|
1313
|
-
balanceUsd: prepaid.balanceUsd,
|
|
1314
|
-
fallbackEnabled: prepaid.fallbackEnabled
|
|
1315
|
-
},
|
|
1316
|
-
canManageBilling: raw.canManageBilling,
|
|
1317
|
-
admission: { eligible: admission.eligible, reason: admission.reason }
|
|
1318
|
-
};
|
|
1319
|
-
}
|
|
1320
|
-
/**
|
|
1321
|
-
* Fetch request-level usage metadata for the operator's hosted
|
|
1322
|
-
* inference sessions. Returns lightweight metadata records (model,
|
|
1323
|
-
* tokens, provider, timestamp) — no prompt/response payload.
|
|
1324
|
-
*/
|
|
1325
|
-
async getInferenceUsage() {
|
|
1326
|
-
return this.getJson("/api/inference/usage");
|
|
1327
|
-
}
|
|
1328
|
-
// ── Audit-skills helpers (#audit-skills) ──
|
|
1329
|
-
/** List all audit skills for the authenticated organization. */
|
|
1330
|
-
async listAuditSkills() {
|
|
1331
|
-
return this.getJson("/api/audit-skills");
|
|
1332
|
-
}
|
|
1333
|
-
/**
|
|
1334
|
-
* Get a single audit skill with its revision history and project
|
|
1335
|
-
* assignments.
|
|
1336
|
-
*/
|
|
1337
|
-
async getAuditSkill(id) {
|
|
1338
|
-
return this.getJson(`/api/audit-skills/${encodeURIComponent(id)}`);
|
|
1339
|
-
}
|
|
1340
|
-
/** Create a new markdown-based audit skill. */
|
|
1341
|
-
async createAuditSkill(input) {
|
|
1342
|
-
return this.postJson("/api/audit-skills", input);
|
|
1343
|
-
}
|
|
1344
|
-
/** Import an audit skill from a GitHub repository. */
|
|
1345
|
-
async importAuditSkillFromGithub(input) {
|
|
1346
|
-
return this.postJson("/api/audit-skills/import", input);
|
|
1347
|
-
}
|
|
1348
|
-
/** Create a new revision of an audit skill (CAS — 409 on stale expectedRevision). */
|
|
1349
|
-
async createAuditSkillRevision(id, input) {
|
|
1350
|
-
return this.postJson(`/api/audit-skills/${encodeURIComponent(id)}/revisions`, input);
|
|
1351
|
-
}
|
|
1352
|
-
/** Re-fetch the skill from its original GitHub source. */
|
|
1353
|
-
async syncAuditSkill(id, expectedRevision) {
|
|
1354
|
-
return this.postJson(`/api/audit-skills/${encodeURIComponent(id)}/sync`, { expectedRevision });
|
|
1355
|
-
}
|
|
1356
|
-
/** Pin an audit skill revision to a project for future scans. */
|
|
1357
|
-
async assignAuditSkill(id, projectId, revisionId) {
|
|
1358
|
-
return this.postJson(`/api/audit-skills/${encodeURIComponent(id)}/projects/${encodeURIComponent(projectId)}`, { revisionId });
|
|
1359
|
-
}
|
|
1360
|
-
/** Unpin an audit skill from a project (future scans no longer use it). */
|
|
1361
|
-
async unassignAuditSkill(id, projectId) {
|
|
1362
|
-
return this.deleteJson(`/api/audit-skills/${encodeURIComponent(id)}/projects/${encodeURIComponent(projectId)}`);
|
|
1363
|
-
}
|
|
1364
|
-
/** Archive an audit skill (disables future bindings, preserves history). */
|
|
1365
|
-
async archiveAuditSkill(id) {
|
|
1366
|
-
await this.deleteJson(`/api/audit-skills/${encodeURIComponent(id)}`);
|
|
1367
|
-
}
|
|
1368
|
-
/**
|
|
1369
|
-
* List audit skills available to a specific project, along with current
|
|
1370
|
-
* assignments for that project. The project must belong to the caller's org.
|
|
1371
|
-
*/
|
|
1372
|
-
async listAuditSkillsByProject(projectId) {
|
|
1373
|
-
return this.getJson(`/api/audit-skills/by-project/${encodeURIComponent(projectId)}`);
|
|
1374
|
-
}
|
|
1375
|
-
/**
|
|
1376
|
-
* Generic JSON DELETE helper with the same error mapping as getJson/postJson.
|
|
1377
|
-
* Used by `0 service disconnect` to remove scan schedules.
|
|
1378
|
-
*/
|
|
1379
|
-
async deleteJson(path) {
|
|
1380
|
-
const url = `${this.host}${path}`;
|
|
1381
|
-
let res;
|
|
1382
|
-
try {
|
|
1383
|
-
res = await this.fetchImpl(url, {
|
|
1384
|
-
method: "DELETE",
|
|
1385
|
-
headers: { ...this.headers(), "Content-Type": "application/json" }
|
|
1386
|
-
});
|
|
1387
|
-
} catch (err) {
|
|
1388
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1389
|
-
throw new CloudNetworkError(this.scrub(msg), path);
|
|
1390
|
-
}
|
|
1391
|
-
if (!res.ok) {
|
|
1392
|
-
let code;
|
|
1393
|
-
try {
|
|
1394
|
-
const parsed = await res.json();
|
|
1395
|
-
const raw = typeof parsed?.error === "object" ? parsed.error?.code : void 0;
|
|
1396
|
-
if (typeof raw === "string" && raw.length > 0)
|
|
1397
|
-
code = raw;
|
|
1398
|
-
} catch {
|
|
1399
|
-
}
|
|
1400
|
-
this.throwForStatus(res.status, path, code);
|
|
1401
|
-
}
|
|
1402
|
-
if (res.status === 204)
|
|
1403
|
-
return void 0;
|
|
1404
|
-
return await res.json();
|
|
1405
|
-
}
|
|
1406
|
-
/**
|
|
1407
|
-
* Generic JSON POST helper with the same error mapping as getJson.
|
|
1408
|
-
* Used by `0 connect` to enqueue scans and schedules.
|
|
1409
|
-
*/
|
|
1410
|
-
async postJson(path, body) {
|
|
1411
|
-
const url = `${this.host}${path}`;
|
|
1412
|
-
let res;
|
|
1413
|
-
try {
|
|
1414
|
-
res = await this.fetchImpl(url, {
|
|
1415
|
-
method: "POST",
|
|
1416
|
-
headers: { ...this.headers(), "Content-Type": "application/json" },
|
|
1417
|
-
body: JSON.stringify(body)
|
|
1418
|
-
});
|
|
1419
|
-
} catch (err) {
|
|
1420
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1421
|
-
throw new CloudNetworkError(this.scrub(msg), path);
|
|
1422
|
-
}
|
|
1423
|
-
if (!res.ok) {
|
|
1424
|
-
let code;
|
|
1425
|
-
try {
|
|
1426
|
-
const parsed = await res.json();
|
|
1427
|
-
const raw = typeof parsed?.error === "object" ? parsed.error?.code : void 0;
|
|
1428
|
-
if (typeof raw === "string" && raw.length > 0)
|
|
1429
|
-
code = raw;
|
|
1430
|
-
} catch {
|
|
1431
|
-
}
|
|
1432
|
-
this.throwForStatus(res.status, path, code);
|
|
1433
|
-
}
|
|
1434
|
-
return await res.json();
|
|
1435
|
-
}
|
|
1436
|
-
/**
|
|
1437
|
-
* Generic JSON GET helper. Public so future modules (scans, findings)
|
|
1438
|
-
* can reuse the same error mapping without duplicating it. Not exported
|
|
1439
|
-
* past the package boundary — see ./index.ts.
|
|
1440
|
-
*/
|
|
1441
|
-
async getJson(path) {
|
|
1442
|
-
const url = `${this.host}${path}`;
|
|
1443
|
-
let res;
|
|
1444
|
-
try {
|
|
1445
|
-
res = await this.fetchImpl(url, {
|
|
1446
|
-
method: "GET",
|
|
1447
|
-
headers: this.headers()
|
|
1448
|
-
});
|
|
1449
|
-
} catch (err) {
|
|
1450
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
1451
|
-
throw new CloudNetworkError(this.scrub(msg), path);
|
|
1452
|
-
}
|
|
1453
|
-
if (!res.ok) {
|
|
1454
|
-
let code;
|
|
1455
|
-
try {
|
|
1456
|
-
const body = await res.json();
|
|
1457
|
-
const raw = body?.error?.code;
|
|
1458
|
-
if (typeof raw === "string" && raw.length > 0)
|
|
1459
|
-
code = raw;
|
|
1460
|
-
} catch {
|
|
1461
|
-
}
|
|
1462
|
-
this.throwForStatus(res.status, path, code);
|
|
1463
|
-
}
|
|
1464
|
-
return await res.json();
|
|
1465
|
-
}
|
|
1466
|
-
/** Throw a typed error for a non-2xx status, carrying the gateway's body `code`. */
|
|
1467
|
-
throwForStatus(status, path, code) {
|
|
1468
|
-
if (status === 401)
|
|
1469
|
-
throw new CloudUnauthorizedError(path);
|
|
1470
|
-
if (status === 403)
|
|
1471
|
-
throw new CloudForbiddenError(path);
|
|
1472
|
-
throw new CloudError(`0-cloud request failed (HTTP ${status}${code ? ` ${code}` : ""}) on ${path}.`, status, path, code);
|
|
1473
|
-
}
|
|
1474
|
-
/**
|
|
1475
|
-
* Throw a typed error for non-2xx responses. Public so direct callers
|
|
1476
|
-
* (e.g. an integration test driving raw fetch) can reuse the mapping.
|
|
1477
|
-
*/
|
|
1478
|
-
assertOk(res, path) {
|
|
1479
|
-
if (res.ok)
|
|
1480
|
-
return;
|
|
1481
|
-
if (res.status === 401)
|
|
1482
|
-
throw new CloudUnauthorizedError(path);
|
|
1483
|
-
if (res.status === 403)
|
|
1484
|
-
throw new CloudForbiddenError(path);
|
|
1485
|
-
throw new CloudError(`0-cloud request failed (HTTP ${res.status}) on ${path}.`, res.status, path);
|
|
1486
|
-
}
|
|
1487
|
-
// ── internals ──
|
|
1488
|
-
headers() {
|
|
1489
|
-
return {
|
|
1490
|
-
Authorization: `Bearer ${this.token}`,
|
|
1491
|
-
Accept: "application/json",
|
|
1492
|
-
"User-Agent": `@0/cli/${VERSION}`
|
|
1493
|
-
};
|
|
1494
|
-
}
|
|
1495
|
-
/**
|
|
1496
|
-
* Strip anything that looks like our own token from a string. The
|
|
1497
|
-
* cloud token may be interpolated into a TLS-layer error message in
|
|
1498
|
-
* exotic failure modes — we redact it to keep the no-leak invariant
|
|
1499
|
-
* local to this module.
|
|
1500
|
-
*/
|
|
1501
|
-
scrub(s) {
|
|
1502
|
-
if (!this.token)
|
|
1503
|
-
return s;
|
|
1504
|
-
return s.split(this.token).join("[REDACTED]");
|
|
1505
|
-
}
|
|
1506
|
-
};
|
|
1507
|
-
|
|
1508
1026
|
// packages/core/dist/runtime/llm-api.js
|
|
1509
|
-
import { randomUUID } from "node:crypto";
|
|
1510
|
-
import { appendFileSync, existsSync, readFileSync
|
|
1027
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
1028
|
+
import { appendFileSync, existsSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
1511
1029
|
import { homedir } from "node:os";
|
|
1512
|
-
import { join
|
|
1513
|
-
|
|
1514
|
-
// packages/core/dist/runtime/hosted-request-queue.js
|
|
1515
|
-
var MAX_IN_FLIGHT = 4;
|
|
1516
|
-
var endpoints = /* @__PURE__ */ new Map();
|
|
1517
|
-
function acquireHostedRequestSlot(endpoint, token, signal) {
|
|
1518
|
-
signal?.throwIfAborted();
|
|
1519
|
-
let accounts = endpoints.get(endpoint);
|
|
1520
|
-
if (!accounts)
|
|
1521
|
-
endpoints.set(endpoint, accounts = /* @__PURE__ */ new Map());
|
|
1522
|
-
let queue = accounts.get(token);
|
|
1523
|
-
if (!queue)
|
|
1524
|
-
accounts.set(token, queue = { active: 0, waiting: [] });
|
|
1525
|
-
const accountQueues = accounts;
|
|
1526
|
-
const current = queue;
|
|
1527
|
-
return new Promise((resolve, reject) => {
|
|
1528
|
-
const abort = () => {
|
|
1529
|
-
const index = current.waiting.indexOf(waiter);
|
|
1530
|
-
if (index !== -1)
|
|
1531
|
-
current.waiting.splice(index, 1);
|
|
1532
|
-
reject(signal.reason);
|
|
1533
|
-
};
|
|
1534
|
-
const waiter = { grant: () => {
|
|
1535
|
-
signal?.removeEventListener("abort", abort);
|
|
1536
|
-
current.active++;
|
|
1537
|
-
let released = false;
|
|
1538
|
-
resolve(() => {
|
|
1539
|
-
if (released)
|
|
1540
|
-
return;
|
|
1541
|
-
released = true;
|
|
1542
|
-
current.active--;
|
|
1543
|
-
const next = current.waiting.shift();
|
|
1544
|
-
if (next)
|
|
1545
|
-
next.grant();
|
|
1546
|
-
else if (current.active === 0) {
|
|
1547
|
-
accountQueues.delete(token);
|
|
1548
|
-
if (accountQueues.size === 0)
|
|
1549
|
-
endpoints.delete(endpoint);
|
|
1550
|
-
}
|
|
1551
|
-
});
|
|
1552
|
-
} };
|
|
1553
|
-
if (current.active < MAX_IN_FLIGHT)
|
|
1554
|
-
waiter.grant();
|
|
1555
|
-
else {
|
|
1556
|
-
current.waiting.push(waiter);
|
|
1557
|
-
signal?.addEventListener("abort", abort, { once: true });
|
|
1558
|
-
}
|
|
1559
|
-
});
|
|
1560
|
-
}
|
|
1030
|
+
import { join } from "node:path";
|
|
1561
1031
|
|
|
1562
1032
|
// packages/core/dist/runtime/prompt-cache.js
|
|
1563
1033
|
var MAX_CACHE_BREAKPOINTS = 4;
|
|
@@ -2085,8 +1555,7 @@ function parseLlmFallbackChain(env2 = process.env) {
|
|
|
2085
1555
|
xai: true,
|
|
2086
1556
|
opencode: true,
|
|
2087
1557
|
copilot: true,
|
|
2088
|
-
google: true
|
|
2089
|
-
hosted: true
|
|
1558
|
+
google: true
|
|
2090
1559
|
};
|
|
2091
1560
|
for (const part of raw.split(",")) {
|
|
2092
1561
|
const trimmed = part.trim();
|
|
@@ -2192,24 +1661,6 @@ function resolveFailoverProvider(provider, model, env2 = process.env, apiKey) {
|
|
|
2192
1661
|
return void 0;
|
|
2193
1662
|
return { apiKey: "", baseUrl: CODE_ASSIST_ENDPOINT, wireApi: "google_generate_content" };
|
|
2194
1663
|
}
|
|
2195
|
-
case "hosted": {
|
|
2196
|
-
try {
|
|
2197
|
-
const creds = loadCloudCredentials({
|
|
2198
|
-
env: env2,
|
|
2199
|
-
warn: () => {
|
|
2200
|
-
}
|
|
2201
|
-
});
|
|
2202
|
-
return {
|
|
2203
|
-
apiKey: creds.token,
|
|
2204
|
-
baseUrl: `${creds.host}/api/inference/v1`,
|
|
2205
|
-
wireApi: "chat_completions"
|
|
2206
|
-
};
|
|
2207
|
-
} catch (err) {
|
|
2208
|
-
if (err instanceof CloudAuthMissingError)
|
|
2209
|
-
return void 0;
|
|
2210
|
-
throw err;
|
|
2211
|
-
}
|
|
2212
|
-
}
|
|
2213
1664
|
}
|
|
2214
1665
|
}
|
|
2215
1666
|
var fallbackChainCache;
|
|
@@ -2235,6 +1686,12 @@ var KIMI_DEFAULT_MODEL = "k3";
|
|
|
2235
1686
|
var QWEN_DEFAULT_BASE_URL = "https://token-plan.ap-southeast-1.maas.aliyuncs.com/compatible-mode/v1";
|
|
2236
1687
|
var QWEN_DEFAULT_MODEL = "qwen3.8-max";
|
|
2237
1688
|
var CODEX_API_ENDPOINT = "https://chatgpt.com/backend-api/codex/responses";
|
|
1689
|
+
var CODEX_CLIENT_VERSION = "0.153.0";
|
|
1690
|
+
var CODEX_PROTOCOL_HEADERS = {
|
|
1691
|
+
"OpenAI-Beta": "responses=experimental",
|
|
1692
|
+
originator: "0",
|
|
1693
|
+
version: CODEX_CLIENT_VERSION
|
|
1694
|
+
};
|
|
2238
1695
|
var CODEX_OAUTH_ISSUER = "https://auth.openai.com";
|
|
2239
1696
|
var CODEX_OAUTH_CLIENT_ID = "app_EMoamEEZ73f0CkXaXp7hrann";
|
|
2240
1697
|
var CODEX_DEFAULT_MODEL = "gpt-5.5";
|
|
@@ -2258,13 +1715,13 @@ function readChatGptCodexEnv(env2 = process.env) {
|
|
|
2258
1715
|
};
|
|
2259
1716
|
}
|
|
2260
1717
|
function resolveChatGptCodexAuthPath(env2 = process.env) {
|
|
2261
|
-
return env2["ZERO_CHATGPT_AUTH_FILE"] ??
|
|
1718
|
+
return env2["ZERO_CHATGPT_AUTH_FILE"] ?? join(env2.HOME ?? homedir(), ".codex", "auth.json");
|
|
2262
1719
|
}
|
|
2263
1720
|
function persistChatGptCodexAuthFile(authPath, tokens, usedRefreshToken) {
|
|
2264
1721
|
try {
|
|
2265
1722
|
let existing = {};
|
|
2266
1723
|
try {
|
|
2267
|
-
existing = JSON.parse(
|
|
1724
|
+
existing = JSON.parse(readFileSync(authPath, "utf8"));
|
|
2268
1725
|
} catch {
|
|
2269
1726
|
existing = {};
|
|
2270
1727
|
}
|
|
@@ -2296,7 +1753,7 @@ function readChatGptCodexAuthFile(env2 = process.env) {
|
|
|
2296
1753
|
if (!existsSync(authPath))
|
|
2297
1754
|
return void 0;
|
|
2298
1755
|
try {
|
|
2299
|
-
const auth = JSON.parse(
|
|
1756
|
+
const auth = JSON.parse(readFileSync(authPath, "utf8"));
|
|
2300
1757
|
const tokens = auth.tokens;
|
|
2301
1758
|
if (!tokens)
|
|
2302
1759
|
return void 0;
|
|
@@ -2642,7 +2099,7 @@ function parseCodexAzureConfig(env2 = process.env) {
|
|
|
2642
2099
|
if (!existsSync(configPath))
|
|
2643
2100
|
return {};
|
|
2644
2101
|
try {
|
|
2645
|
-
const content =
|
|
2102
|
+
const content = readFileSync(configPath, "utf8");
|
|
2646
2103
|
const azureSectionMatch = content.match(/\[model_providers\.azure\]([\s\S]*?)(?:\n\[|$)/);
|
|
2647
2104
|
const activeProviderMatch = content.match(/^\s*model_provider\s*=\s*"([^"]+)"/m);
|
|
2648
2105
|
const baseUrlMatch = azureSectionMatch?.[1]?.match(/base_url\s*=\s*"([^"]+)"/);
|
|
@@ -2698,7 +2155,7 @@ function providerForModel(model, env2) {
|
|
|
2698
2155
|
return env2["ZERO_GEMINI_ACCESS_TOKEN"] || env2["ZERO_GEMINI_OAUTH_REFRESH_TOKEN"] ? "google" : void 0;
|
|
2699
2156
|
}
|
|
2700
2157
|
if (/^gpt-|^o[1-4](?:[-_]|$)/.test(m)) {
|
|
2701
|
-
if (env2
|
|
2158
|
+
if (readChatGptCodexEnv(env2) || readChatGptCodexAuthFile(env2))
|
|
2702
2159
|
return "chatgpt-codex";
|
|
2703
2160
|
if (env2.OPENAI_API_KEY)
|
|
2704
2161
|
return "openai";
|
|
@@ -2726,8 +2183,7 @@ var DEFAULT_PROVIDER_MODELS = {
|
|
|
2726
2183
|
xai: XAI_DEFAULT_MODEL,
|
|
2727
2184
|
opencode: OPENCODE_DEFAULT_MODEL,
|
|
2728
2185
|
copilot: COPILOT_DEFAULT_MODEL,
|
|
2729
|
-
google: GEMINI_DEFAULT_MODEL
|
|
2730
|
-
hosted: ""
|
|
2186
|
+
google: GEMINI_DEFAULT_MODEL
|
|
2731
2187
|
};
|
|
2732
2188
|
var AUTO_MODEL_SENTINEL = "auto";
|
|
2733
2189
|
function detectProvider(configApiKey, preferredModel, env2, configProvider) {
|
|
@@ -2748,11 +2204,11 @@ function detectProvider(configApiKey, preferredModel, env2, configProvider) {
|
|
|
2748
2204
|
throw new Error(`${source} is unsupported: ${pinnedProviderRaw}`);
|
|
2749
2205
|
}
|
|
2750
2206
|
const provider = pinnedProviderRaw;
|
|
2751
|
-
const model = preferredModel ?? env2["ZERO_MODEL"] ?? (configProvider !== void 0
|
|
2752
|
-
if (model === void 0 || model === ""
|
|
2207
|
+
const model = preferredModel ?? env2["ZERO_MODEL"] ?? (configProvider !== void 0 ? DEFAULT_PROVIDER_MODELS[provider] : void 0);
|
|
2208
|
+
if (model === void 0 || model === "") {
|
|
2753
2209
|
throw new Error(`${source} requires an explicit model`);
|
|
2754
2210
|
}
|
|
2755
|
-
if (configApiKey &&
|
|
2211
|
+
if (configApiKey && provider === "chatgpt-codex") {
|
|
2756
2212
|
throw new Error(`${source}=${provider} requires its own authentication, not RuntimeConfig.apiKey`);
|
|
2757
2213
|
}
|
|
2758
2214
|
const resolved = resolveFailoverProvider(provider, model, env2, configApiKey);
|
|
@@ -2906,21 +2362,6 @@ function detectProvider(configApiKey, preferredModel, env2, configProvider) {
|
|
|
2906
2362
|
default:
|
|
2907
2363
|
break;
|
|
2908
2364
|
}
|
|
2909
|
-
try {
|
|
2910
|
-
const hostedCreds = loadCloudCredentials({
|
|
2911
|
-
env: env2,
|
|
2912
|
-
warn: () => {
|
|
2913
|
-
}
|
|
2914
|
-
});
|
|
2915
|
-
return {
|
|
2916
|
-
provider: "hosted",
|
|
2917
|
-
apiKey: hostedCreds.token,
|
|
2918
|
-
baseUrl: `${hostedCreds.host}/api/inference/v1`,
|
|
2919
|
-
defaultModel: "",
|
|
2920
|
-
wireApi: "chat_completions"
|
|
2921
|
-
};
|
|
2922
|
-
} catch {
|
|
2923
|
-
}
|
|
2924
2365
|
const chatGptAccess = env2["ZERO_CHATGPT_ACCESS_TOKEN"];
|
|
2925
2366
|
const chatGptRefresh = env2["ZERO_CHATGPT_OAUTH_REFRESH_TOKEN"];
|
|
2926
2367
|
const chatGptAuthFile = !chatGptAccess && !chatGptRefresh ? readChatGptCodexAuthFile(env2) : void 0;
|
|
@@ -3084,6 +2525,9 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3084
2525
|
apiKey;
|
|
3085
2526
|
baseUrl;
|
|
3086
2527
|
model;
|
|
2528
|
+
pricingModelSource = "";
|
|
2529
|
+
pricingProviderSource;
|
|
2530
|
+
pricingModelKey = "";
|
|
3087
2531
|
wireApi;
|
|
3088
2532
|
reasoningEffort;
|
|
3089
2533
|
azureConfig;
|
|
@@ -3092,19 +2536,12 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3092
2536
|
fallbackChain;
|
|
3093
2537
|
/** Index into fallbackChain — which entry to try next. */
|
|
3094
2538
|
fallbackIndex;
|
|
3095
|
-
/** Resolve and validate the hosted model and wire protocol once per runtime. */
|
|
3096
|
-
hostedCatalogPromise = null;
|
|
3097
|
-
/** Catalog ceiling, resolved before hosted inference is submitted. */
|
|
3098
|
-
hostedMaxOutputTokens;
|
|
3099
2539
|
constructor(config, inherited) {
|
|
3100
2540
|
if (inherited) {
|
|
3101
2541
|
const timeout = config.timeout ?? inherited.config.timeout ?? 12e4;
|
|
3102
2542
|
if (!Number.isFinite(timeout) || timeout <= 0) {
|
|
3103
2543
|
throw new Error("Subagent timeout must be a positive finite number");
|
|
3104
2544
|
}
|
|
3105
|
-
if (inherited.provider === "hosted" && inherited.hostedMaxOutputTokens === void 0) {
|
|
3106
|
-
throw new Error("Hosted model catalog must resolve before creating a subagent");
|
|
3107
|
-
}
|
|
3108
2545
|
const model = config.model ?? inherited.model;
|
|
3109
2546
|
const modelChanged = model !== inherited.model;
|
|
3110
2547
|
this.config = {
|
|
@@ -3138,10 +2575,6 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3138
2575
|
this.geminiAuthState = inherited.geminiAuthState;
|
|
3139
2576
|
this.fallbackChain = [];
|
|
3140
2577
|
this.fallbackIndex = 0;
|
|
3141
|
-
if (!modelChanged) {
|
|
3142
|
-
this.hostedMaxOutputTokens = inherited.hostedMaxOutputTokens;
|
|
3143
|
-
this.hostedCatalogPromise = inherited.hostedCatalogPromise;
|
|
3144
|
-
}
|
|
3145
2578
|
return;
|
|
3146
2579
|
}
|
|
3147
2580
|
this.applyConfiguration(config);
|
|
@@ -3201,66 +2634,59 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3201
2634
|
});
|
|
3202
2635
|
}
|
|
3203
2636
|
}
|
|
2637
|
+
/** Non-secret identity for preferences scoped to the captured connection. */
|
|
2638
|
+
connectionIdentity() {
|
|
2639
|
+
let identity;
|
|
2640
|
+
if (this.provider === "chatgpt-codex") {
|
|
2641
|
+
const state = this.codexAuthState;
|
|
2642
|
+
if (!state)
|
|
2643
|
+
return void 0;
|
|
2644
|
+
if (state.accountId) {
|
|
2645
|
+
identity = [this.provider, "account", state.accountId];
|
|
2646
|
+
} else {
|
|
2647
|
+
const credential = state.refreshToken || state.accessToken;
|
|
2648
|
+
if (!credential)
|
|
2649
|
+
return void 0;
|
|
2650
|
+
identity = [this.provider, "credential", credential];
|
|
2651
|
+
}
|
|
2652
|
+
} else if (this.provider === "google") {
|
|
2653
|
+
const credential = this.geminiAuthState?.refreshToken || this.geminiAuthState?.accessToken;
|
|
2654
|
+
if (!credential)
|
|
2655
|
+
return void 0;
|
|
2656
|
+
identity = [this.provider, this.baseUrl, credential, firstNonEmptyEnv(this.env, "GOOGLE_CLOUD_PROJECT", "ZERO_GEMINI_PROJECT") ?? ""];
|
|
2657
|
+
} else {
|
|
2658
|
+
if (!this.apiKey)
|
|
2659
|
+
return void 0;
|
|
2660
|
+
identity = [this.provider, this.baseUrl, this.apiKey];
|
|
2661
|
+
}
|
|
2662
|
+
return createHash("sha256").update(JSON.stringify(identity)).digest("hex");
|
|
2663
|
+
}
|
|
3204
2664
|
/** Discover models using this runtime's captured account, including after a separate login changes. */
|
|
3205
2665
|
async codexModelCatalog(signal) {
|
|
3206
2666
|
const state = this.codexAuthState;
|
|
3207
2667
|
if (this.provider !== "chatgpt-codex" || !state)
|
|
3208
2668
|
throw new Error("No active Codex subscription");
|
|
3209
|
-
const { loadCodexModelCatalog } = await import("./codex-models-
|
|
2669
|
+
const { loadCodexModelCatalog } = await import("./codex-models-NHQW45SO.js");
|
|
3210
2670
|
return loadCodexModelCatalog({ signal, resolveCredentials: () => refreshChatGptCodexAuthState(state) });
|
|
3211
2671
|
}
|
|
3212
|
-
/** Check account admission and resolve the service model without inference.
|
|
3213
|
-
* Each explicit check refreshes admission; failed discovery is never cached.
|
|
3214
|
-
*/
|
|
3215
|
-
async prepare() {
|
|
3216
|
-
while (this.provider === "hosted") {
|
|
3217
|
-
const config = this.config;
|
|
3218
|
-
const client = new CloudClient({
|
|
3219
|
-
host: this.baseUrl.replace(/\/api\/inference\/v1$/, ""),
|
|
3220
|
-
token: this.apiKey
|
|
3221
|
-
});
|
|
3222
|
-
try {
|
|
3223
|
-
const account = await client.getInferenceAccount();
|
|
3224
|
-
if (this.config !== config)
|
|
3225
|
-
continue;
|
|
3226
|
-
if (!account) {
|
|
3227
|
-
throw new CloudError("0cloud account availability could not be read. Check again or review your account in /connect.", void 0, "/api/inference/account", "unsupported_account_data");
|
|
3228
|
-
}
|
|
3229
|
-
if (!account.admission.eligible) {
|
|
3230
|
-
const reason = account.admission.reason ?? account.reason ?? "account_restricted";
|
|
3231
|
-
throw new CloudError(account.state === "unavailable" ? `0cloud account availability could not be checked (${reason}). Check again or review your account in /connect.` : `0cloud account access is restricted (${reason}). Review your account in /connect or contact your organization owner.`, void 0, "/api/inference/account", reason);
|
|
3232
|
-
}
|
|
3233
|
-
await this.ensureHostedModel();
|
|
3234
|
-
if (this.config === config)
|
|
3235
|
-
return;
|
|
3236
|
-
} catch (error) {
|
|
3237
|
-
if (this.config !== config)
|
|
3238
|
-
continue;
|
|
3239
|
-
throw error;
|
|
3240
|
-
}
|
|
3241
|
-
}
|
|
3242
|
-
}
|
|
3243
2672
|
/**
|
|
3244
2673
|
* Mutate the live selection in place so the NEXT turn (the engine reads
|
|
3245
2674
|
* `config.runtime` per turn) and the NEXT `forkForSubagent` pick up the new
|
|
3246
|
-
* model / provider / role map with zero session teardown.
|
|
3247
|
-
*
|
|
2675
|
+
* model / provider / role map with zero session teardown. Undefined fields
|
|
2676
|
+
* preserve the current state, except a provider change resets an omitted model.
|
|
3248
2677
|
*/
|
|
3249
2678
|
reconfigure(sel) {
|
|
3250
2679
|
const providerChanged = sel.provider !== void 0 && sel.provider !== this.provider;
|
|
3251
|
-
if (providerChanged
|
|
2680
|
+
if (providerChanged) {
|
|
3252
2681
|
const merged = {
|
|
3253
2682
|
...this.config,
|
|
3254
|
-
...providerChanged && sel.provider === "hosted" && sel.model === void 0 ? { model: "" } : {},
|
|
3255
2683
|
apiKey: void 0,
|
|
3256
2684
|
provider: sel.provider ?? this.provider,
|
|
3257
|
-
|
|
2685
|
+
model: sel.model,
|
|
3258
2686
|
...sel.agentModels !== void 0 ? { agentModels: sel.agentModels } : {},
|
|
3259
2687
|
...sel.singleModel !== void 0 ? { singleModel: sel.singleModel } : {},
|
|
3260
2688
|
...sel.env !== void 0 ? { env: sel.env } : {}
|
|
3261
2689
|
};
|
|
3262
|
-
this.hostedCatalogPromise = null;
|
|
3263
|
-
this.hostedMaxOutputTokens = void 0;
|
|
3264
2690
|
this.applyConfiguration(merged);
|
|
3265
2691
|
return;
|
|
3266
2692
|
}
|
|
@@ -3283,15 +2709,13 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3283
2709
|
this.wireApi = openAICompatibleWireApi(this.env, "AZURE_OPENAI_WIRE_API", this.azureConfig.wireApi);
|
|
3284
2710
|
this.applyModelWireApi();
|
|
3285
2711
|
this.reasoningEffort = void 0;
|
|
3286
|
-
this.hostedCatalogPromise = null;
|
|
3287
|
-
this.hostedMaxOutputTokens = void 0;
|
|
3288
2712
|
}
|
|
3289
2713
|
}
|
|
3290
2714
|
}
|
|
3291
|
-
/**
|
|
2715
|
+
/** Modern OpenAI tool calls use Responses, shared by roots and forks. */
|
|
3292
2716
|
applyModelWireApi() {
|
|
3293
2717
|
const normalizedModel = this.model.toLowerCase();
|
|
3294
|
-
if (this.wireApi === "chat_completions" && (this.provider === "azure" && normalizedModel === "gpt-5.6-sol" || this.provider === "openai" && normalizedModel === "gpt-5.6-luna")) {
|
|
2718
|
+
if (this.wireApi === "chat_completions" && (this.provider === "azure" && normalizedModel === "gpt-5.6-sol" || this.provider === "openai" && (normalizedModel === "gpt-5.6-luna" || /^gpt-(?:[6-9]|\d{2,})(?:[-.]|$)/.test(normalizedModel)))) {
|
|
3295
2719
|
this.wireApi = "responses";
|
|
3296
2720
|
}
|
|
3297
2721
|
}
|
|
@@ -3300,18 +2724,14 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3300
2724
|
* Providers whose credentials are present in THIS runtime's environment
|
|
3301
2725
|
* (`this.env`, never process-global). A provider counts as accessible iff
|
|
3302
2726
|
* `resolveFailoverProvider` — the same auth-presence check the cross-provider
|
|
3303
|
-
* failover chain uses —
|
|
3304
|
-
* (chatgpt-codex OAuth) and cloud-hosted are covered by the identical rule.
|
|
2727
|
+
* failover chain uses — including auth-only providers (chatgpt-codex OAuth).
|
|
3305
2728
|
*/
|
|
3306
2729
|
accessibleProviders() {
|
|
3307
2730
|
const out = [];
|
|
3308
2731
|
for (const provider of Object.keys(DEFAULT_PROVIDER_MODELS)) {
|
|
3309
2732
|
const probeModel = DEFAULT_PROVIDER_MODELS[provider] || "probe";
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
out.push(provider);
|
|
3313
|
-
} catch {
|
|
3314
|
-
}
|
|
2733
|
+
if (resolveFailoverProvider(provider, probeModel, this.env))
|
|
2734
|
+
out.push(provider);
|
|
3315
2735
|
}
|
|
3316
2736
|
return out;
|
|
3317
2737
|
}
|
|
@@ -3348,7 +2768,6 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3348
2768
|
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {
|
|
3349
2769
|
throw new Error("Subagent timeout must be a positive finite number");
|
|
3350
2770
|
}
|
|
3351
|
-
await this.ensureHostedModel();
|
|
3352
2771
|
const roleModel = selection?.role !== void 0 && this.config.agentModels && Object.hasOwn(this.config.agentModels, selection.role) ? this.config.agentModels[selection.role] : void 0;
|
|
3353
2772
|
const autoInEffect = roleModel === AUTO_MODEL_SENTINEL || this.config.autoRoute === true && roleModel === void 0;
|
|
3354
2773
|
const configuredModel = roleModel === AUTO_MODEL_SENTINEL ? void 0 : roleModel;
|
|
@@ -3364,70 +2783,15 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3364
2783
|
throw new Error(autoInEffect ? `Subagent model "${selectedModel}" is not reachable: its provider has no configured credentials.` : `Subagent model "${selectedModel}" is not operator-approved. Configure agentModels before selecting it.`);
|
|
3365
2784
|
}
|
|
3366
2785
|
const child = new _LlmApiRuntime({ type: "api", timeout: timeoutMs, model }, this);
|
|
3367
|
-
await child.ensureHostedModel();
|
|
3368
2786
|
return child;
|
|
3369
2787
|
}
|
|
3370
|
-
/** The server catalog is authoritative even when a model was selected explicitly. */
|
|
3371
|
-
async ensureHostedModel() {
|
|
3372
|
-
while (this.provider === "hosted") {
|
|
3373
|
-
let pending = this.hostedCatalogPromise;
|
|
3374
|
-
if (!pending) {
|
|
3375
|
-
const requestedModel = this.model;
|
|
3376
|
-
const client = new CloudClient({
|
|
3377
|
-
host: this.baseUrl.replace(/\/api\/inference\/v1$/, ""),
|
|
3378
|
-
token: this.apiKey
|
|
3379
|
-
});
|
|
3380
|
-
const request = client.getInferenceModels().then((catalog) => {
|
|
3381
|
-
if (this.hostedCatalogPromise !== request)
|
|
3382
|
-
return;
|
|
3383
|
-
const selected = requestedModel ? catalog.data.find((model) => model.id === requestedModel) : catalog.data[0];
|
|
3384
|
-
if (!selected) {
|
|
3385
|
-
throw new Error(requestedModel ? `Hosted model "${requestedModel}" is unavailable. Run \`0 models\` for available models.` : "No hosted models are available. Run `0 models` to check service availability.");
|
|
3386
|
-
}
|
|
3387
|
-
this.model = selected.id;
|
|
3388
|
-
this.wireApi = selected.wire_api;
|
|
3389
|
-
this.hostedMaxOutputTokens = selected.max_output_tokens;
|
|
3390
|
-
});
|
|
3391
|
-
this.hostedCatalogPromise = pending = request;
|
|
3392
|
-
}
|
|
3393
|
-
try {
|
|
3394
|
-
await pending;
|
|
3395
|
-
} catch (error) {
|
|
3396
|
-
if (this.hostedCatalogPromise !== pending)
|
|
3397
|
-
continue;
|
|
3398
|
-
this.hostedCatalogPromise = null;
|
|
3399
|
-
throw error;
|
|
3400
|
-
}
|
|
3401
|
-
if (this.hostedCatalogPromise === pending)
|
|
3402
|
-
return;
|
|
3403
|
-
}
|
|
3404
|
-
}
|
|
3405
|
-
/** All audits and nested workers on this hosted credential share admission. */
|
|
3406
|
-
async acquireHostedSlot(signal) {
|
|
3407
|
-
while (this.provider === "hosted") {
|
|
3408
|
-
const config = this.config;
|
|
3409
|
-
const release = await acquireHostedRequestSlot(this.baseUrl, this.apiKey, signal);
|
|
3410
|
-
if (this.config === config)
|
|
3411
|
-
return release;
|
|
3412
|
-
release();
|
|
3413
|
-
await this.ensureHostedModel();
|
|
3414
|
-
}
|
|
3415
|
-
return void 0;
|
|
3416
|
-
}
|
|
3417
2788
|
/**
|
|
3418
2789
|
* A hard dollar ceiling needs a provider-enforced bound on the next response.
|
|
3419
2790
|
* ChatGPT Codex OAuth rejects `max_output_tokens`, so it cannot support that
|
|
3420
2791
|
* contract; callers must fail closed before making a metered comparison call.
|
|
3421
2792
|
*/
|
|
3422
2793
|
get outputTokenLimit() {
|
|
3423
|
-
return this.provider === "chatgpt-codex" ? void 0 :
|
|
3424
|
-
}
|
|
3425
|
-
/** Hosted requests honor both the catalog ceiling and the local hard cap. */
|
|
3426
|
-
get effectiveOutputTokens() {
|
|
3427
|
-
if (this.provider === "hosted" && this.hostedMaxOutputTokens !== void 0) {
|
|
3428
|
-
return Math.min(NATIVE_COMPLETION_TOKEN_LIMIT, this.hostedMaxOutputTokens);
|
|
3429
|
-
}
|
|
3430
|
-
return NATIVE_COMPLETION_TOKEN_LIMIT;
|
|
2794
|
+
return this.provider === "chatgpt-codex" ? void 0 : NATIVE_COMPLETION_TOKEN_LIMIT;
|
|
3431
2795
|
}
|
|
3432
2796
|
/**
|
|
3433
2797
|
* Whether this provider uses OpenAI-compatible chat/completions format.
|
|
@@ -3439,7 +2803,7 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3439
2803
|
* inert default — it is intentionally unused for these two providers.
|
|
3440
2804
|
*/
|
|
3441
2805
|
get isOpenAICompat() {
|
|
3442
|
-
return this.provider === "openrouter" || this.provider === "openai" || this.provider === "azure" || this.provider === "deepseek" || this.provider === "qwen" || this.provider === "xai" || this.provider === "copilot" || this.provider === "
|
|
2806
|
+
return this.provider === "openrouter" || this.provider === "openai" || this.provider === "azure" || this.provider === "deepseek" || this.provider === "qwen" || this.provider === "xai" || this.provider === "copilot" || this.provider === "opencode" && (this.wireApi === "chat_completions" || this.wireApi === "responses") || // chatgpt-codex always speaks Responses API; treat it as
|
|
3443
2807
|
// OpenAI-compat for body-shape branching purposes (the Responses
|
|
3444
2808
|
// wire-API code paths below already key on `wireApi === "responses"`
|
|
3445
2809
|
// and produce a body codex's backend accepts as-is).
|
|
@@ -3485,12 +2849,24 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3485
2849
|
resolvedModel() {
|
|
3486
2850
|
return this.model;
|
|
3487
2851
|
}
|
|
2852
|
+
/** Price discovered IDs on their actual route without changing the wire model. */
|
|
2853
|
+
resolvedPricingModel() {
|
|
2854
|
+
if (this.provider === "chatgpt-codex" || this.provider === "copilot" || this.provider === "google")
|
|
2855
|
+
return this.model;
|
|
2856
|
+
if (this.pricingModelSource !== this.model || this.pricingProviderSource !== this.provider) {
|
|
2857
|
+
this.pricingModelSource = this.model;
|
|
2858
|
+
this.pricingProviderSource = this.provider;
|
|
2859
|
+
this.pricingModelKey = `${this.provider}/${this.model}`;
|
|
2860
|
+
}
|
|
2861
|
+
return this.pricingModelKey;
|
|
2862
|
+
}
|
|
3488
2863
|
/** Build the appropriate headers for the configured provider. */
|
|
3489
2864
|
buildHeaders() {
|
|
3490
2865
|
if (this.provider === "chatgpt-codex") {
|
|
3491
2866
|
return {
|
|
3492
2867
|
"Content-Type": "application/json",
|
|
3493
|
-
|
|
2868
|
+
...CODEX_PROTOCOL_HEADERS,
|
|
2869
|
+
"x-codex-routing-hint": `model=${this.model}`,
|
|
3494
2870
|
"User-Agent": `0/${VERSION}`
|
|
3495
2871
|
};
|
|
3496
2872
|
}
|
|
@@ -3753,12 +3129,10 @@ var LlmApiRuntime = class _LlmApiRuntime {
|
|
|
3753
3129
|
return "GitHub Copilot";
|
|
3754
3130
|
case "google":
|
|
3755
3131
|
return "Google Gemini (Code Assist)";
|
|
3756
|
-
case "hosted":
|
|
3757
|
-
return "0.security Cloud";
|
|
3758
3132
|
}
|
|
3759
3133
|
}
|
|
3760
3134
|
noKeyError() {
|
|
3761
|
-
return "No provider credential found. Set one of:\n env ZERO_CHATGPT_OAUTH_REFRESH_TOKEN=... 0 <command> (ChatGPT Codex subscription auth)\n export OPENROUTER_API_KEY=sk-or-... (OpenRouter \u2014 many models, one key)\n export DEEPSEEK_API_KEY=... (DeepSeek \u2014 direct Flash 0731 inference)\n export ANTHROPIC_API_KEY=sk-ant-... (Anthropic \u2014 direct Claude access)\n export AZURE_OPENAI_API_KEY=... (Azure OpenAI \u2014 reuse your Codex Azure provider)\n export OPENAI_API_KEY=sk-... (OpenAI \u2014 direct GPT access)\n export Z_AI_API_KEY=... (Z.ai GLM \u2014 flat-rate Coding Plan, Anthropic-compatible)\n export KIMI_API_KEY=... (Moonshot Kimi K3 \u2014 flat-rate coding, Anthropic-compatible)\n export QWEN_API_KEY=... (Alibaba Qwen \u2014 Token Plan sub, OpenAI-compatible)\n export XAI_API_KEY=... (xAI Grok \u2014 OpenAI-compatible)\n export OPENCODE_API_KEY=... (OpenCode Zen \u2014 multi-wire gateway)\n export ZERO_COPILOT_GITHUB_TOKEN=... (GitHub Copilot \u2014 device-code OAuth token)
|
|
3135
|
+
return "No provider credential found. Set one of:\n env ZERO_CHATGPT_OAUTH_REFRESH_TOKEN=... 0 <command> (ChatGPT Codex subscription auth)\n export OPENROUTER_API_KEY=sk-or-... (OpenRouter \u2014 many models, one key)\n export DEEPSEEK_API_KEY=... (DeepSeek \u2014 direct Flash 0731 inference)\n export ANTHROPIC_API_KEY=sk-ant-... (Anthropic \u2014 direct Claude access)\n export AZURE_OPENAI_API_KEY=... (Azure OpenAI \u2014 reuse your Codex Azure provider)\n export OPENAI_API_KEY=sk-... (OpenAI \u2014 direct GPT access)\n export Z_AI_API_KEY=... (Z.ai GLM \u2014 flat-rate Coding Plan, Anthropic-compatible)\n export KIMI_API_KEY=... (Moonshot Kimi K3 \u2014 flat-rate coding, Anthropic-compatible)\n export QWEN_API_KEY=... (Alibaba Qwen \u2014 Token Plan sub, OpenAI-compatible)\n export XAI_API_KEY=... (xAI Grok \u2014 OpenAI-compatible)\n export OPENCODE_API_KEY=... (OpenCode Zen \u2014 multi-wire gateway)\n export ZERO_COPILOT_GITHUB_TOKEN=... (GitHub Copilot \u2014 device-code OAuth token)";
|
|
3762
3136
|
}
|
|
3763
3137
|
getConfigurationDiagnostics() {
|
|
3764
3138
|
if (!this.apiKey && this.provider !== "chatgpt-codex") {
|
|
@@ -3851,7 +3225,6 @@ Missing: ${missing.join("; ")}
|
|
|
3851
3225
|
this.apiKey = cfg.apiKey;
|
|
3852
3226
|
this.baseUrl = cfg.baseUrl;
|
|
3853
3227
|
this.wireApi = cfg.wireApi;
|
|
3854
|
-
this.hostedCatalogPromise = null;
|
|
3855
3228
|
diag.warn("failover_engaged", `${reason} \u2014 failover to ${entry.provider} (${entry.model})`, { reason, provider: entry.provider, model: entry.model });
|
|
3856
3229
|
return true;
|
|
3857
3230
|
}
|
|
@@ -3865,9 +3238,8 @@ Missing: ${missing.join("; ")}
|
|
|
3865
3238
|
* hammering the limit in lockstep).
|
|
3866
3239
|
*
|
|
3867
3240
|
* The body factory is valid only for the current provider and wire protocol.
|
|
3868
|
-
* A null result signals failover
|
|
3869
|
-
*
|
|
3870
|
-
*
|
|
3241
|
+
* A null result signals failover so the caller rebuilds the complete request
|
|
3242
|
+
* under its existing timeout/cancellation signal.
|
|
3871
3243
|
* Retry + failover caps documented on `retryBackoffMs` / `llm429MaxRetries`.
|
|
3872
3244
|
*
|
|
3873
3245
|
* Headers are re-resolved per attempt (via ensureFreshHeaders → OAuth
|
|
@@ -3888,9 +3260,6 @@ Missing: ${missing.join("; ")}
|
|
|
3888
3260
|
});
|
|
3889
3261
|
} catch (error) {
|
|
3890
3262
|
abort?.throwIfCancelled();
|
|
3891
|
-
if (this.provider === "hosted") {
|
|
3892
|
-
throw new Error("0 hosted request outcome is unknown. Automatic replay is disabled; check your inference usage before retrying.", { cause: error });
|
|
3893
|
-
}
|
|
3894
3263
|
const cause = error instanceof Error ? error.cause : void 0;
|
|
3895
3264
|
const causeCode = cause && typeof cause === "object" && "code" in cause && typeof cause.code === "string" ? cause.code : "unknown";
|
|
3896
3265
|
const causeHost = cause && typeof cause === "object" && "hostname" in cause && typeof cause.hostname === "string" ? `@${cause.hostname}` : "";
|
|
@@ -3917,13 +3286,6 @@ Missing: ${missing.join("; ")}
|
|
|
3917
3286
|
if (res.ok || !isRetryableHttpStatus(res.status)) {
|
|
3918
3287
|
return res;
|
|
3919
3288
|
}
|
|
3920
|
-
if (this.provider === "hosted" && res.status === 429 && res.headers.get("x-0-retry-safe") !== "1") {
|
|
3921
|
-
return res;
|
|
3922
|
-
}
|
|
3923
|
-
if (this.provider === "hosted" && res.status >= 500) {
|
|
3924
|
-
await res.body?.cancel();
|
|
3925
|
-
throw new Error(`0 hosted request returned HTTP ${res.status}; its outcome may be unknown. Automatic replay is disabled; check your inference usage before retrying.`);
|
|
3926
|
-
}
|
|
3927
3289
|
abort?.throwIfCancelled();
|
|
3928
3290
|
const is429 = res.status === 429;
|
|
3929
3291
|
let bodyText;
|
|
@@ -4014,7 +3376,6 @@ Missing: ${missing.join("; ")}
|
|
|
4014
3376
|
}
|
|
4015
3377
|
// ── Legacy Runtime interface (single-prompt) ──
|
|
4016
3378
|
async execute(prompt, context) {
|
|
4017
|
-
await this.ensureHostedModel();
|
|
4018
3379
|
const start = Date.now();
|
|
4019
3380
|
if (!this.apiKey && this.provider !== "chatgpt-codex" && this.provider !== "google") {
|
|
4020
3381
|
return {
|
|
@@ -4026,15 +3387,11 @@ Missing: ${missing.join("; ")}
|
|
|
4026
3387
|
};
|
|
4027
3388
|
}
|
|
4028
3389
|
const systemPrompt = context?.systemPrompt ?? "";
|
|
4029
|
-
let releaseHostedSlot = this.provider === "hosted" ? await this.acquireHostedSlot() : void 0;
|
|
4030
3390
|
const controller = new AbortController();
|
|
4031
3391
|
const timer = setTimeout(() => controller.abort(), this.config.timeout || 12e4);
|
|
4032
3392
|
try {
|
|
4033
3393
|
let res;
|
|
4034
3394
|
do {
|
|
4035
|
-
if (this.provider === "hosted" && !releaseHostedSlot) {
|
|
4036
|
-
releaseHostedSlot = await this.acquireHostedSlot(controller.signal);
|
|
4037
|
-
}
|
|
4038
3395
|
if (this.isOpenAICompat && this.wireApi === "chat_completions") {
|
|
4039
3396
|
const messages = [];
|
|
4040
3397
|
if (systemPrompt) {
|
|
@@ -4043,7 +3400,7 @@ Missing: ${missing.join("; ")}
|
|
|
4043
3400
|
messages.push({ role: "user", content: prompt });
|
|
4044
3401
|
res = await this.postWithRetry(() => JSON.stringify({
|
|
4045
3402
|
model: this.model,
|
|
4046
|
-
[this.maxTokensParamKey]:
|
|
3403
|
+
[this.maxTokensParamKey]: NATIVE_COMPLETION_TOKEN_LIMIT,
|
|
4047
3404
|
messages,
|
|
4048
3405
|
// See executeNative: explicit reasoning_effort passthrough only.
|
|
4049
3406
|
...this.reasoningEffort ? { reasoning_effort: this.reasoningEffort } : {}
|
|
@@ -4064,7 +3421,7 @@ Missing: ${missing.join("; ")}
|
|
|
4064
3421
|
res = await this.postWithRetry(() => JSON.stringify({
|
|
4065
3422
|
model: this.model,
|
|
4066
3423
|
input,
|
|
4067
|
-
...isCodex ? { store: false } : { max_output_tokens:
|
|
3424
|
+
...isCodex ? { store: false } : { max_output_tokens: NATIVE_COMPLETION_TOKEN_LIMIT }
|
|
4068
3425
|
}), controller.signal);
|
|
4069
3426
|
} else if (this.isGeminiCodeAssist) {
|
|
4070
3427
|
const request = {
|
|
@@ -4091,8 +3448,6 @@ Missing: ${missing.join("; ")}
|
|
|
4091
3448
|
} else {
|
|
4092
3449
|
throw new Error(`execute: provider ${this.provider} is not mapped to a wire`);
|
|
4093
3450
|
}
|
|
4094
|
-
if (!res)
|
|
4095
|
-
await this.ensureHostedModel();
|
|
4096
3451
|
} while (!res);
|
|
4097
3452
|
clearTimeout(timer);
|
|
4098
3453
|
const body = await res.text();
|
|
@@ -4162,8 +3517,6 @@ Missing: ${missing.join("; ")}
|
|
|
4162
3517
|
durationMs: Date.now() - start,
|
|
4163
3518
|
error: timedOut ? `${this.providerLabel} API request timed out` : `${this.providerLabel} API error: ${msg}`
|
|
4164
3519
|
};
|
|
4165
|
-
} finally {
|
|
4166
|
-
releaseHostedSlot?.();
|
|
4167
3520
|
}
|
|
4168
3521
|
}
|
|
4169
3522
|
// ── Native Runtime interface (structured messages + tool_use) ──
|
|
@@ -4177,14 +3530,7 @@ Missing: ${missing.join("; ")}
|
|
|
4177
3530
|
error: `${this.providerLabel} request cancelled by operator`
|
|
4178
3531
|
};
|
|
4179
3532
|
}
|
|
4180
|
-
/**
|
|
4181
|
-
* Public entry point. Runs {@link executeNativeAttempt} and, ONLY for a
|
|
4182
|
-
* transient empty stream (see {@link shouldRetryNativeStream}), re-issues the
|
|
4183
|
-
* whole request up to {@link llmStreamMaxAttempts} times with a short backoff.
|
|
4184
|
-
* Every other outcome — success, a real API error, a timeout, an operator
|
|
4185
|
-
* cancellation — is returned from the first attempt untouched, preserving the
|
|
4186
|
-
* existing behaviour exactly.
|
|
4187
|
-
*/
|
|
3533
|
+
/** Public entry point. Retries a transient empty stream with bounded backoff. */
|
|
4188
3534
|
async executeNative(system, messages, tools, callbacks, signal) {
|
|
4189
3535
|
const maxAttempts = llmStreamMaxAttempts();
|
|
4190
3536
|
let result;
|
|
@@ -4205,7 +3551,6 @@ Missing: ${missing.join("; ")}
|
|
|
4205
3551
|
return result;
|
|
4206
3552
|
}
|
|
4207
3553
|
async executeNativeAttempt(system, messages, tools, callbacks, signal) {
|
|
4208
|
-
await this.ensureHostedModel();
|
|
4209
3554
|
const start = Date.now();
|
|
4210
3555
|
if (!this.apiKey && this.provider !== "chatgpt-codex" && this.provider !== "google") {
|
|
4211
3556
|
return {
|
|
@@ -4217,25 +3562,12 @@ Missing: ${missing.join("; ")}
|
|
|
4217
3562
|
}
|
|
4218
3563
|
if (signal?.aborted)
|
|
4219
3564
|
return this.cancelledResult(start);
|
|
4220
|
-
let releaseHostedSlot;
|
|
4221
|
-
if (this.provider === "hosted") {
|
|
4222
|
-
try {
|
|
4223
|
-
releaseHostedSlot = await this.acquireHostedSlot(signal);
|
|
4224
|
-
} catch (error) {
|
|
4225
|
-
if (signal?.aborted)
|
|
4226
|
-
return this.cancelledResult(start);
|
|
4227
|
-
throw error;
|
|
4228
|
-
}
|
|
4229
|
-
}
|
|
4230
3565
|
const controller = new AbortController();
|
|
4231
3566
|
const timer = setTimeout(() => controller.abort(), this.config.timeout || 12e4);
|
|
4232
3567
|
const call = composeCallAbort(controller.signal, signal);
|
|
4233
3568
|
try {
|
|
4234
3569
|
let res;
|
|
4235
3570
|
do {
|
|
4236
|
-
if (this.provider === "hosted" && !releaseHostedSlot) {
|
|
4237
|
-
releaseHostedSlot = await this.acquireHostedSlot(call.signal);
|
|
4238
|
-
}
|
|
4239
3571
|
if (this.isOpenAICompat && this.wireApi === "chat_completions") {
|
|
4240
3572
|
const chatMessages = [];
|
|
4241
3573
|
chatMessages.push({ role: "system", content: system });
|
|
@@ -4283,7 +3615,7 @@ Missing: ${missing.join("; ")}
|
|
|
4283
3615
|
}
|
|
4284
3616
|
const body = {
|
|
4285
3617
|
model: this.model,
|
|
4286
|
-
[this.maxTokensParamKey]:
|
|
3618
|
+
[this.maxTokensParamKey]: NATIVE_COMPLETION_TOKEN_LIMIT,
|
|
4287
3619
|
messages: chatMessages
|
|
4288
3620
|
};
|
|
4289
3621
|
if (this.reasoningEffort) {
|
|
@@ -4351,7 +3683,7 @@ Missing: ${missing.join("; ")}
|
|
|
4351
3683
|
const body = {
|
|
4352
3684
|
model: this.model,
|
|
4353
3685
|
input,
|
|
4354
|
-
...isCodex ? { store: false, instructions: system } : { max_output_tokens:
|
|
3686
|
+
...isCodex ? { store: false, instructions: system } : { max_output_tokens: NATIVE_COMPLETION_TOKEN_LIMIT },
|
|
4355
3687
|
...reasoningEffort ? {
|
|
4356
3688
|
reasoning: {
|
|
4357
3689
|
effort: reasoningEffort,
|
|
@@ -4410,10 +3742,8 @@ Missing: ${missing.join("; ")}
|
|
|
4410
3742
|
}
|
|
4411
3743
|
}
|
|
4412
3744
|
res = await this.postWithRetry(() => JSON.stringify({ ...body, stream: true, model: this.model }), call.signal, call);
|
|
4413
|
-
if (!res)
|
|
4414
|
-
await this.ensureHostedModel();
|
|
3745
|
+
if (!res)
|
|
4415
3746
|
continue;
|
|
4416
|
-
}
|
|
4417
3747
|
if (!res.ok) {
|
|
4418
3748
|
const responseText2 = await res.text();
|
|
4419
3749
|
clearTimeout(timer);
|
|
@@ -4522,8 +3852,6 @@ Missing: ${missing.join("; ")}
|
|
|
4522
3852
|
} else {
|
|
4523
3853
|
throw new Error(`executeNative: provider ${this.provider} is not mapped to a wire`);
|
|
4524
3854
|
}
|
|
4525
|
-
if (!res)
|
|
4526
|
-
await this.ensureHostedModel();
|
|
4527
3855
|
} while (!res);
|
|
4528
3856
|
const responseText = await res.text();
|
|
4529
3857
|
clearTimeout(timer);
|
|
@@ -4734,7 +4062,6 @@ Missing: ${missing.join("; ")}
|
|
|
4734
4062
|
error: timedOut ? `${this.providerLabel} API request timed out` : `${this.providerLabel} API error: ${msg}`
|
|
4735
4063
|
};
|
|
4736
4064
|
} finally {
|
|
4737
|
-
releaseHostedSlot?.();
|
|
4738
4065
|
call.dispose();
|
|
4739
4066
|
}
|
|
4740
4067
|
}
|
|
@@ -5083,18 +4410,11 @@ export {
|
|
|
5083
4410
|
isDiagnosticsClaimed,
|
|
5084
4411
|
recentDiagnostics,
|
|
5085
4412
|
_resetDiagnosticsForTests,
|
|
5086
|
-
DEFAULT_CLOUD_HOST,
|
|
5087
|
-
CloudAuthMissingError,
|
|
5088
|
-
CloudAuthError,
|
|
5089
|
-
loadCloudCredentials,
|
|
5090
|
-
CloudError,
|
|
5091
|
-
CloudUnauthorizedError,
|
|
5092
|
-
CloudForbiddenError,
|
|
5093
|
-
CloudNetworkError,
|
|
5094
|
-
CloudClient,
|
|
5095
4413
|
QuotaExhaustedError,
|
|
5096
4414
|
OperatorAbortError,
|
|
5097
4415
|
parseUsageLimitReached,
|
|
4416
|
+
CODEX_CLIENT_VERSION,
|
|
4417
|
+
CODEX_PROTOCOL_HEADERS,
|
|
5098
4418
|
LOOP_SERVER_COMPACTION_TOKENS,
|
|
5099
4419
|
getChatGptCodexAccessToken,
|
|
5100
4420
|
LlmApiRuntime
|