gsd-pi 2.44.0-dev.62b5d6c → 2.44.0-dev.848dd4c
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/README.md +30 -12
- package/dist/resources/extensions/gsd/auto-start.js +10 -0
- package/dist/resources/extensions/gsd/commands/handlers/workflow.js +5 -0
- package/dist/web/standalone/.next/BUILD_ID +1 -1
- package/dist/web/standalone/.next/app-path-routes-manifest.json +18 -18
- 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 +2 -2
- 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 +18 -18
- package/dist/web/standalone/.next/server/pages/404.html +1 -1
- package/dist/web/standalone/.next/server/pages/500.html +2 -2
- 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.test.js +6 -8
- package/packages/pi-coding-agent/dist/core/auth-storage.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js +24 -26
- package/packages/pi-coding-agent/dist/core/extensions/runner.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js +29 -48
- package/packages/pi-coding-agent/dist/core/fs-utils.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js +34 -44
- package/packages/pi-coding-agent/dist/core/resolve-config-value.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/session-manager.test.js +30 -34
- package/packages/pi-coding-agent/dist/core/session-manager.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js +10 -12
- package/packages/pi-coding-agent/dist/core/tools/edit-diff.test.js.map +1 -1
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js +43 -47
- package/packages/pi-coding-agent/dist/resources/extensions/memory/storage.test.js.map +1 -1
- package/packages/pi-coding-agent/src/core/auth-storage.test.ts +7 -7
- package/packages/pi-coding-agent/src/core/extensions/runner.test.ts +26 -26
- package/packages/pi-coding-agent/src/core/fs-utils.test.ts +31 -43
- package/packages/pi-coding-agent/src/core/resolve-config-value.test.ts +40 -45
- package/packages/pi-coding-agent/src/core/session-manager.test.ts +33 -33
- package/packages/pi-coding-agent/src/core/tools/edit-diff.test.ts +17 -17
- package/packages/pi-coding-agent/src/resources/extensions/memory/storage.test.ts +74 -74
- package/src/resources/extensions/gsd/auto-start.ts +14 -0
- package/src/resources/extensions/gsd/commands/handlers/workflow.ts +8 -0
- package/src/resources/extensions/gsd/tests/all-milestones-complete-merge.test.ts +99 -99
- package/src/resources/extensions/gsd/tests/auto-lock-creation.test.ts +14 -16
- package/src/resources/extensions/gsd/tests/auto-paused-session-validation.test.ts +43 -57
- package/src/resources/extensions/gsd/tests/auto-preflight.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/auto-recovery.test.ts +465 -523
- package/src/resources/extensions/gsd/tests/auto-secrets-gate.test.ts +73 -75
- package/src/resources/extensions/gsd/tests/auto-start-needs-discussion.test.ts +34 -56
- package/src/resources/extensions/gsd/tests/auto-worktree-milestone-merge.test.ts +533 -656
- package/src/resources/extensions/gsd/tests/auto-worktree.test.ts +165 -143
- package/src/resources/extensions/gsd/tests/cache-staleness-regression.test.ts +29 -52
- package/src/resources/extensions/gsd/tests/captures.test.ts +148 -176
- package/src/resources/extensions/gsd/tests/claude-import-tui.test.ts +32 -33
- package/src/resources/extensions/gsd/tests/collect-from-manifest.test.ts +141 -143
- package/src/resources/extensions/gsd/tests/commands-inspect-open-db.test.ts +25 -25
- package/src/resources/extensions/gsd/tests/commands-logs.test.ts +81 -81
- package/src/resources/extensions/gsd/tests/complete-milestone.test.ts +38 -59
- package/src/resources/extensions/gsd/tests/complete-slice.test.ts +228 -263
- package/src/resources/extensions/gsd/tests/complete-task.test.ts +250 -302
- package/src/resources/extensions/gsd/tests/context-store.test.ts +354 -367
- package/src/resources/extensions/gsd/tests/continue-here.test.ts +68 -72
- package/src/resources/extensions/gsd/tests/cost-projection.test.ts +92 -106
- package/src/resources/extensions/gsd/tests/crash-recovery.test.ts +27 -35
- package/src/resources/extensions/gsd/tests/dashboard-budget.test.ts +220 -237
- package/src/resources/extensions/gsd/tests/db-writer.test.ts +390 -420
- package/src/resources/extensions/gsd/tests/definition-loader.test.ts +76 -92
- package/src/resources/extensions/gsd/tests/derive-state-crossval.test.ts +68 -83
- package/src/resources/extensions/gsd/tests/derive-state-db.test.ts +152 -183
- package/src/resources/extensions/gsd/tests/derive-state-deps.test.ts +78 -101
- package/src/resources/extensions/gsd/tests/derive-state.test.ts +192 -227
- package/src/resources/extensions/gsd/tests/detection.test.ts +232 -278
- package/src/resources/extensions/gsd/tests/dev-engine-wrapper.test.ts +30 -34
- package/src/resources/extensions/gsd/tests/dispatch-guard.test.ts +164 -180
- package/src/resources/extensions/gsd/tests/dispatch-missing-task-plans.test.ts +43 -49
- package/src/resources/extensions/gsd/tests/dispatch-uat-last-completed.test.ts +28 -32
- package/src/resources/extensions/gsd/tests/doctor-completion-deferral.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/doctor-delimiter-fix.test.ts +34 -38
- package/src/resources/extensions/gsd/tests/doctor-enhancements.test.ts +54 -75
- package/src/resources/extensions/gsd/tests/doctor-environment-worktree.test.ts +21 -32
- package/src/resources/extensions/gsd/tests/doctor-environment.test.ts +72 -97
- package/src/resources/extensions/gsd/tests/doctor-fixlevel.test.ts +38 -44
- package/src/resources/extensions/gsd/tests/doctor-git.test.ts +104 -145
- package/src/resources/extensions/gsd/tests/doctor-proactive.test.ts +84 -106
- package/src/resources/extensions/gsd/tests/doctor-roadmap-summary-atomicity.test.ts +54 -60
- package/src/resources/extensions/gsd/tests/doctor-runtime.test.ts +72 -93
- package/src/resources/extensions/gsd/tests/doctor.test.ts +104 -134
- package/src/resources/extensions/gsd/tests/ensure-db-open.test.ts +123 -131
- package/src/resources/extensions/gsd/tests/exit-command.test.ts +20 -24
- package/src/resources/extensions/gsd/tests/feature-branch-lifecycle-integration.test.ts +48 -57
- package/src/resources/extensions/gsd/tests/files-loadfile-eisdir.test.ts +5 -7
- package/src/resources/extensions/gsd/tests/flag-file-db.test.ts +30 -42
- package/src/resources/extensions/gsd/tests/freeform-decisions.test.ts +198 -206
- package/src/resources/extensions/gsd/tests/git-locale.test.ts +13 -27
- package/src/resources/extensions/gsd/tests/git-service.test.ts +285 -388
- package/src/resources/extensions/gsd/tests/gitignore-tracked-gsd.test.ts +31 -39
- package/src/resources/extensions/gsd/tests/graph-operations.test.ts +63 -69
- package/src/resources/extensions/gsd/tests/gsd-db.test.ts +255 -264
- package/src/resources/extensions/gsd/tests/gsd-inspect.test.ts +108 -119
- package/src/resources/extensions/gsd/tests/gsd-recover.test.ts +81 -103
- package/src/resources/extensions/gsd/tests/gsd-tools.test.ts +229 -262
- package/src/resources/extensions/gsd/tests/headless-answers.test.ts +13 -13
- package/src/resources/extensions/gsd/tests/health-widget.test.ts +29 -37
- package/src/resources/extensions/gsd/tests/idle-recovery.test.ts +81 -102
- package/src/resources/extensions/gsd/tests/init-wizard.test.ts +16 -18
- package/src/resources/extensions/gsd/tests/integration-edge.test.ts +41 -46
- package/src/resources/extensions/gsd/tests/integration-lifecycle.test.ts +42 -53
- package/src/resources/extensions/gsd/tests/integration-mixed-milestones.test.ts +75 -91
- package/src/resources/extensions/gsd/tests/integration-proof.test.ts +18 -18
- package/src/resources/extensions/gsd/tests/markdown-renderer.test.ts +150 -194
- package/src/resources/extensions/gsd/tests/md-importer.test.ts +101 -125
- package/src/resources/extensions/gsd/tests/memory-extractor.test.ts +45 -54
- package/src/resources/extensions/gsd/tests/memory-store.test.ts +80 -93
- package/src/resources/extensions/gsd/tests/migrate-command.test.ts +57 -66
- package/src/resources/extensions/gsd/tests/migrate-hierarchy.test.ts +83 -93
- package/src/resources/extensions/gsd/tests/migrate-parser.test.ts +161 -170
- package/src/resources/extensions/gsd/tests/migrate-transformer.test.ts +125 -141
- package/src/resources/extensions/gsd/tests/migrate-validator-parsers.test.ts +107 -131
- package/src/resources/extensions/gsd/tests/migrate-writer-integration.test.ts +87 -96
- package/src/resources/extensions/gsd/tests/migrate-writer.test.ts +125 -164
- package/src/resources/extensions/gsd/tests/must-have-parser.test.ts +81 -94
- package/src/resources/extensions/gsd/tests/none-mode-gates.test.ts +35 -36
- package/src/resources/extensions/gsd/tests/overrides.test.ts +99 -106
- package/src/resources/extensions/gsd/tests/parallel-crash-recovery.test.ts +40 -47
- package/src/resources/extensions/gsd/tests/parallel-worker-monitoring.test.ts +25 -28
- package/src/resources/extensions/gsd/tests/parallel-workers-multi-milestone-e2e.test.ts +66 -83
- package/src/resources/extensions/gsd/tests/park-edge-cases.test.ts +54 -77
- package/src/resources/extensions/gsd/tests/park-milestone.test.ts +68 -115
- package/src/resources/extensions/gsd/tests/parsers.test.ts +546 -611
- package/src/resources/extensions/gsd/tests/paths.test.ts +72 -87
- package/src/resources/extensions/gsd/tests/post-unit-hooks.test.ts +77 -117
- package/src/resources/extensions/gsd/tests/prompt-db.test.ts +56 -56
- package/src/resources/extensions/gsd/tests/queue-draft-detection.test.ts +93 -119
- package/src/resources/extensions/gsd/tests/queue-order.test.ts +70 -82
- package/src/resources/extensions/gsd/tests/queue-reorder-e2e.test.ts +42 -55
- package/src/resources/extensions/gsd/tests/quick-auto-guard.test.ts +100 -0
- package/src/resources/extensions/gsd/tests/quick-branch-lifecycle.test.ts +45 -73
- package/src/resources/extensions/gsd/tests/reassess-prompt.test.ts +28 -38
- package/src/resources/extensions/gsd/tests/replan-slice.test.ts +73 -80
- package/src/resources/extensions/gsd/tests/repo-identity-worktree.test.ts +71 -74
- package/src/resources/extensions/gsd/tests/requirements.test.ts +70 -75
- package/src/resources/extensions/gsd/tests/retry-state-reset.test.ts +44 -66
- package/src/resources/extensions/gsd/tests/roadmap-parse-regression.test.ts +114 -181
- package/src/resources/extensions/gsd/tests/rule-registry.test.ts +63 -65
- package/src/resources/extensions/gsd/tests/run-uat.test.ts +66 -128
- package/src/resources/extensions/gsd/tests/session-lock-multipath.test.ts +18 -25
- package/src/resources/extensions/gsd/tests/session-lock-regression.test.ts +37 -44
- package/src/resources/extensions/gsd/tests/shared-wal.test.ts +19 -26
- package/src/resources/extensions/gsd/tests/sqlite-unavailable-gate.test.ts +63 -0
- package/src/resources/extensions/gsd/tests/stalled-tool-recovery.test.ts +6 -8
- package/src/resources/extensions/gsd/tests/symlink-numbered-variants.test.ts +22 -28
- package/src/resources/extensions/gsd/tests/token-savings.test.ts +54 -56
- package/src/resources/extensions/gsd/tests/tool-call-loop-guard.test.ts +23 -25
- package/src/resources/extensions/gsd/tests/tool-naming.test.ts +9 -11
- package/src/resources/extensions/gsd/tests/unique-milestone-ids.test.ts +66 -82
- package/src/resources/extensions/gsd/tests/unit-runtime.test.ts +46 -47
- package/src/resources/extensions/gsd/tests/visualizer-critical-path.test.ts +20 -22
- package/src/resources/extensions/gsd/tests/visualizer-data.test.ts +84 -86
- package/src/resources/extensions/gsd/tests/visualizer-overlay.test.ts +41 -43
- package/src/resources/extensions/gsd/tests/visualizer-views.test.ts +94 -96
- package/src/resources/extensions/gsd/tests/windows-path-normalization.test.ts +11 -13
- package/src/resources/extensions/gsd/tests/worker-registry.test.ts +27 -29
- package/src/resources/extensions/gsd/tests/workflow-templates.test.ts +50 -52
- package/src/resources/extensions/gsd/tests/worktree-bugfix.test.ts +10 -13
- package/src/resources/extensions/gsd/tests/worktree-db-integration.test.ts +14 -18
- package/src/resources/extensions/gsd/tests/worktree-db.test.ts +38 -39
- package/src/resources/extensions/gsd/tests/worktree-e2e.test.ts +17 -21
- package/src/resources/extensions/gsd/tests/worktree-health.test.ts +25 -30
- package/src/resources/extensions/gsd/tests/worktree-integration.test.ts +30 -37
- package/src/resources/extensions/gsd/tests/worktree-symlink-removal.test.ts +15 -22
- package/src/resources/extensions/gsd/tests/worktree-sync-milestones.test.ts +59 -66
- package/src/resources/extensions/gsd/tests/worktree.test.ts +44 -50
- /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → -zps1Q9mQmioAKLcQiCr8}/_buildManifest.js +0 -0
- /package/dist/web/standalone/.next/static/{fOnWQBjWXMKUs4bqTg530 → -zps1Q9mQmioAKLcQiCr8}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
1
|
+
<!DOCTYPE html><!--_zps1Q9mQmioAKLcQiCr8--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><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/8a727f372cf53002.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-9014b5adb127a98a.js"/><script src="/_next/static/chunks/4bd1b696-e5d7c65570c947b7.js" async=""></script><script src="/_next/static/chunks/3794-337d1ca25ad99a89.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><script src="/_next/static/chunks/app/page-b9367c5ae13b99c6.js" async=""></script><meta name="next-size-adjust" content=""/><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><!--$!--><template data-dgst="BAILOUT_TO_CLIENT_SIDE_RENDERING"></template><div class="flex h-screen items-center justify-center bg-background text-sm text-muted-foreground">Loading workspace…</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-9014b5adb127a98a.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[61304,[],\"ClientPageRoot\"]\n7:I[66919,[\"8974\",\"static/chunks/app/page-b9367c5ae13b99c6.js\"],\"default\"]\na:I[90484,[],\"OutletBoundary\"]\nb:\"$Sreact.suspense\"\nd:I[90484,[],\"ViewportBoundary\"]\nf:I[90484,[],\"MetadataBoundary\"]\n11:I[27123,[],\"\"]\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/8a727f372cf53002.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"-zps1Q9mQmioAKLcQiCr8\",\"c\":[\"\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$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/8a727f372cf53002.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\":[[[\"$\",\"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.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],[\"$\",\"$L5\",null,{\"position\":\"bottom-right\"}]]}]}]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"$L6\",null,{\"Component\":\"$7\",\"serverProvidedParams\":{\"searchParams\":{},\"params\":{},\"promises\":[\"$@8\",\"$@9\"]}}],null,[\"$\",\"$La\",null,{\"children\":[\"$\",\"$b\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@c\"}]}]]}],{},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$Ld\",null,{\"children\":\"$Le\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lf\",null,{\"children\":[\"$\",\"$b\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L10\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$11\",[]],\"S\":true}\n"])</script><script>self.__next_f.push([1,"8:{}\n9:\"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params\"\n"])</script><script>self.__next_f.push([1,"e:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"12:I[86869,[],\"IconMark\"]\nc:null\n10:[[\"$\",\"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\"}],[\"$\",\"$L12\",\"6\",{}]]\n"])</script></body></html>
|
|
@@ -14,7 +14,7 @@ f:I[90484,[],"MetadataBoundary"]
|
|
|
14
14
|
:HL["/_next/static/media/93f479601ee12b01-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
15
15
|
:HL["/_next/static/css/de70bee13400563f.css","style"]
|
|
16
16
|
:HL["/_next/static/css/8a727f372cf53002.css","style"]
|
|
17
|
-
0:{"P":null,"b":"
|
|
17
|
+
0:{"P":null,"b":"-zps1Q9mQmioAKLcQiCr8","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$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/8a727f372cf53002.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":[[["$","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."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}],["$","$L5",null,{"position":"bottom-right"}]]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L6",null,{"Component":"$7","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@8","$@9"]}}],null,["$","$La",null,{"children":["$","$b",null,{"name":"Next.MetadataOutlet","children":"$@c"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Ld",null,{"children":"$Le"}],["$","div",null,{"hidden":true,"children":["$","$Lf",null,{"children":["$","$b",null,{"name":"Next.Metadata","children":"$L10"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$11",[]],"S":true}
|
|
18
18
|
8:{}
|
|
19
19
|
9:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
|
|
20
20
|
e:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
3:I[66919,["8974","static/chunks/app/page-b9367c5ae13b99c6.js"],"default"]
|
|
4
4
|
6:I[90484,[],"OutletBoundary"]
|
|
5
5
|
7:"$Sreact.suspense"
|
|
6
|
-
0:{"buildId":"
|
|
6
|
+
0:{"buildId":"-zps1Q9mQmioAKLcQiCr8","rsc":["$","$1","c",{"children":[["$","$L2",null,{"Component":"$3","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@4","$@5"]}}],null,["$","$L6",null,{"children":["$","$7",null,{"name":"Next.MetadataOutlet","children":"$@8"}]}]]}],"loading":null,"isPartial":false}
|
|
7
7
|
4:{}
|
|
8
8
|
5:"$0:rsc:props:children:0:props:serverProvidedParams:params"
|
|
9
9
|
8:null
|
|
@@ -14,7 +14,7 @@ f:I[90484,[],"MetadataBoundary"]
|
|
|
14
14
|
:HL["/_next/static/media/93f479601ee12b01-s.p.woff2","font",{"crossOrigin":"","type":"font/woff2"}]
|
|
15
15
|
:HL["/_next/static/css/de70bee13400563f.css","style"]
|
|
16
16
|
:HL["/_next/static/css/8a727f372cf53002.css","style"]
|
|
17
|
-
0:{"P":null,"b":"
|
|
17
|
+
0:{"P":null,"b":"-zps1Q9mQmioAKLcQiCr8","c":["",""],"q":"","i":false,"f":[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],[["$","$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/8a727f372cf53002.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":[[["$","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."}]}]]}]}]],[]],"forbidden":"$undefined","unauthorized":"$undefined"}],["$","$L5",null,{"position":"bottom-right"}]]}]}]}]]}],{"children":[["$","$1","c",{"children":[["$","$L6",null,{"Component":"$7","serverProvidedParams":{"searchParams":{},"params":{},"promises":["$@8","$@9"]}}],null,["$","$La",null,{"children":["$","$b",null,{"name":"Next.MetadataOutlet","children":"$@c"}]}]]}],{},null,false,false]},null,false,false],["$","$1","h",{"children":[null,["$","$Ld",null,{"children":"$Le"}],["$","div",null,{"hidden":true,"children":["$","$Lf",null,{"children":["$","$b",null,{"name":"Next.Metadata","children":"$L10"}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],false]],"m":"$undefined","G":["$11",[]],"S":true}
|
|
18
18
|
8:{}
|
|
19
19
|
9:"$0:f:0:1:1:children:0:props:children:0:props:serverProvidedParams:params"
|
|
20
20
|
e:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]
|
|
@@ -3,4 +3,4 @@
|
|
|
3
3
|
3:I[90484,[],"MetadataBoundary"]
|
|
4
4
|
4:"$Sreact.suspense"
|
|
5
5
|
5:I[86869,[],"IconMark"]
|
|
6
|
-
0:{"buildId":"
|
|
6
|
+
0:{"buildId":"-zps1Q9mQmioAKLcQiCr8","rsc":["$","$1","h",{"children":[null,["$","$L2",null,{"children":[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]]}],["$","div",null,{"hidden":true,"children":["$","$L3",null,{"children":["$","$4",null,{"name":"Next.Metadata","children":[["$","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"}],["$","$L5","6",{}]]}]}]}],["$","meta",null,{"name":"next-size-adjust","content":""}]]}],"loading":null,"isPartial":false}
|
|
@@ -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/8a727f372cf53002.css","style"]
|
|
8
|
-
0:{"buildId":"
|
|
8
|
+
0:{"buildId":"-zps1Q9mQmioAKLcQiCr8","rsc":["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/de70bee13400563f.css","precedence":"next"}],["$","link","1",{"rel":"stylesheet","href":"/_next/static/css/8a727f372cf53002.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"}]]}]}]}]]}],"loading":null,"isPartial":false}
|
|
@@ -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/8a727f372cf53002.css","style"]
|
|
5
|
-
0:{"buildId":"
|
|
5
|
+
0:{"buildId":"-zps1Q9mQmioAKLcQiCr8","tree":{"name":"","paramType":null,"paramKey":"","hasRuntimePrefetch":false,"slots":{"children":{"name":"__PAGE__","paramType":null,"paramKey":"__PAGE__","hasRuntimePrefetch":false,"slots":null,"isRootLayout":false}},"isRootLayout":true},"staleTime":300}
|
|
@@ -2,44 +2,44 @@
|
|
|
2
2
|
"/_not-found/page": "app/_not-found/page.js",
|
|
3
3
|
"/_global-error/page": "app/_global-error/page.js",
|
|
4
4
|
"/api/bridge-terminal/input/route": "app/api/bridge-terminal/input/route.js",
|
|
5
|
-
"/api/boot/route": "app/api/boot/route.js",
|
|
6
|
-
"/api/bridge-terminal/stream/route": "app/api/bridge-terminal/stream/route.js",
|
|
7
5
|
"/api/bridge-terminal/resize/route": "app/api/bridge-terminal/resize/route.js",
|
|
6
|
+
"/api/dev-mode/route": "app/api/dev-mode/route.js",
|
|
8
7
|
"/api/browse-directories/route": "app/api/browse-directories/route.js",
|
|
8
|
+
"/api/boot/route": "app/api/boot/route.js",
|
|
9
9
|
"/api/cleanup/route": "app/api/cleanup/route.js",
|
|
10
|
-
"/api/doctor/route": "app/api/doctor/route.js",
|
|
11
10
|
"/api/export-data/route": "app/api/export-data/route.js",
|
|
11
|
+
"/api/captures/route": "app/api/captures/route.js",
|
|
12
|
+
"/api/forensics/route": "app/api/forensics/route.js",
|
|
12
13
|
"/api/git/route": "app/api/git/route.js",
|
|
13
|
-
"/api/
|
|
14
|
-
"/api/dev-mode/route": "app/api/dev-mode/route.js",
|
|
14
|
+
"/api/doctor/route": "app/api/doctor/route.js",
|
|
15
15
|
"/api/inspect/route": "app/api/inspect/route.js",
|
|
16
|
-
"/api/forensics/route": "app/api/forensics/route.js",
|
|
17
|
-
"/api/captures/route": "app/api/captures/route.js",
|
|
18
|
-
"/api/hooks/route": "app/api/hooks/route.js",
|
|
19
16
|
"/api/knowledge/route": "app/api/knowledge/route.js",
|
|
17
|
+
"/api/history/route": "app/api/history/route.js",
|
|
18
|
+
"/api/hooks/route": "app/api/hooks/route.js",
|
|
19
|
+
"/api/bridge-terminal/stream/route": "app/api/bridge-terminal/stream/route.js",
|
|
20
20
|
"/api/live-state/route": "app/api/live-state/route.js",
|
|
21
|
-
"/api/projects/route": "app/api/projects/route.js",
|
|
22
21
|
"/api/recovery/route": "app/api/recovery/route.js",
|
|
22
|
+
"/api/preferences/route": "app/api/preferences/route.js",
|
|
23
23
|
"/api/session/browser/route": "app/api/session/browser/route.js",
|
|
24
24
|
"/api/onboarding/route": "app/api/onboarding/route.js",
|
|
25
|
-
"/api/
|
|
25
|
+
"/api/projects/route": "app/api/projects/route.js",
|
|
26
26
|
"/api/session/command/route": "app/api/session/command/route.js",
|
|
27
|
-
"/api/files/route": "app/api/files/route.js",
|
|
28
27
|
"/api/settings-data/route": "app/api/settings-data/route.js",
|
|
29
|
-
"/api/session/manage/route": "app/api/session/manage/route.js",
|
|
30
|
-
"/api/shutdown/route": "app/api/shutdown/route.js",
|
|
31
28
|
"/api/session/events/route": "app/api/session/events/route.js",
|
|
32
29
|
"/api/skill-health/route": "app/api/skill-health/route.js",
|
|
30
|
+
"/api/session/manage/route": "app/api/session/manage/route.js",
|
|
31
|
+
"/api/shutdown/route": "app/api/shutdown/route.js",
|
|
33
32
|
"/api/steer/route": "app/api/steer/route.js",
|
|
34
|
-
"/api/switch-root/route": "app/api/switch-root/route.js",
|
|
35
33
|
"/api/terminal/input/route": "app/api/terminal/input/route.js",
|
|
36
|
-
"/api/terminal/sessions/route": "app/api/terminal/sessions/route.js",
|
|
37
34
|
"/api/terminal/resize/route": "app/api/terminal/resize/route.js",
|
|
38
|
-
"/api/
|
|
39
|
-
"/api/
|
|
35
|
+
"/api/terminal/sessions/route": "app/api/terminal/sessions/route.js",
|
|
36
|
+
"/api/files/route": "app/api/files/route.js",
|
|
40
37
|
"/api/terminal/stream/route": "app/api/terminal/stream/route.js",
|
|
41
|
-
"/api/
|
|
38
|
+
"/api/visualizer/route": "app/api/visualizer/route.js",
|
|
39
|
+
"/api/switch-root/route": "app/api/switch-root/route.js",
|
|
42
40
|
"/api/terminal/upload/route": "app/api/terminal/upload/route.js",
|
|
41
|
+
"/api/undo/route": "app/api/undo/route.js",
|
|
43
42
|
"/api/update/route": "app/api/update/route.js",
|
|
43
|
+
"/api/remote-questions/route": "app/api/remote-questions/route.js",
|
|
44
44
|
"/page": "app/page.js"
|
|
45
45
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
1
|
+
<!DOCTYPE html><!--_zps1Q9mQmioAKLcQiCr8--><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><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/8a727f372cf53002.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/webpack-9014b5adb127a98a.js"/><script src="/_next/static/chunks/4bd1b696-e5d7c65570c947b7.js" async=""></script><script src="/_next/static/chunks/3794-337d1ca25ad99a89.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-9014b5adb127a98a.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\"\n9:I[90484,[],\"ViewportBoundary\"]\nb:I[90484,[],\"MetadataBoundary\"]\nd:I[27123,[],\"\"]\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/8a727f372cf53002.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"-zps1Q9mQmioAKLcQiCr8\",\"c\":[\"\",\"_not-found\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"_not-found\",{\"children\":[\"__PAGE__\",{}]}]},\"$undefined\",\"$undefined\",true],[[\"$\",\"$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/8a727f372cf53002.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,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[[\"$\",\"meta\",null,{\"name\":\"robots\",\"content\":\"noindex\"}],[\"$\",\"$L9\",null,{\"children\":\"$La\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$Lb\",null,{\"children\":[\"$\",\"$7\",null,{\"name\":\"Next.Metadata\",\"children\":\"$Lc\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$d\",[]],\"S\":true}\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"e:I[86869,[],\"IconMark\"]\n8:null\nc:[[\"$\",\"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\"}],[\"$\",\"$Le\",\"6\",{}]]\n"])</script></body></html>
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<!DOCTYPE html><!--
|
|
2
|
-
@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-right:23px;font-size:24px;font-weight:500;vertical-align:top">500</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">Internal Server Error.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/webpack-9014b5adb127a98a.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\"\n7:I[90484,[],\"ViewportBoundary\"]\n9:I[90484,[],\"MetadataBoundary\"]\nb:I[27123,[],\"\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"
|
|
1
|
+
<!DOCTYPE html><!--_zps1Q9mQmioAKLcQiCr8--><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-9014b5adb127a98a.js"/><script src="/_next/static/chunks/4bd1b696-e5d7c65570c947b7.js" async=""></script><script src="/_next/static/chunks/3794-337d1ca25ad99a89.js" async=""></script><script src="/_next/static/chunks/main-app-fdab67f7802d7832.js" async=""></script><meta name="next-size-adjust" content=""/><title>500: Internal Server Error.</title><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;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}
|
|
2
|
+
@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-right:23px;font-size:24px;font-weight:500;vertical-align:top">500</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">Internal Server Error.</h2></div></div></div><!--$--><!--/$--><script src="/_next/static/chunks/webpack-9014b5adb127a98a.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\"\n7:I[90484,[],\"ViewportBoundary\"]\n9:I[90484,[],\"MetadataBoundary\"]\nb:I[27123,[],\"\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"b\":\"-zps1Q9mQmioAKLcQiCr8\",\"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: Internal Server Error.\"}]}],[\"$\",\"body\",null,{\"children\":[\"$\",\"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,{\"style\":{\"lineHeight\":\"48px\"},\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}\\n@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\",\"paddingRight\":23,\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\"},\"children\":\"500\"}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"28px\"},\"children\":\"Internal Server Error.\"}]}]]}]}]}]]}],null,[\"$\",\"$L4\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@6\"}]}]]}],{},null,false,false]},null,false,false]},null,false,false],[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L7\",null,{\"children\":\"$L8\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L9\",null,{\"children\":[\"$\",\"$5\",null,{\"name\":\"Next.Metadata\",\"children\":\"$La\"}]}]}],[\"$\",\"meta\",null,{\"name\":\"next-size-adjust\",\"content\":\"\"}]]}],false]],\"m\":\"$undefined\",\"G\":[\"$b\",[]],\"S\":true}\n"])</script><script>self.__next_f.push([1,"8:[[\"$\",\"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\na:[]\n"])</script></body></html>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"node":{},"edge":{},"encryptionKey":"
|
|
1
|
+
{"node":{},"edge":{},"encryptionKey":"oGIXwQzePRWnEF/4TsFANf+DFedqL4fsGu8gLudYV/I="}
|
package/package.json
CHANGED
|
@@ -234,7 +234,7 @@ describe("AuthStorage — oauth credential for non-OAuth provider (#2083)", () =
|
|
|
234
234
|
// should be skipped, and getApiKey should fall through to env / fallback.
|
|
235
235
|
assert.equal(key, undefined);
|
|
236
236
|
});
|
|
237
|
-
it("falls through to env var when openrouter has type:oauth credential", async () => {
|
|
237
|
+
it("falls through to env var when openrouter has type:oauth credential", async (t) => {
|
|
238
238
|
const storage = inMemory({
|
|
239
239
|
openrouter: {
|
|
240
240
|
type: "oauth",
|
|
@@ -245,19 +245,17 @@ describe("AuthStorage — oauth credential for non-OAuth provider (#2083)", () =
|
|
|
245
245
|
});
|
|
246
246
|
// Simulate OPENROUTER_API_KEY being set via env
|
|
247
247
|
const origEnv = process.env.OPENROUTER_API_KEY;
|
|
248
|
-
|
|
249
|
-
process.env.OPENROUTER_API_KEY = "sk-or-v1-env-key";
|
|
250
|
-
const key = await storage.getApiKey("openrouter");
|
|
251
|
-
assert.equal(key, "sk-or-v1-env-key");
|
|
252
|
-
}
|
|
253
|
-
finally {
|
|
248
|
+
t.after(() => {
|
|
254
249
|
if (origEnv === undefined) {
|
|
255
250
|
delete process.env.OPENROUTER_API_KEY;
|
|
256
251
|
}
|
|
257
252
|
else {
|
|
258
253
|
process.env.OPENROUTER_API_KEY = origEnv;
|
|
259
254
|
}
|
|
260
|
-
}
|
|
255
|
+
});
|
|
256
|
+
process.env.OPENROUTER_API_KEY = "sk-or-v1-env-key";
|
|
257
|
+
const key = await storage.getApiKey("openrouter");
|
|
258
|
+
assert.equal(key, "sk-or-v1-env-key");
|
|
261
259
|
});
|
|
262
260
|
it("falls through to fallback resolver when openrouter has type:oauth credential", async () => {
|
|
263
261
|
const storage = inMemory({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-storage.test.js","sourceRoot":"","sources":["../../src/core/auth-storage.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { AuthStorage } from \"./auth-storage.js\";\n\n// ─── helpers ──────────────────────────────────────────────────────────────────\n\nfunction makeKey(key: string) {\n\treturn { type: \"api_key\" as const, key };\n}\n\nfunction inMemory(data: Record<string, unknown> = {}) {\n\treturn AuthStorage.inMemory(data as any);\n}\n\n// ─── single credential (backward compat) ─────────────────────────────────────\n\ndescribe(\"AuthStorage — single credential (backward compat)\", () => {\n\tit(\"returns the api key for a provider with one key\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-abc\") });\n\t\tconst key = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(key, \"sk-abc\");\n\t});\n\n\tit(\"returns undefined for unknown provider\", async () => {\n\t\tconst storage = inMemory({});\n\t\tconst key = await storage.getApiKey(\"unknown\");\n\t\tassert.equal(key, undefined);\n\t});\n\n\tit(\"runtime override takes precedence over stored key\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-stored\") });\n\t\tstorage.setRuntimeApiKey(\"anthropic\", \"sk-runtime\");\n\t\tconst key = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(key, \"sk-runtime\");\n\t});\n});\n\n// ─── multiple credentials ─────────────────────────────────────────────────────\n\ndescribe(\"AuthStorage — multiple credentials\", () => {\n\tit(\"round-robins across multiple api keys without sessionId\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\"), makeKey(\"sk-3\")],\n\t\t});\n\n\t\tconst keys = new Set<string>();\n\t\tfor (let i = 0; i < 6; i++) {\n\t\t\tconst k = await storage.getApiKey(\"anthropic\");\n\t\t\tassert.ok(k, `call ${i} should return a key`);\n\t\t\tkeys.add(k);\n\t\t}\n\t\t// All three keys should have been selected across 6 calls\n\t\tassert.deepEqual(keys, new Set([\"sk-1\", \"sk-2\", \"sk-3\"]));\n\t});\n\n\tit(\"session-sticky: same sessionId always picks the same key\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\"), makeKey(\"sk-3\")],\n\t\t});\n\n\t\tconst sessionId = \"sess-abc\";\n\t\tconst first = await storage.getApiKey(\"anthropic\", sessionId);\n\t\tfor (let i = 0; i < 5; i++) {\n\t\t\tconst k = await storage.getApiKey(\"anthropic\", sessionId);\n\t\t\tassert.equal(k, first, `call ${i} should be sticky to first selection`);\n\t\t}\n\t});\n\n\tit(\"different sessionIds may select different keys\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\"), makeKey(\"sk-3\")],\n\t\t});\n\n\t\tconst results = new Set<string>();\n\t\tfor (let i = 0; i < 20; i++) {\n\t\t\tconst k = await storage.getApiKey(\"anthropic\", `sess-${i}`);\n\t\t\tif (k) results.add(k);\n\t\t}\n\t\t// With 20 different sessions and 3 keys, we should see more than one key\n\t\tassert.ok(results.size > 1, \"multiple sessions should hash to different keys\");\n\t});\n});\n\n// ─── login accumulation ───────────────────────────────────────────────────────\n\ndescribe(\"AuthStorage — login accumulation\", () => {\n\tit(\"accumulates api keys on repeated set()\", () => {\n\t\tconst storage = inMemory({});\n\t\tstorage.set(\"anthropic\", makeKey(\"sk-1\"));\n\t\tstorage.set(\"anthropic\", makeKey(\"sk-2\"));\n\t\tconst creds = storage.getCredentialsForProvider(\"anthropic\");\n\t\tassert.equal(creds.length, 2);\n\t\tassert.deepEqual(\n\t\t\tcreds.map((c) => (c.type === \"api_key\" ? c.key : null)),\n\t\t\t[\"sk-1\", \"sk-2\"],\n\t\t);\n\t});\n\n\tit(\"deduplicates identical api keys\", () => {\n\t\tconst storage = inMemory({});\n\t\tstorage.set(\"anthropic\", makeKey(\"sk-1\"));\n\t\tstorage.set(\"anthropic\", makeKey(\"sk-1\"));\n\t\tconst creds = storage.getCredentialsForProvider(\"anthropic\");\n\t\tassert.equal(creds.length, 1);\n\t});\n});\n\n// ─── backoff / markUsageLimitReached ─────────────────────────────────────────\n\ndescribe(\"AuthStorage — rate-limit backoff\", () => {\n\tit(\"returns true when a backed-off credential has an alternate\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t});\n\n\t\t// Use sk-1 via round-robin (first call, index 0)\n\t\tawait storage.getApiKey(\"anthropic\");\n\n\t\t// Mark it as rate-limited; sk-2 should still be available\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\");\n\t\tassert.equal(hasAlternate, true);\n\t});\n\n\tit(\"returns false when all credentials are backed off\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t});\n\n\t\t// Back off both keys\n\t\tawait storage.getApiKey(\"anthropic\"); // uses index 0\n\t\tstorage.markUsageLimitReached(\"anthropic\"); // backs off index 0\n\t\tawait storage.getApiKey(\"anthropic\"); // uses index 1\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\"); // backs off index 1\n\t\tassert.equal(hasAlternate, false);\n\t});\n\n\tit(\"backed-off credential is skipped; next available key is returned\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t});\n\n\t\t// First call → sk-1 (round-robin index 0)\n\t\tconst first = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(first, \"sk-1\");\n\n\t\t// Back off sk-1\n\t\tstorage.markUsageLimitReached(\"anthropic\");\n\n\t\t// Next call should skip backed-off sk-1 and return sk-2\n\t\tconst second = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(second, \"sk-2\");\n\t});\n\n\tit(\"single credential: markUsageLimitReached returns false\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-only\") });\n\t\tawait storage.getApiKey(\"anthropic\");\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\");\n\t\tassert.equal(hasAlternate, false);\n\t});\n\n\tit(\"single credential: unknown error type skips backoff entirely\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-only\") });\n\t\tawait storage.getApiKey(\"anthropic\");\n\n\t\t// Mark with unknown error type (transport failure)\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\", undefined, {\n\t\t\terrorType: \"unknown\",\n\t\t});\n\t\tassert.equal(hasAlternate, false);\n\n\t\t// Key should still be available — backoff was not applied\n\t\tconst key = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(key, \"sk-only\");\n\t});\n\n\tit(\"multiple credentials: unknown error type still backs off the used credential\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t});\n\t\tawait storage.getApiKey(\"anthropic\"); // uses sk-1\n\n\t\t// Mark with unknown error type — should still back off when alternates exist\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\", undefined, {\n\t\t\terrorType: \"unknown\",\n\t\t});\n\t\tassert.equal(hasAlternate, true);\n\n\t\t// Next call should return sk-2\n\t\tconst key = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(key, \"sk-2\");\n\t});\n\n\tit(\"single credential: rate_limit error type still backs off\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-only\") });\n\t\tawait storage.getApiKey(\"anthropic\");\n\n\t\t// rate_limit should still back off even single credentials\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\", undefined, {\n\t\t\terrorType: \"rate_limit\",\n\t\t});\n\t\tassert.equal(hasAlternate, false);\n\n\t\t// Key should be backed off\n\t\tconst key = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(key, undefined);\n\t});\n\n\tit(\"session-sticky: marks the correct credential as backed off\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t});\n\n\t\tconst sessionId = \"sess-xyz\";\n\t\tconst chosen = await storage.getApiKey(\"anthropic\", sessionId);\n\t\tassert.ok(chosen);\n\n\t\t// Back off the chosen credential for this session\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\", sessionId);\n\t\tassert.equal(hasAlternate, true);\n\n\t\t// Next call with same session should return the other key\n\t\tconst next = await storage.getApiKey(\"anthropic\", sessionId);\n\t\tassert.ok(next);\n\t\tassert.notEqual(next, chosen);\n\t});\n});\n\n// ─── areAllCredentialsBackedOff ───────────────────────────────────────────────\n\ndescribe(\"AuthStorage — areAllCredentialsBackedOff\", () => {\n\tit(\"returns false when no credentials are configured\", () => {\n\t\tconst storage = inMemory({});\n\t\tassert.equal(storage.areAllCredentialsBackedOff(\"anthropic\"), false);\n\t});\n\n\tit(\"returns false when credentials exist and none are backed off\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-abc\") });\n\t\tassert.equal(storage.areAllCredentialsBackedOff(\"anthropic\"), false);\n\t});\n\n\tit(\"returns true when the single credential is backed off\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-only\") });\n\t\tawait storage.getApiKey(\"anthropic\");\n\t\tstorage.markUsageLimitReached(\"anthropic\");\n\t\tassert.equal(storage.areAllCredentialsBackedOff(\"anthropic\"), true);\n\t});\n\n\tit(\"returns false when at least one credential is still available\", async () => {\n\t\tconst storage = inMemory({ anthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")] });\n\t\tawait storage.getApiKey(\"anthropic\"); // uses index 0\n\t\tstorage.markUsageLimitReached(\"anthropic\"); // backs off index 0\n\t\t// index 1 is still available\n\t\tassert.equal(storage.areAllCredentialsBackedOff(\"anthropic\"), false);\n\t});\n\n\tit(\"returns true when all credentials are backed off\", async () => {\n\t\tconst storage = inMemory({ anthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")] });\n\t\tawait storage.getApiKey(\"anthropic\"); // uses index 0\n\t\tstorage.markUsageLimitReached(\"anthropic\"); // backs off index 0\n\t\tawait storage.getApiKey(\"anthropic\"); // uses index 1\n\t\tstorage.markUsageLimitReached(\"anthropic\"); // backs off index 1\n\t\tassert.equal(storage.areAllCredentialsBackedOff(\"anthropic\"), true);\n\t});\n});\n\n// ─── mismatched oauth credential for non-OAuth provider (#2083) ───────────────\n\ndescribe(\"AuthStorage — oauth credential for non-OAuth provider (#2083)\", () => {\n\tit(\"returns undefined when openrouter has type:oauth (no registered OAuth provider)\", async () => {\n\t\t// Simulates the bug: OpenRouter credential stored as type:\"oauth\"\n\t\t// but OpenRouter is not a registered OAuth provider.\n\t\tconst storage = inMemory({\n\t\t\topenrouter: {\n\t\t\t\ttype: \"oauth\",\n\t\t\t\taccess_token: \"sk-or-v1-fake\",\n\t\t\t\trefresh_token: \"rt-fake\",\n\t\t\t\texpires: Date.now() + 3_600_000,\n\t\t\t},\n\t\t});\n\n\t\t// Before the fix, getApiKey returns undefined because\n\t\t// resolveCredentialApiKey calls getOAuthProvider(\"openrouter\") → null → undefined.\n\t\t// The key in the oauth credential is never extracted.\n\t\tconst key = await storage.getApiKey(\"openrouter\");\n\t\t// After the fix, the oauth credential with an unrecognised provider\n\t\t// should be skipped, and getApiKey should fall through to env / fallback.\n\t\tassert.equal(key, undefined);\n\t});\n\n\tit(\"falls through to env var when openrouter has type:oauth credential\", async () => {\n\t\tconst storage = inMemory({\n\t\t\topenrouter: {\n\t\t\t\ttype: \"oauth\",\n\t\t\t\taccess_token: \"sk-or-v1-fake\",\n\t\t\t\trefresh_token: \"rt-fake\",\n\t\t\t\texpires: Date.now() + 3_600_000,\n\t\t\t},\n\t\t});\n\n\t\t// Simulate OPENROUTER_API_KEY being set via env\n\t\tconst origEnv = process.env.OPENROUTER_API_KEY;\n\t\ttry {\n\t\t\tprocess.env.OPENROUTER_API_KEY = \"sk-or-v1-env-key\";\n\t\t\tconst key = await storage.getApiKey(\"openrouter\");\n\t\t\tassert.equal(key, \"sk-or-v1-env-key\");\n\t\t} finally {\n\t\t\tif (origEnv === undefined) {\n\t\t\t\tdelete process.env.OPENROUTER_API_KEY;\n\t\t\t} else {\n\t\t\t\tprocess.env.OPENROUTER_API_KEY = origEnv;\n\t\t\t}\n\t\t}\n\t});\n\n\tit(\"falls through to fallback resolver when openrouter has type:oauth credential\", async () => {\n\t\tconst storage = inMemory({\n\t\t\topenrouter: {\n\t\t\t\ttype: \"oauth\",\n\t\t\t\taccess_token: \"sk-or-v1-fake\",\n\t\t\t\trefresh_token: \"rt-fake\",\n\t\t\t\texpires: Date.now() + 3_600_000,\n\t\t\t},\n\t\t});\n\n\t\tstorage.setFallbackResolver((provider) =>\n\t\t\tprovider === \"openrouter\" ? \"sk-or-v1-fallback\" : undefined,\n\t\t);\n\n\t\tconst key = await storage.getApiKey(\"openrouter\");\n\t\tassert.equal(key, \"sk-or-v1-fallback\");\n\t});\n});\n\n// ─── getAll truncation ────────────────────────────────────────────────────────\n\ndescribe(\"AuthStorage — getAll()\", () => {\n\tit(\"returns first credential only for providers with multiple keys\", () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t\topenai: makeKey(\"sk-openai\"),\n\t\t});\n\t\tconst all = storage.getAll();\n\t\tassert.ok(all[\"anthropic\"]?.type === \"api_key\");\n\t\tassert.equal((all[\"anthropic\"] as any).key, \"sk-1\");\n\t\tassert.equal((all[\"openai\"] as any).key, \"sk-openai\");\n\t});\n});\n"]}
|
|
1
|
+
{"version":3,"file":"auth-storage.test.js","sourceRoot":"","sources":["../../src/core/auth-storage.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, it } from \"node:test\";\nimport assert from \"node:assert/strict\";\nimport { AuthStorage } from \"./auth-storage.js\";\n\n// ─── helpers ──────────────────────────────────────────────────────────────────\n\nfunction makeKey(key: string) {\n\treturn { type: \"api_key\" as const, key };\n}\n\nfunction inMemory(data: Record<string, unknown> = {}) {\n\treturn AuthStorage.inMemory(data as any);\n}\n\n// ─── single credential (backward compat) ─────────────────────────────────────\n\ndescribe(\"AuthStorage — single credential (backward compat)\", () => {\n\tit(\"returns the api key for a provider with one key\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-abc\") });\n\t\tconst key = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(key, \"sk-abc\");\n\t});\n\n\tit(\"returns undefined for unknown provider\", async () => {\n\t\tconst storage = inMemory({});\n\t\tconst key = await storage.getApiKey(\"unknown\");\n\t\tassert.equal(key, undefined);\n\t});\n\n\tit(\"runtime override takes precedence over stored key\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-stored\") });\n\t\tstorage.setRuntimeApiKey(\"anthropic\", \"sk-runtime\");\n\t\tconst key = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(key, \"sk-runtime\");\n\t});\n});\n\n// ─── multiple credentials ─────────────────────────────────────────────────────\n\ndescribe(\"AuthStorage — multiple credentials\", () => {\n\tit(\"round-robins across multiple api keys without sessionId\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\"), makeKey(\"sk-3\")],\n\t\t});\n\n\t\tconst keys = new Set<string>();\n\t\tfor (let i = 0; i < 6; i++) {\n\t\t\tconst k = await storage.getApiKey(\"anthropic\");\n\t\t\tassert.ok(k, `call ${i} should return a key`);\n\t\t\tkeys.add(k);\n\t\t}\n\t\t// All three keys should have been selected across 6 calls\n\t\tassert.deepEqual(keys, new Set([\"sk-1\", \"sk-2\", \"sk-3\"]));\n\t});\n\n\tit(\"session-sticky: same sessionId always picks the same key\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\"), makeKey(\"sk-3\")],\n\t\t});\n\n\t\tconst sessionId = \"sess-abc\";\n\t\tconst first = await storage.getApiKey(\"anthropic\", sessionId);\n\t\tfor (let i = 0; i < 5; i++) {\n\t\t\tconst k = await storage.getApiKey(\"anthropic\", sessionId);\n\t\t\tassert.equal(k, first, `call ${i} should be sticky to first selection`);\n\t\t}\n\t});\n\n\tit(\"different sessionIds may select different keys\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\"), makeKey(\"sk-3\")],\n\t\t});\n\n\t\tconst results = new Set<string>();\n\t\tfor (let i = 0; i < 20; i++) {\n\t\t\tconst k = await storage.getApiKey(\"anthropic\", `sess-${i}`);\n\t\t\tif (k) results.add(k);\n\t\t}\n\t\t// With 20 different sessions and 3 keys, we should see more than one key\n\t\tassert.ok(results.size > 1, \"multiple sessions should hash to different keys\");\n\t});\n});\n\n// ─── login accumulation ───────────────────────────────────────────────────────\n\ndescribe(\"AuthStorage — login accumulation\", () => {\n\tit(\"accumulates api keys on repeated set()\", () => {\n\t\tconst storage = inMemory({});\n\t\tstorage.set(\"anthropic\", makeKey(\"sk-1\"));\n\t\tstorage.set(\"anthropic\", makeKey(\"sk-2\"));\n\t\tconst creds = storage.getCredentialsForProvider(\"anthropic\");\n\t\tassert.equal(creds.length, 2);\n\t\tassert.deepEqual(\n\t\t\tcreds.map((c) => (c.type === \"api_key\" ? c.key : null)),\n\t\t\t[\"sk-1\", \"sk-2\"],\n\t\t);\n\t});\n\n\tit(\"deduplicates identical api keys\", () => {\n\t\tconst storage = inMemory({});\n\t\tstorage.set(\"anthropic\", makeKey(\"sk-1\"));\n\t\tstorage.set(\"anthropic\", makeKey(\"sk-1\"));\n\t\tconst creds = storage.getCredentialsForProvider(\"anthropic\");\n\t\tassert.equal(creds.length, 1);\n\t});\n});\n\n// ─── backoff / markUsageLimitReached ─────────────────────────────────────────\n\ndescribe(\"AuthStorage — rate-limit backoff\", () => {\n\tit(\"returns true when a backed-off credential has an alternate\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t});\n\n\t\t// Use sk-1 via round-robin (first call, index 0)\n\t\tawait storage.getApiKey(\"anthropic\");\n\n\t\t// Mark it as rate-limited; sk-2 should still be available\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\");\n\t\tassert.equal(hasAlternate, true);\n\t});\n\n\tit(\"returns false when all credentials are backed off\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t});\n\n\t\t// Back off both keys\n\t\tawait storage.getApiKey(\"anthropic\"); // uses index 0\n\t\tstorage.markUsageLimitReached(\"anthropic\"); // backs off index 0\n\t\tawait storage.getApiKey(\"anthropic\"); // uses index 1\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\"); // backs off index 1\n\t\tassert.equal(hasAlternate, false);\n\t});\n\n\tit(\"backed-off credential is skipped; next available key is returned\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t});\n\n\t\t// First call → sk-1 (round-robin index 0)\n\t\tconst first = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(first, \"sk-1\");\n\n\t\t// Back off sk-1\n\t\tstorage.markUsageLimitReached(\"anthropic\");\n\n\t\t// Next call should skip backed-off sk-1 and return sk-2\n\t\tconst second = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(second, \"sk-2\");\n\t});\n\n\tit(\"single credential: markUsageLimitReached returns false\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-only\") });\n\t\tawait storage.getApiKey(\"anthropic\");\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\");\n\t\tassert.equal(hasAlternate, false);\n\t});\n\n\tit(\"single credential: unknown error type skips backoff entirely\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-only\") });\n\t\tawait storage.getApiKey(\"anthropic\");\n\n\t\t// Mark with unknown error type (transport failure)\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\", undefined, {\n\t\t\terrorType: \"unknown\",\n\t\t});\n\t\tassert.equal(hasAlternate, false);\n\n\t\t// Key should still be available — backoff was not applied\n\t\tconst key = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(key, \"sk-only\");\n\t});\n\n\tit(\"multiple credentials: unknown error type still backs off the used credential\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t});\n\t\tawait storage.getApiKey(\"anthropic\"); // uses sk-1\n\n\t\t// Mark with unknown error type — should still back off when alternates exist\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\", undefined, {\n\t\t\terrorType: \"unknown\",\n\t\t});\n\t\tassert.equal(hasAlternate, true);\n\n\t\t// Next call should return sk-2\n\t\tconst key = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(key, \"sk-2\");\n\t});\n\n\tit(\"single credential: rate_limit error type still backs off\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-only\") });\n\t\tawait storage.getApiKey(\"anthropic\");\n\n\t\t// rate_limit should still back off even single credentials\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\", undefined, {\n\t\t\terrorType: \"rate_limit\",\n\t\t});\n\t\tassert.equal(hasAlternate, false);\n\n\t\t// Key should be backed off\n\t\tconst key = await storage.getApiKey(\"anthropic\");\n\t\tassert.equal(key, undefined);\n\t});\n\n\tit(\"session-sticky: marks the correct credential as backed off\", async () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t});\n\n\t\tconst sessionId = \"sess-xyz\";\n\t\tconst chosen = await storage.getApiKey(\"anthropic\", sessionId);\n\t\tassert.ok(chosen);\n\n\t\t// Back off the chosen credential for this session\n\t\tconst hasAlternate = storage.markUsageLimitReached(\"anthropic\", sessionId);\n\t\tassert.equal(hasAlternate, true);\n\n\t\t// Next call with same session should return the other key\n\t\tconst next = await storage.getApiKey(\"anthropic\", sessionId);\n\t\tassert.ok(next);\n\t\tassert.notEqual(next, chosen);\n\t});\n});\n\n// ─── areAllCredentialsBackedOff ───────────────────────────────────────────────\n\ndescribe(\"AuthStorage — areAllCredentialsBackedOff\", () => {\n\tit(\"returns false when no credentials are configured\", () => {\n\t\tconst storage = inMemory({});\n\t\tassert.equal(storage.areAllCredentialsBackedOff(\"anthropic\"), false);\n\t});\n\n\tit(\"returns false when credentials exist and none are backed off\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-abc\") });\n\t\tassert.equal(storage.areAllCredentialsBackedOff(\"anthropic\"), false);\n\t});\n\n\tit(\"returns true when the single credential is backed off\", async () => {\n\t\tconst storage = inMemory({ anthropic: makeKey(\"sk-only\") });\n\t\tawait storage.getApiKey(\"anthropic\");\n\t\tstorage.markUsageLimitReached(\"anthropic\");\n\t\tassert.equal(storage.areAllCredentialsBackedOff(\"anthropic\"), true);\n\t});\n\n\tit(\"returns false when at least one credential is still available\", async () => {\n\t\tconst storage = inMemory({ anthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")] });\n\t\tawait storage.getApiKey(\"anthropic\"); // uses index 0\n\t\tstorage.markUsageLimitReached(\"anthropic\"); // backs off index 0\n\t\t// index 1 is still available\n\t\tassert.equal(storage.areAllCredentialsBackedOff(\"anthropic\"), false);\n\t});\n\n\tit(\"returns true when all credentials are backed off\", async () => {\n\t\tconst storage = inMemory({ anthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")] });\n\t\tawait storage.getApiKey(\"anthropic\"); // uses index 0\n\t\tstorage.markUsageLimitReached(\"anthropic\"); // backs off index 0\n\t\tawait storage.getApiKey(\"anthropic\"); // uses index 1\n\t\tstorage.markUsageLimitReached(\"anthropic\"); // backs off index 1\n\t\tassert.equal(storage.areAllCredentialsBackedOff(\"anthropic\"), true);\n\t});\n});\n\n// ─── mismatched oauth credential for non-OAuth provider (#2083) ───────────────\n\ndescribe(\"AuthStorage — oauth credential for non-OAuth provider (#2083)\", () => {\n\tit(\"returns undefined when openrouter has type:oauth (no registered OAuth provider)\", async () => {\n\t\t// Simulates the bug: OpenRouter credential stored as type:\"oauth\"\n\t\t// but OpenRouter is not a registered OAuth provider.\n\t\tconst storage = inMemory({\n\t\t\topenrouter: {\n\t\t\t\ttype: \"oauth\",\n\t\t\t\taccess_token: \"sk-or-v1-fake\",\n\t\t\t\trefresh_token: \"rt-fake\",\n\t\t\t\texpires: Date.now() + 3_600_000,\n\t\t\t},\n\t\t});\n\n\t\t// Before the fix, getApiKey returns undefined because\n\t\t// resolveCredentialApiKey calls getOAuthProvider(\"openrouter\") → null → undefined.\n\t\t// The key in the oauth credential is never extracted.\n\t\tconst key = await storage.getApiKey(\"openrouter\");\n\t\t// After the fix, the oauth credential with an unrecognised provider\n\t\t// should be skipped, and getApiKey should fall through to env / fallback.\n\t\tassert.equal(key, undefined);\n\t});\n\n\tit(\"falls through to env var when openrouter has type:oauth credential\", async (t) => {\n\t\tconst storage = inMemory({\n\t\t\topenrouter: {\n\t\t\t\ttype: \"oauth\",\n\t\t\t\taccess_token: \"sk-or-v1-fake\",\n\t\t\t\trefresh_token: \"rt-fake\",\n\t\t\t\texpires: Date.now() + 3_600_000,\n\t\t\t},\n\t\t});\n\n\t\t// Simulate OPENROUTER_API_KEY being set via env\n\t\tconst origEnv = process.env.OPENROUTER_API_KEY;\n\t\tt.after(() => {\n\t\t\tif (origEnv === undefined) {\n\t\t\t\tdelete process.env.OPENROUTER_API_KEY;\n\t\t\t} else {\n\t\t\t\tprocess.env.OPENROUTER_API_KEY = origEnv;\n\t\t\t}\n\t\t});\n\n\t\tprocess.env.OPENROUTER_API_KEY = \"sk-or-v1-env-key\";\n\t\tconst key = await storage.getApiKey(\"openrouter\");\n\t\tassert.equal(key, \"sk-or-v1-env-key\");\n\t});\n\n\tit(\"falls through to fallback resolver when openrouter has type:oauth credential\", async () => {\n\t\tconst storage = inMemory({\n\t\t\topenrouter: {\n\t\t\t\ttype: \"oauth\",\n\t\t\t\taccess_token: \"sk-or-v1-fake\",\n\t\t\t\trefresh_token: \"rt-fake\",\n\t\t\t\texpires: Date.now() + 3_600_000,\n\t\t\t},\n\t\t});\n\n\t\tstorage.setFallbackResolver((provider) =>\n\t\t\tprovider === \"openrouter\" ? \"sk-or-v1-fallback\" : undefined,\n\t\t);\n\n\t\tconst key = await storage.getApiKey(\"openrouter\");\n\t\tassert.equal(key, \"sk-or-v1-fallback\");\n\t});\n});\n\n// ─── getAll truncation ────────────────────────────────────────────────────────\n\ndescribe(\"AuthStorage — getAll()\", () => {\n\tit(\"returns first credential only for providers with multiple keys\", () => {\n\t\tconst storage = inMemory({\n\t\t\tanthropic: [makeKey(\"sk-1\"), makeKey(\"sk-2\")],\n\t\t\topenai: makeKey(\"sk-openai\"),\n\t\t});\n\t\tconst all = storage.getAll();\n\t\tassert.ok(all[\"anthropic\"]?.type === \"api_key\");\n\t\tassert.equal((all[\"anthropic\"] as any).key, \"sk-1\");\n\t\tassert.equal((all[\"openai\"] as any).key, \"sk-openai\");\n\t});\n});\n"]}
|