openclaw-apikey-cli 1.0.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 +73 -0
- package/index.js +175 -0
- package/package.json +15 -0
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# OpenClaw API Key CLI
|
|
2
|
+
|
|
3
|
+
一个简单的 npx CLI 工具,用于快速更新 OpenClaw 的 CSDN Custom Provider API Key。
|
|
4
|
+
|
|
5
|
+
## 使用方法
|
|
6
|
+
|
|
7
|
+
### 通过 npx 直接运行(推荐)
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx openclaw-set-key sk-your-api-key-here
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### 全局安装后使用
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install -g openclaw-apikey-cli
|
|
17
|
+
openclaw-set-key sk-your-api-key-here
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## 配置说明
|
|
21
|
+
|
|
22
|
+
该工具会自动配置以下固定参数:
|
|
23
|
+
|
|
24
|
+
- **Provider ID**: `custom-models-csdn-net`
|
|
25
|
+
- **Base URL**: `https://test-models.csdn.net/api/v1`
|
|
26
|
+
- **Model ID**: `glm-4.7`
|
|
27
|
+
- **Endpoint**: OpenAI-compatible (自动添加 `/chat/completions` 路径)
|
|
28
|
+
- **Authorization**: API Key 通过命令行传入
|
|
29
|
+
|
|
30
|
+
实际请求 URL: `https://test-models.csdn.net/api/v1/chat/completions`
|
|
31
|
+
|
|
32
|
+
你只需要提供 API Key 作为参数即可。
|
|
33
|
+
|
|
34
|
+
## 工作原理
|
|
35
|
+
|
|
36
|
+
该工具会修改以下两个配置文件:
|
|
37
|
+
|
|
38
|
+
1. `~/.openclaw/openclaw.json` - 主配置文件
|
|
39
|
+
2. `~/.openclaw/agents/main/agent/models.json` - 模型配置文件
|
|
40
|
+
|
|
41
|
+
修改前会自动创建备份文件,以防需要恢复。
|
|
42
|
+
|
|
43
|
+
## 示例
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
$ npx openclaw-set-key sk-ofudiveyqumxobnaaioracekvxipvjshiakdjkwxqgixm
|
|
47
|
+
|
|
48
|
+
✓ OpenClaw API key updated successfully!
|
|
49
|
+
|
|
50
|
+
Configuration:
|
|
51
|
+
Provider: custom-models-csdn-net
|
|
52
|
+
Base URL: https://test-models.csdn.net/api/v1
|
|
53
|
+
Model: glm-4.7
|
|
54
|
+
API Key: sk-exnww...rjszm
|
|
55
|
+
|
|
56
|
+
Backup files created:
|
|
57
|
+
/root/.openclaw/openclaw.json.backup-1741523456789
|
|
58
|
+
/root/.openclaw/agents/main/agent/models.json.backup-1741523456789
|
|
59
|
+
|
|
60
|
+
Please restart OpenClaw to apply the changes.
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 发布到 npm
|
|
64
|
+
|
|
65
|
+
如果你想发布这个包到 npm:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
cd /root/openclaw-apikey-cli
|
|
69
|
+
npm login
|
|
70
|
+
npm publish
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
发布后,任何人都可以通过 `npx openclaw-apikey-cli` 使用。
|
package/index.js
ADDED
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const os = require('os');
|
|
6
|
+
|
|
7
|
+
// 固定配置
|
|
8
|
+
const CONFIG = {
|
|
9
|
+
providerId: 'custom-models-csdn-net',
|
|
10
|
+
baseUrl: 'https://test-models.csdn.net/api/v1',
|
|
11
|
+
modelId: 'glm-4.7',
|
|
12
|
+
api: 'openai-completions',
|
|
13
|
+
modelName: 'GLM-4.7 (CSDN Test)'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
// 获取 OpenClaw 配置路径
|
|
17
|
+
function getOpenClawPaths() {
|
|
18
|
+
const homeDir = os.homedir();
|
|
19
|
+
return {
|
|
20
|
+
mainConfig: path.join(homeDir, '.openclaw', 'openclaw.json'),
|
|
21
|
+
modelsConfig: path.join(homeDir, '.openclaw', 'agents', 'main', 'agent', 'models.json')
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// 更新 openclaw.json 中的 API Key
|
|
26
|
+
function updateMainConfig(configPath, apiKey) {
|
|
27
|
+
const content = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
28
|
+
|
|
29
|
+
if (!content.models?.providers?.[CONFIG.providerId]) {
|
|
30
|
+
content.models = content.models || {};
|
|
31
|
+
content.models.mode = 'merge';
|
|
32
|
+
content.models.providers = content.models.providers || {};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
content.models.providers[CONFIG.providerId] = {
|
|
36
|
+
baseUrl: CONFIG.baseUrl,
|
|
37
|
+
apiKey: apiKey,
|
|
38
|
+
api: CONFIG.api,
|
|
39
|
+
models: [
|
|
40
|
+
{
|
|
41
|
+
id: CONFIG.modelId,
|
|
42
|
+
name: CONFIG.modelName,
|
|
43
|
+
reasoning: false,
|
|
44
|
+
input: ['text'],
|
|
45
|
+
cost: {
|
|
46
|
+
input: 0,
|
|
47
|
+
output: 0,
|
|
48
|
+
cacheRead: 0,
|
|
49
|
+
cacheWrite: 0
|
|
50
|
+
},
|
|
51
|
+
contextWindow: 4096,
|
|
52
|
+
maxTokens: 4096
|
|
53
|
+
}
|
|
54
|
+
]
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// 更新默认模型
|
|
58
|
+
if (!content.agents) {
|
|
59
|
+
content.agents = {};
|
|
60
|
+
}
|
|
61
|
+
if (!content.agents.defaults) {
|
|
62
|
+
content.agents.defaults = {};
|
|
63
|
+
}
|
|
64
|
+
content.agents.defaults.model = {
|
|
65
|
+
primary: `${CONFIG.providerId}/${CONFIG.modelId}`
|
|
66
|
+
};
|
|
67
|
+
if (!content.agents.defaults.models) {
|
|
68
|
+
content.agents.defaults.models = {};
|
|
69
|
+
}
|
|
70
|
+
content.agents.defaults.models[`${CONFIG.providerId}/${CONFIG.modelId}`] = {};
|
|
71
|
+
|
|
72
|
+
fs.writeFileSync(configPath, JSON.stringify(content, null, 2), 'utf8');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// 更新 models.json 中的 API Key
|
|
76
|
+
function updateModelsConfig(configPath, apiKey) {
|
|
77
|
+
let content = {};
|
|
78
|
+
|
|
79
|
+
if (fs.existsSync(configPath)) {
|
|
80
|
+
content = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
if (!content.providers) {
|
|
84
|
+
content.providers = {};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
content.providers[CONFIG.providerId] = {
|
|
88
|
+
baseUrl: CONFIG.baseUrl,
|
|
89
|
+
apiKey: apiKey,
|
|
90
|
+
api: CONFIG.api,
|
|
91
|
+
models: [
|
|
92
|
+
{
|
|
93
|
+
id: CONFIG.modelId,
|
|
94
|
+
name: CONFIG.modelName,
|
|
95
|
+
reasoning: false,
|
|
96
|
+
input: ['text'],
|
|
97
|
+
cost: {
|
|
98
|
+
input: 0,
|
|
99
|
+
output: 0,
|
|
100
|
+
cacheRead: 0,
|
|
101
|
+
cacheWrite: 0
|
|
102
|
+
},
|
|
103
|
+
contextWindow: 4096,
|
|
104
|
+
maxTokens: 4096,
|
|
105
|
+
api: CONFIG.api
|
|
106
|
+
}
|
|
107
|
+
]
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
fs.writeFileSync(configPath, JSON.stringify(content, null, 2), 'utf8');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 主函数
|
|
114
|
+
function main() {
|
|
115
|
+
const args = process.argv.slice(2);
|
|
116
|
+
|
|
117
|
+
if (args.length === 0) {
|
|
118
|
+
console.log('Usage: openclaw-set-key <api-key>');
|
|
119
|
+
console.log('');
|
|
120
|
+
console.log('Example:');
|
|
121
|
+
console.log(' openclaw-set-key sk-your-api-key-here');
|
|
122
|
+
process.exit(1);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const apiKey = args[0];
|
|
126
|
+
|
|
127
|
+
if (!apiKey || !apiKey.startsWith('sk-')) {
|
|
128
|
+
console.error('Error: Invalid API key format. API key should start with "sk-"');
|
|
129
|
+
process.exit(1);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const paths = getOpenClawPaths();
|
|
133
|
+
|
|
134
|
+
// 检查配置文件是否存在
|
|
135
|
+
if (!fs.existsSync(paths.mainConfig)) {
|
|
136
|
+
console.error(`Error: OpenClaw config not found at ${paths.mainConfig}`);
|
|
137
|
+
console.error('Please make sure OpenClaw is installed and configured.');
|
|
138
|
+
process.exit(1);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
try {
|
|
142
|
+
// 备份原配置
|
|
143
|
+
const backupSuffix = '.backup-' + Date.now();
|
|
144
|
+
fs.copyFileSync(paths.mainConfig, paths.mainConfig + backupSuffix);
|
|
145
|
+
if (fs.existsSync(paths.modelsConfig)) {
|
|
146
|
+
fs.copyFileSync(paths.modelsConfig, paths.modelsConfig + backupSuffix);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// 更新配置
|
|
150
|
+
updateMainConfig(paths.mainConfig, apiKey);
|
|
151
|
+
updateModelsConfig(paths.modelsConfig, apiKey);
|
|
152
|
+
|
|
153
|
+
console.log('✓ OpenClaw API key updated successfully!');
|
|
154
|
+
console.log('');
|
|
155
|
+
console.log('Configuration:');
|
|
156
|
+
console.log(` Provider: ${CONFIG.providerId}`);
|
|
157
|
+
console.log(` Base URL: ${CONFIG.baseUrl}`);
|
|
158
|
+
console.log(` Model: ${CONFIG.modelId}`);
|
|
159
|
+
console.log(` API Key: ${apiKey.substring(0, 10)}...${apiKey.substring(apiKey.length - 4)}`);
|
|
160
|
+
console.log('');
|
|
161
|
+
console.log('Backup files created:');
|
|
162
|
+
console.log(` ${paths.mainConfig}${backupSuffix}`);
|
|
163
|
+
if (fs.existsSync(paths.modelsConfig + backupSuffix)) {
|
|
164
|
+
console.log(` ${paths.modelsConfig}${backupSuffix}`);
|
|
165
|
+
}
|
|
166
|
+
console.log('');
|
|
167
|
+
console.log('Please restart OpenClaw to apply the changes.');
|
|
168
|
+
|
|
169
|
+
} catch (error) {
|
|
170
|
+
console.error('Error updating configuration:', error.message);
|
|
171
|
+
process.exit(1);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
main();
|
package/package.json
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "openclaw-apikey-cli",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI tool to update OpenClaw API key for CSDN custom provider",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"openclaw-set-key": "./index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
11
|
+
},
|
|
12
|
+
"keywords": ["openclaw", "apikey", "cli"],
|
|
13
|
+
"author": "",
|
|
14
|
+
"license": "ISC"
|
|
15
|
+
}
|