@steipete/oracle 0.21.1 → 0.21.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/dist/bin/oracle-cli.js +6 -10
  2. package/dist/src/browser/profileState.js +2 -0
  3. package/package.json +10 -10
  4. package/dist/docs-site/.nojekyll +0 -0
  5. package/dist/docs-site/CNAME +0 -1
  6. package/dist/docs-site/RELEASING.html +0 -403
  7. package/dist/docs-site/advisor.html +0 -317
  8. package/dist/docs-site/agents.html +0 -375
  9. package/dist/docs-site/anthropic.html +0 -368
  10. package/dist/docs-site/bridge.html +0 -421
  11. package/dist/docs-site/browser-mode.html +0 -637
  12. package/dist/docs-site/chromium-forks.html +0 -355
  13. package/dist/docs-site/cli-reference.html +0 -347
  14. package/dist/docs-site/configuration.html +0 -464
  15. package/dist/docs-site/favicon.svg +0 -14
  16. package/dist/docs-site/followup.html +0 -375
  17. package/dist/docs-site/gemini.html +0 -388
  18. package/dist/docs-site/grok.html +0 -325
  19. package/dist/docs-site/index.html +0 -360
  20. package/dist/docs-site/install.html +0 -335
  21. package/dist/docs-site/linux.html +0 -321
  22. package/dist/docs-site/llms.txt +0 -44
  23. package/dist/docs-site/manual-tests.html +0 -621
  24. package/dist/docs-site/mcp.html +0 -412
  25. package/dist/docs-site/multimodel.html +0 -364
  26. package/dist/docs-site/mythical-pro-agents.html +0 -360
  27. package/dist/docs-site/notifier.html +0 -338
  28. package/dist/docs-site/openai-endpoints.html +0 -417
  29. package/dist/docs-site/openrouter.html +0 -344
  30. package/dist/docs-site/quickstart.html +0 -369
  31. package/dist/docs-site/refactor/ux.html +0 -321
  32. package/dist/docs-site/sessions.html +0 -397
  33. package/dist/docs-site/social-card.png +0 -0
  34. package/dist/docs-site/social-card.svg +0 -79
  35. package/dist/docs-site/spec.html +0 -363
  36. package/dist/docs-site/testing.html +0 -323
  37. package/dist/docs-site/tui-debug.html +0 -326
  38. package/dist/docs-site/windows-work.html +0 -348
  39. package/dist/docs-site/windows.html +0 -320
