0sec-cli 0.22.4 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/0.js +73 -68
- package/README.md +95 -61
- package/chunks/{adapt-loop-3CCOWE43.js → adapt-loop-TEJPXWFG.js} +4 -4
- package/chunks/{artifact-scraper-Z4UUIOH3.js → artifact-scraper-AJZ3LOQY.js} +2 -2
- package/chunks/{assumption-mining-2UAKQB6V.js → assumption-mining-EATDC4BB.js} +18 -18
- package/chunks/backend-connections-QE4NASAK.js +23 -0
- package/chunks/chunk-3XLEDCFX.js +566 -0
- package/chunks/{chunk-BGX53365.js → chunk-3XLFB46W.js} +5 -3
- package/chunks/{chunk-IXAHQICR.js → chunk-4TUR47H5.js} +8 -3
- package/chunks/{chunk-5WAJGLCW.js → chunk-4YRXIVPZ.js} +3 -3
- package/chunks/{chunk-4ZYYX5GY.js → chunk-52AWIBCT.js} +1 -1
- package/chunks/{chunk-TO35Y326.js → chunk-554D4AYM.js} +5 -2
- package/chunks/{chunk-GQ3DGHWE.js → chunk-5FHFG5P2.js} +174 -710
- package/chunks/chunk-5POT5OYF.js +733 -0
- package/chunks/chunk-62PGWN7Y.js +700 -0
- package/chunks/{chunk-H6Q2QAIY.js → chunk-A3EKBUEM.js} +1424 -859
- package/chunks/{chunk-6WQDXWQC.js → chunk-A6AZZ6XX.js} +2 -2
- package/chunks/{chunk-6YZE552K.js → chunk-AV5BF4V7.js} +1281 -2580
- package/chunks/{chunk-2WWAPKAW.js → chunk-BIJPMYFA.js} +6 -6
- package/chunks/{chunk-SCWWLABR.js → chunk-CIMN2AO6.js} +1 -1
- package/chunks/{chunk-H4DH7COV.js → chunk-CSPF47S3.js} +30 -20
- package/chunks/{chunk-RCRTSKQN.js → chunk-DNV3ZMPX.js} +1 -1
- package/chunks/{chunk-GVY3S5E5.js → chunk-E42XEJTK.js} +2 -2
- package/chunks/{chunk-VDOWARMJ.js → chunk-ESM447R6.js} +15 -1
- package/chunks/{chunk-WBRGXCU2.js → chunk-EXTN4SQV.js} +1 -1
- package/chunks/{chunk-QVIRWJ45.js → chunk-EYBMTELO.js} +108 -24
- package/chunks/chunk-FEOPHBMY.js +56 -0
- package/chunks/{chunk-IHPTOTLL.js → chunk-FKGFHLLS.js} +1 -1
- package/chunks/chunk-G2EJ3R5I.js +5198 -0
- package/chunks/chunk-GHEBZKUS.js +5417 -0
- package/chunks/chunk-GNR3APR6.js +295 -0
- package/chunks/{chunk-ELI3BVIK.js → chunk-H76JYUPE.js} +3 -3
- package/chunks/{chunk-E74LXQFY.js → chunk-HRBOZBMC.js} +1 -1
- package/chunks/{chunk-TM74SSHC.js → chunk-IIBNQTOK.js} +3 -2
- package/chunks/{chunk-UELXHK2Y.js → chunk-IK27KMVV.js} +16 -5
- package/chunks/{chunk-WHUAUFSX.js → chunk-J6G73WYF.js} +1 -1
- package/chunks/chunk-JSTLXPJS.js +284 -0
- package/chunks/{chunk-G2BE2FC7.js → chunk-O3ADFN2A.js} +1 -1
- package/chunks/chunk-O7Q2G2KW.js +117 -0
- package/chunks/{chunk-XODDLNBI.js → chunk-QEA2VHBD.js} +284 -33
- package/chunks/{chunk-C6JPA32H.js → chunk-RBOMXUYL.js} +3 -111
- package/chunks/{chunk-L2CCO4KE.js → chunk-RCHAFSWS.js} +838 -39
- package/chunks/{chunk-3BPX75OR.js → chunk-RD4FKFWR.js} +1 -1
- package/chunks/{chunk-DPUXXMJW.js → chunk-RPTO5FY2.js} +1 -1
- package/chunks/{chunk-6KFB6AYN.js → chunk-RZR2XXAK.js} +531 -17
- package/chunks/chunk-SGILXLR3.js +289 -0
- package/chunks/{chunk-E3OOBVOK.js → chunk-TOAAYJVN.js} +2 -2
- package/chunks/chunk-TOFIGQ63.js +83 -0
- package/chunks/{chunk-QWK4R3DB.js → chunk-TTDFBFNZ.js} +6 -6
- package/chunks/chunk-TZRHWP7R.js +736 -0
- package/chunks/chunk-UHUW45S3.js +164 -0
- package/chunks/{chunk-5JNTMWPK.js → chunk-V4BD7GSP.js} +2 -2
- package/chunks/{chunk-OAS5SAVZ.js → chunk-V5I5GAQH.js} +3226 -1683
- package/chunks/{chunk-PS5E7LUQ.js → chunk-W6IYTSZH.js} +79 -9
- package/chunks/{chunk-RTBZ36BD.js → chunk-WUPN3D37.js} +22 -248
- package/chunks/{chunk-CF3MNS3O.js → chunk-Y7KV7WV6.js} +2 -2
- package/chunks/{chunk-2OQOQ2FZ.js → chunk-YERUDEXT.js} +763 -688
- package/chunks/{chunk-CPCHLL6A.js → chunk-YJU7QACE.js} +1 -1
- package/chunks/{chunk-YED25PA4.js → chunk-YORL5S5V.js} +1 -1
- package/chunks/{chunk-YAZARMJY.js → chunk-YYOQADBB.js} +4 -3
- package/chunks/chunk-ZPFBQ3SD.js +127 -0
- package/chunks/{codex-models-Z43V3427.js → codex-models-FQPCWRPC.js} +7 -7
- package/chunks/{commands-EUGF4FUZ.js → commands-I5L3VD2A.js} +6187 -12196
- package/chunks/dashboard-B2AEGCFM.js +76 -0
- package/chunks/{db-NVAW4WWR.js → db-P5EIKMLP.js} +3 -3
- package/chunks/deep-review-I7RD5QSS.js +82 -0
- package/chunks/{disclose-LDNKAVRH.js → disclose-PFBWESVJ.js} +4 -2
- package/chunks/{dist-7RUOKPRJ.js → dist-3SWWY5FZ.js} +18 -2
- package/chunks/{dist-27BNG6WD.js → dist-AJU25UXA.js} +112 -63
- package/chunks/{dist-NG2HT5XU.js → dist-VK2M4HNW.js} +85 -1
- package/chunks/eval-runner-XVRX3R2Y.js +31 -0
- package/chunks/{exploit-agent-FCCR2HYX.js → exploit-agent-A4RTIJ4J.js} +1 -1
- package/chunks/{exploit-autoclimb-X5ZS5FAO.js → exploit-autoclimb-ABMMBC3M.js} +1 -1
- package/chunks/{exploit-climb-3JHGEO36.js → exploit-climb-BQ2SVU63.js} +2 -2
- package/chunks/{fix-NSNPU33B.js → fix-4YCLHFDT.js} +7 -7
- package/chunks/{harness-KXQOVIDQ.js → harness-DHWULEIZ.js} +3 -3
- package/chunks/{hunt-scan-ELTKGKC4.js → hunt-scan-DXV5H6YN.js} +16 -16
- package/chunks/{kernel-primitive-MT7YZSIG.js → kernel-primitive-SF4NALVR.js} +2 -2
- package/chunks/{kernel-vm-runner-YFRHYC6G.js → kernel-vm-runner-WEBEZEIC.js} +2 -2
- package/chunks/local-engine-XUG7XRKM.js +21 -0
- package/chunks/managed-operation-SQFMBWHG.js +60 -0
- package/chunks/{memsafety-scan-FCPAXIZE.js → memsafety-scan-L2Z7E7TE.js} +2 -2
- package/chunks/{native-loop-OFJDRHPI.js → native-loop-ZNAELJGB.js} +14 -13
- package/chunks/orchestrate-YHFJXGID.js +63 -0
- package/chunks/{prepare-72GWTRVI.js → prepare-SODWQN6O.js} +5 -5
- package/chunks/provider-model-discovery-QGUGL3XW.js +277 -0
- package/chunks/remote-workflow-runtime-XNNGI2PG.js +12 -0
- package/chunks/{run-WTJCZZHV.js → run-5T4Z3Q2D.js} +924 -327
- package/chunks/{runtime-LCJ4XSKE.js → runtime-HFFRUOPL.js} +4 -2
- package/chunks/{runtime-FCKOUB7V.js → runtime-MB4GEFBY.js} +7 -7
- package/chunks/{scan-stream-GT6GKQ3U.js → scan-stream-GXBJHCDF.js} +3 -2
- package/chunks/{scope-E5QZUOOH.js → scope-M7L3CD6X.js} +2 -2
- package/chunks/service-plugins-BGS6QKSZ.js +64 -0
- package/chunks/{session-store-H3Q7KCYG.js → session-store-K7I4GLNH.js} +2 -2
- package/chunks/{variant-candidates-SZKDCOLK.js → variant-candidates-2KSP5EHH.js} +7 -7
- package/chunks/{web-recon-prepass-IO3GXQMW.js → web-recon-prepass-RAXXTEWH.js} +5 -5
- package/chunks/workflow-runtime-V26HIJO3.js +178 -0
- package/dashboard/assets/abnfDiagram-VCTEODGH-CGCueOp5.js +1 -0
- package/dashboard/assets/arc-BjZaQcCc.js +1 -0
- package/dashboard/assets/architecture-7GRP2DOG-hcbO-9zX.js +1 -0
- package/dashboard/assets/architectureDiagram-5GKGNRK7-DReOXTSq.js +36 -0
- package/dashboard/assets/array-BifhSqXX.js +1 -0
- package/dashboard/assets/blockDiagram-I7D4REHJ-C-byT12_.js +129 -0
- package/dashboard/assets/c4Diagram-7LVT6UL2-DoYjz-Uv.js +38 -0
- package/dashboard/assets/channel-CUURBnpZ.js +1 -0
- package/dashboard/assets/chunk-2Q5K7J3B-C1jixKkw.js +1 -0
- package/dashboard/assets/chunk-4HAMMTFA-NBNp2zdt.js +62 -0
- package/dashboard/assets/chunk-5VM5RSS4-ZNzvKenW.js +15 -0
- package/dashboard/assets/chunk-75Z2AOVW-BHmkuP0B.js +2 -0
- package/dashboard/assets/chunk-DU6HZSFF-DgfLNaL2.js +127 -0
- package/dashboard/assets/chunk-F27PBJKO-3wwNFUgZ.js +1 -0
- package/dashboard/assets/chunk-FOHPRMQF-DHwB1DNv.js +161 -0
- package/dashboard/assets/chunk-GMAD6QVW-Btg7huZW.js +72 -0
- package/dashboard/assets/chunk-GVQU2GXP-ihCURK5O.js +1 -0
- package/dashboard/assets/chunk-IMKFNOWR-FsXj7slg.js +231 -0
- package/dashboard/assets/chunk-JWPE2WC7-DVXcaiue.js +1 -0
- package/dashboard/assets/chunk-L3NEJ4N5-DorFIxJY.js +1 -0
- package/dashboard/assets/chunk-OSK3NFVY-DKun_KfC.js +10 -0
- package/dashboard/assets/chunk-P2QGCYS3-XGgiU1Bz.js +1 -0
- package/dashboard/assets/chunk-POPQ4Y6H-BTXEnGhJ.js +1 -0
- package/dashboard/assets/chunk-PWAF6VOD-DYZcGkTL.js +1 -0
- package/dashboard/assets/chunk-SHT3W25Y-C4WQfwf8.js +168 -0
- package/dashboard/assets/chunk-SVP7TREG-C4nCh0-1.js +88 -0
- package/dashboard/assets/chunk-TICWLB2K-DSB-IiGc.js +206 -0
- package/dashboard/assets/chunk-XXDRQBXY-CS6fjUcj.js +1 -0
- package/dashboard/assets/chunk-Y2CYZVJY-DsF7k-Jl.js +1 -0
- package/dashboard/assets/classDiagram-ZZMXUADV-CD1Buc26.js +1 -0
- package/dashboard/assets/classDiagram-v2-VYDZK3BY-CD1Buc26.js +1 -0
- package/dashboard/assets/common-BMdQBwfR.js +5 -0
- package/dashboard/assets/cose-bilkent-JH36ORCC-CUjQHTML.js +1 -0
- package/dashboard/assets/cynefin-OW5HDTMX-BC7zCtFq.js +1 -0
- package/dashboard/assets/cynefinDiagram-5FMLGOSQ-CgDOOY67.js +62 -0
- package/dashboard/assets/cytoscape.esm-CGd-uY3x.js +321 -0
- package/dashboard/assets/dagre-GXQ25YYZ-Dqc8FS9x.js +4 -0
- package/dashboard/assets/dagre-PrKaheQc.js +1 -0
- package/dashboard/assets/defaultLocale-BFoDCU3G.js +1 -0
- package/dashboard/assets/diagram-S7CK7UJ4-CrKqRXZb.js +30 -0
- package/dashboard/assets/diagram-UQ7AKVKN-Cu6Es0-v.js +41 -0
- package/dashboard/assets/diagram-VSXAHHWV-eK4d8FwS.js +3 -0
- package/dashboard/assets/diagram-VX7I27RA-bFxeFKOc.js +24 -0
- package/dashboard/assets/diagram-Z3DM3KII-C0ClmnhC.js +24 -0
- package/dashboard/assets/dist-BZh8Kb3O.js +1 -0
- package/dashboard/assets/ebnfDiagram-PWID7BFC-CUqxFPzf.js +1 -0
- package/dashboard/assets/erDiagram-RLTQ6QDP-CcYM7pLi.js +99 -0
- package/dashboard/assets/eventmodeling-NTZA5JFV-D8ZNnPkV.js +1 -0
- package/dashboard/assets/flowDiagram-HODETNUW-pDb1AYm8.js +1 -0
- package/dashboard/assets/ganttDiagram-EL5Y4UJY-UmZfbMyD.js +292 -0
- package/dashboard/assets/gitGraph-4MIJSDKK-mvNUo0ZA.js +1 -0
- package/dashboard/assets/gitGraphDiagram-WWUBYQGX-CvzeCxVy.js +106 -0
- package/dashboard/assets/graphlib-DS17s2tU.js +1 -0
- package/dashboard/assets/info-A6RAGUB7-DChKqZMi.js +1 -0
- package/dashboard/assets/infoDiagram-27XIBGKW-DjkpNtVW.js +2 -0
- package/dashboard/assets/init-C-OQMol4.js +1 -0
- package/dashboard/assets/ishikawaDiagram-5VMMS53U-8FhjJaWT.js +70 -0
- package/dashboard/assets/journeyDiagram-3NMN7TZE-DyNJ755f.js +139 -0
- package/dashboard/assets/kanban-definition-UXKFOSKX-_jCmtaY1.js +89 -0
- package/dashboard/assets/katex-BdBmVSus.js +257 -0
- package/dashboard/assets/line-Bf0nxyWf.js +1 -0
- package/dashboard/assets/linear-Bl6JKbf4.js +1 -0
- package/dashboard/assets/mermaid-parser.core-Cc6sgCzs.js +7 -0
- package/dashboard/assets/mermaid.core-B4yCwiN-.js +44 -0
- package/dashboard/assets/mindmap-definition-YA3MSWOX-D5DjWyXj.js +96 -0
- package/dashboard/assets/operations-B7JAWOi6.js +130 -0
- package/dashboard/assets/operations-QjKT0Hwi.css +1 -0
- package/dashboard/assets/ordinal-BDEzSJ7C.js +1 -0
- package/dashboard/assets/packet-AYTQ26CC-bQXLDhQC.js +1 -0
- package/dashboard/assets/path-fybaL0A-.js +1 -0
- package/dashboard/assets/pegDiagram-XKGWAZYB-Bf6a1vaf.js +1 -0
- package/dashboard/assets/pie-WAS4IAKB-DfzoABIi.js +1 -0
- package/dashboard/assets/pieDiagram-E7YTZNPT-D0L1qbch.js +39 -0
- package/dashboard/assets/quadrantDiagram-AXDQQJYC-CbFyy2Pe.js +7 -0
- package/dashboard/assets/radar-RG4KPBEZ-CZ2pyeUT.js +1 -0
- package/dashboard/assets/railroad-74A4TZTK-CP4Jazfd.js +1 -0
- package/dashboard/assets/railroad-abnf-HS5TGJTU-3MvEiHwD.js +1 -0
- package/dashboard/assets/railroad-ebnf-LZEXJU2U-BWto6cXE.js +1 -0
- package/dashboard/assets/railroad-peg-WCYAUIDC-DasEjbyf.js +1 -0
- package/dashboard/assets/railroadDiagram-O6MQD6OU-t7Gp9g2R.js +1 -0
- package/dashboard/assets/requirementDiagram-BXWQKSXE-LYmqeBXi.js +84 -0
- package/dashboard/assets/rough.esm-Dy-Kn_BL.js +1 -0
- package/dashboard/assets/sankeyDiagram-P5KCCOFB-DnpfA_94.js +40 -0
- package/dashboard/assets/sequenceDiagram-WJ2MYXX4-C8s3pTUE.js +162 -0
- package/dashboard/assets/sizeCapture-INFHLROL-B0uUizjq.js +1 -0
- package/dashboard/assets/src-CaNUT1AQ.js +1 -0
- package/dashboard/assets/stateDiagram-D77RDMKH-BMzm6fK1.js +1 -0
- package/dashboard/assets/stateDiagram-v2-MP3YSRHH-B3REMjpY.js +1 -0
- package/dashboard/assets/swimlanes-42K2YHIH-uJE05Tt_.js +1 -0
- package/dashboard/assets/swimlanesDiagram-VR7AAH4N-CIaVMZEy.js +8 -0
- package/dashboard/assets/timeline-definition-24CTP7MA-BfLJMVeG.js +120 -0
- package/dashboard/assets/treeView-Q6P3EWNA-ZOE2enu2.js +1 -0
- package/dashboard/assets/treemap-WGGIJYW6-yIZoPBF5.js +1 -0
- package/dashboard/assets/vennDiagram-4TSXK5OY-BYJRHEaL.js +34 -0
- package/dashboard/assets/wardley-WFR3VGLG-D5V-jLbB.js +1 -0
- package/dashboard/assets/wardleyDiagram-VM6X3IG4-DgPN4nSe.js +78 -0
- package/dashboard/assets/xychartDiagram-S5SC5T6Z-BhkAMAOT.js +7 -0
- package/dashboard/index.html +3 -3
- package/package.json +3 -2
- package/worker-assets/demo-target/README.md +15 -0
- package/worker-assets/demo-target/include/decoder.h +27 -0
- package/worker-assets/demo-target/patched-decoder.c +40 -0
- package/worker-assets/demo-target/src/decoder.c +50 -0
- package/worker-assets/demo-target/witness-65537x1.bin +0 -0
- package/chunks/chunk-FFHRANYC.js +0 -547
- package/chunks/eval-runner-6Q3H52SP.js +0 -30
- package/chunks/orchestrate-DRZ2SVCP.js +0 -62
- package/chunks/service-plugins-MSK2EQP6.js +0 -62
- package/dashboard/assets/operations-BvB5Qpmk.css +0 -1
- package/dashboard/assets/operations-D8Ii01SV.js +0 -114
- package/dashboard/assets/zero-peek-Dzm3MT3X.png +0 -0
|
@@ -0,0 +1,700 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createRequire as __0CreateRequire } from "node:module";
|
|
3
|
+
const require = __0CreateRequire(import.meta.url);
|
|
4
|
+
import {
|
|
5
|
+
PROVIDERS,
|
|
6
|
+
SETTING_DEFS,
|
|
7
|
+
isOperatorSetting,
|
|
8
|
+
loadGlobalSettings,
|
|
9
|
+
loadLayeredSettings,
|
|
10
|
+
normalizeSettings,
|
|
11
|
+
projectSettingsExist,
|
|
12
|
+
providerSupportsMethod,
|
|
13
|
+
readProjectOverrides,
|
|
14
|
+
resolveLayeredSettings,
|
|
15
|
+
saveProjectOverrides,
|
|
16
|
+
saveSettings
|
|
17
|
+
} from "./chunk-QEA2VHBD.js";
|
|
18
|
+
import {
|
|
19
|
+
expandHomePath,
|
|
20
|
+
isExistingLocalTargetPath,
|
|
21
|
+
isExplicitLocalTargetPath
|
|
22
|
+
} from "./chunk-E42XEJTK.js";
|
|
23
|
+
import {
|
|
24
|
+
ANALYTICS_LEVEL_ENV,
|
|
25
|
+
analyticsOptedOut,
|
|
26
|
+
analyticsPipeline,
|
|
27
|
+
levelAtLeast,
|
|
28
|
+
resolveAnalyticsLevel
|
|
29
|
+
} from "./chunk-BIJPMYFA.js";
|
|
30
|
+
import {
|
|
31
|
+
homeStateDir
|
|
32
|
+
} from "./chunk-RZR2XXAK.js";
|
|
33
|
+
|
|
34
|
+
// packages/cli/src/tui/settings-store.ts
|
|
35
|
+
import { useSyncExternalStore } from "react";
|
|
36
|
+
var cached = null;
|
|
37
|
+
var globalDraft = null;
|
|
38
|
+
var projectDraft = null;
|
|
39
|
+
var homeDir;
|
|
40
|
+
var projectDir;
|
|
41
|
+
var subscribers = /* @__PURE__ */ new Set();
|
|
42
|
+
function notify(settings) {
|
|
43
|
+
bridgeAnalyticsLevel(settings);
|
|
44
|
+
for (const fn of [...subscribers]) {
|
|
45
|
+
try {
|
|
46
|
+
fn(settings);
|
|
47
|
+
} catch {
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
function loadLayered() {
|
|
52
|
+
return globalDraft === null && projectDraft === null ? loadLayeredSettings({ homeDir, projectDir }) : resolveLayeredSettings(globalDraft ?? loadGlobalSettings(homeDir), projectDraft ?? readProjectOverrides(projectDir));
|
|
53
|
+
}
|
|
54
|
+
function getSettings() {
|
|
55
|
+
if (cached === null) {
|
|
56
|
+
cached = loadLayered();
|
|
57
|
+
bridgeAnalyticsLevel(cached.settings);
|
|
58
|
+
}
|
|
59
|
+
return cached.settings;
|
|
60
|
+
}
|
|
61
|
+
function getSettingSources() {
|
|
62
|
+
getSettings();
|
|
63
|
+
return cached.sources;
|
|
64
|
+
}
|
|
65
|
+
function getAnalyticsSetupDraft() {
|
|
66
|
+
const settings = getSettings();
|
|
67
|
+
const current = process.env[ANALYTICS_LEVEL_ENV];
|
|
68
|
+
const shellPreference = current !== void 0 && current !== bridgedAnalyticsEnv;
|
|
69
|
+
if (analyticsOptedOut() || shellPreference && resolveAnalyticsLevel() === "off") return "off";
|
|
70
|
+
return cached.sources.analyticsLevel === "default" ? "usage" : settings.analyticsLevel;
|
|
71
|
+
}
|
|
72
|
+
function setSettings(next) {
|
|
73
|
+
const value = normalizeSettings(next);
|
|
74
|
+
const saved = saveSettings(value, homeDir);
|
|
75
|
+
globalDraft = saved ? null : value;
|
|
76
|
+
cached = loadLayered();
|
|
77
|
+
notify(cached.settings);
|
|
78
|
+
return saved;
|
|
79
|
+
}
|
|
80
|
+
function defaultWriteLayer() {
|
|
81
|
+
return projectSettingsExist(projectDir) ? "project" : "global";
|
|
82
|
+
}
|
|
83
|
+
function updateSetting(key, value, opts = {}) {
|
|
84
|
+
const operatorOnly = isOperatorSetting(key);
|
|
85
|
+
if (operatorOnly && opts.scope === "project") return false;
|
|
86
|
+
const layer = operatorOnly ? "global" : opts.scope ?? defaultWriteLayer();
|
|
87
|
+
if (layer === "global") {
|
|
88
|
+
return setSettings({ ...globalDraft ?? loadGlobalSettings(homeDir), [key]: value });
|
|
89
|
+
}
|
|
90
|
+
const patch = { ...projectDraft ?? readProjectOverrides(projectDir), [key]: value };
|
|
91
|
+
const saved = saveProjectOverrides(patch, projectDir);
|
|
92
|
+
projectDraft = saved ? null : patch;
|
|
93
|
+
cached = loadLayered();
|
|
94
|
+
notify(cached.settings);
|
|
95
|
+
return saved;
|
|
96
|
+
}
|
|
97
|
+
function resetSettings(next, keys) {
|
|
98
|
+
const selected = keys.filter((key) => SETTING_DEFS.some((def) => def.key === key));
|
|
99
|
+
if (selected.length === 0) return true;
|
|
100
|
+
const global = { ...globalDraft ?? loadGlobalSettings(homeDir) };
|
|
101
|
+
const project = { ...projectDraft ?? readProjectOverrides(projectDir) };
|
|
102
|
+
let projectChanged = false;
|
|
103
|
+
for (const key of selected) {
|
|
104
|
+
global[key] = next[key];
|
|
105
|
+
if (Object.hasOwn(project, key)) {
|
|
106
|
+
delete project[key];
|
|
107
|
+
projectChanged = true;
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
const value = normalizeSettings(global);
|
|
111
|
+
const globalSaved = saveSettings(value, homeDir);
|
|
112
|
+
globalDraft = globalSaved ? null : value;
|
|
113
|
+
const projectSaved = !projectChanged || saveProjectOverrides(project, projectDir);
|
|
114
|
+
if (projectChanged) projectDraft = projectSaved ? null : project;
|
|
115
|
+
cached = loadLayered();
|
|
116
|
+
notify(cached.settings);
|
|
117
|
+
return globalSaved && projectSaved;
|
|
118
|
+
}
|
|
119
|
+
function previewSetting(key, value) {
|
|
120
|
+
if (cached === null) cached = loadLayered();
|
|
121
|
+
cached = { settings: { ...cached.settings, [key]: value }, sources: cached.sources };
|
|
122
|
+
notify(cached.settings);
|
|
123
|
+
}
|
|
124
|
+
function subscribeSettings(fn) {
|
|
125
|
+
subscribers.add(fn);
|
|
126
|
+
return () => {
|
|
127
|
+
subscribers.delete(fn);
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
var bridgedAnalyticsEnv;
|
|
131
|
+
function bridgeAnalyticsLevel(settings) {
|
|
132
|
+
try {
|
|
133
|
+
const current = process.env[ANALYTICS_LEVEL_ENV];
|
|
134
|
+
if (current === void 0 || current === bridgedAnalyticsEnv) {
|
|
135
|
+
process.env[ANALYTICS_LEVEL_ENV] = settings.analyticsLevel;
|
|
136
|
+
bridgedAnalyticsEnv = settings.analyticsLevel;
|
|
137
|
+
} else {
|
|
138
|
+
bridgedAnalyticsEnv = void 0;
|
|
139
|
+
}
|
|
140
|
+
const environmentLevel = resolveAnalyticsLevel();
|
|
141
|
+
analyticsPipeline.setLevel(levelAtLeast(environmentLevel, settings.analyticsLevel) ? settings.analyticsLevel : environmentLevel);
|
|
142
|
+
} catch {
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
function reloadSettings() {
|
|
146
|
+
globalDraft = null;
|
|
147
|
+
projectDraft = null;
|
|
148
|
+
cached = loadLayered();
|
|
149
|
+
notify(cached.settings);
|
|
150
|
+
return cached.settings;
|
|
151
|
+
}
|
|
152
|
+
function configureSettingsStore(options) {
|
|
153
|
+
homeDir = options.homeDir;
|
|
154
|
+
projectDir = options.projectDir;
|
|
155
|
+
reloadSettings();
|
|
156
|
+
}
|
|
157
|
+
function useSettings() {
|
|
158
|
+
return useSyncExternalStore(subscribeSettings, getSettings, getSettings);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// packages/cli/src/codex-auth.ts
|
|
162
|
+
import { readFileSync, existsSync } from "node:fs";
|
|
163
|
+
import { homedir } from "node:os";
|
|
164
|
+
import { join } from "node:path";
|
|
165
|
+
var AUTH_FILE_ENV = "ZERO_CHATGPT_AUTH_FILE";
|
|
166
|
+
var LEGACY_AUTH_FILE_ENV = "ZERO_CODEX_AUTH_JSON_PATH";
|
|
167
|
+
function maybeLoadCodexAuth(options = {}) {
|
|
168
|
+
const env = options.env ?? process.env;
|
|
169
|
+
if (!options.force && (env["ZERO_CHATGPT_ACCESS_TOKEN"] || env["ZERO_CHATGPT_OAUTH_REFRESH_TOKEN"])) {
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
const home = options.home ?? homedir();
|
|
173
|
+
const override = nonEmpty(env[AUTH_FILE_ENV]) ?? nonEmpty(env[LEGACY_AUTH_FILE_ENV]);
|
|
174
|
+
const path = override ?? join(home, ".codex", "auth.json");
|
|
175
|
+
if (!existsSync(path)) return;
|
|
176
|
+
try {
|
|
177
|
+
const raw = JSON.parse(readFileSync(path, "utf8"));
|
|
178
|
+
const accessToken = nonEmpty(asString(raw.tokens?.access_token));
|
|
179
|
+
const refreshToken = nonEmpty(asString(raw.tokens?.refresh_token));
|
|
180
|
+
if (!accessToken && !refreshToken) return;
|
|
181
|
+
if (options.force) {
|
|
182
|
+
delete env["ZERO_CHATGPT_ACCESS_TOKEN"];
|
|
183
|
+
delete env["ZERO_CHATGPT_OAUTH_REFRESH_TOKEN"];
|
|
184
|
+
}
|
|
185
|
+
if (accessToken) {
|
|
186
|
+
env["ZERO_CHATGPT_ACCESS_TOKEN"] = accessToken;
|
|
187
|
+
}
|
|
188
|
+
if (refreshToken) {
|
|
189
|
+
env["ZERO_CHATGPT_OAUTH_REFRESH_TOKEN"] = refreshToken;
|
|
190
|
+
}
|
|
191
|
+
} catch {
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
function nonEmpty(value) {
|
|
195
|
+
return typeof value === "string" && value.length > 0 ? value : void 0;
|
|
196
|
+
}
|
|
197
|
+
function asString(value) {
|
|
198
|
+
return typeof value === "string" ? value : void 0;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// packages/cli/src/engagement-plan.ts
|
|
202
|
+
var PACKAGE_PREFIXES = {
|
|
203
|
+
"npm:": { ecosystem: "npm", targetType: "npm-package" },
|
|
204
|
+
"pypi:": { ecosystem: "pypi", targetType: "pypi-package" },
|
|
205
|
+
"cargo:": { ecosystem: "cargo", targetType: "cargo-package" },
|
|
206
|
+
"oci:": { ecosystem: "oci", targetType: "oci-image" }
|
|
207
|
+
};
|
|
208
|
+
function resolveEngagement(rawTarget) {
|
|
209
|
+
const raw = rawTarget.trim();
|
|
210
|
+
if (raw.length === 0) return { ok: false, message: "Enter a URL, source path, git URL, or ecosystem-prefixed package." };
|
|
211
|
+
for (const [prefix, packagePlan] of Object.entries(PACKAGE_PREFIXES)) {
|
|
212
|
+
if (!raw.startsWith(prefix)) continue;
|
|
213
|
+
const target = raw.slice(prefix.length).trim();
|
|
214
|
+
if (target.length === 0) return { ok: false, message: `${prefix} requires a package name.` };
|
|
215
|
+
return {
|
|
216
|
+
ok: true,
|
|
217
|
+
plan: {
|
|
218
|
+
kind: "package",
|
|
219
|
+
target,
|
|
220
|
+
targetType: packagePlan.targetType,
|
|
221
|
+
ecosystem: packagePlan.ecosystem,
|
|
222
|
+
label: `${packagePlan.ecosystem} package ${target}`
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
if (raw.startsWith("source:")) {
|
|
227
|
+
const target = raw.slice("source:".length).trim();
|
|
228
|
+
if (target.length === 0) return { ok: false, message: "source: requires a local path or git URL." };
|
|
229
|
+
return {
|
|
230
|
+
ok: true,
|
|
231
|
+
plan: {
|
|
232
|
+
kind: "source",
|
|
233
|
+
target: expandHomePath(target),
|
|
234
|
+
targetType: "source-code",
|
|
235
|
+
label: `source review ${target}`
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
if (raw.startsWith("git@") || raw.startsWith("git://") || raw.endsWith(".git") || raw.startsWith("https://github.com/")) {
|
|
240
|
+
return {
|
|
241
|
+
ok: true,
|
|
242
|
+
plan: {
|
|
243
|
+
kind: "source",
|
|
244
|
+
target: raw,
|
|
245
|
+
targetType: "source-code",
|
|
246
|
+
label: `source review ${raw}`
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
if (raw.startsWith("mcp://") || raw.startsWith("http://") || raw.startsWith("https://")) {
|
|
251
|
+
return {
|
|
252
|
+
ok: true,
|
|
253
|
+
plan: {
|
|
254
|
+
kind: "web",
|
|
255
|
+
target: raw,
|
|
256
|
+
targetType: "url",
|
|
257
|
+
label: `web target ${raw}`
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
}
|
|
261
|
+
if (isExplicitLocalTargetPath(raw) || isExistingLocalTargetPath(raw)) {
|
|
262
|
+
const target = expandHomePath(raw);
|
|
263
|
+
return {
|
|
264
|
+
ok: true,
|
|
265
|
+
plan: {
|
|
266
|
+
kind: "source",
|
|
267
|
+
target,
|
|
268
|
+
targetType: "source-code",
|
|
269
|
+
label: `source review ${target}`
|
|
270
|
+
}
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
ok: false,
|
|
275
|
+
message: "Ambiguous target. Use https://\u2026, ./path, source:\u2026, npm:\u2026, pypi:\u2026, cargo:\u2026, or oci:\u2026."
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// packages/cli/src/tui/credential-store.ts
|
|
280
|
+
import { chmodSync, mkdirSync, readFileSync as readFileSync2, writeFileSync } from "node:fs";
|
|
281
|
+
import { dirname, join as join2 } from "node:path";
|
|
282
|
+
var CREDENTIALS_FILENAME = "credentials.json";
|
|
283
|
+
var FILE_MODE = 384;
|
|
284
|
+
var DIR_MODE = 448;
|
|
285
|
+
function credentialsFilePath(homeDir2) {
|
|
286
|
+
return join2(homeStateDir(homeDir2), CREDENTIALS_FILENAME);
|
|
287
|
+
}
|
|
288
|
+
var STORABLE_PROVIDER_IDS = new Set(
|
|
289
|
+
PROVIDERS.filter((provider) => provider.methods.includes("api-key")).map((provider) => provider.id)
|
|
290
|
+
);
|
|
291
|
+
function hasCredential(value) {
|
|
292
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
293
|
+
}
|
|
294
|
+
function normalizeCredentials(raw) {
|
|
295
|
+
const out = {};
|
|
296
|
+
if (typeof raw !== "object" || raw === null || Array.isArray(raw)) return out;
|
|
297
|
+
for (const [providerId, value] of Object.entries(raw)) {
|
|
298
|
+
if (!STORABLE_PROVIDER_IDS.has(providerId)) continue;
|
|
299
|
+
if (typeof value !== "string") continue;
|
|
300
|
+
const secret = value.trim();
|
|
301
|
+
if (secret.length === 0) continue;
|
|
302
|
+
out[providerId] = secret;
|
|
303
|
+
}
|
|
304
|
+
return out;
|
|
305
|
+
}
|
|
306
|
+
function loadCredentials(homeDir2) {
|
|
307
|
+
return projectApiKeys(loadAccountStore(homeDir2));
|
|
308
|
+
}
|
|
309
|
+
function saveCredentials(creds, homeDir2) {
|
|
310
|
+
const store = loadAccountStore(homeDir2);
|
|
311
|
+
const desired = normalizeCredentials(creds);
|
|
312
|
+
return saveAccountStore(replaceApiKeyLayer(store, desired), homeDir2);
|
|
313
|
+
}
|
|
314
|
+
function projectApiKeys(store) {
|
|
315
|
+
const out = {};
|
|
316
|
+
for (const providerId of Object.keys(store.providers)) {
|
|
317
|
+
const record = getActiveAccount(store, providerId);
|
|
318
|
+
if (record?.kind === "api_key") out[providerId] = record.secret;
|
|
319
|
+
}
|
|
320
|
+
return out;
|
|
321
|
+
}
|
|
322
|
+
function replaceApiKeyLayer(store, desired) {
|
|
323
|
+
const providers = {};
|
|
324
|
+
for (const [providerId, entry] of Object.entries(store.providers)) {
|
|
325
|
+
const kept = {};
|
|
326
|
+
for (const [accountId, record] of Object.entries(entry.accounts)) {
|
|
327
|
+
if (record.kind !== "api_key") kept[accountId] = record;
|
|
328
|
+
}
|
|
329
|
+
const keptIds = Object.keys(kept);
|
|
330
|
+
if (keptIds.length === 0) continue;
|
|
331
|
+
const active = entry.activeAccountId !== void 0 && kept[entry.activeAccountId] !== void 0 ? entry.activeAccountId : keptIds[0];
|
|
332
|
+
providers[providerId] = { activeAccountId: active, accounts: kept };
|
|
333
|
+
}
|
|
334
|
+
for (const [providerId, secret] of Object.entries(desired)) {
|
|
335
|
+
const existing = providers[providerId];
|
|
336
|
+
const accounts = existing ? { ...existing.accounts } : {};
|
|
337
|
+
accounts[DEFAULT_ACCOUNT_ID] = { kind: "api_key", secret };
|
|
338
|
+
providers[providerId] = { activeAccountId: DEFAULT_ACCOUNT_ID, accounts };
|
|
339
|
+
}
|
|
340
|
+
return { version: STORE_VERSION, providers };
|
|
341
|
+
}
|
|
342
|
+
function credentialEnvPatch(creds, env) {
|
|
343
|
+
const stored = normalizeCredentials(creds);
|
|
344
|
+
const patch = {};
|
|
345
|
+
for (const info of PROVIDERS) {
|
|
346
|
+
const secret = stored[info.id];
|
|
347
|
+
if (secret === void 0) continue;
|
|
348
|
+
if (info.envVars.some((name) => hasCredential(env[name]))) continue;
|
|
349
|
+
const target = info.envVars[0];
|
|
350
|
+
if (target === void 0) continue;
|
|
351
|
+
patch[target] = secret;
|
|
352
|
+
}
|
|
353
|
+
return patch;
|
|
354
|
+
}
|
|
355
|
+
var MASK = "\u2022\u2022\u2022\u2022\u2022\u2022\u2022\u2022";
|
|
356
|
+
var TAIL = 4;
|
|
357
|
+
var PREFIX = 6;
|
|
358
|
+
var MIN_LENGTH_FOR_TAIL = 12;
|
|
359
|
+
var MIN_LENGTH_FOR_PREFIX = 20;
|
|
360
|
+
function redactSecret(secret) {
|
|
361
|
+
const value = typeof secret === "string" ? secret.trim() : "";
|
|
362
|
+
if (value.length < MIN_LENGTH_FOR_TAIL) return MASK;
|
|
363
|
+
const tail = value.slice(-TAIL);
|
|
364
|
+
if (value.length < MIN_LENGTH_FOR_PREFIX) return `${MASK}${tail}`;
|
|
365
|
+
return `${value.slice(0, PREFIX)}\u2026${tail}`;
|
|
366
|
+
}
|
|
367
|
+
var STORE_VERSION = 2;
|
|
368
|
+
var DEFAULT_ACCOUNT_ID = "default";
|
|
369
|
+
var KNOWN_PROVIDER_IDS = new Set(PROVIDERS.map((provider) => provider.id));
|
|
370
|
+
function emptyStore() {
|
|
371
|
+
return { version: STORE_VERSION, providers: {} };
|
|
372
|
+
}
|
|
373
|
+
function isPlainObject(value) {
|
|
374
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
375
|
+
}
|
|
376
|
+
function isSafeKey(key) {
|
|
377
|
+
return key.length > 0 && key !== "__proto__" && key !== "constructor" && key !== "prototype";
|
|
378
|
+
}
|
|
379
|
+
function trimmedString(value) {
|
|
380
|
+
if (typeof value !== "string") return void 0;
|
|
381
|
+
const trimmed = value.trim();
|
|
382
|
+
return trimmed.length > 0 ? trimmed : void 0;
|
|
383
|
+
}
|
|
384
|
+
function normalizeTokens(raw) {
|
|
385
|
+
if (!isPlainObject(raw)) return void 0;
|
|
386
|
+
const tokens = {};
|
|
387
|
+
const accessToken = trimmedString(raw.accessToken);
|
|
388
|
+
const refreshToken = trimmedString(raw.refreshToken);
|
|
389
|
+
if (accessToken !== void 0) tokens.accessToken = accessToken;
|
|
390
|
+
if (refreshToken !== void 0) tokens.refreshToken = refreshToken;
|
|
391
|
+
if (tokens.accessToken === void 0 && tokens.refreshToken === void 0) return void 0;
|
|
392
|
+
if (typeof raw.expiresAt === "number" && Number.isFinite(raw.expiresAt)) tokens.expiresAt = raw.expiresAt;
|
|
393
|
+
const tokenType = trimmedString(raw.tokenType);
|
|
394
|
+
if (tokenType !== void 0) tokens.tokenType = tokenType;
|
|
395
|
+
const scope = trimmedString(raw.scope);
|
|
396
|
+
if (scope !== void 0) tokens.scope = scope;
|
|
397
|
+
return tokens;
|
|
398
|
+
}
|
|
399
|
+
function normalizeIdentity(raw) {
|
|
400
|
+
if (!isPlainObject(raw)) return void 0;
|
|
401
|
+
const identity = {};
|
|
402
|
+
const label = trimmedString(raw.label);
|
|
403
|
+
const accountId = trimmedString(raw.accountId);
|
|
404
|
+
const email = trimmedString(raw.email);
|
|
405
|
+
if (label !== void 0) identity.label = label;
|
|
406
|
+
if (accountId !== void 0) identity.accountId = accountId;
|
|
407
|
+
if (email !== void 0) identity.email = email;
|
|
408
|
+
return Object.keys(identity).length > 0 ? identity : void 0;
|
|
409
|
+
}
|
|
410
|
+
function normalizeRecord(providerId, raw) {
|
|
411
|
+
if (!isPlainObject(raw)) return void 0;
|
|
412
|
+
if (raw.kind === "api_key") {
|
|
413
|
+
if (!providerSupportsMethod(providerId, "api-key")) return void 0;
|
|
414
|
+
const secret = trimmedString(raw.secret);
|
|
415
|
+
return secret === void 0 ? void 0 : { kind: "api_key", secret };
|
|
416
|
+
}
|
|
417
|
+
if (raw.kind === "oauth") {
|
|
418
|
+
if (!providerSupportsMethod(providerId, "oauth")) return void 0;
|
|
419
|
+
const tokens = normalizeTokens(raw.tokens);
|
|
420
|
+
if (tokens === void 0) return void 0;
|
|
421
|
+
const identity = normalizeIdentity(raw.identity);
|
|
422
|
+
return identity === void 0 ? { kind: "oauth", tokens } : { kind: "oauth", tokens, identity };
|
|
423
|
+
}
|
|
424
|
+
return void 0;
|
|
425
|
+
}
|
|
426
|
+
function normalizeProviderAccounts(providerId, raw) {
|
|
427
|
+
if (!isPlainObject(raw)) return void 0;
|
|
428
|
+
const accountsRaw = isPlainObject(raw.accounts) ? raw.accounts : {};
|
|
429
|
+
const accounts = {};
|
|
430
|
+
for (const [accountId, recordRaw] of Object.entries(accountsRaw)) {
|
|
431
|
+
if (!isSafeKey(accountId)) continue;
|
|
432
|
+
const record = normalizeRecord(providerId, recordRaw);
|
|
433
|
+
if (record !== void 0) accounts[accountId] = record;
|
|
434
|
+
}
|
|
435
|
+
const ids = Object.keys(accounts);
|
|
436
|
+
if (ids.length === 0) return void 0;
|
|
437
|
+
const active = typeof raw.activeAccountId === "string" && accounts[raw.activeAccountId] !== void 0 ? raw.activeAccountId : ids[0];
|
|
438
|
+
return { activeAccountId: active, accounts };
|
|
439
|
+
}
|
|
440
|
+
function normalizeAccountStore(raw) {
|
|
441
|
+
if (!isPlainObject(raw)) return emptyStore();
|
|
442
|
+
const looksV2 = isPlainObject(raw.providers) || raw.version !== void 0;
|
|
443
|
+
const store = emptyStore();
|
|
444
|
+
if (looksV2) {
|
|
445
|
+
const providersRaw = isPlainObject(raw.providers) ? raw.providers : {};
|
|
446
|
+
for (const [providerId, entry] of Object.entries(providersRaw)) {
|
|
447
|
+
if (!isSafeKey(providerId) || !KNOWN_PROVIDER_IDS.has(providerId)) continue;
|
|
448
|
+
const accounts = normalizeProviderAccounts(providerId, entry);
|
|
449
|
+
if (accounts !== void 0) store.providers[providerId] = accounts;
|
|
450
|
+
}
|
|
451
|
+
return store;
|
|
452
|
+
}
|
|
453
|
+
for (const [providerId, secret] of Object.entries(normalizeCredentials(raw))) {
|
|
454
|
+
store.providers[providerId] = {
|
|
455
|
+
activeAccountId: DEFAULT_ACCOUNT_ID,
|
|
456
|
+
accounts: { [DEFAULT_ACCOUNT_ID]: { kind: "api_key", secret } }
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
return store;
|
|
460
|
+
}
|
|
461
|
+
function loadAccountStore(homeDir2) {
|
|
462
|
+
try {
|
|
463
|
+
const text = readFileSync2(credentialsFilePath(homeDir2), "utf8");
|
|
464
|
+
return normalizeAccountStore(JSON.parse(text));
|
|
465
|
+
} catch {
|
|
466
|
+
return emptyStore();
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
function saveAccountStore(store, homeDir2) {
|
|
470
|
+
try {
|
|
471
|
+
const path = credentialsFilePath(homeDir2);
|
|
472
|
+
const dir = dirname(path);
|
|
473
|
+
mkdirSync(dir, { recursive: true, mode: DIR_MODE });
|
|
474
|
+
chmodSync(dir, DIR_MODE);
|
|
475
|
+
writeFileSync(path, `${JSON.stringify(normalizeAccountStore(store), null, 2)}
|
|
476
|
+
`, {
|
|
477
|
+
encoding: "utf8",
|
|
478
|
+
mode: FILE_MODE
|
|
479
|
+
});
|
|
480
|
+
chmodSync(path, FILE_MODE);
|
|
481
|
+
return true;
|
|
482
|
+
} catch {
|
|
483
|
+
return false;
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
function getActiveAccount(store, providerId) {
|
|
487
|
+
const entry = store.providers[providerId];
|
|
488
|
+
if (entry === void 0) return void 0;
|
|
489
|
+
const id = entry.activeAccountId;
|
|
490
|
+
if (id !== void 0 && entry.accounts[id] !== void 0) return entry.accounts[id];
|
|
491
|
+
const first = Object.keys(entry.accounts)[0];
|
|
492
|
+
return first === void 0 ? void 0 : entry.accounts[first];
|
|
493
|
+
}
|
|
494
|
+
function listAccounts(store, providerId) {
|
|
495
|
+
const entry = store.providers[providerId];
|
|
496
|
+
if (entry === void 0) return [];
|
|
497
|
+
return Object.entries(entry.accounts).map(([accountId, record]) => ({
|
|
498
|
+
accountId,
|
|
499
|
+
record,
|
|
500
|
+
active: accountId === entry.activeAccountId
|
|
501
|
+
}));
|
|
502
|
+
}
|
|
503
|
+
function chooseAccountId(record, requested) {
|
|
504
|
+
if (requested !== void 0 && isSafeKey(requested)) return requested;
|
|
505
|
+
if (record.kind === "oauth" && record.identity?.accountId !== void 0 && isSafeKey(record.identity.accountId)) {
|
|
506
|
+
return record.identity.accountId;
|
|
507
|
+
}
|
|
508
|
+
if (record.kind === "api_key") return DEFAULT_ACCOUNT_ID;
|
|
509
|
+
return `account-${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 8)}`;
|
|
510
|
+
}
|
|
511
|
+
function addAccount(store, providerId, record, options) {
|
|
512
|
+
if (!KNOWN_PROVIDER_IDS.has(providerId)) {
|
|
513
|
+
throw new Error(`unknown provider "${providerId}"`);
|
|
514
|
+
}
|
|
515
|
+
const method = record.kind === "api_key" ? "api-key" : "oauth";
|
|
516
|
+
if (!providerSupportsMethod(providerId, method)) {
|
|
517
|
+
throw new Error(`provider "${providerId}" does not support ${record.kind} accounts`);
|
|
518
|
+
}
|
|
519
|
+
const accountId = chooseAccountId(record, options?.accountId);
|
|
520
|
+
const existing = store.providers[providerId];
|
|
521
|
+
const accounts = { ...existing?.accounts ?? {} };
|
|
522
|
+
accounts[accountId] = record;
|
|
523
|
+
const makeActive = options?.makeActive ?? true;
|
|
524
|
+
const activeAccountId = makeActive ? accountId : existing?.activeAccountId !== void 0 && accounts[existing.activeAccountId] !== void 0 ? existing.activeAccountId : accountId;
|
|
525
|
+
return {
|
|
526
|
+
store: { version: STORE_VERSION, providers: { ...store.providers, [providerId]: { activeAccountId, accounts } } },
|
|
527
|
+
accountId
|
|
528
|
+
};
|
|
529
|
+
}
|
|
530
|
+
function setActiveAccount(store, providerId, accountId) {
|
|
531
|
+
const entry = store.providers[providerId];
|
|
532
|
+
if (entry === void 0 || entry.accounts[accountId] === void 0) return store;
|
|
533
|
+
return {
|
|
534
|
+
version: STORE_VERSION,
|
|
535
|
+
providers: { ...store.providers, [providerId]: { ...entry, activeAccountId: accountId } }
|
|
536
|
+
};
|
|
537
|
+
}
|
|
538
|
+
function removeAccount(store, providerId, accountId) {
|
|
539
|
+
const entry = store.providers[providerId];
|
|
540
|
+
if (entry === void 0 || entry.accounts[accountId] === void 0) return store;
|
|
541
|
+
const accounts = { ...entry.accounts };
|
|
542
|
+
delete accounts[accountId];
|
|
543
|
+
const providers = { ...store.providers };
|
|
544
|
+
const remaining = Object.keys(accounts);
|
|
545
|
+
if (remaining.length === 0) {
|
|
546
|
+
delete providers[providerId];
|
|
547
|
+
} else {
|
|
548
|
+
const activeAccountId = entry.activeAccountId !== void 0 && accounts[entry.activeAccountId] !== void 0 ? entry.activeAccountId : remaining[0];
|
|
549
|
+
providers[providerId] = { activeAccountId, accounts };
|
|
550
|
+
}
|
|
551
|
+
return { version: STORE_VERSION, providers };
|
|
552
|
+
}
|
|
553
|
+
function logoutProvider(store, providerId) {
|
|
554
|
+
if (store.providers[providerId] === void 0) return store;
|
|
555
|
+
const providers = { ...store.providers };
|
|
556
|
+
delete providers[providerId];
|
|
557
|
+
return { version: STORE_VERSION, providers };
|
|
558
|
+
}
|
|
559
|
+
function accountEnvPatch(store, env) {
|
|
560
|
+
const normalized = normalizeAccountStore(store);
|
|
561
|
+
const patch = {};
|
|
562
|
+
for (const info of PROVIDERS) {
|
|
563
|
+
const record = getActiveAccount(normalized, info.id);
|
|
564
|
+
if (record === void 0) continue;
|
|
565
|
+
if (info.envVars.some((name) => hasCredential(env[name]))) continue;
|
|
566
|
+
if (record.kind === "api_key") {
|
|
567
|
+
const target = info.envVars[0];
|
|
568
|
+
if (target !== void 0) patch[target] = record.secret;
|
|
569
|
+
continue;
|
|
570
|
+
}
|
|
571
|
+
const accessVar = info.envVars[0];
|
|
572
|
+
if (accessVar !== void 0 && record.tokens.accessToken !== void 0) {
|
|
573
|
+
patch[accessVar] = record.tokens.accessToken;
|
|
574
|
+
}
|
|
575
|
+
if (record.tokens.refreshToken !== void 0) {
|
|
576
|
+
const refreshVar = info.envVars.find((name) => /REFRESH/i.test(name));
|
|
577
|
+
if (refreshVar !== void 0) patch[refreshVar] = record.tokens.refreshToken;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
return patch;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
// packages/cli/src/web/connection-config.ts
|
|
584
|
+
import { chmodSync as chmodSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync3, renameSync, rmSync, writeFileSync as writeFileSync2 } from "node:fs";
|
|
585
|
+
import { dirname as dirname2, join as join3 } from "node:path";
|
|
586
|
+
import { randomUUID } from "node:crypto";
|
|
587
|
+
var BASE_URL_VARS = {
|
|
588
|
+
deepseek: "DEEPSEEK_BASE_URL",
|
|
589
|
+
anthropic: "ANTHROPIC_BASE_URL",
|
|
590
|
+
azure: "AZURE_OPENAI_BASE_URL",
|
|
591
|
+
openai: "OPENAI_BASE_URL",
|
|
592
|
+
"z-ai": "Z_AI_BASE_URL",
|
|
593
|
+
kimi: "KIMI_BASE_URL",
|
|
594
|
+
qwen: "QWEN_BASE_URL",
|
|
595
|
+
xai: "XAI_BASE_URL",
|
|
596
|
+
opencode: "OPENCODE_BASE_URL",
|
|
597
|
+
cline: "CLINE_BASE_URL",
|
|
598
|
+
copilot: "COPILOT_BASE_URL"
|
|
599
|
+
};
|
|
600
|
+
function validateConnectionConfig(providerId, value) {
|
|
601
|
+
const result = {};
|
|
602
|
+
if (value.baseUrl !== void 0) {
|
|
603
|
+
if (!BASE_URL_VARS[providerId]) throw new Error("This provider does not support a custom API endpoint.");
|
|
604
|
+
const url = new URL(value.baseUrl);
|
|
605
|
+
if (url.username || url.password || url.search || url.hash || url.protocol !== "https:" && !(url.protocol === "http:" && ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname))) {
|
|
606
|
+
throw new Error("API endpoint must be credential-free HTTPS, or loopback HTTP, without a query or fragment.");
|
|
607
|
+
}
|
|
608
|
+
result.baseUrl = url.href.replace(/\/$/, "");
|
|
609
|
+
}
|
|
610
|
+
if (value.model !== void 0) {
|
|
611
|
+
if (providerId !== "azure") throw new Error("Deployment model configuration is only supported for Azure; select other models through runtime selection.");
|
|
612
|
+
if (!value.model.trim() || value.model.length > 256 || /[\s\x00-\x1f\x7f]/.test(value.model)) throw new Error("Invalid deployment model.");
|
|
613
|
+
result.model = value.model;
|
|
614
|
+
}
|
|
615
|
+
if (value.projectId !== void 0) {
|
|
616
|
+
if (providerId !== "google" || !/^[a-z][a-z0-9-]{4,62}[a-z0-9]$/.test(value.projectId)) throw new Error("Invalid Google Cloud project ID.");
|
|
617
|
+
result.projectId = value.projectId;
|
|
618
|
+
}
|
|
619
|
+
return result;
|
|
620
|
+
}
|
|
621
|
+
function loadConnectionConfigs(homeDir2) {
|
|
622
|
+
let raw;
|
|
623
|
+
try {
|
|
624
|
+
raw = JSON.parse(readFileSync3(join3(homeStateDir(homeDir2), "web-connections.json"), "utf8"));
|
|
625
|
+
} catch {
|
|
626
|
+
return {};
|
|
627
|
+
}
|
|
628
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) return {};
|
|
629
|
+
const result = {};
|
|
630
|
+
for (const providerId of [...Object.keys(BASE_URL_VARS), "google"]) {
|
|
631
|
+
const row = raw[providerId];
|
|
632
|
+
if (!row || typeof row !== "object" || Array.isArray(row)) continue;
|
|
633
|
+
const config = row;
|
|
634
|
+
try {
|
|
635
|
+
result[providerId] = validateConnectionConfig(providerId, {
|
|
636
|
+
...typeof config.baseUrl === "string" ? { baseUrl: config.baseUrl } : {},
|
|
637
|
+
...typeof config.model === "string" ? { model: config.model } : {},
|
|
638
|
+
...typeof config.projectId === "string" ? { projectId: config.projectId } : {}
|
|
639
|
+
});
|
|
640
|
+
} catch {
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
return result;
|
|
644
|
+
}
|
|
645
|
+
function saveConnectionConfig(providerId, config, homeDir2) {
|
|
646
|
+
const value = validateConnectionConfig(providerId, config);
|
|
647
|
+
const next = { ...loadConnectionConfigs(homeDir2), [providerId]: value };
|
|
648
|
+
const path = join3(homeStateDir(homeDir2), "web-connections.json");
|
|
649
|
+
mkdirSync2(dirname2(path), { recursive: true, mode: 448 });
|
|
650
|
+
chmodSync2(dirname2(path), 448);
|
|
651
|
+
const temporary = `${path}.${randomUUID()}.tmp`;
|
|
652
|
+
try {
|
|
653
|
+
writeFileSync2(temporary, JSON.stringify(next) + "\n", { mode: 384, flag: "wx" });
|
|
654
|
+
renameSync(temporary, path);
|
|
655
|
+
} finally {
|
|
656
|
+
rmSync(temporary, { force: true });
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
function connectionConfigEnvPatch(env, homeDir2) {
|
|
660
|
+
const patch = {};
|
|
661
|
+
for (const [id, config] of Object.entries(loadConnectionConfigs(homeDir2))) {
|
|
662
|
+
const variable = BASE_URL_VARS[id];
|
|
663
|
+
if (variable && config.baseUrl && !env[variable]) patch[variable] = config.baseUrl;
|
|
664
|
+
if (id === "azure" && config.model && !env.AZURE_OPENAI_MODEL) patch.AZURE_OPENAI_MODEL = config.model;
|
|
665
|
+
if (id === "google" && config.projectId && !env.GOOGLE_CLOUD_PROJECT && !env.ZERO_GEMINI_PROJECT) patch.ZERO_GEMINI_PROJECT = config.projectId;
|
|
666
|
+
}
|
|
667
|
+
return patch;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
export {
|
|
671
|
+
getSettings,
|
|
672
|
+
getSettingSources,
|
|
673
|
+
getAnalyticsSetupDraft,
|
|
674
|
+
defaultWriteLayer,
|
|
675
|
+
updateSetting,
|
|
676
|
+
resetSettings,
|
|
677
|
+
previewSetting,
|
|
678
|
+
subscribeSettings,
|
|
679
|
+
reloadSettings,
|
|
680
|
+
configureSettingsStore,
|
|
681
|
+
useSettings,
|
|
682
|
+
maybeLoadCodexAuth,
|
|
683
|
+
loadCredentials,
|
|
684
|
+
saveCredentials,
|
|
685
|
+
credentialEnvPatch,
|
|
686
|
+
redactSecret,
|
|
687
|
+
loadAccountStore,
|
|
688
|
+
saveAccountStore,
|
|
689
|
+
listAccounts,
|
|
690
|
+
addAccount,
|
|
691
|
+
setActiveAccount,
|
|
692
|
+
removeAccount,
|
|
693
|
+
logoutProvider,
|
|
694
|
+
accountEnvPatch,
|
|
695
|
+
validateConnectionConfig,
|
|
696
|
+
loadConnectionConfigs,
|
|
697
|
+
saveConnectionConfig,
|
|
698
|
+
connectionConfigEnvPatch,
|
|
699
|
+
resolveEngagement
|
|
700
|
+
};
|