@bitkyc08/opencodex 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/LICENSE +21 -0
  2. package/README.ko.md +164 -0
  3. package/README.md +165 -0
  4. package/README.zh-CN.md +162 -0
  5. package/gui/README.md +73 -0
  6. package/gui/dist/assets/index-C1wlp1SM.css +1 -0
  7. package/gui/dist/assets/index-C9y3iMF1.js +9 -0
  8. package/gui/dist/favicon.png +0 -0
  9. package/gui/dist/icons.svg +24 -0
  10. package/gui/dist/index.html +15 -0
  11. package/gui/dist/logo.png +0 -0
  12. package/package.json +56 -0
  13. package/scripts/postinstall.mjs +57 -0
  14. package/src/adapters/anthropic.ts +306 -0
  15. package/src/adapters/azure.ts +31 -0
  16. package/src/adapters/base.ts +20 -0
  17. package/src/adapters/google.ts +195 -0
  18. package/src/adapters/image.ts +23 -0
  19. package/src/adapters/openai-chat.ts +265 -0
  20. package/src/adapters/openai-responses.ts +43 -0
  21. package/src/bridge.ts +296 -0
  22. package/src/cli.ts +183 -0
  23. package/src/codex-catalog.ts +318 -0
  24. package/src/codex-inject.ts +186 -0
  25. package/src/config.ts +108 -0
  26. package/src/index.ts +20 -0
  27. package/src/init.ts +163 -0
  28. package/src/model-cache.ts +42 -0
  29. package/src/oauth/anthropic.ts +151 -0
  30. package/src/oauth/callback-server.ts +249 -0
  31. package/src/oauth/index.ts +235 -0
  32. package/src/oauth/key-providers.ts +126 -0
  33. package/src/oauth/kimi.ts +160 -0
  34. package/src/oauth/local-token-detect.ts +71 -0
  35. package/src/oauth/login-cli.ts +90 -0
  36. package/src/oauth/pkce.ts +15 -0
  37. package/src/oauth/store.ts +39 -0
  38. package/src/oauth/types.ts +22 -0
  39. package/src/oauth/xai.ts +234 -0
  40. package/src/responses/parser.ts +402 -0
  41. package/src/responses/schema.ts +145 -0
  42. package/src/router.ts +86 -0
  43. package/src/server.ts +522 -0
  44. package/src/service.ts +130 -0
  45. package/src/star-prompt.ts +50 -0
  46. package/src/types.ts +228 -0
  47. package/src/update.ts +64 -0
  48. package/src/vision/describe.ts +98 -0
  49. package/src/vision/index.ts +141 -0
  50. package/src/web-search/executor.ts +75 -0
  51. package/src/web-search/format-result.ts +45 -0
  52. package/src/web-search/index.ts +62 -0
  53. package/src/web-search/loop.ts +188 -0
  54. package/src/web-search/parse.ts +128 -0
  55. package/src/web-search/synthetic-tool.ts +42 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 opencodex contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.ko.md ADDED
