Skip to content

Commit cc70dbd

Browse files
committed
Add bilingual documentation and screenshot
1 parent 9773694 commit cc70dbd

6 files changed

Lines changed: 156 additions & 45 deletions

File tree

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@ Thumbs.db
99
*.jpeg
1010
*.webp
1111
*.gif
12+
!assets/
13+
!assets/screenshot.png
1214
outputs/
1315
work/

README.en.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Codex API Switchboard
2+
3+
Default language: [简体中文](README.md) | English
4+
5+
A privacy-first static utility for generating a complete Codex configuration TXT when switching custom API providers.
6+
7+
[Live demo](https://codex-config-txt.pages.dev)
8+
9+
![Codex API Switchboard interface screenshot](assets/screenshot.png)
10+
11+
## Purpose
12+
13+
Codex users may sign in with account credentials while routing model requests through a custom API provider. When switching API sites, replacing the entire configuration can accidentally remove plugin, conversation, feature, and profile settings.
14+
15+
Codex API Switchboard focuses on this narrow workflow:
16+
17+
- import, drag in, or paste a local `config.toml`
18+
- replace only `base_url` and `experimental_bearer_token` under `[model_providers.custom]`
19+
- automatically normalize `base_url` with a `/v1` suffix
20+
- export a complete TXT while preserving the rest of the Codex configuration
21+
- mask the token in the visible output while copy/download use the full generated content in the current session
22+
23+
## Important Scope
24+
25+
This tool is only for account credential login combined with custom API usage.
26+
27+
It is not a Codex account-login replacement, and it does not create, validate, or host API credentials.
28+
29+
## Privacy and Security Model
30+
31+
This is a static, browser-local utility.
32+
33+
- No upload.
34+
- No storage.
35+
- No cookies.
36+
- No network requests from the page.
37+
- No backend service.
38+
- Cloudflare Pages `_headers` uses `connect-src 'none'`.
39+
40+
File reading, text replacement, and TXT generation all happen inside the current browser tab.
41+
42+
## Technical Tags
43+
44+
`Codex` `Cloudflare Pages` `Static HTML` `Vanilla JavaScript` `TOML` `Content Security Policy` `Privacy-first` `API Routing` `Config Tooling`
45+
46+
## Tech Stack
47+
48+
- HTML, CSS, and vanilla JavaScript
49+
- Static deployment on Cloudflare Pages
50+
- Strict CSP through `_headers`
51+
- Local public artifact validation with Node.js
52+
- GitHub Actions validation workflow
53+
54+
## Local Validation
55+
56+
```bash
57+
npm run validate
58+
```
59+
60+
The validation script checks:
61+
62+
- inline JavaScript parses
63+
- the important scope warning remains visible
64+
- `_headers` keeps `connect-src 'none'`
65+
- no browser storage or network APIs are used
66+
- public files do not contain local machine paths, default API providers, or token-like secrets
67+
- removed legacy layout elements do not reappear
68+
69+
## Deployment
70+
71+
Deploy the repository root to Cloudflare Pages:
72+
73+
```bash
74+
wrangler pages deploy . --project-name codex-config-txt
75+
```
76+
77+
## License
78+
79+
MIT

README.md

Lines changed: 45 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,75 +1,79 @@
11
# Codex API Switchboard
22

3-
Privacy-first static tool for rebuilding a complete Codex configuration TXT when switching custom API providers.
3+
默认语言:简体中文 | [English](README.en.md)
44

5-
[Live demo](https://codex-config-txt.pages.dev)
5+
隐私优先的静态工具,用于在切换 Codex 自定义 API 站点时,生成完整的配置 TXT。
66

7-
## Purpose
7+
[在线演示](https://codex-config-txt.pages.dev)
88

9-
Codex users who sign in with account credentials may still route model requests through a custom API provider. When switching API sites, replacing the whole configuration can accidentally drop plugin, conversation, feature, and profile settings.
9+
![Codex API Switchboard 界面截图](assets/screenshot.png)
1010

11-
Codex API Switchboard solves that narrow workflow:
11+
## 项目定位
1212

13-
- import or paste a local `config.toml`
14-
- replace only `base_url` and `experimental_bearer_token`
15-
- automatically normalize `base_url` with a `/v1` suffix
16-
- export a complete TXT while preserving the rest of the configuration
17-
- mask the token in the visible output while copy/download still use the full generated content
13+
Codex 用户通过账号凭证登录后,仍可能把模型请求路由到自定义 API Provider。切换不同 API 站点时,如果直接替换整份配置,容易丢失插件、对话、功能开关、profiles 等已有设置。
1814

19-
## Important Scope
15+
Codex API Switchboard 专注解决这个窄场景:
2016

21-
This tool is only for account credential login combined with custom API usage.
17+
- 导入、拖入或粘贴本地 `config.toml`
18+
- 只替换 `[model_providers.custom]` 下的 `base_url``experimental_bearer_token`
19+
- `base_url` 自动补齐 `/v1`
20+
- 输出完整 TXT,并保留其余 Codex 配置
21+
- 页面可见输出默认遮罩 token,复制和下载仍使用当前会话生成的完整内容
2222

23-
It is not a general Codex account-login replacement, and it does not create or validate API credentials.
23+
## 重要适用范围
2424

25-
## Privacy Model
25+
仅适用于账号凭证登录 + 使用自定义 API 的情况。
2626

27-
The page is a static browser-only utility.
27+
本工具不是 Codex 账号登录替代方案,也不会创建、校验或托管 API 凭证。
2828

29-
- No upload.
30-
- No storage.
31-
- No cookies.
32-
- No network requests from the page.
33-
- No backend service.
34-
- Cloudflare Pages CSP uses `connect-src 'none'`.
29+
## 隐私与安全模型
3530

36-
All file reading and text replacement happens inside the current browser tab.
31+
这是一个纯静态、浏览器本地运行的工具。
3732

38-
## Technical Tags
33+
- 不上传文件
34+
- 不存储数据
35+
- 不使用 Cookie
36+
- 页面不发起网络请求
37+
- 没有后端服务
38+
- Cloudflare Pages `_headers` 使用 `connect-src 'none'`
3939

40-
`Codex` `Cloudflare Pages` `Static HTML` `Vanilla JavaScript` `TOML` `Content Security Policy` `Privacy-first` `API routing` `Config tooling`
40+
文件读取、文本替换和 TXT 生成都发生在当前浏览器标签页内。
4141

42-
## Tech Stack
42+
## 技术标签
4343

44-
- HTML, CSS, and vanilla JavaScript
45-
- Static deployment on Cloudflare Pages
46-
- Strict CSP via `_headers`
47-
- Local validation script with Node.js
48-
- GitHub Actions validation workflow
44+
`Codex` `Cloudflare Pages` `Static HTML` `Vanilla JavaScript` `TOML` `Content Security Policy` `Privacy-first` `API Routing` `Config Tooling`
4945

50-
## Local Validation
46+
## 技术栈
47+
48+
- HTML、CSS、Vanilla JavaScript
49+
- Cloudflare Pages 静态部署
50+
- `_headers` 配置严格 CSP
51+
- Node.js 本地公开产物校验
52+
- GitHub Actions 自动验证
53+
54+
## 本地验证
5155

5256
```bash
5357
npm run validate
5458
```
5559

56-
The validation script checks:
60+
校验脚本会检查:
5761

58-
- inline JavaScript parses
59-
- required scope warning remains visible
60-
- `connect-src 'none'` remains in `_headers`
61-
- no browser storage or network APIs are used
62-
- no local machine paths, default provider URLs, or token-like secrets are present in the public page
63-
- removed layout elements do not reappear
62+
- 内联 JavaScript 可解析
63+
- 重要适用范围提示仍存在
64+
- `_headers` 保留 `connect-src 'none'`
65+
- 未使用浏览器存储或联网 API
66+
- 公开页面不包含本机路径、默认 API 站点或 token-like secret
67+
- 已删除的旧布局元素不会重新出现
6468

65-
## Deployment
69+
## 部署
6670

67-
Deploy the repository root to Cloudflare Pages:
71+
将仓库根目录部署到 Cloudflare Pages
6872

6973
```bash
7074
wrangler pages deploy . --project-name codex-config-txt
7175
```
7276

73-
## License
77+
## 许可证
7478

7579
MIT

assets/screenshot.png

117 KB
Loading

index.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1684,7 +1684,7 @@ <h2 id="outputTitle">完整 TXT 输出</h2>
16841684
}
16851685

16861686
const testBaseUrl = "https://selftest.local";
1687-
const testToken = "selftest-token-123";
1687+
const testToken = "dummy-credential-value";
16881688
if (!state.source.trim()) {
16891689
state.source = [
16901690
'model_provider = "custom"',
@@ -1706,8 +1706,8 @@ <h2 id="outputTitle">完整 TXT 输出</h2>
17061706
const visibleOutput = elements.output.value;
17071707
const checks = [
17081708
/^base_url\s*=\s*"https:\/\/selftest\.local\/v1"$/m.test(output),
1709-
/^experimental_bearer_token\s*=\s*"selftest-token-123"$/m.test(output),
1710-
!visibleOutput.includes("selftest-token-123"),
1709+
/^experimental_bearer_token\s*=\s*"dummy-credential-value"$/m.test(output),
1710+
!visibleOutput.includes("dummy-credential-value"),
17111711
!/^experimental_bearer_token\s*=\s*""$/m.test(output),
17121712
elements.copyButton.disabled === false,
17131713
elements.downloadButton.disabled === false,
@@ -1736,4 +1736,4 @@ <h2 id="outputTitle">完整 TXT 输出</h2>
17361736
runSelfTest();
17371737
</script>
17381738
</body>
1739-
</html>
1739+
</html>

scripts/validate-public.js

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ const path = require("path");
44
const root = path.resolve(__dirname, "..");
55
const indexPath = path.join(root, "index.html");
66
const headersPath = path.join(root, "_headers");
7+
const readmePath = path.join(root, "README.md");
8+
const readmeEnPath = path.join(root, "README.en.md");
9+
const screenshotPath = path.join(root, "assets", "screenshot.png");
710

811
function read(filePath) {
912
return fs.readFileSync(filePath, "utf8");
@@ -17,6 +20,8 @@ function assert(condition, message) {
1720

1821
const index = read(indexPath);
1922
const headers = read(headersPath);
23+
const readme = read(readmePath);
24+
const readmeEn = read(readmeEnPath);
2025
const publicText = `${index}\n${headers}`;
2126

2227
const scriptMatch = index.match(/<script>([\s\S]*?)<\/script>/);
@@ -40,6 +45,8 @@ const forbiddenStrings = [
4045
"routePreview",
4146
"tokenSummary",
4247
"替换摘要",
48+
"selftest-token",
49+
"repair-token",
4350
];
4451

4552
const forbiddenHits = forbiddenStrings.filter((needle) => publicText.includes(needle));
@@ -51,5 +58,24 @@ assert(headers.includes("connect-src 'none'"), "CSP must keep connect-src 'none'
5158
assert(index.includes("重要提示:仅适用于账号凭证登录 + 使用 API 的情况"), "scope warning is missing");
5259
assert(index.includes("保留不变"), "preserved configuration panel is missing");
5360
assert(index.includes("impact-panel"), "impact panel alignment class is missing");
61+
assert(fs.existsSync(screenshotPath), "repository screenshot is missing");
62+
assert(readme.includes("默认语言:简体中文"), "Chinese README must be the default landing document");
63+
assert(readme.includes("[English](README.en.md)"), "Chinese README must link to the English version");
64+
assert(readmeEn.includes("[简体中文](README.md)"), "English README must link back to the Chinese version");
65+
assert(readme.includes("![Codex API Switchboard 界面截图](assets/screenshot.png)"), "Chinese README screenshot is missing");
66+
assert(readmeEn.includes("![Codex API Switchboard interface screenshot](assets/screenshot.png)"), "English README screenshot is missing");
67+
68+
const requiredTags = [
69+
"Codex",
70+
"Cloudflare Pages",
71+
"Vanilla JavaScript",
72+
"TOML",
73+
"Content Security Policy",
74+
"Privacy-first",
75+
"API Routing",
76+
"Config Tooling",
77+
];
78+
const missingTags = requiredTags.filter((tag) => !readme.includes(tag) || !readmeEn.includes(tag));
79+
assert(missingTags.length === 0, `README technical tags missing: ${missingTags.join(", ")}`);
5480

5581
console.log("PUBLIC_VALIDATE:OK");

0 commit comments

Comments
 (0)