gsd-pi 2.73.0-dev.1cfd50c → 2.73.0-dev.27730dc
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/dist/cli.js +0 -47
- package/dist/help-text.js +1 -1
- package/dist/resources/extensions/gsd/auto-dispatch.js +5 -3
- package/dist/resources/extensions/gsd/auto-prompts.js +9 -6
- package/dist/resources/extensions/gsd/auto.js +5 -1
- package/dist/resources/extensions/gsd/bootstrap/crash-log.js +31 -0
- package/dist/resources/extensions/gsd/bootstrap/register-extension.js +18 -7
- package/dist/resources/extensions/gsd/bootstrap/system-context.js +6 -1
- package/dist/resources/extensions/gsd/crash-recovery.js +51 -0
- package/dist/resources/extensions/gsd/gsd-db.js +36 -2
- package/dist/resources/extensions/gsd/milestone-actions.js +19 -1
- package/dist/startup-model-validation.js +8 -5
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +11 -11
- package/dist/web/standalone/.next/build-manifest.json +2 -2
- package/dist/web/standalone/.next/prerender-manifest.json +3 -3
- package/dist/web/standalone/.next/server/app/_global-error.html +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.html +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.html +1 -1
- package/dist/web/standalone/.next/server/app/index.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_full.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_head.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_index.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app/index.segments/_tree.segment.rsc +1 -1
- package/dist/web/standalone/.next/server/app-paths-manifest.json +11 -11
- package/dist/web/standalone/.next/server/middleware-build-manifest.js +1 -1
- package/dist/web/standalone/.next/server/middleware-manifest.json +5 -5
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +1 -1
- package/dist/web/standalone/.next/server/server-reference-manifest.json +1 -1
- package/package.json +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js +27 -0
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.d.ts.map +1 -1
- package/packages/pi-coding-agent/dist/core/model-resolver.js +25 -68
- package/packages/pi-coding-agent/dist/core/model-resolver.js.map +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +38 -0
- package/packages/pi-coding-agent/src/core/auth-storage.ts +1 -1
- package/packages/pi-coding-agent/src/core/model-resolver.ts +26 -70
- package/src/resources/extensions/gsd/auto-dispatch.ts +5 -0
- package/src/resources/extensions/gsd/auto-prompts.ts +9 -3
- package/src/resources/extensions/gsd/auto.ts +5 -0
- package/src/resources/extensions/gsd/bootstrap/crash-log.ts +32 -0
- package/src/resources/extensions/gsd/bootstrap/register-extension.ts +19 -7
- package/src/resources/extensions/gsd/bootstrap/system-context.ts +8 -1
- package/src/resources/extensions/gsd/crash-recovery.ts +59 -0
- package/src/resources/extensions/gsd/gsd-db.ts +52 -2
- package/src/resources/extensions/gsd/milestone-actions.ts +19 -1
- package/src/resources/extensions/gsd/tests/crash-handler-secondary.test.ts +235 -0
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +59 -1
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +64 -0
- package/src/resources/extensions/gsd/tests/subagent-model-dispatch.test.ts +267 -0
- /package/dist/web/standalone/.next/static/{uNGVqSkAnszMl0okA4nnp → jNiH700EcljeLnbQ2_RCv}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{uNGVqSkAnszMl0okA4nnp → jNiH700EcljeLnbQ2_RCv}/_ssgManifest.js +0 -0
|
@@ -5,4 +5,4 @@
|
|
|
5
5
|
5:I[61549,["4986","static/chunks/4986-c2fc8845ce785303.js","7177","static/chunks/app/layout-a16c7a7ecdf0c2cf.js"],"Toaster"]
|
|
6
6
|
:HL["/_next/static/css/de70bee13400563f.css","style"]
|
|
7
7
|
:HL["/_next/static/css/f6e8833d46e738d8.css","style"]
|
|
8
|
-
0:{"rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/de70bee13400563f.css","precedence":"next"}],["$","link","1",{"rel":"stylesheet","href":"/_next/static/css/f6e8833d46e738d8.css","precedence":"next"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"__variable_188709 __variable_9a8899 font-sans antialiased","children":["$","$L2",null,{"attribute":"class","defaultTheme":"dark","children":[["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}],["$","$L5",null,{"position":"bottom-right"}]]}]}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"
|
|
8
|
+
0:{"rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/de70bee13400563f.css","precedence":"next"}],["$","link","1",{"rel":"stylesheet","href":"/_next/static/css/f6e8833d46e738d8.css","precedence":"next"}]],["$","html",null,{"lang":"en","suppressHydrationWarning":true,"children":["$","body",null,{"className":"__variable_188709 __variable_9a8899 font-sans antialiased","children":["$","$L2",null,{"attribute":"class","defaultTheme":"dark","children":[["$","$L3",null,{"parallelRouterKey":"children","template":["$","$L4",null,{}],"notFound":[[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":404}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],[]]}],["$","$L5",null,{"position":"bottom-right"}]]}]}]}]]}],"isPartial":false,"staleTime":300,"varyParams":null,"buildId":"jNiH700EcljeLnbQ2_RCv"}
|
|
@@ -2,4 +2,4 @@
|
|
|
2
2
|
:HL["/_next/static/media/93f479601ee12b01-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
3
3
|
:HL["/_next/static/css/de70bee13400563f.css","style"]
|
|
4
4
|
:HL["/_next/static/css/f6e8833d46e738d8.css","style"]
|
|
5
|
-
0:{"tree":{"name":"","param":null,"prefetchHints":16,"slots":{"children":{"name":"__PAGE__","param":null,"prefetchHints":0,"slots":null}}},"staleTime":300,"buildId":"
|
|
5
|
+
0:{"tree":{"name":"","param":null,"prefetchHints":16,"slots":{"children":{"name":"__PAGE__","param":null,"prefetchHints":0,"slots":null}}},"staleTime":300,"buildId":"jNiH700EcljeLnbQ2_RCv"}
|
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"/_not-found/page": "app/_not-found/page.js",
|
|
3
3
|
"/_global-error/page": "app/_global-error/page.js",
|
|
4
|
-
"/api/bridge-terminal/input/route": "app/api/bridge-terminal/input/route.js",
|
|
5
4
|
"/api/boot/route": "app/api/boot/route.js",
|
|
6
5
|
"/api/bridge-terminal/resize/route": "app/api/bridge-terminal/resize/route.js",
|
|
7
|
-
"/api/
|
|
6
|
+
"/api/bridge-terminal/input/route": "app/api/bridge-terminal/input/route.js",
|
|
7
|
+
"/api/bridge-terminal/stream/route": "app/api/bridge-terminal/stream/route.js",
|
|
8
8
|
"/api/dev-mode/route": "app/api/dev-mode/route.js",
|
|
9
9
|
"/api/captures/route": "app/api/captures/route.js",
|
|
10
|
-
"/api/
|
|
11
|
-
"/api/browse-directories/route": "app/api/browse-directories/route.js",
|
|
10
|
+
"/api/cleanup/route": "app/api/cleanup/route.js",
|
|
12
11
|
"/api/doctor/route": "app/api/doctor/route.js",
|
|
12
|
+
"/api/browse-directories/route": "app/api/browse-directories/route.js",
|
|
13
13
|
"/api/export-data/route": "app/api/export-data/route.js",
|
|
14
|
-
"/api/experimental/route": "app/api/experimental/route.js",
|
|
15
|
-
"/api/git/route": "app/api/git/route.js",
|
|
16
14
|
"/api/forensics/route": "app/api/forensics/route.js",
|
|
15
|
+
"/api/git/route": "app/api/git/route.js",
|
|
17
16
|
"/api/history/route": "app/api/history/route.js",
|
|
18
17
|
"/api/hooks/route": "app/api/hooks/route.js",
|
|
19
18
|
"/api/inspect/route": "app/api/inspect/route.js",
|
|
20
19
|
"/api/knowledge/route": "app/api/knowledge/route.js",
|
|
20
|
+
"/api/experimental/route": "app/api/experimental/route.js",
|
|
21
21
|
"/api/live-state/route": "app/api/live-state/route.js",
|
|
22
22
|
"/api/notifications/route": "app/api/notifications/route.js",
|
|
23
|
-
"/api/onboarding/route": "app/api/onboarding/route.js",
|
|
24
23
|
"/api/preferences/route": "app/api/preferences/route.js",
|
|
25
24
|
"/api/recovery/route": "app/api/recovery/route.js",
|
|
25
|
+
"/api/onboarding/route": "app/api/onboarding/route.js",
|
|
26
26
|
"/api/projects/route": "app/api/projects/route.js",
|
|
27
|
-
"/api/files/route": "app/api/files/route.js",
|
|
28
27
|
"/api/session/browser/route": "app/api/session/browser/route.js",
|
|
29
28
|
"/api/session/command/route": "app/api/session/command/route.js",
|
|
30
|
-
"/api/settings-data/route": "app/api/settings-data/route.js",
|
|
31
29
|
"/api/session/events/route": "app/api/session/events/route.js",
|
|
30
|
+
"/api/settings-data/route": "app/api/settings-data/route.js",
|
|
32
31
|
"/api/shutdown/route": "app/api/shutdown/route.js",
|
|
33
32
|
"/api/session/manage/route": "app/api/session/manage/route.js",
|
|
34
33
|
"/api/skill-health/route": "app/api/skill-health/route.js",
|
|
@@ -36,12 +35,13 @@
|
|
|
36
35
|
"/api/terminal/input/route": "app/api/terminal/input/route.js",
|
|
37
36
|
"/api/terminal/resize/route": "app/api/terminal/resize/route.js",
|
|
38
37
|
"/api/switch-root/route": "app/api/switch-root/route.js",
|
|
38
|
+
"/api/files/route": "app/api/files/route.js",
|
|
39
39
|
"/api/terminal/sessions/route": "app/api/terminal/sessions/route.js",
|
|
40
40
|
"/api/terminal/stream/route": "app/api/terminal/stream/route.js",
|
|
41
41
|
"/api/undo/route": "app/api/undo/route.js",
|
|
42
|
-
"/api/terminal/upload/route": "app/api/terminal/upload/route.js",
|
|
43
42
|
"/api/visualizer/route": "app/api/visualizer/route.js",
|
|
44
|
-
"/api/remote-questions/route": "app/api/remote-questions/route.js",
|
|
45
43
|
"/api/update/route": "app/api/update/route.js",
|
|
44
|
+
"/api/terminal/upload/route": "app/api/terminal/upload/route.js",
|
|
45
|
+
"/api/remote-questions/route": "app/api/remote-questions/route.js",
|
|
46
46
|
"/page": "app/page.js"
|
|
47
47
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
globalThis.__BUILD_MANIFEST={polyfillFiles:["static/chunks/polyfills-42372ed130431b0a.js"],devFiles:[],lowPriorityFiles:["static/
|
|
1
|
+
globalThis.__BUILD_MANIFEST={polyfillFiles:["static/chunks/polyfills-42372ed130431b0a.js"],devFiles:[],lowPriorityFiles:["static/jNiH700EcljeLnbQ2_RCv/_buildManifest.js","static/jNiH700EcljeLnbQ2_RCv/_ssgManifest.js"],rootMainFiles:["static/chunks/webpack-b868033a5834586d.js","static/chunks/4bd1b696-e356ca5ba0218e27.js","static/chunks/3794-42fdce068d44fa4f.js","static/chunks/main-app-fdab67f7802d7832.js"],rootMainFilesTree:{},pages:{"/_app":[]}};
|
|
@@ -18,11 +18,11 @@
|
|
|
18
18
|
"wasm": [],
|
|
19
19
|
"assets": [],
|
|
20
20
|
"env": {
|
|
21
|
-
"__NEXT_BUILD_ID": "
|
|
22
|
-
"NEXT_SERVER_ACTIONS_ENCRYPTION_KEY": "
|
|
23
|
-
"__NEXT_PREVIEW_MODE_ID": "
|
|
24
|
-
"__NEXT_PREVIEW_MODE_SIGNING_KEY": "
|
|
25
|
-
"__NEXT_PREVIEW_MODE_ENCRYPTION_KEY": "
|
|
21
|
+
"__NEXT_BUILD_ID": "jNiH700EcljeLnbQ2_RCv",
|
|
22
|
+
"NEXT_SERVER_ACTIONS_ENCRYPTION_KEY": "lxvUlI6K8yjJ6M359DXhJFyiB9qskxFea5NAUoicWAM=",
|
|
23
|
+
"__NEXT_PREVIEW_MODE_ID": "a077dc3cc6e9642c24e04033900df612",
|
|
24
|
+
"__NEXT_PREVIEW_MODE_SIGNING_KEY": "347e44062d1fc69fe14a618159fcbcbb2eac15a8a09ed79f6da66ac0d7261bef",
|
|
25
|
+
"__NEXT_PREVIEW_MODE_ENCRYPTION_KEY": "70332a2c4d947505326136e6685542ca7703638f75f1a73e3b886bb61a464551"
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/><link rel="preload" href="/_next/static/media/4cf2300e9c8272f7-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/93f479601ee12b01-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/css/de70bee13400563f.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/f6e8833d46e738d8.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-b868033a5834586d.js"/><script src="/_next/static/chunks/4bd1b696-e356ca5ba0218e27.js" async=""></script><script src="/_next/static/chunks/3794-42fdce068d44fa4f.js" async=""></script><script src="/_next/static/chunks/main-app-fdab67f7802d7832.js" async=""></script><script src="/_next/static/chunks/4986-c2fc8845ce785303.js" async=""></script><script src="/_next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>404: This page could not be found.</title><title>GSD</title><meta name="description" content="The evolution of Get Shit Done — now a real coding agent. One command. Walk away. Come back to a built project."/><meta name="application-name" content="GSD"/><link rel="icon" href="/icon-light-32x32.png" media="(prefers-color-scheme: light)"/><link rel="icon" href="/icon-dark-32x32.png" media="(prefers-color-scheme: dark)"/><link rel="icon" href="/icon.svg" type="image/svg+xml"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body class="__variable_188709 __variable_9a8899 font-sans antialiased"><div hidden=""><!--$--><!--/$--></div><script>((a,b,c,d,e,f,g,h)=>{let i=document.documentElement,j=["light","dark"];function k(b){var c;(Array.isArray(a)?a:[a]).forEach(a=>{let c="class"===a,d=c&&f?e.map(a=>f[a]||a):e;c?(i.classList.remove(...d),i.classList.add(f&&f[b]?f[b]:b)):i.setAttribute(a,b)}),c=b,h&&j.includes(c)&&(i.style.colorScheme=c)}if(d)k(d);else try{let a=localStorage.getItem(b)||c,d=g&&"system"===a?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":a;k(d)}catch(a){}})("class","theme","dark",null,["light","dark"],null,true,true)</script><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><section aria-label="Notifications alt+T" tabindex="-1" aria-live="polite" aria-relevant="additions text" aria-atomic="false"></section><script src="/_next/static/chunks/webpack-b868033a5834586d.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[21942,[\"4986\",\"static/chunks/4986-c2fc8845ce785303.js\",\"7177\",\"static/chunks/app/layout-a16c7a7ecdf0c2cf.js\"],\"ThemeProvider\"]\n3:I[57121,[],\"\"]\n4:I[74581,[],\"\"]\n5:I[61549,[\"4986\",\"static/chunks/4986-c2fc8845ce785303.js\",\"7177\",\"static/chunks/app/layout-a16c7a7ecdf0c2cf.js\"],\"Toaster\"]\n6:I[90484,[],\"OutletBoundary\"]\n7:\"$Sreact.suspense\"\na:I[90484,[],\"ViewportBoundary\"]\nc:I[90484,[],\"MetadataBoundary\"]\ne:I[27123,[],\"default\",1]\n:HL[\"/_next/static/media/4cf2300e9c8272f7-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/93f479601ee12b01-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/css/de70bee13400563f.css\",\"style\"]\n:HL[\"/_next/static/css/f6e8833d46e738d8.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/de70bee13400563f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/f6e8833d46e738d8.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[\"$\",\"body\",null,{\"className\":\"__variable_188709 __variable_9a8899 font-sans antialiased\",\"children\":[\"$\",\"$L2\",null,{\"attribute\":\"class\",\"defaultTheme\":\"dark\",\"children\":[[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],[\"$\",\"$L5\",null,{\"position\":\"bottom-right\"}]]}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L6\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@8\"}]}]]}],{},null,false,null]},null,false,\"$@9\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$La\",null,{\"children\":\"$Lb\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lc\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Ld\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$e\",[]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"
|
|
1
|
+
<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/><link rel="preload" href="/_next/static/media/4cf2300e9c8272f7-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="preload" href="/_next/static/media/93f479601ee12b01-s.p.woff2" as="font" crossorigin="" type="font/woff2"/><link rel="stylesheet" href="/_next/static/css/de70bee13400563f.css" data-precedence="next"/><link rel="stylesheet" href="/_next/static/css/f6e8833d46e738d8.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-b868033a5834586d.js"/><script src="/_next/static/chunks/4bd1b696-e356ca5ba0218e27.js" async=""></script><script src="/_next/static/chunks/3794-42fdce068d44fa4f.js" async=""></script><script src="/_next/static/chunks/main-app-fdab67f7802d7832.js" async=""></script><script src="/_next/static/chunks/4986-c2fc8845ce785303.js" async=""></script><script src="/_next/static/chunks/app/layout-a16c7a7ecdf0c2cf.js" async=""></script><meta name="robots" content="noindex"/><meta name="next-size-adjust" content=""/><title>404: This page could not be found.</title><title>GSD</title><meta name="description" content="The evolution of Get Shit Done — now a real coding agent. One command. Walk away. Come back to a built project."/><meta name="application-name" content="GSD"/><link rel="icon" href="/icon-light-32x32.png" media="(prefers-color-scheme: light)"/><link rel="icon" href="/icon-dark-32x32.png" media="(prefers-color-scheme: dark)"/><link rel="icon" href="/icon.svg" type="image/svg+xml"/><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body class="__variable_188709 __variable_9a8899 font-sans antialiased"><div hidden=""><!--$--><!--/$--></div><script>((a,b,c,d,e,f,g,h)=>{let i=document.documentElement,j=["light","dark"];function k(b){var c;(Array.isArray(a)?a:[a]).forEach(a=>{let c="class"===a,d=c&&f?e.map(a=>f[a]||a):e;c?(i.classList.remove(...d),i.classList.add(f&&f[b]?f[b]:b)):i.setAttribute(a,b)}),c=b,h&&j.includes(c)&&(i.style.colorScheme=c)}if(d)k(d);else try{let a=localStorage.getItem(b)||c,d=g&&"system"===a?window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light":a;k(d)}catch(a){}})("class","theme","dark",null,["light","dark"],null,true,true)</script><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding:0 23px 0 0;font-size:24px;font-weight:500;vertical-align:top;line-height:49px">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:49px;margin:0">This page could not be found.</h2></div></div></div><!--$--><!--/$--><section aria-label="Notifications alt+T" tabindex="-1" aria-live="polite" aria-relevant="additions text" aria-atomic="false"></section><script src="/_next/static/chunks/webpack-b868033a5834586d.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[21942,[\"4986\",\"static/chunks/4986-c2fc8845ce785303.js\",\"7177\",\"static/chunks/app/layout-a16c7a7ecdf0c2cf.js\"],\"ThemeProvider\"]\n3:I[57121,[],\"\"]\n4:I[74581,[],\"\"]\n5:I[61549,[\"4986\",\"static/chunks/4986-c2fc8845ce785303.js\",\"7177\",\"static/chunks/app/layout-a16c7a7ecdf0c2cf.js\"],\"Toaster\"]\n6:I[90484,[],\"OutletBoundary\"]\n7:\"$Sreact.suspense\"\na:I[90484,[],\"ViewportBoundary\"]\nc:I[90484,[],\"MetadataBoundary\"]\ne:I[27123,[],\"default\",1]\n:HL[\"/_next/static/media/4cf2300e9c8272f7-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/media/93f479601ee12b01-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n:HL[\"/_next/static/css/de70bee13400563f.css\",\"style\"]\n:HL[\"/_next/static/css/f6e8833d46e738d8.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",16],[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/de70bee13400563f.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"link\",\"1\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/css/f6e8833d46e738d8.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"suppressHydrationWarning\":true,\"children\":[\"$\",\"body\",null,{\"className\":\"__variable_188709 __variable_9a8899 font-sans antialiased\",\"children\":[\"$\",\"$L2\",null,{\"attribute\":\"class\",\"defaultTheme\":\"dark\",\"children\":[[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],[\"$\",\"$L5\",null,{\"position\":\"bottom-right\"}]]}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L3\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L4\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],null,[\"$\",\"$L6\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@8\"}]}]]}],{},null,false,null]},null,false,\"$@9\"]},null,false,null],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$La\",null,{\"children\":\"$Lb\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lc\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Ld\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$e\",[]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"jNiH700EcljeLnbQ2_RCv\"}\n"])</script><script>self.__next_f.push([1,"f:[]\n9:\"$Wf\"\n"])</script><script>self.__next_f.push([1,"b:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no\"}]]\n"])</script><script>self.__next_f.push([1,"10:I[86869,[],\"IconMark\"]\n8:null\nd:[[\"$\",\"title\",\"0\",{\"children\":\"GSD\"}],[\"$\",\"meta\",\"1\",{\"name\":\"description\",\"content\":\"The evolution of Get Shit Done — now a real coding agent. One command. Walk away. Come back to a built project.\"}],[\"$\",\"meta\",\"2\",{\"name\":\"application-name\",\"content\":\"GSD\"}],[\"$\",\"link\",\"3\",{\"rel\":\"icon\",\"href\":\"/icon-light-32x32.png\",\"media\":\"(prefers-color-scheme: light)\"}],[\"$\",\"link\",\"4\",{\"rel\":\"icon\",\"href\":\"/icon-dark-32x32.png\",\"media\":\"(prefers-color-scheme: dark)\"}],[\"$\",\"link\",\"5\",{\"rel\":\"icon\",\"href\":\"/icon.svg\",\"type\":\"image/svg+xml\"}],[\"$\",\"$L10\",\"6\",{}]]\n"])</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-b868033a5834586d.js"/><script src="/_next/static/chunks/4bd1b696-e356ca5ba0218e27.js" async=""></script><script src="/_next/static/chunks/3794-42fdce068d44fa4f.js" async=""></script><script src="/_next/static/chunks/main-app-fdab67f7802d7832.js" async=""></script><meta name="next-size-adjust" content=""/><title>500: This page couldn’t load</title><style>:root {--next-error-bg: #fff;--next-error-text: #171717;--next-error-title: #171717;--next-error-message: #171717;--next-error-digest: #666666;--next-error-btn-text: #fff;--next-error-btn-bg: #171717;--next-error-btn-border: none;--next-error-btn-secondary-text: #171717;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(0,0,0,0.08);}@media (prefers-color-scheme: dark) {:root {--next-error-bg: #0a0a0a;--next-error-text: #ededed;--next-error-title: #ededed;--next-error-message: #ededed;--next-error-digest: #a0a0a0;--next-error-btn-text: #0a0a0a;--next-error-btn-bg: #ededed;--next-error-btn-border: none;--next-error-btn-secondary-text: #ededed;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(255,255,255,0.14);}}body { margin: 0; color: var(--next-error-text); background: var(--next-error-bg); }</style><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;display:flex;align-items:center;justify-content:center"><div style="margin-top:-32px;max-width:325px;padding:32px 28px;text-align:left"><svg width="32" height="32" viewBox="-0.2 -1.5 32 32" fill="none" style="margin-bottom:24px"><path d="M16.9328 0C18.0839 0.000116771 19.1334 0.658832 19.634 1.69531L31.4299 26.1309C32.0708 27.4588 31.1036 28.9999 29.6291 29H2.00215C0.527541 29 -0.439628 27.4588 0.201371 26.1309L11.9973 1.69531C12.4979 0.658823 13.5474 7.75066e-05 14.6984 0H16.9328ZM3.59493 26H28.0363L16.9328 3H14.6984L3.59493 26ZM15.8156 19C16.9202 19.0001 17.8156 19.8955 17.8156 21C17.8156 22.1045 16.9202 22.9999 15.8156 23C14.7111 23 13.8156 22.1046 13.8156 21C13.8156 19.8954 14.7111 19 15.8156 19ZM17.3156 16.5H14.3156V8.5H17.3156V16.5Z" fill="var(--next-error-title)"></path></svg><h1 style="font-size:24px;font-weight:500;letter-spacing:-0.02em;line-height:32px;margin:0 0 12px 0;color:var(--next-error-title)">This page couldn’t load</h1><p style="font-size:14px;font-weight:400;line-height:21px;margin:0 0 20px 0;color:var(--next-error-message)">A server error occurred. Reload to try again.</p><form style="margin:0"><button type="submit" style="display:inline-flex;align-items:center;justify-content:center;height:32px;padding:0 12px;font-size:14px;font-weight:500;line-height:20px;border-radius:6px;cursor:pointer;color:var(--next-error-btn-text);background:var(--next-error-btn-bg);border:var(--next-error-btn-border)">Reload</button></form></div></div><!--$--><!--/$--><script src="/_next/static/chunks/webpack-b868033a5834586d.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[57121,[],\"\"]\n3:I[74581,[],\"\"]\n4:I[90484,[],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n8:I[90484,[],\"ViewportBoundary\"]\na:I[90484,[],\"MetadataBoundary\"]\nc:I[27123,[],\"default\",1]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"_global-error\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"_global-error\",{\"children\":[\"__PAGE__\",{}]}]}],[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"html\",null,{\"id\":\"__next_error__\",\"children\":[[\"$\",\"head\",null,{\"children\":[[\"$\",\"title\",null,{\"children\":\"500: This page couldn’t load\"}],[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\":root {--next-error-bg: #fff;--next-error-text: #171717;--next-error-title: #171717;--next-error-message: #171717;--next-error-digest: #666666;--next-error-btn-text: #fff;--next-error-btn-bg: #171717;--next-error-btn-border: none;--next-error-btn-secondary-text: #171717;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(0,0,0,0.08);}@media (prefers-color-scheme: dark) {:root {--next-error-bg: #0a0a0a;--next-error-text: #ededed;--next-error-title: #ededed;--next-error-message: #ededed;--next-error-digest: #a0a0a0;--next-error-btn-text: #0a0a0a;--next-error-btn-bg: #ededed;--next-error-btn-border: none;--next-error-btn-secondary-text: #ededed;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(255,255,255,0.14);}}body { margin: 0; color: var(--next-error-text); background: var(--next-error-bg); }\"}}]]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"display\":\"flex\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"style\":{\"marginTop\":\"-32px\",\"maxWidth\":\"325px\",\"padding\":\"32px 28px\",\"textAlign\":\"left\"},\"children\":[[\"$\",\"svg\",null,{\"width\":\"32\",\"height\":\"32\",\"viewBox\":\"-0.2 -1.5 32 32\",\"fill\":\"none\",\"style\":{\"marginBottom\":\"24px\"},\"children\":[\"$\",\"path\",null,{\"d\":\"M16.9328 0C18.0839 0.000116771 19.1334 0.658832 19.634 1.69531L31.4299 26.1309C32.0708 27.4588 31.1036 28.9999 29.6291 29H2.00215C0.527541 29 -0.439628 27.4588 0.201371 26.1309L11.9973 1.69531C12.4979 0.658823 13.5474 7.75066e-05 14.6984 0H16.9328ZM3.59493 26H28.0363L16.9328 3H14.6984L3.59493 26ZM15.8156 19C16.9202 19.0001 17.8156 19.8955 17.8156 21C17.8156 22.1045 16.9202 22.9999 15.8156 23C14.7111 23 13.8156 22.1046 13.8156 21C13.8156 19.8954 14.7111 19 15.8156 19ZM17.3156 16.5H14.3156V8.5H17.3156V16.5Z\",\"fill\":\"var(--next-error-title)\"}]}],[\"$\",\"h1\",null,{\"style\":{\"fontSize\":\"24px\",\"fontWeight\":500,\"letterSpacing\":\"-0.02em\",\"lineHeight\":\"32px\",\"margin\":\"0 0 12px 0\",\"color\":\"var(--next-error-title)\"},\"children\":\"This page couldn’t load\"}],[\"$\",\"p\",null,{\"style\":{\"fontSize\":\"14px\",\"fontWeight\":400,\"lineHeight\":\"21px\",\"margin\":\"0 0 20px 0\",\"color\":\"var(--next-error-message)\"},\"children\":\"A server error occurred. Reload to try again.\"}],[\"$\",\"form\",null,{\"style\":{\"margin\":0},\"children\":[\"$\",\"button\",null,{\"type\":\"submit\",\"style\":{\"display\":\"inline-flex\",\"alignItems\":\"center\",\"justifyContent\":\"center\",\"height\":\"32px\",\"padding\":\"0 12px\",\"fontSize\":\"14px\",\"fontWeight\":500,\"lineHeight\":\"20px\",\"borderRadius\":\"6px\",\"cursor\":\"pointer\",\"color\":\"var(--next-error-btn-text)\",\"background\":\"var(--next-error-btn-bg)\",\"border\":\"var(--next-error-btn-border)\"},\"children\":\"Reload\"}]}]]}]}]}]]}],null,[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,null]},null,false,\"$@7\"]},null,false,\"$@7\"],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",[]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"
|
|
1
|
+
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-b868033a5834586d.js"/><script src="/_next/static/chunks/4bd1b696-e356ca5ba0218e27.js" async=""></script><script src="/_next/static/chunks/3794-42fdce068d44fa4f.js" async=""></script><script src="/_next/static/chunks/main-app-fdab67f7802d7832.js" async=""></script><meta name="next-size-adjust" content=""/><title>500: This page couldn’t load</title><style>:root {--next-error-bg: #fff;--next-error-text: #171717;--next-error-title: #171717;--next-error-message: #171717;--next-error-digest: #666666;--next-error-btn-text: #fff;--next-error-btn-bg: #171717;--next-error-btn-border: none;--next-error-btn-secondary-text: #171717;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(0,0,0,0.08);}@media (prefers-color-scheme: dark) {:root {--next-error-bg: #0a0a0a;--next-error-text: #ededed;--next-error-title: #ededed;--next-error-message: #ededed;--next-error-digest: #a0a0a0;--next-error-btn-text: #0a0a0a;--next-error-btn-bg: #ededed;--next-error-btn-border: none;--next-error-btn-secondary-text: #ededed;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(255,255,255,0.14);}}body { margin: 0; color: var(--next-error-text); background: var(--next-error-bg); }</style><script src="/_next/static/chunks/polyfills-42372ed130431b0a.js" noModule=""></script></head><body><div hidden=""><!--$--><!--/$--></div><div style="font-family:system-ui,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;display:flex;align-items:center;justify-content:center"><div style="margin-top:-32px;max-width:325px;padding:32px 28px;text-align:left"><svg width="32" height="32" viewBox="-0.2 -1.5 32 32" fill="none" style="margin-bottom:24px"><path d="M16.9328 0C18.0839 0.000116771 19.1334 0.658832 19.634 1.69531L31.4299 26.1309C32.0708 27.4588 31.1036 28.9999 29.6291 29H2.00215C0.527541 29 -0.439628 27.4588 0.201371 26.1309L11.9973 1.69531C12.4979 0.658823 13.5474 7.75066e-05 14.6984 0H16.9328ZM3.59493 26H28.0363L16.9328 3H14.6984L3.59493 26ZM15.8156 19C16.9202 19.0001 17.8156 19.8955 17.8156 21C17.8156 22.1045 16.9202 22.9999 15.8156 23C14.7111 23 13.8156 22.1046 13.8156 21C13.8156 19.8954 14.7111 19 15.8156 19ZM17.3156 16.5H14.3156V8.5H17.3156V16.5Z" fill="var(--next-error-title)"></path></svg><h1 style="font-size:24px;font-weight:500;letter-spacing:-0.02em;line-height:32px;margin:0 0 12px 0;color:var(--next-error-title)">This page couldn’t load</h1><p style="font-size:14px;font-weight:400;line-height:21px;margin:0 0 20px 0;color:var(--next-error-message)">A server error occurred. Reload to try again.</p><form style="margin:0"><button type="submit" style="display:inline-flex;align-items:center;justify-content:center;height:32px;padding:0 12px;font-size:14px;font-weight:500;line-height:20px;border-radius:6px;cursor:pointer;color:var(--next-error-btn-text);background:var(--next-error-btn-bg);border:var(--next-error-btn-border)">Reload</button></form></div></div><!--$--><!--/$--><script src="/_next/static/chunks/webpack-b868033a5834586d.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[57121,[],\"\"]\n3:I[74581,[],\"\"]\n4:I[90484,[],\"OutletBoundary\"]\n5:\"$Sreact.suspense\"\n8:I[90484,[],\"ViewportBoundary\"]\na:I[90484,[],\"MetadataBoundary\"]\nc:I[27123,[],\"default\",1]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"_global-error\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"_global-error\",{\"children\":[\"__PAGE__\",{}]}]}],[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":\"$undefined\",\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"html\",null,{\"id\":\"__next_error__\",\"children\":[[\"$\",\"head\",null,{\"children\":[[\"$\",\"title\",null,{\"children\":\"500: This page couldn’t load\"}],[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\":root {--next-error-bg: #fff;--next-error-text: #171717;--next-error-title: #171717;--next-error-message: #171717;--next-error-digest: #666666;--next-error-btn-text: #fff;--next-error-btn-bg: #171717;--next-error-btn-border: none;--next-error-btn-secondary-text: #171717;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(0,0,0,0.08);}@media (prefers-color-scheme: dark) {:root {--next-error-bg: #0a0a0a;--next-error-text: #ededed;--next-error-title: #ededed;--next-error-message: #ededed;--next-error-digest: #a0a0a0;--next-error-btn-text: #0a0a0a;--next-error-btn-bg: #ededed;--next-error-btn-border: none;--next-error-btn-secondary-text: #ededed;--next-error-btn-secondary-bg: transparent;--next-error-btn-secondary-border: 1px solid rgba(255,255,255,0.14);}}body { margin: 0; color: var(--next-error-text); background: var(--next-error-bg); }\"}}]]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"display\":\"flex\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"style\":{\"marginTop\":\"-32px\",\"maxWidth\":\"325px\",\"padding\":\"32px 28px\",\"textAlign\":\"left\"},\"children\":[[\"$\",\"svg\",null,{\"width\":\"32\",\"height\":\"32\",\"viewBox\":\"-0.2 -1.5 32 32\",\"fill\":\"none\",\"style\":{\"marginBottom\":\"24px\"},\"children\":[\"$\",\"path\",null,{\"d\":\"M16.9328 0C18.0839 0.000116771 19.1334 0.658832 19.634 1.69531L31.4299 26.1309C32.0708 27.4588 31.1036 28.9999 29.6291 29H2.00215C0.527541 29 -0.439628 27.4588 0.201371 26.1309L11.9973 1.69531C12.4979 0.658823 13.5474 7.75066e-05 14.6984 0H16.9328ZM3.59493 26H28.0363L16.9328 3H14.6984L3.59493 26ZM15.8156 19C16.9202 19.0001 17.8156 19.8955 17.8156 21C17.8156 22.1045 16.9202 22.9999 15.8156 23C14.7111 23 13.8156 22.1046 13.8156 21C13.8156 19.8954 14.7111 19 15.8156 19ZM17.3156 16.5H14.3156V8.5H17.3156V16.5Z\",\"fill\":\"var(--next-error-title)\"}]}],[\"$\",\"h1\",null,{\"style\":{\"fontSize\":\"24px\",\"fontWeight\":500,\"letterSpacing\":\"-0.02em\",\"lineHeight\":\"32px\",\"margin\":\"0 0 12px 0\",\"color\":\"var(--next-error-title)\"},\"children\":\"This page couldn’t load\"}],[\"$\",\"p\",null,{\"style\":{\"fontSize\":\"14px\",\"fontWeight\":400,\"lineHeight\":\"21px\",\"margin\":\"0 0 20px 0\",\"color\":\"var(--next-error-message)\"},\"children\":\"A server error occurred. Reload to try again.\"}],[\"$\",\"form\",null,{\"style\":{\"margin\":0},\"children\":[\"$\",\"button\",null,{\"type\":\"submit\",\"style\":{\"display\":\"inline-flex\",\"alignItems\":\"center\",\"justifyContent\":\"center\",\"height\":\"32px\",\"padding\":\"0 12px\",\"fontSize\":\"14px\",\"fontWeight\":500,\"lineHeight\":\"20px\",\"borderRadius\":\"6px\",\"cursor\":\"pointer\",\"color\":\"var(--next-error-btn-text)\",\"background\":\"var(--next-error-btn-bg)\",\"border\":\"var(--next-error-btn-border)\"},\"children\":\"Reload\"}]}]]}]}]}]]}],null,[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,null]},null,false,\"$@7\"]},null,false,\"$@7\"],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L8\",null,{\"children\":\"$L9\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$La\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lb\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$c\",[]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"jNiH700EcljeLnbQ2_RCv\"}\n"])</script><script>self.__next_f.push([1,"d:[]\n7:\"$Wd\"\n"])</script><script>self.__next_f.push([1,"9:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"6:null\nb:[]\n"])</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"node":{},"edge":{},"encryptionKey":"
|
|
1
|
+
{"node":{},"edge":{},"encryptionKey":"lxvUlI6K8yjJ6M359DXhJFyiB9qskxFea5NAUoicWAM="}
|
package/package.json
CHANGED
|
@@ -717,7 +717,7 @@ export class AuthStorage {
|
|
|
717
717
|
*/
|
|
718
718
|
async getApiKey(providerId, sessionId, options) {
|
|
719
719
|
// If the model has a local baseUrl, return a dummy key to avoid auth blocking
|
|
720
|
-
if (options?.baseUrl) {
|
|
720
|
+
if (options?.baseUrl && !this.fallbackResolver?.(providerId)) {
|
|
721
721
|
try {
|
|
722
722
|
const hostname = new URL(options.baseUrl).hostname;
|
|
723
723
|
if (hostname === "localhost" || hostname === "127.0.0.1" || hostname === "0.0.0.0" || hostname === "::1") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-storage.js","sourceRoot":"","sources":["../../src/core/auth-storage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Credential storage for API keys and OAuth tokens.\n * Handles loading, saving, and refreshing credentials from auth.json.\n *\n * Supports multiple credentials per provider with round-robin selection,\n * session-sticky hashing, and automatic rate-limit fallback.\n *\n * Uses file locking to prevent race conditions when multiple pi instances\n * try to refresh tokens simultaneously.\n */\n\nimport {\n\tgetEnvApiKey,\n\ttype OAuthCredentials,\n\ttype OAuthLoginCallbacks,\n\ttype OAuthProviderId,\n} from \"@gsd/pi-ai\";\nimport { getOAuthApiKey, getOAuthProvider, getOAuthProviders } from \"@gsd/pi-ai/oauth\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\nimport { AUTH_LOCK_STALE_MS } from \"./constants.js\";\nimport { acquireLockAsync, acquireLockSyncWithRetry } from \"./lock-utils.js\";\nimport { resolveConfigValue } from \"./resolve-config-value.js\";\n\nexport type ApiKeyCredential = {\n\ttype: \"api_key\";\n\tkey: string;\n};\n\nexport type OAuthCredential = {\n\ttype: \"oauth\";\n} & OAuthCredentials;\n\nexport type AuthCredential = ApiKeyCredential | OAuthCredential;\n\n// ============================================================================\n// Google OAuth token detection\n// ============================================================================\n\n/**\n * Providers that use Google AI Studio API keys (not OAuth tokens).\n * OAuth access tokens (ya29.*) are not valid API keys for these providers.\n */\nconst GOOGLE_API_KEY_PROVIDERS = new Set([\"google\"]);\n\n/**\n * Detect if a string is a Google OAuth access token rather than an API key.\n * Google OAuth access tokens start with \"ya29.\" — these are issued by\n * Google's OAuth2 token endpoint and are not valid as AI Studio API keys.\n *\n * Users who installed Google's Gemini CLI may have these tokens and\n * mistakenly set them as GEMINI_API_KEY.\n */\nexport function isGoogleOAuthToken(key: string): boolean {\n\treturn key.startsWith(\"ya29.\");\n}\n\n/**\n * Validate that an API key is not a Google OAuth token being used for\n * a provider that requires actual API keys (e.g., Google AI Studio).\n * Throws a descriptive error if the key appears to be an OAuth token.\n */\nfunction validateNotGoogleOAuthToken(provider: string, key: string): void {\n\tif (GOOGLE_API_KEY_PROVIDERS.has(provider) && isGoogleOAuthToken(key)) {\n\t\tthrow new Error(\n\t\t\t`The provided key for \"${provider}\" appears to be a Google OAuth access token (ya29.*), ` +\n\t\t\t\t`not a valid API key. Google AI Studio requires an API key starting with \"AIza...\". ` +\n\t\t\t\t`\\n\\nIf you're using Google's Gemini CLI, its OAuth tokens are not compatible. ` +\n\t\t\t\t`Either:\\n` +\n\t\t\t\t` 1. Get an API key from https://aistudio.google.com/apikey and set GEMINI_API_KEY\\n` +\n\t\t\t\t` 2. Use '/login google-gemini-cli' to authenticate via Cloud Code Assist`,\n\t\t);\n\t}\n}\n\n/**\n * On-disk format: each provider maps to a single credential or an array of credentials.\n * Single credentials are normalized to arrays at load time for internal use.\n */\nexport type AuthStorageData = Record<string, AuthCredential | AuthCredential[]>;\n\ntype LockResult<T> = {\n\tresult: T;\n\tnext?: string;\n};\n\nexport interface AuthStorageBackend {\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T;\n\twithLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T>;\n}\n\nexport class FileAuthStorageBackend implements AuthStorageBackend {\n\tconstructor(private authPath: string = join(getAgentDir(), \"auth.json\")) {}\n\n\tprivate ensureParentDir(): void {\n\t\tconst dir = dirname(this.authPath);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t\t}\n\t}\n\n\tprivate ensureFileExists(): void {\n\t\tif (!existsSync(this.authPath)) {\n\t\t\twriteFileSync(this.authPath, \"{}\", \"utf-8\");\n\t\t\tchmodSync(this.authPath, 0o600);\n\t\t}\n\t}\n\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T {\n\t\tthis.ensureParentDir();\n\t\tthis.ensureFileExists();\n\n\t\tlet release: (() => void) | undefined;\n\t\ttry {\n\t\t\trelease = acquireLockSyncWithRetry(this.authPath);\n\t\t\tconst current = existsSync(this.authPath) ? readFileSync(this.authPath, \"utf-8\") : undefined;\n\t\t\tconst { result, next } = fn(current);\n\t\t\tif (next !== undefined) {\n\t\t\t\twriteFileSync(this.authPath, next, \"utf-8\");\n\t\t\t\tchmodSync(this.authPath, 0o600);\n\t\t\t}\n\t\t\treturn result;\n\t\t} finally {\n\t\t\tif (release) {\n\t\t\t\trelease();\n\t\t\t}\n\t\t}\n\t}\n\n\tasync withLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T> {\n\t\tthis.ensureParentDir();\n\t\tthis.ensureFileExists();\n\n\t\tlet release: (() => Promise<void>) | undefined;\n\t\tlet lockCompromised = false;\n\t\tlet lockCompromisedError: Error | undefined;\n\t\tconst throwIfCompromised = () => {\n\t\t\tif (lockCompromised) {\n\t\t\t\tthrow lockCompromisedError ?? new Error(\"Auth storage lock was compromised\");\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\trelease = await acquireLockAsync(this.authPath, {\n\t\t\t\tstaleMs: AUTH_LOCK_STALE_MS,\n\t\t\t\tonCompromised: (err) => {\n\t\t\t\t\tlockCompromised = true;\n\t\t\t\t\tlockCompromisedError = err;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tthrowIfCompromised();\n\t\t\tconst current = existsSync(this.authPath) ? readFileSync(this.authPath, \"utf-8\") : undefined;\n\t\t\tconst { result, next } = await fn(current);\n\t\t\tthrowIfCompromised();\n\t\t\tif (next !== undefined) {\n\t\t\t\twriteFileSync(this.authPath, next, \"utf-8\");\n\t\t\t\tchmodSync(this.authPath, 0o600);\n\t\t\t}\n\t\t\tthrowIfCompromised();\n\t\t\treturn result;\n\t\t} finally {\n\t\t\tif (release) {\n\t\t\t\ttry {\n\t\t\t\t\tawait release();\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore unlock errors when lock is compromised.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class InMemoryAuthStorageBackend implements AuthStorageBackend {\n\tprivate value: string | undefined;\n\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T {\n\t\tconst { result, next } = fn(this.value);\n\t\tif (next !== undefined) {\n\t\t\tthis.value = next;\n\t\t}\n\t\treturn result;\n\t}\n\n\tasync withLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T> {\n\t\tconst { result, next } = await fn(this.value);\n\t\tif (next !== undefined) {\n\t\t\tthis.value = next;\n\t\t}\n\t\treturn result;\n\t}\n}\n\n// ============================================================================\n// Backoff durations for different error types (milliseconds)\n// ============================================================================\n\nconst BACKOFF_RATE_LIMIT_MS = 30_000; // 30s for rate limit / 429\nconst BACKOFF_QUOTA_EXHAUSTED_MS = 30 * 60_000; // 30min for quota exhausted\nconst BACKOFF_SERVER_ERROR_MS = 20_000; // 20s for 5xx server errors\nconst BACKOFF_DEFAULT_MS = 60_000; // 60s fallback\n\nexport type UsageLimitErrorType = \"rate_limit\" | \"quota_exhausted\" | \"server_error\" | \"unknown\";\n\n/**\n * Get backoff duration for an error type.\n */\nfunction getBackoffDuration(errorType: UsageLimitErrorType): number {\n\tswitch (errorType) {\n\t\tcase \"rate_limit\":\n\t\t\treturn BACKOFF_RATE_LIMIT_MS;\n\t\tcase \"quota_exhausted\":\n\t\t\treturn BACKOFF_QUOTA_EXHAUSTED_MS;\n\t\tcase \"server_error\":\n\t\t\treturn BACKOFF_SERVER_ERROR_MS;\n\t\tdefault:\n\t\t\treturn BACKOFF_DEFAULT_MS;\n\t}\n}\n\n/**\n * Simple string hash for session-sticky credential selection.\n * Returns a positive integer.\n */\nfunction hashString(str: string): number {\n\tlet hash = 0;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst char = str.charCodeAt(i);\n\t\thash = ((hash << 5) - hash + char) | 0;\n\t}\n\treturn Math.abs(hash);\n}\n\n/**\n * Credential storage backed by a JSON file.\n * Supports multiple credentials per provider with round-robin rotation and rate-limit fallback.\n */\nexport class AuthStorage {\n\tprivate data: AuthStorageData = {};\n\tprivate runtimeOverrides: Map<string, string> = new Map();\n\tprivate fallbackResolver?: (provider: string) => string | undefined;\n\tprivate loadError: Error | null = null;\n\tprivate errors: Error[] = [];\n\tprivate credentialChangeListeners: Set<() => void> = new Set();\n\n\t/**\n\t * Round-robin index per provider. Incremented on each call to getApiKey\n\t * when no sessionId is provided.\n\t */\n\tprivate providerRoundRobinIndex: Map<string, number> = new Map();\n\n\t/**\n\t * Backoff tracking per provider per credential index.\n\t * Map<provider, Map<credentialIndex, backoffExpiresAt>>\n\t */\n\tprivate credentialBackoff: Map<string, Map<number, number>> = new Map();\n\n\t/**\n\t * Provider-level backoff tracking.\n\t * Set when all credentials for a provider are backed off.\n\t * Map<provider, backoffExpiresAt>\n\t */\n\tprivate providerBackoff: Map<string, number> = new Map();\n\n\tprivate constructor(private storage: AuthStorageBackend) {\n\t\tthis.reload();\n\t}\n\n\tstatic create(authPath?: string): AuthStorage {\n\t\treturn new AuthStorage(new FileAuthStorageBackend(authPath ?? join(getAgentDir(), \"auth.json\")));\n\t}\n\n\tstatic fromStorage(storage: AuthStorageBackend): AuthStorage {\n\t\treturn new AuthStorage(storage);\n\t}\n\n\tstatic inMemory(data: AuthStorageData = {}): AuthStorage {\n\t\tconst storage = new InMemoryAuthStorageBackend();\n\t\tstorage.withLock(() => ({ result: undefined, next: JSON.stringify(data, null, 2) }));\n\t\treturn AuthStorage.fromStorage(storage);\n\t}\n\n\t/**\n\t * Set a runtime API key override (not persisted to disk).\n\t * Used for CLI --api-key flag.\n\t */\n\tsetRuntimeApiKey(provider: string, apiKey: string): void {\n\t\tthis.runtimeOverrides.set(provider, apiKey);\n\t}\n\n\t/**\n\t * Remove a runtime API key override.\n\t */\n\tremoveRuntimeApiKey(provider: string): void {\n\t\tthis.runtimeOverrides.delete(provider);\n\t}\n\n\t/**\n\t * Set a fallback resolver for API keys not found in auth.json or env vars.\n\t * Used for custom provider keys from models.json.\n\t */\n\tsetFallbackResolver(resolver: (provider: string) => string | undefined): void {\n\t\tthis.fallbackResolver = resolver;\n\t}\n\n\t/**\n\t * Register a callback to be notified when credentials change (e.g., after OAuth token refresh).\n\t * Returns a function to unregister the listener.\n\t */\n\tonCredentialChange(listener: () => void): () => void {\n\t\tthis.credentialChangeListeners.add(listener);\n\t\treturn () => this.credentialChangeListeners.delete(listener);\n\t}\n\n\tprivate notifyCredentialChange(): void {\n\t\tfor (const listener of this.credentialChangeListeners) {\n\t\t\ttry {\n\t\t\t\tlistener();\n\t\t\t} catch {\n\t\t\t\t// Don't let listener errors break the refresh flow\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate recordError(error: unknown): void {\n\t\tconst normalizedError = error instanceof Error ? error : new Error(String(error));\n\t\tthis.errors.push(normalizedError);\n\t}\n\n\tprivate parseStorageData(content: string | undefined): AuthStorageData {\n\t\tif (!content) {\n\t\t\treturn {};\n\t\t}\n\t\treturn JSON.parse(content) as AuthStorageData;\n\t}\n\n\t/**\n\t * Normalize a storage entry to an array of credentials.\n\t * Handles both single credential (backward compat) and array formats.\n\t */\n\tgetCredentialsForProvider(provider: string): AuthCredential[] {\n\t\tconst entry = this.data[provider];\n\t\tif (!entry) return [];\n\t\tif (Array.isArray(entry)) return entry;\n\t\treturn [entry];\n\t}\n\n\t/**\n\t * Reload credentials from storage.\n\t */\n\treload(): void {\n\t\tlet content: string | undefined;\n\t\ttry {\n\t\t\tthis.storage.withLock((current) => {\n\t\t\t\tcontent = current;\n\t\t\t\treturn { result: undefined };\n\t\t\t});\n\t\t\tthis.data = this.parseStorageData(content);\n\t\t\tthis.loadError = null;\n\t\t} catch (error) {\n\t\t\tthis.loadError = error as Error;\n\t\t\tthis.recordError(error);\n\t\t}\n\t}\n\n\tprivate persistProviderChange(provider: string, credential: AuthCredential | AuthCredential[] | undefined): void {\n\t\tif (this.loadError) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.storage.withLock((current) => {\n\t\t\t\tconst currentData = this.parseStorageData(current);\n\t\t\t\tconst merged: AuthStorageData = { ...currentData };\n\t\t\t\tif (credential) {\n\t\t\t\t\tmerged[provider] = credential;\n\t\t\t\t} else {\n\t\t\t\t\tdelete merged[provider];\n\t\t\t\t}\n\t\t\t\treturn { result: undefined, next: JSON.stringify(merged, null, 2) };\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.recordError(error);\n\t\t}\n\t}\n\n\t/**\n\t * Get the first credential for a provider (backward-compatible).\n\t */\n\tget(provider: string): AuthCredential | undefined {\n\t\tconst creds = this.getCredentialsForProvider(provider);\n\t\treturn creds[0] ?? undefined;\n\t}\n\n\t/**\n\t * Set credential for a provider. For API key credentials, appends to\n\t * existing credentials (accumulation on duplicate login). For OAuth,\n\t * replaces (only one OAuth token per provider makes sense).\n\t */\n\tset(provider: string, credential: AuthCredential): void {\n\t\tif (credential.type === \"api_key\") {\n\t\t\t// Block Google OAuth tokens being stored as API keys for AI Studio providers\n\t\t\tvalidateNotGoogleOAuthToken(provider, credential.key);\n\n\t\t\tconst existing = this.getCredentialsForProvider(provider);\n\t\t\t// Deduplicate: don't add if same key already exists\n\t\t\tconst isDuplicate = existing.some(\n\t\t\t\t(c) => c.type === \"api_key\" && c.key === credential.key,\n\t\t\t);\n\t\t\tif (isDuplicate) return;\n\n\t\t\tconst updated = [...existing, credential];\n\t\t\tthis.data[provider] = updated.length === 1 ? updated[0] : updated;\n\t\t\tthis.persistProviderChange(provider, updated.length === 1 ? updated[0] : updated);\n\t\t} else {\n\t\t\t// OAuth: replace any existing OAuth credential, keep API keys\n\t\t\tconst existing = this.getCredentialsForProvider(provider);\n\t\t\tconst apiKeys = existing.filter((c) => c.type === \"api_key\");\n\t\t\tif (apiKeys.length === 0) {\n\t\t\t\tthis.data[provider] = credential;\n\t\t\t\tthis.persistProviderChange(provider, credential);\n\t\t\t} else {\n\t\t\t\tconst updated = [...apiKeys, credential];\n\t\t\t\tthis.data[provider] = updated;\n\t\t\t\tthis.persistProviderChange(provider, updated);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Remove all credentials for a provider.\n\t */\n\tremove(provider: string): void {\n\t\tdelete this.data[provider];\n\t\tthis.providerRoundRobinIndex.delete(provider);\n\t\tthis.credentialBackoff.delete(provider);\n\t\tthis.providerBackoff.delete(provider);\n\t\tthis.persistProviderChange(provider, undefined);\n\t}\n\n\t/**\n\t * List all providers with credentials.\n\t */\n\tlist(): string[] {\n\t\treturn Object.keys(this.data);\n\t}\n\n\t/**\n\t * Check if credentials exist for a provider in auth.json.\n\t */\n\thas(provider: string): boolean {\n\t\treturn provider in this.data;\n\t}\n\n\t/**\n\t * Check if any form of auth is configured for a provider.\n\t * Unlike getApiKey(), this doesn't refresh OAuth tokens.\n\t */\n\thasAuth(provider: string): boolean {\n\t\tif (this.runtimeOverrides.has(provider)) return true;\n\t\tif (this.data[provider]) return true;\n\t\tif (getEnvApiKey(provider)) return true;\n\t\tif (this.fallbackResolver?.(provider)) return true;\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get all credentials (for passing to getOAuthApiKey).\n\t * Returns normalized format where each provider has a single credential\n\t * (the first one) for backward compatibility with OAuth refresh.\n\t *\n\t * NOTE: For providers with multiple API keys, only the first credential is\n\t * returned. This is intentional — callers use this for OAuth refresh only,\n\t * which is always single-credential. Do not use for API key enumeration.\n\t */\n\tgetAll(): Record<string, AuthCredential> {\n\t\tconst result: Record<string, AuthCredential> = {};\n\t\tfor (const [provider, entry] of Object.entries(this.data)) {\n\t\t\tresult[provider] = Array.isArray(entry) ? entry[0] : entry;\n\t\t}\n\t\treturn result;\n\t}\n\n\tdrainErrors(): Error[] {\n\t\tconst drained = [...this.errors];\n\t\tthis.errors = [];\n\t\treturn drained;\n\t}\n\n\t/**\n\t * Login to an OAuth provider.\n\t */\n\tasync login(providerId: OAuthProviderId, callbacks: OAuthLoginCallbacks): Promise<void> {\n\t\tconst provider = getOAuthProvider(providerId);\n\t\tif (!provider) {\n\t\t\tthrow new Error(`Unknown OAuth provider: ${providerId}`);\n\t\t}\n\n\t\tconst credentials = await provider.login(callbacks);\n\t\tthis.set(providerId, { type: \"oauth\", ...credentials });\n\t}\n\n\t/**\n\t * Logout from a provider.\n\t */\n\tlogout(provider: string): void {\n\t\tthis.remove(provider);\n\t}\n\n\t/**\n\t * Returns true when the provider has credentials configured but all of them\n\t * are currently in a backoff window (e.g. rate-limited or quota exhausted).\n\t * Returns false when there are no credentials or at least one is available.\n\t */\n\tareAllCredentialsBackedOff(provider: string): boolean {\n\t\tconst credentials = this.getCredentialsForProvider(provider);\n\t\tif (credentials.length === 0) return false;\n\t\tfor (let i = 0; i < credentials.length; i++) {\n\t\t\tif (!this.isCredentialBackedOff(provider, i)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Mark an entire provider as exhausted.\n\t * Called when all credentials for a provider are backed off.\n\t */\n\tmarkProviderExhausted(provider: string, errorType: UsageLimitErrorType): void {\n\t\tconst backoffMs = getBackoffDuration(errorType);\n\t\tthis.providerBackoff.set(provider, Date.now() + backoffMs);\n\t}\n\n\t/**\n\t * Check if a provider is currently available (not backed off at provider level).\n\t */\n\tisProviderAvailable(provider: string): boolean {\n\t\tconst expiresAt = this.providerBackoff.get(provider);\n\t\tif (expiresAt === undefined) return true;\n\t\tif (Date.now() >= expiresAt) {\n\t\t\tthis.providerBackoff.delete(provider);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get milliseconds remaining until provider backoff expires.\n\t * Returns 0 if provider is available.\n\t */\n\tgetProviderBackoffRemaining(provider: string): number {\n\t\tconst expiresAt = this.providerBackoff.get(provider);\n\t\tif (expiresAt === undefined) return 0;\n\t\tconst remaining = expiresAt - Date.now();\n\t\tif (remaining <= 0) {\n\t\t\tthis.providerBackoff.delete(provider);\n\t\t\treturn 0;\n\t\t}\n\t\treturn remaining;\n\t}\n\n\t/**\n\t * Get the earliest timestamp at which any credential for this provider\n\t * will become available again. Returns `undefined` when no credentials\n\t * are backed off (i.e. all are immediately available).\n\t *\n\t * Callers can use this to sleep exactly long enough for the cooldown to\n\t * clear instead of using a fixed retry delay that may be shorter than the\n\t * backoff window.\n\t */\n\tgetEarliestBackoffExpiry(provider: string): number | undefined {\n\t\tconst providerMap = this.credentialBackoff.get(provider);\n\t\tif (!providerMap || providerMap.size === 0) return undefined;\n\n\t\tconst now = Date.now();\n\t\tlet earliest: number | undefined;\n\n\t\tfor (const [index, expiresAt] of providerMap) {\n\t\t\tif (expiresAt <= now) {\n\t\t\t\t// Already expired — clean up\n\t\t\t\tproviderMap.delete(index);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (earliest === undefined || expiresAt < earliest) {\n\t\t\t\tearliest = expiresAt;\n\t\t\t}\n\t\t}\n\n\t\treturn earliest;\n\t}\n\n\t/**\n\t * Check if a credential index is currently backed off.\n\t */\n\tprivate isCredentialBackedOff(provider: string, index: number): boolean {\n\t\tconst providerBackoff = this.credentialBackoff.get(provider);\n\t\tif (!providerBackoff) return false;\n\t\tconst expiresAt = providerBackoff.get(index);\n\t\tif (expiresAt === undefined) return false;\n\t\tif (Date.now() >= expiresAt) {\n\t\t\tproviderBackoff.delete(index);\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Select the best credential index for a provider.\n\t * - If sessionId is provided, uses session-sticky hashing as the starting point.\n\t * - Otherwise, uses round-robin as the starting point.\n\t * - Skips credentials that are currently backed off.\n\t * - Returns -1 if all credentials are backed off.\n\t */\n\tprivate selectCredentialIndex(provider: string, credentials: AuthCredential[], sessionId?: string): number {\n\t\tif (credentials.length === 0) return -1;\n\t\tif (credentials.length === 1) {\n\t\t\treturn this.isCredentialBackedOff(provider, 0) ? -1 : 0;\n\t\t}\n\n\t\tlet startIndex: number;\n\t\tif (sessionId) {\n\t\t\tstartIndex = hashString(sessionId) % credentials.length;\n\t\t} else {\n\t\t\tconst current = this.providerRoundRobinIndex.get(provider) ?? 0;\n\t\t\tstartIndex = current % credentials.length;\n\t\t\tthis.providerRoundRobinIndex.set(provider, current + 1);\n\t\t}\n\n\t\t// Try starting from the preferred index, wrapping around\n\t\tfor (let offset = 0; offset < credentials.length; offset++) {\n\t\t\tconst index = (startIndex + offset) % credentials.length;\n\t\t\tif (!this.isCredentialBackedOff(provider, index)) {\n\t\t\t\treturn index;\n\t\t\t}\n\t\t}\n\n\t\t// All credentials are backed off\n\t\treturn -1;\n\t}\n\n\t/**\n\t * Mark a credential as rate-limited. Finds the credential that was most\n\t * recently used for this provider+session and backs it off.\n\t *\n\t * @returns true if another credential is available (caller should retry),\n\t * false if all credentials for this provider are backed off.\n\t */\n\tmarkUsageLimitReached(\n\t\tprovider: string,\n\t\tsessionId?: string,\n\t\toptions?: { errorType?: UsageLimitErrorType },\n\t): boolean {\n\t\tconst credentials = this.getCredentialsForProvider(provider);\n\t\tif (credentials.length === 0) return false;\n\n\t\tconst errorType = options?.errorType ?? \"rate_limit\";\n\n\t\t// For unknown/transport errors (e.g. connection reset, \"terminated\"),\n\t\t// don't back off the only credential — it would make getApiKey() return\n\t\t// undefined and surface a misleading \"Authentication failed\" message.\n\t\tif (errorType === \"unknown\" && credentials.length === 1) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst backoffMs = getBackoffDuration(errorType);\n\n\t\t// Determine which credential was just used (same logic as selectCredentialIndex\n\t\t// but without incrementing round-robin)\n\t\tlet usedIndex: number;\n\t\tif (credentials.length === 1) {\n\t\t\tusedIndex = 0;\n\t\t} else if (sessionId) {\n\t\t\tusedIndex = hashString(sessionId) % credentials.length;\n\t\t} else {\n\t\t\t// Round-robin was already incremented in getApiKey, so the last-used\n\t\t\t// index is (current - 1). Note: in a concurrent scenario where another\n\t\t\t// getApiKey call fires between the original request and this backoff call,\n\t\t\t// we may back off the wrong credential index. This is acceptable because:\n\t\t\t// (a) pi runs single-threaded event loop, (b) backing off the wrong key\n\t\t\t// is safe — it self-heals when the backoff expires.\n\t\t\tconst current = this.providerRoundRobinIndex.get(provider) ?? 0;\n\t\t\tusedIndex = ((current - 1) % credentials.length + credentials.length) % credentials.length;\n\t\t}\n\n\t\t// Set backoff for this credential\n\t\tlet providerBackoff = this.credentialBackoff.get(provider);\n\t\tif (!providerBackoff) {\n\t\t\tproviderBackoff = new Map();\n\t\t\tthis.credentialBackoff.set(provider, providerBackoff);\n\t\t}\n\t\tproviderBackoff.set(usedIndex, Date.now() + backoffMs);\n\n\t\t// Check if any credential is still available\n\t\tfor (let i = 0; i < credentials.length; i++) {\n\t\t\tif (!this.isCredentialBackedOff(provider, i)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Refresh OAuth token with backend locking to prevent race conditions.\n\t * Multiple pi instances may try to refresh simultaneously when tokens expire.\n\t */\n\tprivate async refreshOAuthTokenWithLock(\n\t\tproviderId: OAuthProviderId,\n\t): Promise<{ apiKey: string; newCredentials: OAuthCredentials } | null> {\n\t\tconst provider = getOAuthProvider(providerId);\n\t\tif (!provider) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst result = await this.storage.withLockAsync(async (current) => {\n\t\t\tconst currentData = this.parseStorageData(current);\n\t\t\tthis.data = currentData;\n\t\t\tthis.loadError = null;\n\n\t\t\t// Find the OAuth credential for this provider\n\t\t\tconst creds = this.getCredentialsForProvider(providerId);\n\t\t\tconst cred = creds.find((c) => c.type === \"oauth\");\n\t\t\tif (!cred || cred.type !== \"oauth\") {\n\t\t\t\treturn { result: null };\n\t\t\t}\n\n\t\t\tif (Date.now() < cred.expires) {\n\t\t\t\treturn { result: { apiKey: provider.getApiKey(cred), newCredentials: cred } };\n\t\t\t}\n\n\t\t\tconst oauthCreds: Record<string, OAuthCredentials> = {};\n\t\t\tfor (const [key, value] of Object.entries(currentData)) {\n\t\t\t\tconst first = Array.isArray(value) ? value.find((c) => c.type === \"oauth\") : value;\n\t\t\t\tif (first?.type === \"oauth\") {\n\t\t\t\t\toauthCreds[key] = first;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst refreshed = await getOAuthApiKey(providerId, oauthCreds);\n\t\t\tif (!refreshed) {\n\t\t\t\treturn { result: null };\n\t\t\t}\n\n\t\t\t// Update the OAuth credential in-place within the array\n\t\t\tconst existingEntry = currentData[providerId];\n\t\t\tconst newOAuthCred: OAuthCredential = { type: \"oauth\", ...refreshed.newCredentials };\n\t\t\tlet updatedEntry: AuthCredential | AuthCredential[];\n\n\t\t\tif (Array.isArray(existingEntry)) {\n\t\t\t\tupdatedEntry = existingEntry.map((c) => (c.type === \"oauth\" ? newOAuthCred : c));\n\t\t\t} else {\n\t\t\t\tupdatedEntry = newOAuthCred;\n\t\t\t}\n\n\t\t\tconst merged: AuthStorageData = {\n\t\t\t\t...currentData,\n\t\t\t\t[providerId]: updatedEntry,\n\t\t\t};\n\t\t\tthis.data = merged;\n\t\t\tthis.loadError = null;\n\t\t\treturn { result: refreshed, next: JSON.stringify(merged, null, 2) };\n\t\t});\n\n\t\t// Notify listeners after credential change (e.g., model registry refresh)\n\t\tif (result) {\n\t\t\tqueueMicrotask(() => this.notifyCredentialChange());\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Resolve an API key from a single credential.\n\t */\n\tprivate async resolveCredentialApiKey(\n\t\tproviderId: string,\n\t\tcred: AuthCredential,\n\t): Promise<string | undefined> {\n\t\tif (cred.type === \"api_key\") {\n\t\t\treturn resolveConfigValue(cred.key);\n\t\t}\n\n\t\tif (cred.type === \"oauth\") {\n\t\t\tconst provider = getOAuthProvider(providerId);\n\t\t\tif (!provider) return undefined;\n\n\t\t\tconst needsRefresh = Date.now() >= cred.expires;\n\t\t\tif (needsRefresh) {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await this.refreshOAuthTokenWithLock(providerId);\n\t\t\t\t\tif (result) return result.apiKey;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.recordError(error);\n\t\t\t\t\tthis.reload();\n\t\t\t\t\tconst updatedCreds = this.getCredentialsForProvider(providerId);\n\t\t\t\t\tconst updatedOAuth = updatedCreds.find((c) => c.type === \"oauth\");\n\t\t\t\t\tif (updatedOAuth?.type === \"oauth\" && Date.now() < updatedOAuth.expires) {\n\t\t\t\t\t\treturn provider.getApiKey(updatedOAuth);\n\t\t\t\t\t}\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn provider.getApiKey(cred);\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Get API key for a provider.\n\t * Priority:\n\t * 1. Runtime override (CLI --api-key)\n\t * 2. Credential(s) from auth.json (with round-robin / session-sticky selection)\n\t * 3. Environment variable\n\t * 4. Fallback resolver (models.json custom providers)\n\t *\n\t * @param providerId - The provider to get an API key for\n\t * @param sessionId - Optional session ID for sticky credential selection\n\t */\n\tasync getApiKey(providerId: string, sessionId?: string, options?: { baseUrl?: string }): Promise<string | undefined> {\n\t\t// If the model has a local baseUrl, return a dummy key to avoid auth blocking\n\t\tif (options?.baseUrl) {\n\t\t\ttry {\n\t\t\t\tconst hostname = new URL(options.baseUrl).hostname;\n\t\t\t\tif (hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"0.0.0.0\" || hostname === \"::1\") {\n\t\t\t\t\treturn \"local-no-key-needed\";\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tif (options.baseUrl.startsWith(\"unix:\")) {\n\t\t\t\t\treturn \"local-no-key-needed\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Runtime override takes highest priority\n\t\tconst runtimeKey = this.runtimeOverrides.get(providerId);\n\t\tif (runtimeKey) {\n\t\t\t// Block Google OAuth tokens used as runtime API key overrides\n\t\t\tif (GOOGLE_API_KEY_PROVIDERS.has(providerId) && isGoogleOAuthToken(runtimeKey)) {\n\t\t\t\tthis.recordError(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`Blocked Google OAuth access token (ya29.*) for provider \"${providerId}\". ` +\n\t\t\t\t\t\t\t`Use an API key from https://aistudio.google.com/apikey or '/login google-gemini-cli'.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn runtimeKey;\n\t\t}\n\n\t\tconst credentials = this.getCredentialsForProvider(providerId);\n\n\t\tif (credentials.length > 0) {\n\t\t\tconst index = this.selectCredentialIndex(providerId, credentials, sessionId);\n\t\t\tif (index >= 0) {\n\t\t\t\tconst resolved = await this.resolveCredentialApiKey(providerId, credentials[index]);\n\t\t\t\tif (resolved) return resolved;\n\t\t\t\t// Credential unresolvable (e.g. type:\"oauth\" for a non-OAuth provider) —\n\t\t\t\t// fall through to env / fallback instead of returning undefined (#2083)\n\t\t\t}\n\t\t\t// All credentials backed off or unresolvable - fall through to env/fallback\n\t\t}\n\n\t\t// Fall back to environment variable\n\t\tconst envKey = getEnvApiKey(providerId);\n\t\tif (envKey) {\n\t\t\t// Block Google OAuth tokens from environment variables (e.g., GEMINI_API_KEY=ya29.*)\n\t\t\tif (GOOGLE_API_KEY_PROVIDERS.has(providerId) && isGoogleOAuthToken(envKey)) {\n\t\t\t\tthis.recordError(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`GEMINI_API_KEY contains a Google OAuth access token (ya29.*), not an API key. ` +\n\t\t\t\t\t\t\t`Get an API key from https://aistudio.google.com/apikey or use '/login google-gemini-cli'.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn envKey;\n\t\t}\n\n\t\t// Fall back to custom resolver (e.g., models.json custom providers)\n\t\treturn this.fallbackResolver?.(providerId) ?? undefined;\n\t}\n\n\t/**\n\t * Get all registered OAuth providers\n\t */\n\tgetOAuthProviders() {\n\t\treturn getOAuthProviders();\n\t}\n}\n"]}
|
|
1
|
+
{"version":3,"file":"auth-storage.js","sourceRoot":"","sources":["../../src/core/auth-storage.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Credential storage for API keys and OAuth tokens.\n * Handles loading, saving, and refreshing credentials from auth.json.\n *\n * Supports multiple credentials per provider with round-robin selection,\n * session-sticky hashing, and automatic rate-limit fallback.\n *\n * Uses file locking to prevent race conditions when multiple pi instances\n * try to refresh tokens simultaneously.\n */\n\nimport {\n\tgetEnvApiKey,\n\ttype OAuthCredentials,\n\ttype OAuthLoginCallbacks,\n\ttype OAuthProviderId,\n} from \"@gsd/pi-ai\";\nimport { getOAuthApiKey, getOAuthProvider, getOAuthProviders } from \"@gsd/pi-ai/oauth\";\nimport { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync } from \"fs\";\nimport { dirname, join } from \"path\";\nimport { getAgentDir } from \"../config.js\";\nimport { AUTH_LOCK_STALE_MS } from \"./constants.js\";\nimport { acquireLockAsync, acquireLockSyncWithRetry } from \"./lock-utils.js\";\nimport { resolveConfigValue } from \"./resolve-config-value.js\";\n\nexport type ApiKeyCredential = {\n\ttype: \"api_key\";\n\tkey: string;\n};\n\nexport type OAuthCredential = {\n\ttype: \"oauth\";\n} & OAuthCredentials;\n\nexport type AuthCredential = ApiKeyCredential | OAuthCredential;\n\n// ============================================================================\n// Google OAuth token detection\n// ============================================================================\n\n/**\n * Providers that use Google AI Studio API keys (not OAuth tokens).\n * OAuth access tokens (ya29.*) are not valid API keys for these providers.\n */\nconst GOOGLE_API_KEY_PROVIDERS = new Set([\"google\"]);\n\n/**\n * Detect if a string is a Google OAuth access token rather than an API key.\n * Google OAuth access tokens start with \"ya29.\" — these are issued by\n * Google's OAuth2 token endpoint and are not valid as AI Studio API keys.\n *\n * Users who installed Google's Gemini CLI may have these tokens and\n * mistakenly set them as GEMINI_API_KEY.\n */\nexport function isGoogleOAuthToken(key: string): boolean {\n\treturn key.startsWith(\"ya29.\");\n}\n\n/**\n * Validate that an API key is not a Google OAuth token being used for\n * a provider that requires actual API keys (e.g., Google AI Studio).\n * Throws a descriptive error if the key appears to be an OAuth token.\n */\nfunction validateNotGoogleOAuthToken(provider: string, key: string): void {\n\tif (GOOGLE_API_KEY_PROVIDERS.has(provider) && isGoogleOAuthToken(key)) {\n\t\tthrow new Error(\n\t\t\t`The provided key for \"${provider}\" appears to be a Google OAuth access token (ya29.*), ` +\n\t\t\t\t`not a valid API key. Google AI Studio requires an API key starting with \"AIza...\". ` +\n\t\t\t\t`\\n\\nIf you're using Google's Gemini CLI, its OAuth tokens are not compatible. ` +\n\t\t\t\t`Either:\\n` +\n\t\t\t\t` 1. Get an API key from https://aistudio.google.com/apikey and set GEMINI_API_KEY\\n` +\n\t\t\t\t` 2. Use '/login google-gemini-cli' to authenticate via Cloud Code Assist`,\n\t\t);\n\t}\n}\n\n/**\n * On-disk format: each provider maps to a single credential or an array of credentials.\n * Single credentials are normalized to arrays at load time for internal use.\n */\nexport type AuthStorageData = Record<string, AuthCredential | AuthCredential[]>;\n\ntype LockResult<T> = {\n\tresult: T;\n\tnext?: string;\n};\n\nexport interface AuthStorageBackend {\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T;\n\twithLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T>;\n}\n\nexport class FileAuthStorageBackend implements AuthStorageBackend {\n\tconstructor(private authPath: string = join(getAgentDir(), \"auth.json\")) {}\n\n\tprivate ensureParentDir(): void {\n\t\tconst dir = dirname(this.authPath);\n\t\tif (!existsSync(dir)) {\n\t\t\tmkdirSync(dir, { recursive: true, mode: 0o700 });\n\t\t}\n\t}\n\n\tprivate ensureFileExists(): void {\n\t\tif (!existsSync(this.authPath)) {\n\t\t\twriteFileSync(this.authPath, \"{}\", \"utf-8\");\n\t\t\tchmodSync(this.authPath, 0o600);\n\t\t}\n\t}\n\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T {\n\t\tthis.ensureParentDir();\n\t\tthis.ensureFileExists();\n\n\t\tlet release: (() => void) | undefined;\n\t\ttry {\n\t\t\trelease = acquireLockSyncWithRetry(this.authPath);\n\t\t\tconst current = existsSync(this.authPath) ? readFileSync(this.authPath, \"utf-8\") : undefined;\n\t\t\tconst { result, next } = fn(current);\n\t\t\tif (next !== undefined) {\n\t\t\t\twriteFileSync(this.authPath, next, \"utf-8\");\n\t\t\t\tchmodSync(this.authPath, 0o600);\n\t\t\t}\n\t\t\treturn result;\n\t\t} finally {\n\t\t\tif (release) {\n\t\t\t\trelease();\n\t\t\t}\n\t\t}\n\t}\n\n\tasync withLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T> {\n\t\tthis.ensureParentDir();\n\t\tthis.ensureFileExists();\n\n\t\tlet release: (() => Promise<void>) | undefined;\n\t\tlet lockCompromised = false;\n\t\tlet lockCompromisedError: Error | undefined;\n\t\tconst throwIfCompromised = () => {\n\t\t\tif (lockCompromised) {\n\t\t\t\tthrow lockCompromisedError ?? new Error(\"Auth storage lock was compromised\");\n\t\t\t}\n\t\t};\n\n\t\ttry {\n\t\t\trelease = await acquireLockAsync(this.authPath, {\n\t\t\t\tstaleMs: AUTH_LOCK_STALE_MS,\n\t\t\t\tonCompromised: (err) => {\n\t\t\t\t\tlockCompromised = true;\n\t\t\t\t\tlockCompromisedError = err;\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tthrowIfCompromised();\n\t\t\tconst current = existsSync(this.authPath) ? readFileSync(this.authPath, \"utf-8\") : undefined;\n\t\t\tconst { result, next } = await fn(current);\n\t\t\tthrowIfCompromised();\n\t\t\tif (next !== undefined) {\n\t\t\t\twriteFileSync(this.authPath, next, \"utf-8\");\n\t\t\t\tchmodSync(this.authPath, 0o600);\n\t\t\t}\n\t\t\tthrowIfCompromised();\n\t\t\treturn result;\n\t\t} finally {\n\t\t\tif (release) {\n\t\t\t\ttry {\n\t\t\t\t\tawait release();\n\t\t\t\t} catch {\n\t\t\t\t\t// Ignore unlock errors when lock is compromised.\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n}\n\nexport class InMemoryAuthStorageBackend implements AuthStorageBackend {\n\tprivate value: string | undefined;\n\n\twithLock<T>(fn: (current: string | undefined) => LockResult<T>): T {\n\t\tconst { result, next } = fn(this.value);\n\t\tif (next !== undefined) {\n\t\t\tthis.value = next;\n\t\t}\n\t\treturn result;\n\t}\n\n\tasync withLockAsync<T>(fn: (current: string | undefined) => Promise<LockResult<T>>): Promise<T> {\n\t\tconst { result, next } = await fn(this.value);\n\t\tif (next !== undefined) {\n\t\t\tthis.value = next;\n\t\t}\n\t\treturn result;\n\t}\n}\n\n// ============================================================================\n// Backoff durations for different error types (milliseconds)\n// ============================================================================\n\nconst BACKOFF_RATE_LIMIT_MS = 30_000; // 30s for rate limit / 429\nconst BACKOFF_QUOTA_EXHAUSTED_MS = 30 * 60_000; // 30min for quota exhausted\nconst BACKOFF_SERVER_ERROR_MS = 20_000; // 20s for 5xx server errors\nconst BACKOFF_DEFAULT_MS = 60_000; // 60s fallback\n\nexport type UsageLimitErrorType = \"rate_limit\" | \"quota_exhausted\" | \"server_error\" | \"unknown\";\n\n/**\n * Get backoff duration for an error type.\n */\nfunction getBackoffDuration(errorType: UsageLimitErrorType): number {\n\tswitch (errorType) {\n\t\tcase \"rate_limit\":\n\t\t\treturn BACKOFF_RATE_LIMIT_MS;\n\t\tcase \"quota_exhausted\":\n\t\t\treturn BACKOFF_QUOTA_EXHAUSTED_MS;\n\t\tcase \"server_error\":\n\t\t\treturn BACKOFF_SERVER_ERROR_MS;\n\t\tdefault:\n\t\t\treturn BACKOFF_DEFAULT_MS;\n\t}\n}\n\n/**\n * Simple string hash for session-sticky credential selection.\n * Returns a positive integer.\n */\nfunction hashString(str: string): number {\n\tlet hash = 0;\n\tfor (let i = 0; i < str.length; i++) {\n\t\tconst char = str.charCodeAt(i);\n\t\thash = ((hash << 5) - hash + char) | 0;\n\t}\n\treturn Math.abs(hash);\n}\n\n/**\n * Credential storage backed by a JSON file.\n * Supports multiple credentials per provider with round-robin rotation and rate-limit fallback.\n */\nexport class AuthStorage {\n\tprivate data: AuthStorageData = {};\n\tprivate runtimeOverrides: Map<string, string> = new Map();\n\tprivate fallbackResolver?: (provider: string) => string | undefined;\n\tprivate loadError: Error | null = null;\n\tprivate errors: Error[] = [];\n\tprivate credentialChangeListeners: Set<() => void> = new Set();\n\n\t/**\n\t * Round-robin index per provider. Incremented on each call to getApiKey\n\t * when no sessionId is provided.\n\t */\n\tprivate providerRoundRobinIndex: Map<string, number> = new Map();\n\n\t/**\n\t * Backoff tracking per provider per credential index.\n\t * Map<provider, Map<credentialIndex, backoffExpiresAt>>\n\t */\n\tprivate credentialBackoff: Map<string, Map<number, number>> = new Map();\n\n\t/**\n\t * Provider-level backoff tracking.\n\t * Set when all credentials for a provider are backed off.\n\t * Map<provider, backoffExpiresAt>\n\t */\n\tprivate providerBackoff: Map<string, number> = new Map();\n\n\tprivate constructor(private storage: AuthStorageBackend) {\n\t\tthis.reload();\n\t}\n\n\tstatic create(authPath?: string): AuthStorage {\n\t\treturn new AuthStorage(new FileAuthStorageBackend(authPath ?? join(getAgentDir(), \"auth.json\")));\n\t}\n\n\tstatic fromStorage(storage: AuthStorageBackend): AuthStorage {\n\t\treturn new AuthStorage(storage);\n\t}\n\n\tstatic inMemory(data: AuthStorageData = {}): AuthStorage {\n\t\tconst storage = new InMemoryAuthStorageBackend();\n\t\tstorage.withLock(() => ({ result: undefined, next: JSON.stringify(data, null, 2) }));\n\t\treturn AuthStorage.fromStorage(storage);\n\t}\n\n\t/**\n\t * Set a runtime API key override (not persisted to disk).\n\t * Used for CLI --api-key flag.\n\t */\n\tsetRuntimeApiKey(provider: string, apiKey: string): void {\n\t\tthis.runtimeOverrides.set(provider, apiKey);\n\t}\n\n\t/**\n\t * Remove a runtime API key override.\n\t */\n\tremoveRuntimeApiKey(provider: string): void {\n\t\tthis.runtimeOverrides.delete(provider);\n\t}\n\n\t/**\n\t * Set a fallback resolver for API keys not found in auth.json or env vars.\n\t * Used for custom provider keys from models.json.\n\t */\n\tsetFallbackResolver(resolver: (provider: string) => string | undefined): void {\n\t\tthis.fallbackResolver = resolver;\n\t}\n\n\t/**\n\t * Register a callback to be notified when credentials change (e.g., after OAuth token refresh).\n\t * Returns a function to unregister the listener.\n\t */\n\tonCredentialChange(listener: () => void): () => void {\n\t\tthis.credentialChangeListeners.add(listener);\n\t\treturn () => this.credentialChangeListeners.delete(listener);\n\t}\n\n\tprivate notifyCredentialChange(): void {\n\t\tfor (const listener of this.credentialChangeListeners) {\n\t\t\ttry {\n\t\t\t\tlistener();\n\t\t\t} catch {\n\t\t\t\t// Don't let listener errors break the refresh flow\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate recordError(error: unknown): void {\n\t\tconst normalizedError = error instanceof Error ? error : new Error(String(error));\n\t\tthis.errors.push(normalizedError);\n\t}\n\n\tprivate parseStorageData(content: string | undefined): AuthStorageData {\n\t\tif (!content) {\n\t\t\treturn {};\n\t\t}\n\t\treturn JSON.parse(content) as AuthStorageData;\n\t}\n\n\t/**\n\t * Normalize a storage entry to an array of credentials.\n\t * Handles both single credential (backward compat) and array formats.\n\t */\n\tgetCredentialsForProvider(provider: string): AuthCredential[] {\n\t\tconst entry = this.data[provider];\n\t\tif (!entry) return [];\n\t\tif (Array.isArray(entry)) return entry;\n\t\treturn [entry];\n\t}\n\n\t/**\n\t * Reload credentials from storage.\n\t */\n\treload(): void {\n\t\tlet content: string | undefined;\n\t\ttry {\n\t\t\tthis.storage.withLock((current) => {\n\t\t\t\tcontent = current;\n\t\t\t\treturn { result: undefined };\n\t\t\t});\n\t\t\tthis.data = this.parseStorageData(content);\n\t\t\tthis.loadError = null;\n\t\t} catch (error) {\n\t\t\tthis.loadError = error as Error;\n\t\t\tthis.recordError(error);\n\t\t}\n\t}\n\n\tprivate persistProviderChange(provider: string, credential: AuthCredential | AuthCredential[] | undefined): void {\n\t\tif (this.loadError) {\n\t\t\treturn;\n\t\t}\n\n\t\ttry {\n\t\t\tthis.storage.withLock((current) => {\n\t\t\t\tconst currentData = this.parseStorageData(current);\n\t\t\t\tconst merged: AuthStorageData = { ...currentData };\n\t\t\t\tif (credential) {\n\t\t\t\t\tmerged[provider] = credential;\n\t\t\t\t} else {\n\t\t\t\t\tdelete merged[provider];\n\t\t\t\t}\n\t\t\t\treturn { result: undefined, next: JSON.stringify(merged, null, 2) };\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tthis.recordError(error);\n\t\t}\n\t}\n\n\t/**\n\t * Get the first credential for a provider (backward-compatible).\n\t */\n\tget(provider: string): AuthCredential | undefined {\n\t\tconst creds = this.getCredentialsForProvider(provider);\n\t\treturn creds[0] ?? undefined;\n\t}\n\n\t/**\n\t * Set credential for a provider. For API key credentials, appends to\n\t * existing credentials (accumulation on duplicate login). For OAuth,\n\t * replaces (only one OAuth token per provider makes sense).\n\t */\n\tset(provider: string, credential: AuthCredential): void {\n\t\tif (credential.type === \"api_key\") {\n\t\t\t// Block Google OAuth tokens being stored as API keys for AI Studio providers\n\t\t\tvalidateNotGoogleOAuthToken(provider, credential.key);\n\n\t\t\tconst existing = this.getCredentialsForProvider(provider);\n\t\t\t// Deduplicate: don't add if same key already exists\n\t\t\tconst isDuplicate = existing.some(\n\t\t\t\t(c) => c.type === \"api_key\" && c.key === credential.key,\n\t\t\t);\n\t\t\tif (isDuplicate) return;\n\n\t\t\tconst updated = [...existing, credential];\n\t\t\tthis.data[provider] = updated.length === 1 ? updated[0] : updated;\n\t\t\tthis.persistProviderChange(provider, updated.length === 1 ? updated[0] : updated);\n\t\t} else {\n\t\t\t// OAuth: replace any existing OAuth credential, keep API keys\n\t\t\tconst existing = this.getCredentialsForProvider(provider);\n\t\t\tconst apiKeys = existing.filter((c) => c.type === \"api_key\");\n\t\t\tif (apiKeys.length === 0) {\n\t\t\t\tthis.data[provider] = credential;\n\t\t\t\tthis.persistProviderChange(provider, credential);\n\t\t\t} else {\n\t\t\t\tconst updated = [...apiKeys, credential];\n\t\t\t\tthis.data[provider] = updated;\n\t\t\t\tthis.persistProviderChange(provider, updated);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Remove all credentials for a provider.\n\t */\n\tremove(provider: string): void {\n\t\tdelete this.data[provider];\n\t\tthis.providerRoundRobinIndex.delete(provider);\n\t\tthis.credentialBackoff.delete(provider);\n\t\tthis.providerBackoff.delete(provider);\n\t\tthis.persistProviderChange(provider, undefined);\n\t}\n\n\t/**\n\t * List all providers with credentials.\n\t */\n\tlist(): string[] {\n\t\treturn Object.keys(this.data);\n\t}\n\n\t/**\n\t * Check if credentials exist for a provider in auth.json.\n\t */\n\thas(provider: string): boolean {\n\t\treturn provider in this.data;\n\t}\n\n\t/**\n\t * Check if any form of auth is configured for a provider.\n\t * Unlike getApiKey(), this doesn't refresh OAuth tokens.\n\t */\n\thasAuth(provider: string): boolean {\n\t\tif (this.runtimeOverrides.has(provider)) return true;\n\t\tif (this.data[provider]) return true;\n\t\tif (getEnvApiKey(provider)) return true;\n\t\tif (this.fallbackResolver?.(provider)) return true;\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get all credentials (for passing to getOAuthApiKey).\n\t * Returns normalized format where each provider has a single credential\n\t * (the first one) for backward compatibility with OAuth refresh.\n\t *\n\t * NOTE: For providers with multiple API keys, only the first credential is\n\t * returned. This is intentional — callers use this for OAuth refresh only,\n\t * which is always single-credential. Do not use for API key enumeration.\n\t */\n\tgetAll(): Record<string, AuthCredential> {\n\t\tconst result: Record<string, AuthCredential> = {};\n\t\tfor (const [provider, entry] of Object.entries(this.data)) {\n\t\t\tresult[provider] = Array.isArray(entry) ? entry[0] : entry;\n\t\t}\n\t\treturn result;\n\t}\n\n\tdrainErrors(): Error[] {\n\t\tconst drained = [...this.errors];\n\t\tthis.errors = [];\n\t\treturn drained;\n\t}\n\n\t/**\n\t * Login to an OAuth provider.\n\t */\n\tasync login(providerId: OAuthProviderId, callbacks: OAuthLoginCallbacks): Promise<void> {\n\t\tconst provider = getOAuthProvider(providerId);\n\t\tif (!provider) {\n\t\t\tthrow new Error(`Unknown OAuth provider: ${providerId}`);\n\t\t}\n\n\t\tconst credentials = await provider.login(callbacks);\n\t\tthis.set(providerId, { type: \"oauth\", ...credentials });\n\t}\n\n\t/**\n\t * Logout from a provider.\n\t */\n\tlogout(provider: string): void {\n\t\tthis.remove(provider);\n\t}\n\n\t/**\n\t * Returns true when the provider has credentials configured but all of them\n\t * are currently in a backoff window (e.g. rate-limited or quota exhausted).\n\t * Returns false when there are no credentials or at least one is available.\n\t */\n\tareAllCredentialsBackedOff(provider: string): boolean {\n\t\tconst credentials = this.getCredentialsForProvider(provider);\n\t\tif (credentials.length === 0) return false;\n\t\tfor (let i = 0; i < credentials.length; i++) {\n\t\t\tif (!this.isCredentialBackedOff(provider, i)) return false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Mark an entire provider as exhausted.\n\t * Called when all credentials for a provider are backed off.\n\t */\n\tmarkProviderExhausted(provider: string, errorType: UsageLimitErrorType): void {\n\t\tconst backoffMs = getBackoffDuration(errorType);\n\t\tthis.providerBackoff.set(provider, Date.now() + backoffMs);\n\t}\n\n\t/**\n\t * Check if a provider is currently available (not backed off at provider level).\n\t */\n\tisProviderAvailable(provider: string): boolean {\n\t\tconst expiresAt = this.providerBackoff.get(provider);\n\t\tif (expiresAt === undefined) return true;\n\t\tif (Date.now() >= expiresAt) {\n\t\t\tthis.providerBackoff.delete(provider);\n\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Get milliseconds remaining until provider backoff expires.\n\t * Returns 0 if provider is available.\n\t */\n\tgetProviderBackoffRemaining(provider: string): number {\n\t\tconst expiresAt = this.providerBackoff.get(provider);\n\t\tif (expiresAt === undefined) return 0;\n\t\tconst remaining = expiresAt - Date.now();\n\t\tif (remaining <= 0) {\n\t\t\tthis.providerBackoff.delete(provider);\n\t\t\treturn 0;\n\t\t}\n\t\treturn remaining;\n\t}\n\n\t/**\n\t * Get the earliest timestamp at which any credential for this provider\n\t * will become available again. Returns `undefined` when no credentials\n\t * are backed off (i.e. all are immediately available).\n\t *\n\t * Callers can use this to sleep exactly long enough for the cooldown to\n\t * clear instead of using a fixed retry delay that may be shorter than the\n\t * backoff window.\n\t */\n\tgetEarliestBackoffExpiry(provider: string): number | undefined {\n\t\tconst providerMap = this.credentialBackoff.get(provider);\n\t\tif (!providerMap || providerMap.size === 0) return undefined;\n\n\t\tconst now = Date.now();\n\t\tlet earliest: number | undefined;\n\n\t\tfor (const [index, expiresAt] of providerMap) {\n\t\t\tif (expiresAt <= now) {\n\t\t\t\t// Already expired — clean up\n\t\t\t\tproviderMap.delete(index);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (earliest === undefined || expiresAt < earliest) {\n\t\t\t\tearliest = expiresAt;\n\t\t\t}\n\t\t}\n\n\t\treturn earliest;\n\t}\n\n\t/**\n\t * Check if a credential index is currently backed off.\n\t */\n\tprivate isCredentialBackedOff(provider: string, index: number): boolean {\n\t\tconst providerBackoff = this.credentialBackoff.get(provider);\n\t\tif (!providerBackoff) return false;\n\t\tconst expiresAt = providerBackoff.get(index);\n\t\tif (expiresAt === undefined) return false;\n\t\tif (Date.now() >= expiresAt) {\n\t\t\tproviderBackoff.delete(index);\n\t\t\treturn false;\n\t\t}\n\t\treturn true;\n\t}\n\n\t/**\n\t * Select the best credential index for a provider.\n\t * - If sessionId is provided, uses session-sticky hashing as the starting point.\n\t * - Otherwise, uses round-robin as the starting point.\n\t * - Skips credentials that are currently backed off.\n\t * - Returns -1 if all credentials are backed off.\n\t */\n\tprivate selectCredentialIndex(provider: string, credentials: AuthCredential[], sessionId?: string): number {\n\t\tif (credentials.length === 0) return -1;\n\t\tif (credentials.length === 1) {\n\t\t\treturn this.isCredentialBackedOff(provider, 0) ? -1 : 0;\n\t\t}\n\n\t\tlet startIndex: number;\n\t\tif (sessionId) {\n\t\t\tstartIndex = hashString(sessionId) % credentials.length;\n\t\t} else {\n\t\t\tconst current = this.providerRoundRobinIndex.get(provider) ?? 0;\n\t\t\tstartIndex = current % credentials.length;\n\t\t\tthis.providerRoundRobinIndex.set(provider, current + 1);\n\t\t}\n\n\t\t// Try starting from the preferred index, wrapping around\n\t\tfor (let offset = 0; offset < credentials.length; offset++) {\n\t\t\tconst index = (startIndex + offset) % credentials.length;\n\t\t\tif (!this.isCredentialBackedOff(provider, index)) {\n\t\t\t\treturn index;\n\t\t\t}\n\t\t}\n\n\t\t// All credentials are backed off\n\t\treturn -1;\n\t}\n\n\t/**\n\t * Mark a credential as rate-limited. Finds the credential that was most\n\t * recently used for this provider+session and backs it off.\n\t *\n\t * @returns true if another credential is available (caller should retry),\n\t * false if all credentials for this provider are backed off.\n\t */\n\tmarkUsageLimitReached(\n\t\tprovider: string,\n\t\tsessionId?: string,\n\t\toptions?: { errorType?: UsageLimitErrorType },\n\t): boolean {\n\t\tconst credentials = this.getCredentialsForProvider(provider);\n\t\tif (credentials.length === 0) return false;\n\n\t\tconst errorType = options?.errorType ?? \"rate_limit\";\n\n\t\t// For unknown/transport errors (e.g. connection reset, \"terminated\"),\n\t\t// don't back off the only credential — it would make getApiKey() return\n\t\t// undefined and surface a misleading \"Authentication failed\" message.\n\t\tif (errorType === \"unknown\" && credentials.length === 1) {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst backoffMs = getBackoffDuration(errorType);\n\n\t\t// Determine which credential was just used (same logic as selectCredentialIndex\n\t\t// but without incrementing round-robin)\n\t\tlet usedIndex: number;\n\t\tif (credentials.length === 1) {\n\t\t\tusedIndex = 0;\n\t\t} else if (sessionId) {\n\t\t\tusedIndex = hashString(sessionId) % credentials.length;\n\t\t} else {\n\t\t\t// Round-robin was already incremented in getApiKey, so the last-used\n\t\t\t// index is (current - 1). Note: in a concurrent scenario where another\n\t\t\t// getApiKey call fires between the original request and this backoff call,\n\t\t\t// we may back off the wrong credential index. This is acceptable because:\n\t\t\t// (a) pi runs single-threaded event loop, (b) backing off the wrong key\n\t\t\t// is safe — it self-heals when the backoff expires.\n\t\t\tconst current = this.providerRoundRobinIndex.get(provider) ?? 0;\n\t\t\tusedIndex = ((current - 1) % credentials.length + credentials.length) % credentials.length;\n\t\t}\n\n\t\t// Set backoff for this credential\n\t\tlet providerBackoff = this.credentialBackoff.get(provider);\n\t\tif (!providerBackoff) {\n\t\t\tproviderBackoff = new Map();\n\t\t\tthis.credentialBackoff.set(provider, providerBackoff);\n\t\t}\n\t\tproviderBackoff.set(usedIndex, Date.now() + backoffMs);\n\n\t\t// Check if any credential is still available\n\t\tfor (let i = 0; i < credentials.length; i++) {\n\t\t\tif (!this.isCredentialBackedOff(provider, i)) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\t\treturn false;\n\t}\n\n\t/**\n\t * Refresh OAuth token with backend locking to prevent race conditions.\n\t * Multiple pi instances may try to refresh simultaneously when tokens expire.\n\t */\n\tprivate async refreshOAuthTokenWithLock(\n\t\tproviderId: OAuthProviderId,\n\t): Promise<{ apiKey: string; newCredentials: OAuthCredentials } | null> {\n\t\tconst provider = getOAuthProvider(providerId);\n\t\tif (!provider) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst result = await this.storage.withLockAsync(async (current) => {\n\t\t\tconst currentData = this.parseStorageData(current);\n\t\t\tthis.data = currentData;\n\t\t\tthis.loadError = null;\n\n\t\t\t// Find the OAuth credential for this provider\n\t\t\tconst creds = this.getCredentialsForProvider(providerId);\n\t\t\tconst cred = creds.find((c) => c.type === \"oauth\");\n\t\t\tif (!cred || cred.type !== \"oauth\") {\n\t\t\t\treturn { result: null };\n\t\t\t}\n\n\t\t\tif (Date.now() < cred.expires) {\n\t\t\t\treturn { result: { apiKey: provider.getApiKey(cred), newCredentials: cred } };\n\t\t\t}\n\n\t\t\tconst oauthCreds: Record<string, OAuthCredentials> = {};\n\t\t\tfor (const [key, value] of Object.entries(currentData)) {\n\t\t\t\tconst first = Array.isArray(value) ? value.find((c) => c.type === \"oauth\") : value;\n\t\t\t\tif (first?.type === \"oauth\") {\n\t\t\t\t\toauthCreds[key] = first;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst refreshed = await getOAuthApiKey(providerId, oauthCreds);\n\t\t\tif (!refreshed) {\n\t\t\t\treturn { result: null };\n\t\t\t}\n\n\t\t\t// Update the OAuth credential in-place within the array\n\t\t\tconst existingEntry = currentData[providerId];\n\t\t\tconst newOAuthCred: OAuthCredential = { type: \"oauth\", ...refreshed.newCredentials };\n\t\t\tlet updatedEntry: AuthCredential | AuthCredential[];\n\n\t\t\tif (Array.isArray(existingEntry)) {\n\t\t\t\tupdatedEntry = existingEntry.map((c) => (c.type === \"oauth\" ? newOAuthCred : c));\n\t\t\t} else {\n\t\t\t\tupdatedEntry = newOAuthCred;\n\t\t\t}\n\n\t\t\tconst merged: AuthStorageData = {\n\t\t\t\t...currentData,\n\t\t\t\t[providerId]: updatedEntry,\n\t\t\t};\n\t\t\tthis.data = merged;\n\t\t\tthis.loadError = null;\n\t\t\treturn { result: refreshed, next: JSON.stringify(merged, null, 2) };\n\t\t});\n\n\t\t// Notify listeners after credential change (e.g., model registry refresh)\n\t\tif (result) {\n\t\t\tqueueMicrotask(() => this.notifyCredentialChange());\n\t\t}\n\n\t\treturn result;\n\t}\n\n\t/**\n\t * Resolve an API key from a single credential.\n\t */\n\tprivate async resolveCredentialApiKey(\n\t\tproviderId: string,\n\t\tcred: AuthCredential,\n\t): Promise<string | undefined> {\n\t\tif (cred.type === \"api_key\") {\n\t\t\treturn resolveConfigValue(cred.key);\n\t\t}\n\n\t\tif (cred.type === \"oauth\") {\n\t\t\tconst provider = getOAuthProvider(providerId);\n\t\t\tif (!provider) return undefined;\n\n\t\t\tconst needsRefresh = Date.now() >= cred.expires;\n\t\t\tif (needsRefresh) {\n\t\t\t\ttry {\n\t\t\t\t\tconst result = await this.refreshOAuthTokenWithLock(providerId);\n\t\t\t\t\tif (result) return result.apiKey;\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.recordError(error);\n\t\t\t\t\tthis.reload();\n\t\t\t\t\tconst updatedCreds = this.getCredentialsForProvider(providerId);\n\t\t\t\t\tconst updatedOAuth = updatedCreds.find((c) => c.type === \"oauth\");\n\t\t\t\t\tif (updatedOAuth?.type === \"oauth\" && Date.now() < updatedOAuth.expires) {\n\t\t\t\t\t\treturn provider.getApiKey(updatedOAuth);\n\t\t\t\t\t}\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\treturn provider.getApiKey(cred);\n\t\t\t}\n\t\t}\n\n\t\treturn undefined;\n\t}\n\n\t/**\n\t * Get API key for a provider.\n\t * Priority:\n\t * 1. Runtime override (CLI --api-key)\n\t * 2. Credential(s) from auth.json (with round-robin / session-sticky selection)\n\t * 3. Environment variable\n\t * 4. Fallback resolver (models.json custom providers)\n\t *\n\t * @param providerId - The provider to get an API key for\n\t * @param sessionId - Optional session ID for sticky credential selection\n\t */\n\tasync getApiKey(providerId: string, sessionId?: string, options?: { baseUrl?: string }): Promise<string | undefined> {\n\t\t// If the model has a local baseUrl, return a dummy key to avoid auth blocking\n\t\tif (options?.baseUrl && !this.fallbackResolver?.(providerId)) {\n\t\t\ttry {\n\t\t\t\tconst hostname = new URL(options.baseUrl).hostname;\n\t\t\t\tif (hostname === \"localhost\" || hostname === \"127.0.0.1\" || hostname === \"0.0.0.0\" || hostname === \"::1\") {\n\t\t\t\t\treturn \"local-no-key-needed\";\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\tif (options.baseUrl.startsWith(\"unix:\")) {\n\t\t\t\t\treturn \"local-no-key-needed\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Runtime override takes highest priority\n\t\tconst runtimeKey = this.runtimeOverrides.get(providerId);\n\t\tif (runtimeKey) {\n\t\t\t// Block Google OAuth tokens used as runtime API key overrides\n\t\t\tif (GOOGLE_API_KEY_PROVIDERS.has(providerId) && isGoogleOAuthToken(runtimeKey)) {\n\t\t\t\tthis.recordError(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`Blocked Google OAuth access token (ya29.*) for provider \"${providerId}\". ` +\n\t\t\t\t\t\t\t`Use an API key from https://aistudio.google.com/apikey or '/login google-gemini-cli'.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn runtimeKey;\n\t\t}\n\n\t\tconst credentials = this.getCredentialsForProvider(providerId);\n\n\t\tif (credentials.length > 0) {\n\t\t\tconst index = this.selectCredentialIndex(providerId, credentials, sessionId);\n\t\t\tif (index >= 0) {\n\t\t\t\tconst resolved = await this.resolveCredentialApiKey(providerId, credentials[index]);\n\t\t\t\tif (resolved) return resolved;\n\t\t\t\t// Credential unresolvable (e.g. type:\"oauth\" for a non-OAuth provider) —\n\t\t\t\t// fall through to env / fallback instead of returning undefined (#2083)\n\t\t\t}\n\t\t\t// All credentials backed off or unresolvable - fall through to env/fallback\n\t\t}\n\n\t\t// Fall back to environment variable\n\t\tconst envKey = getEnvApiKey(providerId);\n\t\tif (envKey) {\n\t\t\t// Block Google OAuth tokens from environment variables (e.g., GEMINI_API_KEY=ya29.*)\n\t\t\tif (GOOGLE_API_KEY_PROVIDERS.has(providerId) && isGoogleOAuthToken(envKey)) {\n\t\t\t\tthis.recordError(\n\t\t\t\t\tnew Error(\n\t\t\t\t\t\t`GEMINI_API_KEY contains a Google OAuth access token (ya29.*), not an API key. ` +\n\t\t\t\t\t\t\t`Get an API key from https://aistudio.google.com/apikey or use '/login google-gemini-cli'.`,\n\t\t\t\t\t),\n\t\t\t\t);\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t\treturn envKey;\n\t\t}\n\n\t\t// Fall back to custom resolver (e.g., models.json custom providers)\n\t\treturn this.fallbackResolver?.(providerId) ?? undefined;\n\t}\n\n\t/**\n\t * Get all registered OAuth providers\n\t */\n\tgetOAuthProviders() {\n\t\treturn getOAuthProviders();\n\t}\n}\n"]}
|
|
@@ -435,4 +435,31 @@ describe("AuthStorage — getEarliestBackoffExpiry", () => {
|
|
|
435
435
|
assert.equal(expiry, nearExpiry, "should return the nearest (smallest) expiry");
|
|
436
436
|
});
|
|
437
437
|
});
|
|
438
|
+
// ─── localhost baseUrl shortcut ────────────────────────────────────────────────
|
|
439
|
+
describe("AuthStorage — localhost baseUrl shortcut", () => {
|
|
440
|
+
it("returns 'local-no-key-needed' for localhost provider with no configured key", async () => {
|
|
441
|
+
const storage = inMemory({});
|
|
442
|
+
const key = await storage.getApiKey("ollama", undefined, { baseUrl: "http://localhost:11434" });
|
|
443
|
+
assert.equal(key, "local-no-key-needed");
|
|
444
|
+
});
|
|
445
|
+
it("returns 'local-no-key-needed' for 127.0.0.1 provider with no configured key", async () => {
|
|
446
|
+
const storage = inMemory({});
|
|
447
|
+
const key = await storage.getApiKey("custom", undefined, { baseUrl: "http://127.0.0.1:8080/v1" });
|
|
448
|
+
assert.equal(key, "local-no-key-needed");
|
|
449
|
+
});
|
|
450
|
+
it("returns configured key from fallback resolver for localhost custom provider (#4106)", async () => {
|
|
451
|
+
// Regression test: compaction called getApiKey(model) where model.baseUrl is localhost.
|
|
452
|
+
// The localhost shortcut must NOT override an explicitly configured apiKey from models.json.
|
|
453
|
+
const storage = inMemory({});
|
|
454
|
+
storage.setFallbackResolver((provider) => provider === "cliproxy" ? "sk-real-proxy-key" : undefined);
|
|
455
|
+
const key = await storage.getApiKey("cliproxy", undefined, { baseUrl: "http://localhost:8317/v1" });
|
|
456
|
+
assert.equal(key, "sk-real-proxy-key");
|
|
457
|
+
});
|
|
458
|
+
it("returns configured key from fallback resolver when baseUrl uses 127.0.0.1 (#4106)", async () => {
|
|
459
|
+
const storage = inMemory({});
|
|
460
|
+
storage.setFallbackResolver((provider) => provider === "myproxy" ? "sk-myproxy-key" : undefined);
|
|
461
|
+
const key = await storage.getApiKey("myproxy", undefined, { baseUrl: "http://127.0.0.1:9000/v1" });
|
|
462
|
+
assert.equal(key, "sk-myproxy-key");
|
|
463
|
+
});
|
|
464
|
+
});
|
|
438
465
|
//# sourceMappingURL=auth-storage.test.js.map
|