@@ -0,0 +1,164 @@
1
+ <div align="center">
2
+
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="assets/logo-dark.png">
5
+ <img alt="opencodex" src="assets/logo-light.png" width="96" height="96">
6
+ </picture>
7
+
8
+ # opencodex (`ocx`)
9
+
10
+ **[OpenAI Codex](https://openai.com/codex)를 위한 범용 프로바이더 proxy — Codex CLI, App, SDK에서 어떤 LLM이든 사용하세요.**
11
+
12
+ [English](README.md) · **한국어** · [简体中文](README.zh-CN.md)
13
+
14
+ 📖 **[전체 문서 →](https://lidge-jun.github.io/opencodex/ko/)**
15
+
16
+ </div>
17
+
18
+ <p align="center">
19
+ <img src="assets/dashboard.png" alt="opencodex 대시보드 — 프록시 상태·프로바이더·모델을 보여주는 다크 컨트롤 패널" width="820">
20
+ </p>
21
+
22
+ Codex는 오직 Responses API(`/v1/responses`)만 사용합니다. opencodex는 Codex와 여러분의 LLM
23
+ 프로바이더 사이에 위치하여, 프로토콜을 실시간으로 변환합니다 — streaming, tool 호출, reasoning, 이미지까지
24
+ 모두 포함해서 — 양방향으로 동작합니다.
25
+
26
+ ```
27
+ Codex CLI / App / SDK ──/v1/responses──▶ opencodex ──▶ Any provider
28
+
29
+ Anthropic · Google · xAI · Kimi · Ollama Cloud · Groq
30
+ OpenRouter · Azure · DeepSeek · GLM · …and OpenAI itself
31
+ ```
32
+
33
+ ## 빠른 시작
34
+
35
+ ```bash
36
+ # Install
37
+ npm install -g @bitkyc08/opencodex # or: bun install -g @bitkyc08/opencodex
38
+
39
+ # Interactive setup (writes config + injects into Codex)
40
+ ocx init
41
+
42
+ # Start the proxy
43
+ ocx start
44
+
45
+ # Use Codex normally — it now routes through opencodex
46
+ codex "Write a hello world in Rust"
47
+ ```
48
+
49
+ <details>
50
+ <summary><b><a href="https://bun.sh">bun</a>이 없으신가요?</b> — 먼저 설치하세요 (opencodex는 bun에서 실행됩니다)</summary>
51
+
52
+ <br/>
53
+
54
+ ```bash
55
+ # macOS / Linux / WSL
56
+ curl -fsSL https://bun.sh/install | bash
57
+
58
+ # Windows (PowerShell)
59
+ powershell -c "irm bun.sh/install.ps1 | iex"
60
+ ```
61
+
62
+ 설치 후 `npm install -g @bitkyc08/opencodex`를 다시 실행하세요. (`ocx` 바이너리는 bun 기반이라 bun이 `PATH`에 있어야 합니다.)
63
+
64
+ </details>
65
+
66
+ `provider/model` 형식으로 라우팅된 특정 모델을 지정할 수 있습니다:
67
+
68
+ ```bash
69
+ codex -m "anthropic/claude-opus-4-8" "Explain this stack trace"
70
+ codex -m "ollama-cloud/glm-5.2" "Write a SQL migration"
71
+ ```
72
+
73
+ ## 주요 기능
74
+
75
+ - **다섯 가지 adapter**로 Anthropic Messages, Google Gemini, Azure, OpenAI Responses passthrough,
76
+ 그리고 **모든 OpenAI 호환 Chat Completions** 엔드포인트를 지원합니다.
77
+ - **OAuth, API 키, 또는 ChatGPT forward.** xAI / Anthropic / Kimi 계정으로 로그인하거나(토큰은
78
+ 자동 갱신됩니다), `codex login`을 forward 하거나, 키를 붙여넣으세요(`${ENV_VARS}` 지원). 18개 프로바이더의
79
+ API 키 카탈로그(**Ollama Cloud** 포함)가 기본 내장되어 있습니다.
80
+ - **Codex에 바로 통합.** `~/.codex/config.toml`에 `[model_providers.opencodex]` 테이블을 주입하고
81
+ 라우팅된 모델을 Codex의 카탈로그와 서브에이전트 선택기에 병합합니다 — 완전히 되돌릴 수 있습니다.
82
+ - **Sidecar.** OpenAI가 아닌 모델에도 ChatGPT 로그인을 통한 `gpt-5.4-mini`를 사용해 실제 **웹 검색**과
83
+ **이미지 이해** 기능을 제공합니다.
84
+ - 프로바이더, OAuth 로그인, 모델 선택, 요청 로그를 위한 **웹 대시보드**.
85
+
86
+ ## 프로바이더 및 adapter
87
+
88
+ | Provider | Adapter | Auth |
89
+ |---|---|---|
90
+ | OpenAI (ChatGPT login) | `openai-responses` | forward (키 불필요) |
91
+ | OpenAI (API key) | `openai-responses` | key |
92
+ | Anthropic Claude | `anthropic` | oauth / key |
93
+ | xAI Grok | `openai-chat` | oauth / key |
94
+ | Kimi (Moonshot) | `openai-chat` | oauth / key |
95
+ | Google Gemini | `google` | key |
96
+ | Azure OpenAI | `azure` | key |
97
+ | Ollama Cloud + 17개 프로바이더 카탈로그 | `openai-chat` | key |
98
+ | Ollama / vLLM / LM Studio (로컬) | `openai-chat` | key (보통 비워둠) |
99
+ | 모든 OpenAI 호환 엔드포인트 | `openai-chat` | key |
100
+
101
+ ## CLI
102
+
103
+ ```bash
104
+ ocx init # interactive setup
105
+ ocx start [--port 10100] # start the proxy
106
+ ocx stop # stop + restore native Codex
107
+ ocx restore # restore without stopping (alias: ocx eject)
108
+ ocx sync # refresh models + re-inject into Codex
109
+ ocx status # is the proxy running?
110
+ ocx login <xai|anthropic|kimi> # OAuth login
111
+ ocx logout <provider> # remove a stored login
112
+ ocx gui # open the web dashboard
113
+ ocx service <install|start|stop|status|uninstall> # run as a background service
114
+ ```
115
+
116
+ ## 설정
117
+
118
+ 설정은 `~/.opencodex/config.json`에 저장됩니다. 최소 예시:
119
+
120
+ ```json
121
+ {
122
+ "port": 10100,
123
+ "defaultProvider": "anthropic",
124
+ "providers": {
125
+ "anthropic": {
126
+ "adapter": "anthropic",
127
+ "baseUrl": "https://api.anthropic.com",
128
+ "authMode": "oauth",
129
+ "defaultModel": "claude-sonnet-4-6"
130
+ },
131
+ "ollama-cloud": {
132
+ "adapter": "openai-chat",
133
+ "baseUrl": "https://ollama.com/v1",
134
+ "apiKey": "${OLLAMA_API_KEY}",
135
+ "defaultModel": "glm-5.2"
136
+ }
137
+ }
138
+ }
139
+ ```
140
+
141
+ 모든 필드에 대한 자세한 내용은 **[설정 레퍼런스](https://lidge-jun.github.io/opencodex/ko/reference/configuration/)**
142
+ 를 참고하세요.
143
+
144
+ ## 문서
145
+
146
+ 전체 개발자 문서 — 아키텍처, 모든 adapter, 요청 라이프사이클, sidecar,
147
+ Codex 통합, CLI/설정 레퍼런스 — 는 [`docs-site/`](./docs-site) 아래의 Astro 사이트이며
148
+ **[lidge-jun.github.io/opencodex](https://lidge-jun.github.io/opencodex/ko/)**에 게시됩니다.
149
+
150
+ ## 개발
151
+
152
+ ```bash
153
+ git clone https://github.com/lidge-jun/opencodex.git
154
+ cd opencodex
155
+ bun install
156
+ bun run dev # start the proxy in dev mode
157
+ bun x tsc --noEmit # typecheck
158
+ ```
159
+
160
+ **[기여하기](https://lidge-jun.github.io/opencodex/ko/contributing/)**를 참고하세요.
161
+
162
+ ## 라이선스
163
+
164
+ MIT
package/README.md ADDED
@@ -0,0 +1,165 @@
1
+ <div align="center">
2
+
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="assets/logo-dark.png">
5
+ <img alt="opencodex" src="assets/logo-light.png" width="96" height="96">
6
+ </picture>
7
+
8
+ # opencodex (`ocx`)
9
+
10
+ **Universal provider proxy for [OpenAI Codex](https://openai.com/codex) — use any LLM with Codex CLI, App, and SDK.**
11
+
12
+ [English](README.md) · [한국어](README.ko.md) · [简体中文](README.zh-CN.md)
13
+
14
+ 📖 **[Full documentation →](https://lidge-jun.github.io/opencodex/)**
15
+
16
+ </div>
17
+
18
+ <p align="center">
19
+ <img src="assets/dashboard.png" alt="opencodex dashboard — a dark provider control panel showing live proxy status, routed providers, and available models" width="820">
20
+ </p>
21
+
22
+ Codex only speaks the Responses API (`/v1/responses`). opencodex sits between Codex and your LLM
23
+ provider, translating the protocol on the fly — streaming, tool calls, reasoning, and images included
24
+ — in both directions.
25
+
26
+ ```
27
+ Codex CLI / App / SDK ──/v1/responses──▶ opencodex ──▶ Any provider
28
+
29
+ Anthropic · Google · xAI · Kimi · Ollama Cloud · Groq
30
+ OpenRouter · Azure · DeepSeek · GLM · …and OpenAI itself
31
+ ```
32
+
33
+ ## Quick start
34
+
35
+ ```bash
36
+ # Install
37
+ npm install -g @bitkyc08/opencodex # or: bun install -g @bitkyc08/opencodex
38
+
39
+ # Interactive setup (writes config + injects into Codex)
40
+ ocx init
41
+
42
+ # Start the proxy
43
+ ocx start
44
+
45
+ # Use Codex normally — it now routes through opencodex
46
+ codex "Write a hello world in Rust"
47
+ ```
48
+
49
+ <details>
50
+ <summary><b>Don't have <a href="https://bun.sh">bun</a>?</b> — install it first (opencodex runs on bun)</summary>
51
+
52
+ <br/>
53
+
54
+ ```bash
55
+ # macOS / Linux / WSL
56
+ curl -fsSL https://bun.sh/install | bash
57
+
58
+ # Windows (PowerShell)
59
+ powershell -c "irm bun.sh/install.ps1 | iex"
60
+ ```
61
+
62
+ Then re-run `npm install -g @bitkyc08/opencodex`. (The `ocx` binary is bun-native, so bun must be on your `PATH`.)
63
+
64
+ </details>
65
+
66
+ Target a specific routed model with the `provider/model` form:
67
+
68
+ ```bash
69
+ codex -m "anthropic/claude-opus-4-8" "Explain this stack trace"
70
+ codex -m "ollama-cloud/glm-5.2" "Write a SQL migration"
71
+ ```
72
+
73
+ ## Highlights
74
+
75
+ - **Five adapters** cover Anthropic Messages, Google Gemini, Azure, the OpenAI Responses passthrough,
76
+ and **every OpenAI-compatible Chat Completions** endpoint.
77
+ - **OAuth, API key, or ChatGPT forward.** Log in with your xAI / Anthropic / Kimi account (tokens
78
+ auto-refresh), forward your `codex login`, or paste a key (`${ENV_VARS}` supported). An 18-provider
79
+ API-key catalog (incl. **Ollama Cloud**) is built in.
80
+ - **Drops into Codex.** Injects a `[model_providers.opencodex]` table into `~/.codex/config.toml` and
81
+ merges routed models into Codex's catalog and subagent picker — fully reversible.
82
+ - **Sidecars.** Give non-OpenAI models real **web search** and **image understanding** via a
83
+ `gpt-5.4-mini` over your ChatGPT login.
84
+ - **Web dashboard** for providers, OAuth login, model selection, and request logs.
85
+
86
+ ## Providers & adapters
87
+
88
+ | Provider | Adapter | Auth |
89
+ |---|---|---|
90
+ | OpenAI (ChatGPT login) | `openai-responses` | forward (no key) |
91
+ | OpenAI (API key) | `openai-responses` | key |
92
+ | Anthropic Claude | `anthropic` | oauth / key |
93
+ | xAI Grok | `openai-chat` | oauth / key |
94
+ | Kimi (Moonshot) | `openai-chat` | oauth / key |
95
+ | Google Gemini | `google` | key |
96
+ | Azure OpenAI | `azure` | key |
97
+ | Ollama Cloud + 17-provider catalog | `openai-chat` | key |
98
+ | Ollama / vLLM / LM Studio (local) | `openai-chat` | key (usually blank) |
99
+ | Any OpenAI-compatible endpoint | `openai-chat` | key |
100
+
101
+ ## CLI
102
+
103
+ ```bash
104
+ ocx init # interactive setup
105
+ ocx start [--port 10100] # start the proxy
106
+ ocx stop # stop + restore native Codex
107
+ ocx restore # restore without stopping (alias: ocx eject)
108
+ ocx sync # refresh models + re-inject into Codex
109
+ ocx status # is the proxy running?
110
+ ocx login <xai|anthropic|kimi> # OAuth login
111
+ ocx logout <provider> # remove a stored login
112
+ ocx gui # open the web dashboard
113
+ ocx service <install|start|stop|status|uninstall> # run as a background service
114
+ ocx update # update opencodex to the latest published version
115
+ ```
116
+
117
+ ## Configuration
118
+
119
+ Config lives at `~/.opencodex/config.json`. Minimal example:
120
+
121
+ ```json
122
+ {
123
+ "port": 10100,
124
+ "defaultProvider": "anthropic",
125
+ "providers": {
126
+ "anthropic": {
127
+ "adapter": "anthropic",
128
+ "baseUrl": "https://api.anthropic.com",
129
+ "authMode": "oauth",
130
+ "defaultModel": "claude-sonnet-4-6"
131
+ },
132
+ "ollama-cloud": {
133
+ "adapter": "openai-chat",
134
+ "baseUrl": "https://ollama.com/v1",
135
+ "apiKey": "${OLLAMA_API_KEY}",
136
+ "defaultModel": "glm-5.2"
137
+ }
138
+ }
139
+ }
140
+ ```
141
+
142
+ See the **[Configuration reference](https://lidge-jun.github.io/opencodex/reference/configuration/)**
143
+ for every field.
144
+
145
+ ## Documentation
146
+
147
+ The full developer documentation — architecture, every adapter, the request lifecycle, the sidecars,
148
+ Codex integration, and the CLI/config reference — is an Astro site under [`docs-site/`](./docs-site)
149
+ and published to **[lidge-jun.github.io/opencodex](https://lidge-jun.github.io/opencodex/)**.
150
+
151
+ ## Development
152
+
153
+ ```bash
154
+ git clone https://github.com/lidge-jun/opencodex.git
155
+ cd opencodex
156
+ bun install
157
+ bun run dev # start the proxy in dev mode
158
+ bun x tsc --noEmit # typecheck
159
+ ```
160
+
161
+ See **[Contributing](https://lidge-jun.github.io/opencodex/contributing/)**.
162
+
163
+ ## License
164
+
165
+ MIT
@@ -0,0 +1,162 @@
1
+ <div align="center">
2
+
3
+ <picture>
4
+ <source media="(prefers-color-scheme: dark)" srcset="assets/logo-dark.png">
5
+ <img alt="opencodex" src="assets/logo-light.png" width="96" height="96">
6
+ </picture>
7
+
8
+ # opencodex (`ocx`)
9
+
10
+ **面向 [OpenAI Codex](https://openai.com/codex) 的通用 provider proxy —— 在 Codex CLI、App 和 SDK 中使用任意 LLM。**
11
+
12
+ [English](README.md) · [한국어](README.ko.md) · **简体中文**
13
+
14
+ 📖 **[完整文档 →](https://lidge-jun.github.io/opencodex/zh-cn/)**
15
+
16
+ </div>
17
+
18
+ <p align="center">
19
+ <img src="assets/dashboard.png" alt="opencodex 控制台 —— 展示代理状态、provider 与可用模型的深色控制面板" width="820">
20
+ </p>
21
+
22
+ Codex 只能使用 Responses API(`/v1/responses`)。opencodex 位于 Codex 与你的 LLM
23
+ provider 之间,实时翻译两者之间的协议 —— 包括 streaming、工具调用、推理(reasoning)和图像
24
+ —— 并且是双向的。
25
+
26
+ ```
27
+ Codex CLI / App / SDK ──/v1/responses──▶ opencodex ──▶ Any provider
28
+
29
+ Anthropic · Google · xAI · Kimi · Ollama Cloud · Groq
30
+ OpenRouter · Azure · DeepSeek · GLM · …and OpenAI itself
31
+ ```
32
+
33
+ ## 快速开始
34
+
35
+ ```bash
36
+ # Install
37
+ npm install -g @bitkyc08/opencodex # or: bun install -g @bitkyc08/opencodex
38
+
39
+ # Interactive setup (writes config + injects into Codex)
40
+ ocx init
41
+
42
+ # Start the proxy
43
+ ocx start
44
+
45
+ # Use Codex normally — it now routes through opencodex
46
+ codex "Write a hello world in Rust"
47
+ ```
48
+
49
+ <details>
50
+ <summary><b>没有 <a href="https://bun.sh">bun</a>?</b> —— 先安装它(opencodex 运行在 bun 上)</summary>
51
+
52
+ <br/>
53
+
54
+ ```bash
55
+ # macOS / Linux / WSL
56
+ curl -fsSL https://bun.sh/install | bash
57
+
58
+ # Windows (PowerShell)
59
+ powershell -c "irm bun.sh/install.ps1 | iex"
60
+ ```
61
+
62
+ 然后重新运行 `npm install -g @bitkyc08/opencodex`。(`ocx` 可执行文件是 bun 原生的,因此 bun 必须在你的 `PATH` 中。)
63
+
64
+ </details>
65
+
66
+ 使用 `provider/model` 形式指定一个具体的已路由模型:
67
+
68
+ ```bash
69
+ codex -m "anthropic/claude-opus-4-8" "Explain this stack trace"
70
+ codex -m "ollama-cloud/glm-5.2" "Write a SQL migration"
71
+ ```
72
+
73
+ ## 亮点
74
+
75
+ - **五种 adapter**,覆盖 Anthropic Messages、Google Gemini、Azure、OpenAI Responses 直通(passthrough),
76
+ 以及**所有 OpenAI 兼容的 Chat Completions** 端点。
77
+ - **OAuth、API key 或 ChatGPT 转发(forward)。** 用你的 xAI / Anthropic / Kimi 账户登录(token
78
+ 自动刷新)、转发你的 `codex login`,或直接粘贴一个 key(支持 `${ENV_VARS}`)。内置一份 18 家 provider 的
79
+ API-key 目录(含 **Ollama Cloud**)。
80
+ - **无缝接入 Codex。** 向 `~/.codex/config.toml` 注入一个 `[model_providers.opencodex]` 表,并
81
+ 将已路由的模型合并进 Codex 的目录和 subagent 选择器 —— 完全可逆。
82
+ - **Sidecars。** 通过基于你 ChatGPT 登录的 `gpt-5.4-mini`,为非 OpenAI 模型提供真正的**网页搜索**和**图像理解**能力。
83
+ - **Web 仪表盘**,用于管理 provider、OAuth 登录、模型选择和请求日志。
84
+
85
+ ## Providers 与 adapters
86
+
87
+ | Provider | Adapter | Auth |
88
+ |---|---|---|
89
+ | OpenAI(ChatGPT 登录) | `openai-responses` | 转发(无需 key) |
90
+ | OpenAI(API key) | `openai-responses` | key |
91
+ | Anthropic Claude | `anthropic` | oauth / key |
92
+ | xAI Grok | `openai-chat` | oauth / key |
93
+ | Kimi(Moonshot) | `openai-chat` | oauth / key |
94
+ | Google Gemini | `google` | key |
95
+ | Azure OpenAI | `azure` | key |
96
+ | Ollama Cloud + 17 家 provider 目录 | `openai-chat` | key |
97
+ | Ollama / vLLM / LM Studio(本地) | `openai-chat` | key(通常留空) |
98
+ | 任意 OpenAI 兼容端点 | `openai-chat` | key |
99
+
100
+ ## CLI
101
+
102
+ ```bash
103
+ ocx init # interactive setup
104
+ ocx start [--port 10100] # start the proxy
105
+ ocx stop # stop + restore native Codex
106
+ ocx restore # restore without stopping (alias: ocx eject)
107
+ ocx sync # refresh models + re-inject into Codex
108
+ ocx status # is the proxy running?
109
+ ocx login <xai|anthropic|kimi> # OAuth login
110
+ ocx logout <provider> # remove a stored login
111
+ ocx gui # open the web dashboard
112
+ ocx service <install|start|stop|status|uninstall> # run as a background service
113
+ ```
114
+
115
+ ## 配置
116
+
117
+ 配置文件位于 `~/.opencodex/config.json`。最小示例:
118
+
119
+ ```json
120
+ {
121
+ "port": 10100,
122
+ "defaultProvider": "anthropic",
123
+ "providers": {
124
+ "anthropic": {
125
+ "adapter": "anthropic",
126
+ "baseUrl": "https://api.anthropic.com",
127
+ "authMode": "oauth",
128
+ "defaultModel": "claude-sonnet-4-6"
129
+ },
130
+ "ollama-cloud": {
131
+ "adapter": "openai-chat",
132
+ "baseUrl": "https://ollama.com/v1",
133
+ "apiKey": "${OLLAMA_API_KEY}",
134
+ "defaultModel": "glm-5.2"
135
+ }
136
+ }
137
+ }
138
+ ```
139
+
140
+ 每个字段的说明请参阅 **[配置参考](https://lidge-jun.github.io/opencodex/zh-cn/reference/configuration/)**。
141
+
142
+ ## 文档
143
+
144
+ 完整的开发者文档 —— 架构、每个 adapter、请求生命周期、sidecars、
145
+ Codex 集成,以及 CLI/配置参考 —— 是位于 [`docs-site/`](./docs-site) 下的一个 Astro 站点,
146
+ 并发布于 **[lidge-jun.github.io/opencodex](https://lidge-jun.github.io/opencodex/zh-cn/)**。
147
+
148
+ ## 开发
149
+
150
+ ```bash
151
+ git clone https://github.com/lidge-jun/opencodex.git
152
+ cd opencodex
153
+ bun install
154
+ bun run dev # start the proxy in dev mode
155
+ bun x tsc --noEmit # typecheck
156
+ ```
157
+
158
+ 请参阅 **[贡献指南](https://lidge-jun.github.io/opencodex/zh-cn/contributing/)**。
159
+
160
+ ## 许可证
161
+
162
+ MIT
package/gui/README.md ADDED
@@ -0,0 +1,73 @@
1
+ # React + TypeScript + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Oxc](https://oxc.rs)
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/)
9
+
10
+ ## React Compiler
11
+
12
+ The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).
13
+
14
+ ## Expanding the ESLint configuration
15
+
16
+ If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
17
+
18
+ ```js
19
+ export default defineConfig([
20
+ globalIgnores(['dist']),
21
+ {
22
+ files: ['**/*.{ts,tsx}'],
23
+ extends: [
24
+ // Other configs...
25
+
26
+ // Remove tseslint.configs.recommended and replace with this
27
+ tseslint.configs.recommendedTypeChecked,
28
+ // Alternatively, use this for stricter rules
29
+ tseslint.configs.strictTypeChecked,
30
+ // Optionally, add this for stylistic rules
31
+ tseslint.configs.stylisticTypeChecked,
32
+
33
+ // Other configs...
34
+ ],
35
+ languageOptions: {
36
+ parserOptions: {
37
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
38
+ tsconfigRootDir: import.meta.dirname,
39
+ },
40
+ // other options...
41
+ },
42
+ },
43
+ ])
44
+ ```
45
+
46
+ You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
47
+
48
+ ```js
49
+ // eslint.config.js
50
+ import reactX from 'eslint-plugin-react-x'
51
+ import reactDom from 'eslint-plugin-react-dom'
52
+
53
+ export default defineConfig([
54
+ globalIgnores(['dist']),
55
+ {
56
+ files: ['**/*.{ts,tsx}'],
57
+ extends: [
58
+ // Other configs...
59
+ // Enable lint rules for React
60
+ reactX.configs['recommended-typescript'],
61
+ // Enable lint rules for React DOM
62
+ reactDom.configs.recommended,
63
+ ],
64
+ languageOptions: {
65
+ parserOptions: {
66
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
67
+ tsconfigRootDir: import.meta.dirname,
68
+ },
69
+ // other options...
70
+ },
71
+ },
72
+ ])
73
+ ```
@@ -0,0 +1 @@
1
+ :root{--bg:#0b0b0f;--surface:#14141a;--raised:#1c1c25;--raised-hover:#232330;--border:#2a2a35;--border-soft:#20202a;--text:#e9e9ee;--muted:#9a9aa6;--faint:#6a6a76;--accent:#7c5cff;--accent-hover:#9077ff;--accent-ink:#fff;--accent-soft:#7c5cff24;--accent-ring:#7c5cff73;--green:#34d399;--green-soft:#34d39921;--red:#f87171;--red-soft:#f8717121;--amber:#fbbf24;--amber-soft:#fbbf2421;--radius:12px;--radius-sm:8px;--radius-xs:6px;--font:-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, system-ui, "Helvetica Neue", sans-serif;--mono:ui-monospace, "SF Mono", "JetBrains Mono", "Cascadia Code", Menlo, Consolas, monospace;--shadow:0 1px 2px #00000080, 0 12px 32px #00000047;--shadow-sm:0 1px 2px #0006;--lightningcss-light: ;--lightningcss-dark:initial;color-scheme:dark}*{box-sizing:border-box}html,body,#root{height:100%}body{background:var(--bg);color:var(--text);font-family:var(--font);-webkit-font-smoothing:antialiased;text-rendering:optimizelegibility;background-image:radial-gradient(1200px 600px at 18% -10%,#7c5cff14,#0000 60%);margin:0;font-size:14px;line-height:1.5}a{color:var(--accent-hover);text-decoration:none}a:hover{text-decoration:underline}code,.mono{font-family:var(--mono);font-size:.92em}h1,h2,h3,h4{letter-spacing:-.01em;margin:0;font-weight:650}::selection{background:var(--accent-soft)}::-webkit-scrollbar{width:10px;height:10px}::-webkit-scrollbar-thumb{background:var(--border);border:2px solid var(--bg);border-radius:99px}::-webkit-scrollbar-thumb:hover{background:#353542}:focus-visible{outline:2px solid var(--accent-ring);outline-offset:2px;border-radius:4px}.app{grid-template-columns:232px 1fr;min-height:100dvh;display:grid}.sidebar{border-right:1px solid var(--border-soft);background:linear-gradient(#ffffff04,#0000);flex-direction:column;align-self:start;gap:4px;height:100dvh;padding:18px 14px;display:flex;position:sticky;top:0}.brand{align-items:center;gap:10px;padding:6px 8px 14px;display:flex}.brand img{width:26px;height:26px}.brand .name{letter-spacing:-.02em;font-size:15px;font-weight:700}.brand .ver{font-family:var(--mono);color:var(--muted);background:var(--raised);border:1px solid var(--border);border-radius:99px;padding:1px 6px;font-size:10px}.nav-item{border-radius:var(--radius-sm);text-align:left;cursor:pointer;width:100%;color:var(--muted);font:inherit;background:0 0;border:none;align-items:center;gap:10px;padding:8px 10px;font-size:13.5px;font-weight:500;transition:background .12s,color .12s;display:flex}.nav-item:hover{background:var(--raised);color:var(--text)}.nav-item.active{background:var(--accent-soft);color:var(--text)}.nav-item svg{width:17px;height:17px;color:var(--faint);flex-shrink:0}.nav-item.active svg{color:var(--accent)}.sidebar-foot{margin-top:auto;padding-top:12px}.sidebar-link{color:var(--muted);border-radius:var(--radius-sm);align-items:center;gap:9px;padding:8px 10px;font-size:13px;display:flex}.sidebar-link:hover{background:var(--raised);color:var(--text);text-decoration:none}.sidebar-link svg{width:16px;height:16px}.main{min-width:0}.main-inner{max-width:980px;margin:0 auto;padding:32px 36px 64px}.page-head{justify-content:space-between;align-items:center;gap:16px;margin-bottom:6px;display:flex}.page-head h2{font-size:19px}.page-sub{color:var(--muted);max-width:70ch;margin:4px 0 22px;font-size:13.5px}.page-sub b{color:var(--text);font-weight:600}.btn{border-radius:var(--radius-sm);font:inherit;cursor:pointer;white-space:nowrap;border:1px solid #0000;justify-content:center;align-items:center;gap:7px;padding:7px 14px;font-size:13px;font-weight:550;transition:background .12s,border-color .12s,opacity .12s;display:inline-flex}.btn svg{width:15px;height:15px}.btn:disabled{opacity:.55;cursor:default}.btn-primary{background:var(--accent);color:var(--accent-ink)}.btn-primary:hover:not(:disabled){background:var(--accent-hover)}.btn-ghost{background:var(--raised);color:var(--text);border-color:var(--border)}.btn-ghost:hover:not(:disabled){background:var(--raised-hover)}.btn-danger{color:var(--red);background:0 0;border-color:#f871714d}.btn-danger:hover:not(:disabled){background:var(--red-soft)}.btn-sm{border-radius:var(--radius-xs);padding:4px 9px;font-size:12px}.btn-icon{padding:5px}.card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius)}.panel{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:18px}.panel-accent{background:linear-gradient(180deg, var(--accent-soft), transparent 120%), var(--surface);border-color:#7c5cff47}.stat-row{grid-template-columns:repeat(4,1fr);gap:12px;margin-bottom:28px;display:grid}.stat{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);padding:15px 16px}.stat .label{color:var(--muted);align-items:center;gap:6px;margin-bottom:7px;font-size:12px;display:flex}.stat .label svg{width:14px;height:14px}.stat .value{letter-spacing:-.02em;font-size:23px;font-weight:700;line-height:1.1}.stat .value.mono{font-family:var(--mono);font-size:19px}.badge{font-size:11px;font-weight:600;font-family:var(--mono);letter-spacing:.01em;border-radius:99px;align-items:center;gap:5px;padding:2px 8px;display:inline-flex}.badge-accent{background:var(--accent-soft);color:var(--accent-hover)}.badge-green{background:var(--green-soft);color:var(--green)}.badge-amber{background:var(--amber-soft);color:var(--amber)}.badge-muted{background:var(--raised);color:var(--muted);border:1px solid var(--border)}.dot{border-radius:50%;flex-shrink:0;width:7px;height:7px}.dot-green{background:var(--green);box-shadow:0 0 0 3px var(--green-soft)}.dot-red{background:var(--red);box-shadow:0 0 0 3px var(--red-soft)}.tbl{border-collapse:collapse;width:100%;font-size:13px}.tbl thead th{text-align:left;color:var(--muted);text-transform:uppercase;letter-spacing:.04em;border-bottom:1px solid var(--border);padding:9px 12px;font-size:11.5px;font-weight:600}.tbl tbody td{border-bottom:1px solid var(--border-soft);padding:10px 12px}.tbl tbody tr:last-child td{border-bottom:none}.tbl tbody tr:hover td{background:#ffffff05}.tbl .num{text-align:right;font-family:var(--mono)}.tbl-wrap{border:1px solid var(--border);border-radius:var(--radius);overflow:hidden}.input,textarea.input{border-radius:var(--radius-sm);background:var(--raised);border:1px solid var(--border);width:100%;color:var(--text);font:inherit;padding:8px 11px;font-size:13px;transition:border-color .12s}.input::placeholder{color:var(--faint)}.input:focus{border-color:var(--accent);outline:none}textarea.input{resize:vertical;font-family:var(--mono);line-height:1.55}.field-label{color:var(--muted);margin-bottom:5px;font-size:12px;font-weight:500;display:block}select.input{appearance:none}.switch{cursor:pointer;background:var(--border);border:none;border-radius:99px;flex-shrink:0;width:34px;height:19px;padding:0;transition:background .15s;position:relative}.switch.on{background:var(--accent)}.switch:disabled{opacity:.6;cursor:default}.switch .knob{background:#fff;border-radius:50%;width:15px;height:15px;transition:left .15s;position:absolute;top:2px;left:2px}.switch.on .knob{left:17px}.muted{color:var(--muted)}.faint{color:var(--faint)}.row{align-items:center;gap:10px;display:flex}.spread{justify-content:space-between;align-items:center;gap:12px;display:flex}.stack{flex-direction:column;display:flex}.chip{font-family:var(--mono);background:var(--raised);border:1px solid var(--border);border-radius:var(--radius-xs);color:var(--text);padding:1px 7px;font-size:12px}.empty{text-align:center;border:1px dashed var(--border);border-radius:var(--radius);color:var(--muted);padding:56px 20px}.empty svg{width:30px;height:30px;color:var(--faint);margin-bottom:12px}.empty .title{color:var(--text);margin-bottom:6px;font-weight:600}.notice{border-radius:var(--radius-sm);align-items:center;gap:8px;margin-bottom:14px;padding:9px 12px;font-size:13px;display:flex}.notice svg{flex-shrink:0;width:15px;height:15px}.notice-ok{background:var(--green-soft);color:var(--green)}.notice-err{background:var(--red-soft);color:var(--red)}.h-section{color:var(--text);align-items:center;gap:8px;margin:30px 0 12px;font-size:13px;font-weight:600;display:flex}.h-section .count{color:var(--muted);font-weight:500;font-family:var(--mono);font-size:12px}.spin{border:2px solid var(--border);border-top-color:var(--accent);border-radius:50%;width:14px;height:14px;animation:.7s linear infinite spin;display:inline-block}@keyframes spin{to{transform:rotate(360deg)}}@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}.modal-overlay{-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px);z-index:50;background:#0009;justify-content:center;align-items:flex-start;padding:8vh 16px;display:flex;position:fixed;inset:0}.modal-card{background:var(--surface);border:1px solid var(--border);border-radius:var(--radius);width:100%;max-width:520px;box-shadow:var(--shadow);max-height:84vh;padding:20px;overflow-y:auto}.modal-head{justify-content:space-between;align-items:center;margin-bottom:16px;display:flex}.modal-head h3{font-size:16px}.list-row{text-align:left;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--raised);cursor:pointer;width:100%;color:var(--text);font:inherit;justify-content:space-between;align-items:center;gap:10px;padding:11px 13px;transition:background .12s,border-color .12s;display:flex}.list-row:hover{background:var(--raised-hover);border-color:#34343f}.list-row .title{font-size:14px;font-weight:600}.list-row .sub{color:var(--muted);margin-top:2px;font-size:12px}.prov-card{justify-content:space-between;align-items:flex-start;gap:12px;padding:15px 16px;display:flex}.link-btn{color:var(--accent-hover);font:inherit;cursor:pointer;background:0 0;border:none;padding:6px 2px;font-size:13px;text-decoration:underline}@media (width<=760px){.app{grid-template-columns:1fr}.sidebar{border-right:none;border-bottom:1px solid var(--border-soft);flex-flow:wrap;align-items:center;height:auto;position:static}.brand{width:100%;padding:6px 8px}.nav-item{width:auto}.sidebar-foot{margin:0;padding:0}.main-inner{padding:22px 18px 48px}.stat-row{grid-template-columns:repeat(2,1fr)}}