@@ -1,417 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <meta name="viewport" content="width=device-width, initial-scale=1">
6
- <title>OpenAI-Compatible Endpoints — oracle</title>
7
- <meta name="description" content="OpenAI-Compatible Endpoints — oracle CLI documentation.">
8
- <link rel="canonical" href="https://askoracle.sh/openai-endpoints.html">
9
- <meta property="og:type" content="website">
10
- <meta property="og:site_name" content="oracle">
11
- <meta property="og:title" content="OpenAI-Compatible Endpoints — oracle">
12
- <meta property="og:description" content="OpenAI-Compatible Endpoints — oracle CLI documentation.">
13
- <meta property="og:url" content="https://askoracle.sh/openai-endpoints.html">
14
- <meta property="og:image" content="https://askoracle.sh/social-card.png">
15
- <meta property="og:image:width" content="1200">
16
- <meta property="og:image:height" content="630">
17
- <meta name="twitter:card" content="summary_large_image">
18
- <meta name="twitter:title" content="OpenAI-Compatible Endpoints — oracle">
19
- <meta name="twitter:description" content="OpenAI-Compatible Endpoints — oracle CLI documentation.">
20
- <meta name="twitter:image" content="https://askoracle.sh/social-card.png">
21
- <link rel="icon" href="favicon.svg" type="image/svg+xml">
22
- <link rel="preconnect" href="https://fonts.googleapis.com">
23
- <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
24
- <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap" rel="stylesheet">
25
- <script>(function(){var s;try{s=localStorage.getItem('theme')}catch(e){}var d=window.matchMedia&&matchMedia('(prefers-color-scheme: dark)').matches;document.documentElement.dataset.theme=s||(d?'dark':'light')})();</script>
26
- <style>
27
- :root{
28
- --ink:#0e0a1f;
29
- --text:#1d1832;
30
- --muted:#6b6582;
31
- --subtle:#9c95b5;
32
- --bg:#fafaff;
33
- --paper:#ffffff;
34
- --accent:#7c3aed;
35
- --accent-soft:rgba(124,58,237,.10);
36
- --accent-strong:#5b21b6;
37
- --accent-2:#0ea5e9;
38
- --accent-glow:#a78bfa;
39
- --line:#e7e3f0;
40
- --line-soft:#f2eff8;
41
- --code-bg:#0c0a1a;
42
- --code-fg:#e9e6f5;
43
- --code-inline-fg:#1c1734;
44
- --pill-border:#dcd5ec;
45
- --shadow-card:0 4px 14px rgba(14,10,31,.08);
46
- --scrollbar:#cbc4dc;
47
- }
48
- :root[data-theme="dark"]{
49
- --ink:#f5f2ff;
50
- --text:#cec7e4;
51
- --muted:#9189a8;
52
- --subtle:#6a6383;
53
- --bg:#0a0815;
54
- --paper:#15102a;
55
- --accent:#a78bfa;
56
- --accent-soft:rgba(167,139,250,.18);
57
- --accent-strong:#c4b5fd;
58
- --accent-2:#38bdf8;
59
- --accent-glow:#c4b5fd;
60
- --line:#272140;
61
- --line-soft:#1c1734;
62
- --code-bg:#06040d;
63
- --code-fg:#e9e6f5;
64
- --code-inline-fg:#e9e6f5;
65
- --pill-border:#2c2549;
66
- --shadow-card:0 4px 18px rgba(0,0,0,.45);
67
- --scrollbar:#3a3358;
68
- }
69
- :root{color-scheme:light}
70
- :root[data-theme="dark"]{color-scheme:dark}
71
- *{box-sizing:border-box}
72
- html{scroll-behavior:smooth;scroll-padding-top:24px}
73
- body{margin:0;background:var(--bg);color:var(--text);font-family:"Inter",ui-sans-serif,system-ui,-apple-system,Segoe UI,sans-serif;line-height:1.65;overflow-x:hidden;-webkit-font-smoothing:antialiased;font-feature-settings:"cv02","cv03","cv04","cv11";transition:background-color .18s,color .18s}
74
- ::selection{background:var(--accent);color:#fff}
75
- a{color:var(--accent);text-decoration:none;transition:color .12s}
76
- a:hover{text-decoration:underline;text-underline-offset:.2em}
77
- .shell{display:grid;grid-template-columns:268px minmax(0,1fr);min-height:100vh}
78
- .sidebar{position:sticky;top:0;height:100vh;overflow:auto;padding:24px 22px;background:var(--paper);border-right:1px solid var(--line);scrollbar-width:thin;scrollbar-color:var(--line) transparent;transition:background-color .18s,border-color .18s}
79
- .sidebar::-webkit-scrollbar{width:6px}
80
- .sidebar::-webkit-scrollbar-thumb{background:var(--line);border-radius:6px}
81
- .sidebar-head{display:flex;align-items:center;gap:10px;margin-bottom:24px}
82
- .brand{display:flex;align-items:center;gap:11px;color:var(--ink);text-decoration:none;flex:1;min-width:0}
83
- .brand:hover{text-decoration:none}
84
- .brand .mark{flex:0 0 30px;width:30px;height:30px;border-radius:50%;background:radial-gradient(circle at 32% 32%,#fff 0,#e0d4ff 22%,#7c3aed 60%,#1e1240 100%);box-shadow:0 0 0 1px rgba(124,58,237,.35),0 6px 18px rgba(124,58,237,.35);position:relative}
85
- .brand .mark::after{content:"";position:absolute;left:50%;top:50%;width:9px;height:9px;border-radius:50%;background:#0c0820;transform:translate(-50%,-50%)}
86
- .brand strong{display:block;font-size:1.05rem;line-height:1.1;font-weight:600;letter-spacing:0;color:var(--ink)}
87
- .brand small{display:block;color:var(--muted);font-size:.74rem;margin-top:3px;font-weight:400}
88
- .theme-toggle{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;width:34px;height:34px;border-radius:8px;border:1px solid var(--line);background:var(--paper);color:var(--muted);cursor:pointer;padding:0;transition:border-color .15s,color .15s,background-color .15s,transform .12s}
89
- .theme-toggle:hover{border-color:var(--ink);color:var(--ink)}
90
- .theme-toggle:active{transform:scale(.94)}
91
- .theme-toggle svg{width:16px;height:16px;display:block}
92
- .theme-icon-sun{display:none}
93
- :root[data-theme="dark"] .theme-icon-sun{display:block}
94
- :root[data-theme="dark"] .theme-icon-moon{display:none}
95
- .search{display:block;margin:0 0 22px}
96
- .search span{display:block;color:var(--muted);font-size:.7rem;font-weight:600;text-transform:uppercase;letter-spacing:0;margin-bottom:7px}
97
- .search input{width:100%;border:1px solid var(--line);background:var(--paper);border-radius:8px;padding:9px 12px;font:inherit;font-size:.9rem;color:var(--text);outline:none;transition:border-color .15s,box-shadow .15s,background-color .18s}
98
- .search input:focus{border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-soft)}
99
- nav section{margin:0 0 18px}
100
- nav h2{font-size:.68rem;color:var(--muted);text-transform:uppercase;letter-spacing:0;margin:0 0 6px;font-weight:600}
101
- .nav-link{display:block;color:var(--text);text-decoration:none;border-radius:6px;padding:5px 10px;margin:1px 0;font-size:.9rem;line-height:1.4;transition:background .12s,color .12s}
102
- .nav-link:hover{background:var(--line-soft);color:var(--ink);text-decoration:none}
103
- .nav-link.active{background:var(--accent-soft);color:var(--accent);font-weight:600}
104
- main{min-width:0;padding:32px clamp(20px,4.5vw,56px) 80px;max-width:1180px;margin:0 auto;width:100%}
105
- .hero{display:flex;align-items:flex-end;justify-content:space-between;gap:22px;border-bottom:1px solid var(--line);padding:8px 0 22px;margin-bottom:8px;flex-wrap:wrap}
106
- .hero-text{min-width:0;flex:1 1 320px}
107
- .eyebrow{margin:0 0 8px;color:var(--muted);font-weight:600;text-transform:uppercase;letter-spacing:0;font-size:.7rem}
108
- .hero h1{font-size:2.25rem;line-height:1.1;letter-spacing:0;margin:0;font-weight:700;color:var(--ink)}
109
- .hero-meta{display:flex;gap:8px;flex:0 0 auto;flex-wrap:wrap}
110
- .repo,.edit,.btn-ghost{border:1px solid var(--line);color:var(--text);text-decoration:none;border-radius:7px;padding:6px 11px;font-weight:500;font-size:.83rem;background:var(--paper);transition:border-color .15s,color .15s,background .15s}
111
- .repo:hover,.edit:hover,.btn-ghost:hover{border-color:var(--ink);color:var(--ink);text-decoration:none}
112
- .edit{color:var(--muted)}
113
- .home-hero{position:relative;padding:24px 0 32px;margin-bottom:8px;border-bottom:1px solid var(--line)}
114
- .home-hero>*{position:relative;z-index:1}
115
- .home-hero h1{font-size:3.4rem;line-height:1.04;letter-spacing:0;margin:0 0 .35em;font-weight:700;color:var(--ink);background:linear-gradient(135deg,var(--ink) 0,#7c3aed 60%,#0ea5e9 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
116
- :root[data-theme="dark"] .home-hero h1{background:linear-gradient(135deg,#f5f2ff 0,#c4b5fd 50%,#7dd3fc 100%);-webkit-background-clip:text;background-clip:text;-webkit-text-fill-color:transparent}
117
- .home-hero .lede{font-size:1.18rem;line-height:1.55;color:var(--text);margin:0 0 1.2em;max-width:62ch}
118
- .home-cta{display:flex;flex-wrap:wrap;gap:10px;align-items:center;margin:0 0 18px}
119
- .home-cta .btn{display:inline-flex;align-items:center;gap:7px;border-radius:8px;padding:10px 16px;font-weight:600;font-size:.92rem;text-decoration:none;transition:background .15s,border-color .15s,color .15s,transform .12s}
120
- .home-cta .btn-primary{background:linear-gradient(135deg,var(--accent),var(--accent-strong));color:#fff;border:1px solid var(--accent);box-shadow:0 4px 14px rgba(124,58,237,.35)}
121
- .home-cta .btn-primary:hover{background:var(--accent-strong);border-color:var(--accent-strong);text-decoration:none;transform:translateY(-1px)}
122
- .home-cta .btn-ghost{padding:10px 16px}
123
- .home-install{display:flex;align-items:center;gap:12px;background:var(--code-bg);color:var(--code-fg);border-radius:8px;padding:10px 10px 10px 16px;font:500 .9rem/1.2 "JetBrains Mono","SF Mono",ui-monospace,monospace;max-width:34em;border:1px solid #1f1840}
124
- .home-install .prompt{color:#6f63a3;user-select:none;flex:0 0 auto}
125
- .home-install code{flex:1;background:transparent;border:0;color:var(--code-fg);font:inherit;padding:0;white-space:pre;overflow:hidden;text-overflow:ellipsis}
126
- .home-install .copy{flex:0 0 auto;background:rgba(255,255,255,.08);color:var(--code-fg);border:1px solid rgba(255,255,255,.16);border-radius:6px;padding:5px 11px;font:500 .72rem/1 "Inter",sans-serif;cursor:pointer;transition:background .15s,border-color .15s}
127
- .home-install .copy:hover{background:rgba(255,255,255,.16)}
128
- .home-install .copy.copied{background:var(--accent);border-color:var(--accent)}
129
- .home-services{display:flex;flex-wrap:wrap;gap:6px;margin:6px 0 18px}
130
- .home-services span{display:inline-block;padding:3px 10px;border:1px solid var(--pill-border);border-radius:999px;font-size:.78rem;color:var(--muted);background:var(--paper)}
131
- .home-services span.pill-pro{background:var(--accent-soft);color:var(--accent);border-color:transparent;font-weight:600}
132
- .home-visual{display:block;width:min(100%,620px);height:auto;margin:22px 0 0;border-radius:8px;border:1px solid var(--line);box-shadow:var(--shadow-card);background:var(--paper)}
133
- .doc-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:48px;margin-top:24px}
134
- .doc-grid-home{margin-top:8px}
135
- @media(min-width:1180px){.doc-grid{grid-template-columns:minmax(0,72ch) 200px;justify-content:start}.doc-grid-home{grid-template-columns:minmax(0,76ch);justify-content:start}}
136
- .doc{min-width:0;max-width:72ch;overflow-wrap:break-word}
137
- .doc-home{max-width:76ch}
138
- .doc h1{font-size:2.6rem;line-height:1.08;letter-spacing:0;margin:0 0 .4em;font-weight:700;color:var(--ink)}
139
- body:not(.home) .doc>h1:first-child{display:none}
140
- .doc h2{font-size:1.45rem;line-height:1.2;margin:2em 0 .5em;font-weight:600;letter-spacing:0;color:var(--ink);position:relative}
141
- .doc h3{font-size:1.1rem;margin:1.7em 0 .35em;position:relative;font-weight:600;color:var(--ink);letter-spacing:0}
142
- .doc h4{font-size:.98rem;margin:1.4em 0 .25em;color:var(--ink);position:relative;font-weight:600}
143
- .doc h2:first-child,.doc h3:first-child,.doc h4:first-child{margin-top:.2em}
144
- .doc :is(h2,h3,h4) .anchor{position:absolute;left:-1.05em;top:0;color:var(--subtle);opacity:0;text-decoration:none;font-weight:400;padding-right:.3em;transition:opacity .12s,color .12s}
145
- .doc :is(h2,h3,h4):hover .anchor{opacity:.7}
146
- .doc :is(h2,h3,h4) .anchor:hover{opacity:1;color:var(--accent);text-decoration:none}
147
- .doc p{margin:0 0 1.05em}
148
- .doc ul,.doc ol{padding-left:1.3rem;margin:0 0 1.15em}
149
- .doc li{margin:.25em 0}
150
- .doc li>p{margin:0 0 .4em}
151
- .doc strong{font-weight:600;color:var(--ink)}
152
- .doc em{font-style:italic}
153
- .doc code{font-family:"JetBrains Mono","SF Mono",ui-monospace,monospace;font-size:.84em;background:var(--line-soft);border:1px solid var(--line);border-radius:5px;padding:.08em .35em;color:var(--code-inline-fg)}
154
- .doc pre{position:relative;overflow:auto;background:var(--code-bg);color:var(--code-fg);border-radius:8px;padding:14px 18px;margin:1.3em 0;font-size:.85em;line-height:1.6;scrollbar-width:thin;scrollbar-color:#3a3358 transparent;border:1px solid #221c40}
155
- .doc pre.shiki{background:var(--code-bg)!important;color:var(--code-fg)!important}
156
- .doc pre::-webkit-scrollbar{height:8px;width:8px}
157
- .doc pre::-webkit-scrollbar-thumb{background:#3a3358;border-radius:8px}
158
- .doc pre code{display:block;background:transparent;border:0;color:inherit;padding:0;font-size:1em;white-space:pre}
159
- .doc pre code .line{display:block;min-height:1.6em}
160
- .doc pre .copy{position:absolute;top:8px;right:8px;background:rgba(255,255,255,.06);color:var(--code-fg);border:1px solid rgba(255,255,255,.16);border-radius:6px;padding:3px 9px;font:500 .7rem/1 "Inter",sans-serif;cursor:pointer;opacity:0;transition:opacity .15s,background .15s,border-color .15s}
161
- .doc pre:hover .copy,.doc pre .copy:focus{opacity:1}
162
- .doc pre .copy:hover{background:rgba(255,255,255,.12)}
163
- .doc pre .copy.copied{background:var(--accent);border-color:var(--accent);opacity:1}
164
- .doc blockquote{margin:1.4em 0;padding:10px 16px;border-left:3px solid var(--accent);background:var(--accent-soft);border-radius:0 8px 8px 0;color:var(--text)}
165
- .doc blockquote p:last-child{margin-bottom:0}
166
- .doc table{width:100%;border-collapse:collapse;margin:1.2em 0;font-size:.92em}
167
- .doc th,.doc td{border-bottom:1px solid var(--line);padding:9px 10px;text-align:left;vertical-align:top}
168
- .doc th{font-weight:600;color:var(--ink);background:var(--line-soft);border-bottom:1px solid var(--line)}
169
- .doc hr{border:0;border-top:1px solid var(--line);margin:2.2em 0}
170
- .toc{position:sticky;top:24px;align-self:start;font-size:.84rem;padding-left:14px;border-left:1px solid var(--line);max-height:calc(100vh - 48px);overflow:auto;scrollbar-width:thin;scrollbar-color:var(--line) transparent}
171
- .toc::-webkit-scrollbar{width:5px}
172
- .toc::-webkit-scrollbar-thumb{background:var(--line);border-radius:5px}
173
- .toc h2{font-size:.66rem;color:var(--muted);text-transform:uppercase;letter-spacing:0;margin:0 0 10px;font-weight:600}
174
- .toc a{display:block;color:var(--muted);text-decoration:none;padding:4px 0 4px 10px;line-height:1.35;border-left:2px solid transparent;margin-left:-12px;transition:color .12s,border-color .12s}
175
- .toc a:hover{color:var(--ink);text-decoration:none}
176
- .toc a.active{color:var(--accent);border-left-color:var(--accent);font-weight:500}
177
- .toc-l3{padding-left:22px!important;font-size:.94em}
178
- @media(max-width:1179px){.toc{display:none}}
179
- .page-nav{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:48px;border-top:1px solid var(--line);padding-top:20px}
180
- .page-nav>a{display:block;border:1px solid var(--line);background:var(--paper);border-radius:9px;padding:13px 16px;text-decoration:none;color:var(--text);transition:border-color .15s,transform .15s,box-shadow .15s,background-color .18s}
181
- .page-nav>a:hover{border-color:var(--accent);text-decoration:none;color:var(--ink)}
182
- .page-nav small{display:block;color:var(--muted);font-size:.7rem;text-transform:uppercase;letter-spacing:0;margin-bottom:5px;font-weight:600}
183
- .page-nav span{display:block;font-weight:600;line-height:1.3;color:var(--ink)}
184
- .page-nav-prev{text-align:left}
185
- .page-nav-next{text-align:right;grid-column:2}
186
- .page-nav-prev:only-child{grid-column:1}
187
- .nav-toggle{display:none;position:fixed;top:14px;right:14px;top:calc(14px + env(safe-area-inset-top, 0px));right:calc(14px + env(safe-area-inset-right, 0px));z-index:20;width:40px;height:40px;border-radius:9px;background:var(--paper);border:1px solid var(--line);color:var(--ink);cursor:pointer;padding:10px 9px;flex-direction:column;align-items:stretch;justify-content:space-between;box-shadow:var(--shadow-card)}
188
- .nav-toggle span{display:block;width:100%;height:2px;flex:0 0 2px;background:currentColor;border-radius:2px;transition:transform .2s,opacity .2s}
189
- .nav-toggle[aria-expanded="true"] span:nth-child(1){transform:translateY(8px) rotate(45deg)}
190
- .nav-toggle[aria-expanded="true"] span:nth-child(2){opacity:0}
191
- .nav-toggle[aria-expanded="true"] span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}
192
- @media(max-width:900px){
193
- .shell{display:block}
194
- .sidebar{position:fixed;inset:0 30% 0 0;max-width:320px;height:100vh;z-index:15;transform:translateX(-100%);transition:transform .25s ease,background-color .18s,border-color .18s;box-shadow:0 18px 40px rgba(0,0,0,.18);background:var(--paper);pointer-events:none}
195
- .sidebar.open{transform:translateX(0);pointer-events:auto}
196
- .nav-toggle{display:flex}
197
- main{padding:64px 18px 56px}
198
- .hero{padding-top:6px}
199
- .hero h1{font-size:1.8rem}
200
- .home-hero h1{font-size:2.45rem}
201
- .doc h1{font-size:2.1rem}
202
- .hero-meta{width:100%;justify-content:flex-start}
203
- .home-hero{padding-top:8px}
204
- .home-visual{margin-top:18px}
205
- .doc{padding:0}
206
- .doc-grid{margin-top:18px;gap:24px}
207
- .doc :is(h2,h3,h4) .anchor{display:none}
208
- }
209
- @media(max-width:520px){
210
- main{padding:60px 14px 48px}
211
- .doc pre{margin-left:-14px;margin-right:-14px;border-radius:0;border-left:0;border-right:0}
212
- .home-install{flex-wrap:wrap}
213
- }
214
- </style>
215
- </head>
216
- <body>
217
- <button class="nav-toggle" type="button" aria-label="Toggle navigation" aria-expanded="false">
218
- <span aria-hidden="true"></span><span aria-hidden="true"></span><span aria-hidden="true"></span>
219
- </button>
220
- <div class="shell">
221
- <aside class="sidebar">
222
- <div class="sidebar-head">
223
- <a class="brand" href="./" aria-label="oracle docs home">
224
- <span class="mark" aria-hidden="true"></span>
225
- <span><strong>oracle</strong><small>askoracle.sh</small></span>
226
- </a>
227
- <button class="theme-toggle" type="button" aria-label="Toggle dark mode" aria-pressed="false" data-theme-toggle>
228
- <svg class="theme-icon-moon" viewBox="0 0 20 20" aria-hidden="true"><path d="M14.6 12.1A6.5 6.5 0 0 1 7.4 2.7a6.5 6.5 0 1 0 7.2 9.4z" fill="currentColor"/></svg>
229
- <svg class="theme-icon-sun" viewBox="0 0 20 20" aria-hidden="true"><circle cx="10" cy="10" r="3.4" fill="currentColor"/><g stroke="currentColor" stroke-width="1.6" stroke-linecap="round"><line x1="10" y1="2" x2="10" y2="4"/><line x1="10" y1="16" x2="10" y2="18"/><line x1="2" y1="10" x2="4" y2="10"/><line x1="16" y1="10" x2="18" y2="10"/><line x1="4.2" y1="4.2" x2="5.6" y2="5.6"/><line x1="14.4" y1="14.4" x2="15.8" y2="15.8"/><line x1="4.2" y1="15.8" x2="5.6" y2="14.4"/><line x1="14.4" y1="5.6" x2="15.8" y2="4.2"/></g></svg>
230
- </button>
231
- </div>
232
- <label class="search"><span>Search</span><input id="doc-search" type="search" placeholder="browser, mcp, sessions"></label>
233
- <nav><section><h2>Start</h2><a class="nav-link" href="./">Overview</a><a class="nav-link" href="install.html">Install</a><a class="nav-link" href="quickstart.html">Quickstart</a><a class="nav-link" href="configuration.html">Local configuration (JSON5)</a></section><section><h2>Mythical Pro Agents</h2><a class="nav-link" href="mythical-pro-agents.html">Mythical Pro Agents</a><a class="nav-link active" href="openai-endpoints.html">OpenAI-Compatible Endpoints</a><a class="nav-link" href="anthropic.html">Anthropic (Claude) Integration Plan</a><a class="nav-link" href="gemini.html">Gemini Integration</a><a class="nav-link" href="openrouter.html">OpenRouter</a><a class="nav-link" href="grok.html">Grok 4.1 (xAI) Support</a></section><section><h2>Browser Mode</h2><a class="nav-link" href="browser-mode.html">Browser Mode</a><a class="nav-link" href="chromium-forks.html">Chromium-based browsers (Chromium, Edge, Brave variants)</a><a class="nav-link" href="linux.html">Linux Notes</a><a class="nav-link" href="windows.html">Windows compatibility notes</a><a class="nav-link" href="windows-work.html">Windows Work</a><a class="nav-link" href="bridge.html">Bridge (Windows-hosted ChatGPT session → Linux clients)</a></section><section><h2>Agents &amp; MCP</h2><a class="nav-link" href="agents.html">Coding Agents</a><a class="nav-link" href="mcp.html">MCP Server</a></section><section><h2>Workflows</h2><a class="nav-link" href="sessions.html">Sessions</a><a class="nav-link" href="followup.html">Followups &amp; Lineage</a><a class="nav-link" href="multimodel.html">Multi-Model Execution</a></section><section><h2>Reference</h2><a class="nav-link" href="cli-reference.html">CLI Reference</a><a class="nav-link" href="spec.html">Spec</a><a class="nav-link" href="notifier.html">Session completion notifications</a><a class="nav-link" href="tui-debug.html">TUI navigation crash notes (2025-11-19)</a><a class="nav-link" href="manual-tests.html">Manual Test Suite (Browser Mode + Live API)</a><a class="nav-link" href="testing.html">Testing quickstart</a><a class="nav-link" href="RELEASING.html">Release Checklist (npm + Homebrew)</a></section></nav>
234
- </aside>
235
- <main>
236
- <header class="hero">
237
- <div class="hero-text">
238
- <p class="eyebrow">Mythical Pro Agents</p>
239
- <h1>OpenAI-Compatible Endpoints</h1>
240
- </div>
241
- <div class="hero-meta">
242
- <a class="repo" href="https://github.com/steipete/oracle" rel="noopener">GitHub</a>
243
- <a class="edit" href="https://github.com/steipete/oracle/edit/main/docs/openai-endpoints.md" rel="noopener">Edit page</a>
244
- </div>
245
- </header>
246
- <div class="doc-grid">
247
- <article class="doc"><h1 id="openai-compatible-endpoints">OpenAI-Compatible Endpoints</h1>
248
- <p>Oracle uses the official OpenAI Node.js SDK, which allows it to connect to any API that adheres to the OpenAI API specification. This includes:</p>
249
- <ul>
250
- <li>Official OpenAI API</li>
251
- <li>Azure OpenAI Service</li>
252
- <li>Local inference servers (e.g., vLLM, Ollama)</li>
253
- <li>Proxy servers (e.g., LiteLLM)</li>
254
- </ul>
255
- <h2 id="azure-openai"><a class="anchor" href="#azure-openai" aria-label="Anchor link">#</a>Azure OpenAI</h2>
256
- <p>Oracle uses Azure&#39;s v1 Responses endpoint when <code>--azure-endpoint</code> (or <code>azure.endpoint</code>) is set. Pass your resource endpoint, Azure key, and deployment name:</p>
257
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F47067">export</span><span style="color:#ADBAC7"> AZURE_OPENAI_ENDPOINT</span><span style="color:#F47067">=</span><span style="color:#96D0FF">"https://your-resource-name.openai.azure.com/"</span></span>
258
- <span class="line"><span style="color:#F47067">export</span><span style="color:#ADBAC7"> AZURE_OPENAI_API_KEY</span><span style="color:#F47067">=</span><span style="color:#96D0FF">"your-azure-api-key"</span></span>
259
- <span class="line"><span style="color:#F47067">export</span><span style="color:#ADBAC7"> AZURE_OPENAI_DEPLOYMENT</span><span style="color:#F47067">=</span><span style="color:#96D0FF">"gpt-5-1-pro"</span></span></code></pre>
260
- <p>Key lookup for GPT-family models when an Azure endpoint is set:</p>
261
- <ul>
262
- <li>First looks for <code>AZURE_OPENAI_API_KEY</code>.</li>
263
- <li>Falls back to <code>OPENAI_API_KEY</code> if the Azure key is missing.</li>
264
- </ul>
265
- <p>Without an Azure endpoint, Oracle keeps using <code>OPENAI_API_KEY</code> as before. If Azure env/config is present but you want first-party OpenAI for one run, pass <code>--provider openai</code> or <code>--no-azure</code>.</p>
266
- <p>Notes:</p>
267
- <ul>
268
- <li>Oracle calls Azure at <code>https://&lt;resource&gt;.openai.azure.com/openai/v1</code>.</li>
269
- <li>When Azure is selected, <code>--base-url</code> and <code>OPENAI_BASE_URL</code> are ignored for both model metadata and requests; Azure keys are never used for OpenRouter catalog lookups.</li>
270
- <li>For Responses API runs, Azure expects <code>model</code> to be your deployment name. Oracle fails early when an Azure endpoint is active without a deployment, except for <code>gpt-5.5-pro</code> where the CLI model id is used as the implicit deployment.</li>
271
- <li>API runs print the selected route without secrets, for example <code>Provider: Azure OpenAI | endpoint: your-resource.openai.azure.com | deployment: my-deployment | key: AZURE_OPENAI_API_KEY|OPENAI_API_KEY</code>.</li>
272
- <li><code>AZURE_OPENAI_API_VERSION</code> is still accepted for back-compat, but Azure&#39;s v1 Responses endpoint does not require it.</li>
273
- </ul>
274
- <h2 id="provider-diagnostics"><a class="anchor" href="#provider-diagnostics" aria-label="Anchor link">#</a>Provider diagnostics</h2>
275
- <p>Check provider readiness before an API run:</p>
276
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#96D0FF"> doctor</span><span style="color:#6CB6FF"> --providers</span><span style="color:#6CB6FF"> --models</span><span style="color:#96D0FF"> gpt-5.4,claude-4.6-sonnet,gemini-3-pro</span></span>
277
- <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --preflight</span><span style="color:#6CB6FF"> --models</span><span style="color:#96D0FF"> gpt-5.4,gemini-3-pro</span></span>
278
- <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --route</span><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.4</span></span></code></pre>
279
- <p>The output is redacted and local: provider, base host, key source, Azure status, and missing-route errors. These commands exit before sending a prompt or creating a session.</p>
280
- <p>When Azure env/config is present, GPT-family API models route through Azure unless you force first-party OpenAI:</p>
281
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --provider</span><span style="color:#96D0FF"> openai</span><span style="color:#6CB6FF"> --route</span><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.4</span></span>
282
- <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --no-azure</span><span style="color:#6CB6FF"> --route</span><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.4</span></span></code></pre>
283
- <h3 id="cli-configuration"><a class="anchor" href="#cli-configuration" aria-label="Anchor link">#</a>CLI Configuration</h3>
284
- <p>You can also pass the Azure settings via CLI flags (env for the key is still recommended):</p>
285
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --azure-endpoint</span><span style="color:#96D0FF"> https://...</span><span style="color:#6CB6FF"> --azure-deployment</span><span style="color:#96D0FF"> my-deployment-name</span></span></code></pre>
286
- <p>Force first-party OpenAI when Azure env vars are exported:</p>
287
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --provider</span><span style="color:#96D0FF"> openai</span><span style="color:#6CB6FF"> --engine</span><span style="color:#96D0FF"> api</span><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.5-pro</span><span style="color:#6CB6FF"> -p</span><span style="color:#96D0FF"> "Review this"</span></span>
288
- <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --no-azure</span><span style="color:#6CB6FF"> --engine</span><span style="color:#96D0FF"> api</span><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.5-pro</span><span style="color:#6CB6FF"> -p</span><span style="color:#96D0FF"> "Review this"</span></span></code></pre>
289
- <h2 id="gpt-5-6-pro-reasoning-mode"><a class="anchor" href="#gpt-5-6-pro-reasoning-mode" aria-label="Anchor link">#</a>GPT-5.6 Pro reasoning mode</h2>
290
- <p>GPT-5.6 Pro is a Responses API execution mode, not a separate model slug. Select the Sol model and enable Pro mode explicitly:</p>
291
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --engine</span><span style="color:#96D0FF"> api</span><span style="color:#F47067"> \</span></span>
292
- <span class="line"><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-5.6-sol</span><span style="color:#F47067"> \</span></span>
293
- <span class="line"><span style="color:#6CB6FF"> --reasoning-mode</span><span style="color:#96D0FF"> pro</span><span style="color:#F47067"> \</span></span>
294
- <span class="line"><span style="color:#6CB6FF"> --reasoning-effort</span><span style="color:#96D0FF"> max</span><span style="color:#F47067"> \</span></span>
295
- <span class="line"><span style="color:#6CB6FF"> -p</span><span style="color:#96D0FF"> "Review this difficult architecture"</span><span style="color:#F47067"> \</span></span>
296
- <span class="line"><span style="color:#6CB6FF"> --file</span><span style="color:#96D0FF"> "src/**"</span></span></code></pre>
297
- <p>Oracle sends <code>model: &quot;gpt-5.6-sol&quot;</code> with <code>reasoning.mode: &quot;pro&quot;</code> and <code>reasoning.effort: &quot;max&quot;</code>. Mode and effort are independent. GPT-5.6 supports <code>none</code>, <code>low</code>, <code>medium</code>, <code>high</code>, <code>xhigh</code>, and <code>max</code>; without an explicit effort, Oracle retains the model&#39;s configured effort. Pro-mode runs use Oracle&#39;s long-running API defaults: they detach unless <code>--wait</code> is supplied, default to a 60-minute timeout, and use Responses background mode when the selected route supports it.</p>
298
- <p><code>--reasoning-mode</code> accepts <code>standard</code> or <code>pro</code>; <code>--reasoning-effort</code> accepts all six GPT-5.6 effort levels. Both are API-only and supported for GPT-5.6 and GPT-6 Astra, with Astra&#39;s restrictions below. Oracle rejects reasoning mode for OpenRouter and custom <code>--base-url</code> routes because those routes currently use Oracle&#39;s Chat Completions adapter, which cannot represent Responses API reasoning mode.</p>
299
- <p>Do not pass <code>--model gpt-5.6-pro</code> or <code>--model gpt-5.6-sol-pro</code>; Oracle rejects those fake slugs and points to <code>--reasoning-mode pro</code>.</p>
300
- <h2 id="gpt-6-astra-api"><a class="anchor" href="#gpt-6-astra-api" aria-label="Anchor link">#</a>GPT-6 Astra API</h2>
301
- <p>Use the exact API model ID and choose reasoning mode separately:</p>
302
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --engine</span><span style="color:#96D0FF"> api</span><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> gpt-6-astra</span><span style="color:#6CB6FF"> --reasoning-mode</span><span style="color:#96D0FF"> pro</span><span style="color:#6CB6FF"> --reasoning-effort</span><span style="color:#96D0FF"> max</span><span style="color:#6CB6FF"> -p</span><span style="color:#96D0FF"> "Review this architecture"</span></span></code></pre>
303
- <p>Oracle supports Astra&#39;s <code>low</code>, <code>medium</code>, <code>high</code>, <code>xhigh</code>, and <code>max</code> efforts and rejects <code>none</code> before inference. The default effort is <code>xhigh</code>; Pro is enabled only with <code>--reasoning-mode pro</code> and retains the long-running behavior above. The default model is unchanged. Browser selection maps this model to ChatGPT&#39;s <code>Latest</code> radio; <code>gpt-6-pro</code> additionally requests verified Pro effort. That Pro alias is browser-only: API calls use the exact model ID and reasoning mode above. The existing <code>current</code> and <code>ignore</code> strategies remain available: they retain the active ChatGPT model without verifying that it is Astra. CLI and MCP both honor these strategies, including saved MCP browser configuration.</p>
304
- <p>The default input budget is a conservative 272,000 tokens at the base-rate boundary, not the model&#39;s maximum capacity. Standard text estimates use $10 per million input tokens and $50 per million output tokens. Cache writes, tool fees, Pro execution, and inputs above the base-rate boundary can change actual billing; Oracle&#39;s basic estimate does not model those adjustments.</p>
305
- <p>References: <a href="https://developers.openai.com/api/docs/models/gpt-6-astra">Astra model</a>, <a href="https://developers.openai.com/api/docs/guides/latest-model">migration guidance</a>, and <a href="https://developers.openai.com/api/docs/pricing">API pricing</a>.</p>
306
- <h2 id="custom-base-urls-litellm-localhost"><a class="anchor" href="#custom-base-urls-litellm-localhost" aria-label="Anchor link">#</a>Custom Base URLs (LiteLLM, Localhost)</h2>
307
- <p>For other compatible services that use the standard OpenAI protocol but a different URL:</p>
308
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --base-url</span><span style="color:#96D0FF"> http://localhost:4000</span></span></code></pre>
309
- <p>Or via <code>config.json</code>:</p>
310
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-json"><span class="line"><span style="color:#ADBAC7">{</span></span>
311
- <span class="line"><span style="color:#8DDB8C"> "apiBaseUrl"</span><span style="color:#ADBAC7">: </span><span style="color:#96D0FF">"http://localhost:4000"</span></span>
312
- <span class="line"><span style="color:#ADBAC7">}</span></span></code></pre>
313
- <p>If a gateway exposes a different on-wire model id, add an API-only override to the user config at <code>~/.oracle/config.json</code>:</p>
314
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-json5"><span class="line"><span style="color:#ADBAC7">{</span></span>
315
- <span class="line"><span style="color:#96D0FF"> apiBaseUrl</span><span style="color:#ADBAC7">: </span><span style="color:#96D0FF">"http://localhost:4000"</span><span style="color:#ADBAC7">,</span></span>
316
- <span class="line"><span style="color:#96D0FF"> model</span><span style="color:#ADBAC7">: </span><span style="color:#96D0FF">"gpt-5.5"</span><span style="color:#ADBAC7">,</span></span>
317
- <span class="line"><span style="color:#96D0FF"> modelOverrides</span><span style="color:#ADBAC7">: {</span></span>
318
- <span class="line"><span style="color:#96D0FF"> "gpt-5.5"</span><span style="color:#ADBAC7">: {</span></span>
319
- <span class="line"><span style="color:#96D0FF"> apiModel</span><span style="color:#ADBAC7">: </span><span style="color:#96D0FF">"gateway-model"</span><span style="color:#ADBAC7">,</span></span>
320
- <span class="line"><span style="color:#96D0FF"> reasoning</span><span style="color:#ADBAC7">: { </span><span style="color:#96D0FF">effort</span><span style="color:#ADBAC7">: </span><span style="color:#96D0FF">"high"</span><span style="color:#ADBAC7"> },</span></span>
321
- <span class="line"><span style="color:#ADBAC7"> },</span></span>
322
- <span class="line"><span style="color:#ADBAC7"> },</span></span>
323
- <span class="line"><span style="color:#ADBAC7">}</span></span></code></pre>
324
- <p>Overrides accept existing built-in model keys only and are ignored in project <code>.oracle/config.json</code> files. See <a href="configuration.html">Local configuration</a> for the full field list and precedence.</p>
325
- <h2 id="model-aliases"><a class="anchor" href="#model-aliases" aria-label="Anchor link">#</a>Model aliases</h2>
326
- <p>Oracle keeps a stable CLI-facing model set, but some names are aliases for the concrete API model ids it sends:</p>
327
- <ul>
328
- <li><code>gpt-5.1-pro</code>, <code>gpt-5.2-pro</code> → <code>gpt-5.5-pro</code> (API)</li>
329
- </ul>
330
- <p>Notes:</p>
331
- <ul>
332
- <li><code>gpt-5.1-pro</code> and <code>gpt-5.2-pro</code> are <strong>CLI aliases</strong> for “the current Pro API model” — OpenAI’s API uses <code>gpt-5.5-pro</code>.</li>
333
- <li>For API runs, use <code>gpt-5-pro</code> when you want the classic Pro tier explicitly. Browser-mode generic Pro aliases follow ChatGPT&#39;s current Pro target; use <code>gpt-5.5-pro</code> there to pin GPT-5.5.</li>
334
- </ul>
335
- <h3 id="browser-engine-vs-api-base-urls"><a class="anchor" href="#browser-engine-vs-api-base-urls" aria-label="Anchor link">#</a>Browser engine vs API base URLs</h3>
336
- <p><code>--base-url</code> / <code>apiBaseUrl</code> only affect API runs. For browser automation, use <code>--chatgpt-url</code> (or <code>browser.chatgptUrl</code> in config) to point Chrome at a specific ChatGPT workspace/folder such as <code>https://chatgpt.com/g/.../project</code>.</p>
337
- <h3 id="example-litellm"><a class="anchor" href="#example-litellm" aria-label="Anchor link">#</a>Example: LiteLLM</h3>
338
- <p><a href="https://docs.litellm.ai/">LiteLLM</a> allows you to use Azure, Anthropic, VertexAI, and more using the OpenAI format.</p>
339
- <ol>
340
- <li>Start LiteLLM:</li>
341
- <p>``<code>bash litellm --model azure/gpt-4-turbo </code>``</p>
342
- <li>Connect Oracle:</li>
343
- <p>``<code>bash oracle --base-url http://localhost:4000 </code>``</p>
344
- </ol>
345
- <h2 id="openrouter"><a class="anchor" href="#openrouter" aria-label="Anchor link">#</a>OpenRouter</h2>
346
- <p>Oracle can also talk to OpenRouter (Responses API compatible) with any model id:</p>
347
- <pre class="shiki github-dark-dimmed" style="background-color:var(--code-bg);color:var(--code-fg)" tabindex="0"><code class="language-bash"><span class="line"><span style="color:#F47067">export</span><span style="color:#ADBAC7"> OPENROUTER_API_KEY</span><span style="color:#F47067">=</span><span style="color:#96D0FF">"sk-or-..."</span></span>
348
- <span class="line"><span style="color:#F69D50">oracle</span><span style="color:#6CB6FF"> --model</span><span style="color:#96D0FF"> minimax/minimax-m2</span><span style="color:#6CB6FF"> --prompt</span><span style="color:#96D0FF"> "Summarize the notes"</span></span></code></pre>
349
- <ul>
350
- <li>If <code>OPENROUTER_API_KEY</code> is set and no provider-specific key is available for the chosen model, Oracle defaults the base URL to <code>https://openrouter.ai/api/v1</code>.</li>
351
- <li>You can still set <code>--base-url</code> explicitly; if it points at OpenRouter (with or without a trailing <code>/responses</code>), Oracle will use <code>OPENROUTER_API_KEY</code> and forward optional attribution headers (<code>OPENROUTER_REFERER</code> / <code>OPENROUTER_TITLE</code>).</li>
352
- <li>Multi-model runs accept OpenRouter ids alongside built-in ones. See <code>docs/openrouter.md</code> for details.</li>
353
- </ul><nav class="page-nav" aria-label="Pager"><a class="page-nav-prev" href="mythical-pro-agents.html"><small>Previous</small><span>Mythical Pro Agents</span></a><a class="page-nav-next" href="anthropic.html"><small>Next</small><span>Anthropic (Claude) Integration Plan</span></a></nav></article>
354
- <nav class="toc" aria-label="On this page"><h2>On this page</h2><a class="toc-l2" href="#azure-openai">Azure OpenAI</a><a class="toc-l2" href="#provider-diagnostics">Provider diagnostics</a><a class="toc-l3" href="#cli-configuration">CLI Configuration</a><a class="toc-l2" href="#gpt-5-6-pro-reasoning-mode">GPT-5.6 Pro reasoning mode</a><a class="toc-l2" href="#gpt-6-astra-api">GPT-6 Astra API</a><a class="toc-l2" href="#custom-base-urls-litellm-localhost">Custom Base URLs (LiteLLM, Localhost)</a><a class="toc-l2" href="#model-aliases">Model aliases</a><a class="toc-l3" href="#browser-engine-vs-api-base-urls">Browser engine vs API base URLs</a><a class="toc-l3" href="#example-litellm">Example: LiteLLM</a><a class="toc-l2" href="#openrouter">OpenRouter</a></nav>
355
- </div>
356
- </main>
357
- </div>
358
- <script>
359
- const themeRoot=document.documentElement;
360
- function applyTheme(mode){themeRoot.dataset.theme=mode;document.querySelectorAll('[data-theme-toggle]').forEach(b=>b.setAttribute('aria-pressed',mode==='dark'?'true':'false'))}
361
- function storedTheme(){try{return localStorage.getItem('theme')}catch(e){return null}}
362
- function persistTheme(mode){try{localStorage.setItem('theme',mode)}catch(e){}}
363
- applyTheme(themeRoot.dataset.theme==='dark'?'dark':'light');
364
- document.querySelectorAll('[data-theme-toggle]').forEach(btn=>{btn.addEventListener('click',()=>{const next=themeRoot.dataset.theme==='dark'?'light':'dark';applyTheme(next);persistTheme(next)})});
365
- const systemDark=window.matchMedia&&matchMedia('(prefers-color-scheme: dark)');
366
- function onSystemChange(e){if(storedTheme())return;applyTheme(e.matches?'dark':'light')}
367
- if(systemDark){if(systemDark.addEventListener)systemDark.addEventListener('change',onSystemChange);else if(systemDark.addListener)systemDark.addListener(onSystemChange)}
368
- const sidebar=document.querySelector('.sidebar');
369
- const toggle=document.querySelector('.nav-toggle');
370
- const mobileNav=window.matchMedia('(max-width: 900px)');
371
- const sidebarFocusable='a[href],button,input,select,textarea,[tabindex]';
372
- function setSidebarFocusable(enabled){
373
- sidebar?.querySelectorAll(sidebarFocusable).forEach((el)=>{
374
- if(enabled){
375
- if(el.dataset.sidebarTabindex!==undefined){
376
- if(el.dataset.sidebarTabindex)el.setAttribute('tabindex',el.dataset.sidebarTabindex);
377
- else el.removeAttribute('tabindex');
378
- delete el.dataset.sidebarTabindex;
379
- }
380
- }else if(el.dataset.sidebarTabindex===undefined){
381
- el.dataset.sidebarTabindex=el.getAttribute('tabindex')??'';
382
- el.setAttribute('tabindex','-1');
383
- }
384
- });
385
- }
386
- function setSidebarOpen(open){
387
- if(!sidebar||!toggle)return;
388
- sidebar.classList.toggle('open',open);
389
- toggle.setAttribute('aria-expanded',open?'true':'false');
390
- if(mobileNav.matches){
391
- sidebar.inert=!open;
392
- if(open)sidebar.removeAttribute('aria-hidden');
393
- else sidebar.setAttribute('aria-hidden','true');
394
- setSidebarFocusable(open);
395
- }else{
396
- sidebar.inert=false;
397
- sidebar.removeAttribute('aria-hidden');
398
- setSidebarFocusable(true);
399
- }
400
- }
401
- setSidebarOpen(false);
402
- toggle?.addEventListener('click',()=>setSidebarOpen(!sidebar?.classList.contains('open')));
403
- document.addEventListener('click',(e)=>{if(!sidebar?.classList.contains('open'))return;if(sidebar.contains(e.target)||toggle?.contains(e.target))return;setSidebarOpen(false)});
404
- document.addEventListener('keydown',(e)=>{if(e.key==='Escape')setSidebarOpen(false)});
405
- const syncSidebarForViewport=()=>setSidebarOpen(sidebar?.classList.contains('open')??false);
406
- if(mobileNav.addEventListener)mobileNav.addEventListener('change',syncSidebarForViewport);
407
- else mobileNav.addListener?.(syncSidebarForViewport);
408
- const input=document.getElementById('doc-search');
409
- input?.addEventListener('input',()=>{const q=input.value.trim().toLowerCase();document.querySelectorAll('nav section').forEach(sec=>{let any=false;sec.querySelectorAll('.nav-link').forEach(a=>{const m=!q||a.textContent.toLowerCase().includes(q);a.style.display=m?'block':'none';if(m)any=true});sec.style.display=any?'block':'none'})});
410
- function attachCopy(target,getText){const btn=document.createElement('button');btn.type='button';btn.className='copy';btn.textContent='Copy';btn.addEventListener('click',async()=>{try{await navigator.clipboard.writeText(getText());btn.textContent='Copied';btn.classList.add('copied');setTimeout(()=>{btn.textContent='Copy';btn.classList.remove('copied')},1400)}catch{btn.textContent='Failed';setTimeout(()=>{btn.textContent='Copy'},1400)}});target.appendChild(btn)}
411
- document.querySelectorAll('.doc pre').forEach(pre=>attachCopy(pre,()=>pre.querySelector('code')?.textContent??''));
412
- document.querySelectorAll('.home-install').forEach(el=>attachCopy(el,()=>el.querySelector('code')?.textContent??''));
413
- const tocLinks=document.querySelectorAll('.toc a');
414
- if(tocLinks.length){const map=new Map();tocLinks.forEach(a=>{const id=a.getAttribute('href').slice(1);const el=document.getElementById(id);if(el)map.set(el,a)});const setActive=l=>{tocLinks.forEach(x=>x.classList.remove('active'));l.classList.add('active')};const obs=new IntersectionObserver(entries=>{const visible=entries.filter(e=>e.isIntersecting).sort((a,b)=>a.boundingClientRect.top-b.boundingClientRect.top);if(visible.length){const link=map.get(visible[0].target);if(link)setActive(link)}},{rootMargin:'-15% 0px -65% 0px',threshold:0});map.forEach((_,el)=>obs.observe(el))}
415
- </script>
416
- </body>
417
- </html>