@tokenaut/opentoken 1.3.6 → 1.4.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.
package/README.md CHANGED
@@ -1,116 +1,132 @@
1
- # OpenToken
1
+ # @opentoken/opentoken
2
2
 
3
- OpenToken 一键配置 CLI,支持 Claude Code 和 Codex。
3
+ 快速接入 [https://gw.opentoken.io](https://gw.opentoken.io) 的强大模型。
4
4
 
5
5
  ## 安装
6
6
 
7
7
  ```bash
8
- npm install -g @tokenaut/opentoken
8
+ npx @opentoken/opentoken
9
+ npm install -g @opentoken/opentoken
9
10
  ```
10
11
 
11
- ## 用法
12
+ ## 命令
12
13
 
13
- ```bash
14
- opentoken <tool> [--key <api_key>] [--model <model>] [--url <base_url>]
15
- ```
14
+ | 命令 | 说明 |
15
+ |------|------|
16
+ | `opentoken` | 交互主菜单 |
17
+ | `opentoken --help` / `-h` | 帮助 |
16
18
 
17
- 各参数均可独立使用,只修改指定的配置项,未指定的保持不变。
19
+ ---
18
20
 
19
- ## 工具
21
+ ## 已支持的应用与配置文件
20
22
 
21
- | 命令 | 说明 | 配置文件 |
22
- |------|------|---------|
23
- | `opentoken cc` | Claude Code | `~/.claude/settings.json` |
24
- | `opentoken codex` / `cx` | Codex | `~/.codex/config.toml` + `~/.codex/auth.json` |
23
+ CLI 会为不同工具写入对应配置文件(路径均在用户目录下)。
25
24
 
26
- ## 模型别名
25
+ | 应用 | 子命令(别名) | 配置文件 |
26
+ |------|----------------|----------|
27
+ | **Claude Code** | `cc`、`claude` | `~/.claude/settings.json`(环境变量:`ANTHROPIC_AUTH_TOKEN`、`ANTHROPIC_BASE_URL`、`ANTHROPIC_MODEL`) |
28
+ | **Atomcode** | `atomcode`、`ac` | `~/.atomcode/config.toml` |
29
+ | **OpenClaw** | `openclaw`、`oc` | `~/.openclaw/openclaw.json`(合并写入 Opentoken:`models.providers.opentoken`、`agents.defaults.model.primary` 等) |
30
+ | **Hermes** | `hermes`、`hm` | `~/.hermes/config.yaml`(`model.provider`、`model.base_url`、`model.default`)与 `~/.hermes/.env`(`OPENTOKEN_API_KEY`) |
31
+ | **OpenCode** | `opencode`、`od` | `~/.config/opencode/opencode.json`(合并写入 Opentoken:`provider.opentoken`) |
32
+ | **Codex** | `codex`、`cx` | `~/.codex/config.toml`(`model_provider`、`model_providers.opentoken`、`wire_api = "responses"`)与 `~/.codex/auth.json`(`OPENAI_API_KEY`) |
27
33
 
28
- ### Claude Code
34
+ OpenClaw 会为 **`opentoken`** 提供方写入 **`baseUrl`**(`https://gw.opentoken.io/v1`)、**`api`**(`openai-completions`)、**`apiKey`** 与 **`models`**,并把 **`agents.defaults.model.primary`** 设为 `opentoken/<模型 ID>`;其它顶级字段与其它 provider **保留不删**(例如已有 `channels`、`gateway`)。Windows 下路径为 `%USERPROFILE%\.openclaw\openclaw.json`。
29
35
 
30
- | 别名 | 模型 ID |
31
- |------|---------|
32
- | `opus` | `claude-opus-4-8`(默认) |
33
- | `sonnet` | `claude-sonnet-4-6` |
34
- | `haiku` | `claude-haiku-4-5` |
36
+ Hermes 使用 Opentoken 时需 **`provider: custom`**,且 **`base_url` 须带 `/v1` 后缀**(本工具写入为 `https://gw.opentoken.io/v1`);密钥写入 `.env` 中的 `OPENTOKEN_API_KEY`。
35
37
 
36
- ### Codex
38
+ OpenCode 会为 **`opentoken`** 提供方写入 **`npm`**(`@ai-sdk/anthropic`)、**`baseURL`**(`https://gw.opentoken.io/v1`,必须带 `/v1`)、**`apiKey`** 与 **`models`**(自动拉取可用模型列表并生成配置);其它 provider **保留不删**。配置文件支持 `$schema` 字段用于 IDE 提示。参考 [OpenCode 文档](https://help.aliyun.com/zh/model-studio/opencode-coding-plan)。
39
+
40
+ Codex 会为 **`opentoken`** 提供方写入 **`base_url`**(默认 `https://gw.opentoken.io/v1`)与 **`wire_api = "responses"`**(不写 `env_key`),并只从模型列表中选择 `supported_endpoint_types` 包含 `responses` 的模型。API Key 写入 **`~/.codex/auth.json`** 的 **`OPENAI_API_KEY`**,Codex 命令行与 IDE 插件共用,无需再 export 环境变量。
41
+
42
+ ---
37
43
 
38
- | 别名 | 模型 ID |
39
- |------|---------|
40
- | `5.4` / `gpt5.4` / `gpt-5.4` | `gpt-5.4`(默认) |
41
- | `5.5` / `gpt5.5` / `gpt-5.5` | `gpt-5.5` |
44
+ ## 快捷一键配置(非交互)
42
45
 
43
- ## 示例
46
+ 以下为各应用在命令行直接写入配置的用法。选项可单独或组合使用:**`--key` / `-k`**,**`--url` / `-u`**(仅 Claude Code),**`--model` / `-m`**。
44
47
 
45
48
  ### Claude Code
46
49
 
47
50
  ```bash
48
- # 一键初始化
49
- opentoken cc --key sk-xxxxx
51
+ opentoken cc --key <api_key>
52
+ opentoken cc --url <base_url>
53
+ opentoken cc --model <model_id>
54
+ opentoken cc -k <api_key> -u <base_url> -m <model_id>
55
+ ```
50
56
 
51
- # 只改模型
52
- opentoken cc --model sonnet
57
+ 示例:
53
58
 
54
- # 完整指定
55
- opentoken cc --key sk-xxxxx --model opus --url https://gw.opentoken.io
59
+ ```bash
60
+ opentoken cc -k sk-xxx
61
+ opentoken cc -k sk-xxx -u https://gw.opentoken.io -m claude-opus-4-5
56
62
  ```
57
63
 
58
- ### Codex
64
+ ### Atomcode
65
+
66
+ Base URL 固定为 Opentoken 的 OpenAI 兼容地址,仅需 Key 与模型:
59
67
 
60
68
  ```bash
61
- # 一键初始化
62
- opentoken cx --key sk-xxxxx --url https://gw.opentoken.io/v1
69
+ opentoken atomcode --key <api_key>
70
+ opentoken ac --model <model_id>
71
+ opentoken ac -k <api_key> -m <model_id>
72
+ ```
73
+
74
+ ### OpenClaw
63
75
 
64
- # 只改模型
65
- opentoken cx --model 5.5
76
+ 写入(或合并)`~/.openclaw/openclaw.json` 中的 Opentoken 配置:
66
77
 
67
- # 完整指定
68
- opentoken cx --key sk-xxxxx --model gpt-5.5 --url https://gw.opentoken.io/v1
78
+ ```bash
79
+ opentoken openclaw --key <api_key>
80
+ opentoken oc --model <model_id>
81
+ opentoken oc -k <api_key> -m <model_id>
69
82
  ```
70
83
 
71
- ## 一键配置命令
84
+ ### Hermes
72
85
 
73
- ### OpenToken 网关
86
+ 写入 `model.default`、`OPENTOKEN_API_KEY`,并强制 `provider: custom` 与 Opentoken `base_url`:
74
87
 
75
88
  ```bash
76
- # Claude Code(注意 cc 的 url 没有 /v1)
77
- opentoken cc --key <your-api-key> --model opus --url https://gw.opentoken.io
78
-
79
- # Codex
80
- opentoken cx --key <your-api-key> --model 5.5 --url https://gw.opentoken.io/v1
89
+ opentoken hermes --key <api_key>
90
+ opentoken hm --model <model_id>
91
+ opentoken hm -k <api_key> -m <model_id>
81
92
  ```
82
93
 
83
- ### Omni 网关
94
+ ### OpenCode
84
95
 
85
- ```bash
86
- # Claude Code
87
- opentoken cc --key <your-api-key> --model opus --url https://omniroute.goio.uk/v1
96
+ 写入(或合并)`~/.config/opencode/opencode.json` 中的 Opentoken 配置:
88
97
 
89
- # Codex
90
- opentoken cx --key <your-api-key> --model 5.5 --url https://omniroute.goio.uk/v1
98
+ ```bash
99
+ opentoken opencode --key <api_key>
100
+ opentoken od --model <model_id>
101
+ opentoken od -k <api_key> -m <model_id>
91
102
  ```
92
103
 
93
- ## 写入字段
104
+ 提供 API Key 后会自动拉取完整模型列表并写入配置。配置格式兼容 Anthropic API,使用 `@ai-sdk/anthropic` SDK。
105
+
106
+ ### Codex
94
107
 
95
- ### Claude Code(`~/.claude/settings.json`)
108
+ 写入(或合并)`~/.codex/config.toml` 中的 Opentoken Responses API 配置:
96
109
 
97
- - `ANTHROPIC_AUTH_TOKEN`
98
- - `ANTHROPIC_BASE_URL`
99
- - `ANTHROPIC_MODEL`(主模型)
100
- - `ANTHROPIC_DEFAULT_SONNET_MODEL`(Sonnet 辅助模型)
101
- - `ANTHROPIC_DEFAULT_HAIKU_MODEL`(Haiku 辅助模型)
102
- - `API_TIMEOUT_MS`
103
- - `CLAUDE_CODE_DISABLE_EXPERIMENTAL_BETAS`
104
- - `ENABLE_TOOL_SEARCH`
110
+ ```bash
111
+ opentoken codex --key <api_key>
112
+ opentoken cx --url https://gw.opentoken.io/v1
113
+ opentoken cx --model <model_id>
114
+ opentoken cx -k <api_key> -u https://gw.opentoken.io/v1 -m <model_id>
115
+ ```
116
+
117
+ 提供 API Key 后会自动拉取 `supported_endpoint_types` 含 `responses` 的模型,并写入 Codex profiles 与 `tui.model_availability_nux`,同时将 Key 写入 `~/.codex/auth.json`:
118
+
119
+ ```json
120
+ {
121
+ "auth_mode": "apikey",
122
+ "OPENAI_API_KEY": "<api_key>"
123
+ }
124
+ ```
105
125
 
106
- 默认 Base URL:`https://gw.opentoken.io/`
126
+ `config.toml` 中仍有旧版 **`env_key`** 行,请删除以免与 `auth.json` 冲突。
107
127
 
108
- ### Codex(`~/.codex/config.toml` + `~/.codex/auth.json`)
128
+ ---
109
129
 
110
- - `model` / `model_provider`
111
- - `model_providers.opentoken`(name、base_url、wire_api)
112
- - `profiles.<model>`
113
- - `tui.model_availability_nux`
114
- - `OPENAI_API_KEY`(写入 auth.json)
130
+ ## 环境
115
131
 
116
- 默认 Base URL:`https://gw.opentoken.io/v1`
132
+ Node.js >= 14 · MIT
package/bin/opentoken.js CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
+
2
3
  'use strict';
3
4
 
4
- const run = require('../src/cli');
5
+ const { run } = require('../src/cli');
5
6
 
6
- run().catch((error) => {
7
- console.error(error.message || error);
7
+ run().catch((err) => {
8
+ console.error(err);
8
9
  process.exit(1);
9
- });
10
+ });
package/package.json CHANGED
@@ -1,32 +1,44 @@
1
1
  {
2
2
  "name": "@tokenaut/opentoken",
3
- "version": "1.3.6",
4
- "description": "OpenToken Claude Code 一键配置 CLI",
3
+ "version": "1.4.0",
4
+ "description": "OpenToken 一键接入 AI 模型 · https://gw.opentoken.io",
5
5
  "main": "src/cli.js",
6
6
  "bin": {
7
7
  "opentoken": "bin/opentoken.js"
8
8
  },
9
- "files": [
10
- "bin",
11
- "src"
12
- ],
13
9
  "scripts": {
14
10
  "start": "node bin/opentoken.js",
15
11
  "dev": "node bin/opentoken.js"
16
12
  },
17
13
  "keywords": [
18
14
  "opentoken",
15
+ "openrouter",
19
16
  "claude",
20
17
  "claude-code",
18
+ "api token",
19
+ "token配置",
20
+ "openrouter token",
21
+ "api配置",
22
+ "anthropic",
23
+ "codex",
21
24
  "cli",
22
- "config"
25
+ "ai工具",
26
+ "openai",
27
+ "模型切换"
23
28
  ],
24
29
  "author": "opentoken",
25
30
  "license": "MIT",
31
+ "dependencies": {
32
+ "@iarna/toml": "^2.2.5",
33
+ "js-yaml": "^4.1.0",
34
+ "chalk": "^4.1.2",
35
+ "inquirer": "^8.2.6",
36
+ "string-width": "^4.2.3"
37
+ },
26
38
  "engines": {
27
39
  "node": ">=14.0.0"
28
40
  },
29
- "dependencies": {
30
- "@iarna/toml": "^2.2.5"
41
+ "publishConfig": {
42
+ "access": "public"
31
43
  }
32
- }
44
+ }
@@ -0,0 +1,94 @@
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const os = require('os');
6
+ const TOML = require('@iarna/toml');
7
+ const {
8
+ ATOMCODE_OPENTOKEN_BASE_URL,
9
+ ATOMCODE_CONTEXT_WINDOW,
10
+ } = require('./models');
11
+
12
+ const CONFIG_DIR = path.join(os.homedir(), '.atomcode');
13
+ const CONFIG_PATH = path.join(CONFIG_DIR, 'config.toml');
14
+
15
+ const PROVIDER_KEY = 'Opentoken';
16
+
17
+ function readRaw() {
18
+ if (!fs.existsSync(CONFIG_PATH)) return '';
19
+ return fs.readFileSync(CONFIG_PATH, 'utf-8');
20
+ }
21
+
22
+ function getCurrentAtomcodeConfig() {
23
+ const raw = readRaw();
24
+ if (!raw || !String(raw).trim()) {
25
+ return { apiKey: '', model: '' };
26
+ }
27
+ const data = TOML.parse(raw);
28
+ const p =
29
+ data &&
30
+ typeof data === 'object' &&
31
+ data.providers &&
32
+ typeof data.providers === 'object' &&
33
+ !Array.isArray(data.providers)
34
+ ? data.providers[PROVIDER_KEY]
35
+ : null;
36
+ return {
37
+ apiKey: p && p.api_key != null ? String(p.api_key) : '',
38
+ model: p && p.model != null ? String(p.model) : '',
39
+ };
40
+ }
41
+
42
+ function applyAtomcodeConfig(patch) {
43
+ const { apiKey, model } = patch || {};
44
+ let data = {};
45
+ const raw = readRaw();
46
+ if (raw && String(raw).trim()) {
47
+ try {
48
+ data = TOML.parse(raw);
49
+ } catch (e) {
50
+ throw new Error(
51
+ '现有 config.toml 无法解析,请先备份后手动修复:' + e.message,
52
+ );
53
+ }
54
+ }
55
+ if (data === null || typeof data !== 'object' || Array.isArray(data)) {
56
+ throw new Error('config.toml 根节点必须是表(TOML table)');
57
+ }
58
+ if (
59
+ !data.providers ||
60
+ typeof data.providers !== 'object' ||
61
+ Array.isArray(data.providers)
62
+ ) {
63
+ data.providers = {};
64
+ }
65
+ const prev =
66
+ data.providers[PROVIDER_KEY] &&
67
+ typeof data.providers[PROVIDER_KEY] === 'object' &&
68
+ !Array.isArray(data.providers[PROVIDER_KEY])
69
+ ? { ...data.providers[PROVIDER_KEY] }
70
+ : {};
71
+ const merged = {
72
+ ...prev,
73
+ type: 'openai',
74
+ base_url: ATOMCODE_OPENTOKEN_BASE_URL,
75
+ context_window: ATOMCODE_CONTEXT_WINDOW,
76
+ };
77
+ if (apiKey !== undefined) merged.api_key = apiKey;
78
+ if (model !== undefined) merged.model = model;
79
+
80
+ data.providers[PROVIDER_KEY] = merged;
81
+ data.default_provider = PROVIDER_KEY;
82
+
83
+ if (!fs.existsSync(CONFIG_DIR)) {
84
+ fs.mkdirSync(CONFIG_DIR, { recursive: true });
85
+ }
86
+ fs.writeFileSync(CONFIG_PATH, TOML.stringify(data), 'utf-8');
87
+ }
88
+
89
+ module.exports = {
90
+ CONFIG_PATH,
91
+ PROVIDER_KEY,
92
+ getCurrentAtomcodeConfig,
93
+ applyAtomcodeConfig,
94
+ };