trinity-config 1.2.5 → 1.3.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 +21 -7
- package/dist/index.js +527 -34
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# trinity-config
|
|
2
2
|
|
|
3
|
-
一键接入 Trinity:Claude Code / Codex / OpenCode / OpenClaw / ZCode
|
|
3
|
+
一键接入 Trinity:Claude Code / Codex / OpenCode / OpenClaw / ZCode / **CC Switch**。
|
|
4
4
|
|
|
5
5
|
协议按 `GET /v1/models/{code}` 的 `capabilities.text.interfaces` **自动择优**(Anthropic → Responses → Completions),再与工具能力求交。
|
|
6
6
|
|
|
@@ -8,15 +8,29 @@
|
|
|
8
8
|
|
|
9
9
|
```bash
|
|
10
10
|
npx -y trinity-config --type zcode -k xh-你的key --model gpt-5.4
|
|
11
|
+
|
|
12
|
+
# CC Switch:按 App 槽位生成 Deep Link(非 Universal)
|
|
13
|
+
npx -y trinity-config --type ccswitch --app claude -k xh-你的key
|
|
14
|
+
npx -y trinity-config --type ccswitch --app codex -k xh-你的key --model gpt-5.4
|
|
15
|
+
npx -y trinity-config --type ccswitch --app claude,codex -k xh-你的key --print-only
|
|
11
16
|
```
|
|
12
17
|
|
|
13
|
-
| type |
|
|
18
|
+
| type | 配置方式 |
|
|
14
19
|
| --- | --- |
|
|
15
|
-
| claude | `~/.claude/settings.json
|
|
16
|
-
| codex | `~/.codex/config.toml` |
|
|
17
|
-
| opencode | `~/.config/opencode/opencode.json
|
|
18
|
-
| openclaw | `~/.openclaw/openclaw.json
|
|
19
|
-
| zcode | `~/.zcode/v2/config.json
|
|
20
|
+
| claude | `~/.claude/settings.json`(直连) |
|
|
21
|
+
| codex | `~/.codex/config.toml` + `auth.json`(直连) |
|
|
22
|
+
| opencode | `~/.config/opencode/opencode.json`(直连) |
|
|
23
|
+
| openclaw | `~/.openclaw/openclaw.json`(直连) |
|
|
24
|
+
| zcode | `~/.zcode/v2/config.json`(直连) |
|
|
25
|
+
| ccswitch | `ccswitch://v1/import` Deep Link;落盘 `~/.cc-switch/trinity-imports/` |
|
|
26
|
+
|
|
27
|
+
### CC Switch 注意
|
|
28
|
+
|
|
29
|
+
- **必填** `--app`:`claude` / `codex` / `opencode` / `openclaw`(不支持 `gemini` / Universal)
|
|
30
|
+
- 与直连 `--type claude` 等**不要混用**同一工具,以免互相覆盖
|
|
31
|
+
- Claude:Anthropic Messages,Endpoint **不带** `/v1`
|
|
32
|
+
- Codex:`wire_api=responses`,Endpoint **带** `/v1`,关闭 Needs Local Routing
|
|
33
|
+
- `--print-only`:只生成链接,不唤起应用
|
|
20
34
|
|
|
21
35
|
Anthropic Base **不带** `/v1`;Responses / Completions **带** `/v1`。
|
|
22
36
|
|
package/dist/index.js
CHANGED
|
@@ -9,7 +9,7 @@ import pc from "picocolors";
|
|
|
9
9
|
|
|
10
10
|
// src/constants.ts
|
|
11
11
|
var PACKAGE_NAME = "trinity-config";
|
|
12
|
-
var PACKAGE_VERSION = "1.
|
|
12
|
+
var PACKAGE_VERSION = "1.3.0";
|
|
13
13
|
var TRINITY_BASE_URL = "https://api.trinitydesk.ai";
|
|
14
14
|
var DEFAULT_CLAUDE_MODEL = "claude-sonnet-4-6";
|
|
15
15
|
var DEFAULT_CLAUDE_FAST_MODEL = "claude-sonnet-4-6";
|
|
@@ -20,7 +20,23 @@ var DEFAULT_ZCODE_MODEL = "gpt-5.4";
|
|
|
20
20
|
var VERIFY_TIMEOUT_MS = 15e3;
|
|
21
21
|
|
|
22
22
|
// src/model.ts
|
|
23
|
-
|
|
23
|
+
var CC_SWITCH_APPS = [
|
|
24
|
+
"claude",
|
|
25
|
+
"codex",
|
|
26
|
+
"gemini",
|
|
27
|
+
"opencode",
|
|
28
|
+
"openclaw"
|
|
29
|
+
];
|
|
30
|
+
var CC_SWITCH_SUPPORTED_APPS = [
|
|
31
|
+
"claude",
|
|
32
|
+
"codex",
|
|
33
|
+
"opencode",
|
|
34
|
+
"openclaw"
|
|
35
|
+
];
|
|
36
|
+
function defaultModelForType(type, app) {
|
|
37
|
+
if (type === "ccswitch") {
|
|
38
|
+
return defaultModelForCcSwitchApp(app ?? "claude");
|
|
39
|
+
}
|
|
24
40
|
switch (type) {
|
|
25
41
|
case "claude":
|
|
26
42
|
return DEFAULT_CLAUDE_MODEL;
|
|
@@ -34,17 +50,77 @@ function defaultModelForType(type) {
|
|
|
34
50
|
return DEFAULT_ZCODE_MODEL;
|
|
35
51
|
}
|
|
36
52
|
}
|
|
37
|
-
function
|
|
38
|
-
|
|
53
|
+
function defaultModelForCcSwitchApp(app) {
|
|
54
|
+
switch (app) {
|
|
55
|
+
case "claude":
|
|
56
|
+
return DEFAULT_CLAUDE_MODEL;
|
|
57
|
+
case "codex":
|
|
58
|
+
case "opencode":
|
|
59
|
+
case "openclaw":
|
|
60
|
+
return DEFAULT_CODEX_MODEL;
|
|
61
|
+
case "gemini":
|
|
62
|
+
return DEFAULT_CODEX_MODEL;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function resolveModel(type, model, app) {
|
|
66
|
+
return model?.trim() || defaultModelForType(type, app);
|
|
39
67
|
}
|
|
40
68
|
function parseToolType(raw) {
|
|
41
69
|
const value = raw.trim().toLowerCase();
|
|
42
|
-
if (value === "claude" || value === "codex" || value === "opencode" || value === "openclaw" || value === "zcode") {
|
|
70
|
+
if (value === "claude" || value === "codex" || value === "opencode" || value === "openclaw" || value === "zcode" || value === "ccswitch") {
|
|
43
71
|
return value;
|
|
44
72
|
}
|
|
45
|
-
throw new Error(
|
|
73
|
+
throw new Error(
|
|
74
|
+
"--type \u987B\u4E3A claude\u3001codex\u3001opencode\u3001openclaw\u3001zcode \u6216 ccswitch"
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
function parseCcSwitchApps(raw) {
|
|
78
|
+
const parts = raw.split(",").map((s) => s.trim().toLowerCase()).filter(Boolean);
|
|
79
|
+
if (parts.length === 0) {
|
|
80
|
+
throw new Error("--app \u4E0D\u80FD\u4E3A\u7A7A\uFF08\u4F8B: --app claude \u6216 --app claude,codex\uFF09");
|
|
81
|
+
}
|
|
82
|
+
const out = [];
|
|
83
|
+
const seen = /* @__PURE__ */ new Set();
|
|
84
|
+
for (const p2 of parts) {
|
|
85
|
+
if (!CC_SWITCH_APPS.includes(p2)) {
|
|
86
|
+
throw new Error(
|
|
87
|
+
`--app \u65E0\u6548: ${p2}\uFF08\u652F\u6301: ${CC_SWITCH_SUPPORTED_APPS.join(" / ")}\uFF09`
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
assertCcSwitchAppSupported(p2);
|
|
91
|
+
if (seen.has(p2)) continue;
|
|
92
|
+
seen.add(p2);
|
|
93
|
+
out.push(p2);
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
46
96
|
}
|
|
47
|
-
function
|
|
97
|
+
function protocolToolForCcSwitchApp(app) {
|
|
98
|
+
switch (app) {
|
|
99
|
+
case "claude":
|
|
100
|
+
return "claude";
|
|
101
|
+
case "codex":
|
|
102
|
+
return "codex";
|
|
103
|
+
case "opencode":
|
|
104
|
+
return "opencode";
|
|
105
|
+
case "openclaw":
|
|
106
|
+
return "openclaw";
|
|
107
|
+
case "gemini":
|
|
108
|
+
throw new Error(
|
|
109
|
+
"CC Switch --app gemini\uFF1ATrinity \u5BF9\u5916\u672A\u63D0\u4F9B Gemini \u539F\u751F\u534F\u8BAE"
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
function assertCcSwitchAppSupported(app) {
|
|
114
|
+
if (app === "gemini") {
|
|
115
|
+
throw new Error(
|
|
116
|
+
"CC Switch --app gemini\uFF1ATrinity \u5BF9\u5916\u672A\u63D0\u4F9B Gemini \u539F\u751F\u534F\u8BAE\uFF0C\u8BF7\u6539\u7528 --app claude / codex / opencode / openclaw"
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function toolLabel(type, app) {
|
|
121
|
+
if (type === "ccswitch") {
|
|
122
|
+
return app ? `CC Switch \xB7 ${app}` : "CC Switch";
|
|
123
|
+
}
|
|
48
124
|
switch (type) {
|
|
49
125
|
case "claude":
|
|
50
126
|
return "Claude Code";
|
|
@@ -70,6 +146,8 @@ function launchCommand(type) {
|
|
|
70
146
|
return "openclaw dashboard";
|
|
71
147
|
case "zcode":
|
|
72
148
|
return "ZCode \u684C\u9762\u5E94\u7528";
|
|
149
|
+
case "ccswitch":
|
|
150
|
+
return "CC Switch \u684C\u9762\u5E94\u7528";
|
|
73
151
|
}
|
|
74
152
|
}
|
|
75
153
|
|
|
@@ -79,27 +157,33 @@ function printHelp() {
|
|
|
79
157
|
trinity-config \u2014 \u4E00\u952E\u628A Trinity API \u63A5\u5165\u7EC8\u7AEF / Agent / \u684C\u9762\u7F16\u7A0B\u52A9\u624B
|
|
80
158
|
|
|
81
159
|
\u7528\u6CD5:
|
|
82
|
-
npx -y trinity-config --type <claude|codex|opencode|openclaw|zcode> [\u9009\u9879]
|
|
160
|
+
npx -y trinity-config --type <claude|codex|opencode|openclaw|zcode|ccswitch> [\u9009\u9879]
|
|
83
161
|
|
|
84
162
|
\u9009\u9879:
|
|
85
163
|
-t, --type <\u2026> \u8981\u914D\u7F6E\u7684\u5DE5\u5177\uFF08\u975E\u4EA4\u4E92\u987B\u6307\u5B9A\uFF09
|
|
86
164
|
-k, --api-key <key> Trinity API Key\uFF08xh- \u524D\u7F00\uFF09
|
|
87
165
|
-M, --model <code> \u9ED8\u8BA4\u6A21\u578B\uFF1B\u534F\u8BAE\u6309\u6A21\u578B\u8BE6\u60C5\u81EA\u52A8\u62E9\u4F18\uFF08\u975E completions \u4F18\u5148\uFF09
|
|
166
|
+
--app <apps> \u4EC5 --type ccswitch\uFF1A\u76EE\u6807\u69FD\u4F4D\uFF0C\u9017\u53F7\u5206\u9694
|
|
167
|
+
claude|codex|opencode|openclaw\uFF08\u4E0D\u652F\u6301 gemini / Universal\uFF09
|
|
168
|
+
--print-only \u4EC5 --type ccswitch\uFF1A\u53EA\u751F\u6210 Deep Link\uFF0C\u4E0D\u5524\u8D77\u5E94\u7528
|
|
88
169
|
--base-url <url> API \u6839\u5730\u5740\uFF08\u9ED8\u8BA4 https://api.trinitydesk.ai\uFF09
|
|
89
170
|
--skip-verify \u8DF3\u8FC7\u8FDE\u901A\u6027 / \u8BE6\u60C5\u62C9\u53D6
|
|
90
|
-
-v, --verbose \u663E\u793A zcf \u8BE6\u7EC6\u8F93\u51FA\uFF08\u4EC5 Claude\uFF09
|
|
171
|
+
-v, --verbose \u663E\u793A zcf \u8BE6\u7EC6\u8F93\u51FA\uFF08\u4EC5 Claude \u76F4\u8FDE\uFF09
|
|
91
172
|
-h, --help \u663E\u793A\u5E2E\u52A9
|
|
92
173
|
-V, --version \u663E\u793A\u7248\u672C
|
|
93
174
|
|
|
94
175
|
\u793A\u4F8B:
|
|
95
176
|
npx -y trinity-config --type zcode -k xh-your-key --model gpt-5.4
|
|
96
|
-
npx -y trinity-config --type
|
|
177
|
+
npx -y trinity-config --type ccswitch --app claude -k xh-your-key
|
|
178
|
+
npx -y trinity-config --type ccswitch --app codex -k xh-your-key --model gpt-5.4
|
|
179
|
+
npx -y trinity-config --type ccswitch --app claude,codex -k xh-your-key
|
|
97
180
|
`);
|
|
98
181
|
}
|
|
99
182
|
function parseArgs(argv) {
|
|
100
183
|
const opts = {
|
|
101
184
|
skipVerify: false,
|
|
102
185
|
verbose: false,
|
|
186
|
+
printOnly: false,
|
|
103
187
|
help: false,
|
|
104
188
|
version: false
|
|
105
189
|
};
|
|
@@ -123,6 +207,9 @@ function parseArgs(argv) {
|
|
|
123
207
|
case "--skip-verify":
|
|
124
208
|
opts.skipVerify = true;
|
|
125
209
|
break;
|
|
210
|
+
case "--print-only":
|
|
211
|
+
opts.printOnly = true;
|
|
212
|
+
break;
|
|
126
213
|
case "-k":
|
|
127
214
|
case "--api-key":
|
|
128
215
|
opts.apiKey = args.shift();
|
|
@@ -135,6 +222,9 @@ function parseArgs(argv) {
|
|
|
135
222
|
case "--model":
|
|
136
223
|
opts.model = args.shift();
|
|
137
224
|
break;
|
|
225
|
+
case "--app":
|
|
226
|
+
opts.apps = parseCcSwitchApps(String(args.shift() ?? ""));
|
|
227
|
+
break;
|
|
138
228
|
case "--base-url":
|
|
139
229
|
opts.baseUrl = args.shift();
|
|
140
230
|
break;
|
|
@@ -159,6 +249,17 @@ function parseArgs(argv) {
|
|
|
159
249
|
if (opts.help) {
|
|
160
250
|
printHelp();
|
|
161
251
|
}
|
|
252
|
+
if (opts.type === "ccswitch" && (!opts.apps || opts.apps.length === 0) && opts.apiKey) {
|
|
253
|
+
throw new Error(
|
|
254
|
+
"\u975E\u4EA4\u4E92\u914D\u7F6E CC Switch \u987B\u6307\u5B9A --app\uFF08\u4F8B: --app claude \u6216 --app claude,codex\uFF09"
|
|
255
|
+
);
|
|
256
|
+
}
|
|
257
|
+
if (opts.apps && opts.type && opts.type !== "ccswitch") {
|
|
258
|
+
throw new Error("--app \u4EC5\u7528\u4E8E --type ccswitch");
|
|
259
|
+
}
|
|
260
|
+
if (opts.printOnly && opts.type && opts.type !== "ccswitch") {
|
|
261
|
+
throw new Error("--print-only \u4EC5\u7528\u4E8E --type ccswitch");
|
|
262
|
+
}
|
|
162
263
|
return opts;
|
|
163
264
|
}
|
|
164
265
|
function normalizeApiKey(raw) {
|
|
@@ -171,22 +272,262 @@ function normalizeApiKey(raw) {
|
|
|
171
272
|
function requireType(type, hasApiKeyFlag) {
|
|
172
273
|
if (type) return type;
|
|
173
274
|
if (!hasApiKeyFlag) return void 0;
|
|
174
|
-
throw new Error(
|
|
275
|
+
throw new Error(
|
|
276
|
+
"\u975E\u4EA4\u4E92\u6A21\u5F0F\u987B\u6307\u5B9A --type claude\u3001codex\u3001opencode\u3001openclaw\u3001zcode \u6216 ccswitch"
|
|
277
|
+
);
|
|
175
278
|
}
|
|
176
279
|
|
|
177
|
-
// src/
|
|
280
|
+
// src/ccswitch-deeplink.ts
|
|
178
281
|
import fs from "fs";
|
|
179
282
|
import os from "os";
|
|
180
283
|
import path from "path";
|
|
284
|
+
import { execa } from "execa";
|
|
285
|
+
var TRINITY_CCSWITCH_PROVIDER_NAME = "Trinity";
|
|
286
|
+
function encodeConfigBase64(raw) {
|
|
287
|
+
return Buffer.from(raw, "utf8").toString("base64");
|
|
288
|
+
}
|
|
289
|
+
function buildClaudeConfigJson(apiKey, endpoint, model) {
|
|
290
|
+
return `${JSON.stringify(
|
|
291
|
+
{
|
|
292
|
+
env: {
|
|
293
|
+
ANTHROPIC_AUTH_TOKEN: apiKey,
|
|
294
|
+
ANTHROPIC_API_KEY: apiKey,
|
|
295
|
+
ANTHROPIC_BASE_URL: endpoint.replace(/\/v1\/?$/, "").replace(/\/+$/, ""),
|
|
296
|
+
ANTHROPIC_MODEL: model,
|
|
297
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: model,
|
|
298
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: model
|
|
299
|
+
}
|
|
300
|
+
},
|
|
301
|
+
null,
|
|
302
|
+
2
|
|
303
|
+
)}
|
|
304
|
+
`;
|
|
305
|
+
}
|
|
306
|
+
function buildCodexConfigToml(apiKey, endpointWithV1, model) {
|
|
307
|
+
const base = endpointWithV1.replace(/\/+$/, "");
|
|
308
|
+
return `model_provider = "trinity"
|
|
309
|
+
model = ${JSON.stringify(model)}
|
|
310
|
+
disable_response_storage = true
|
|
311
|
+
|
|
312
|
+
[model_providers.trinity]
|
|
313
|
+
name = "Trinity"
|
|
314
|
+
base_url = ${JSON.stringify(base)}
|
|
315
|
+
wire_api = "responses"
|
|
316
|
+
requires_openai_auth = true
|
|
317
|
+
temp_env_key = "TRINITY_API_KEY"
|
|
318
|
+
`;
|
|
319
|
+
}
|
|
320
|
+
function buildOpenCodeConfigJson(apiKey, endpoint, model, protocol) {
|
|
321
|
+
const npm = protocol === "anthropic_messages" ? "@ai-sdk/anthropic" : protocol === "responses" ? "@ai-sdk/openai" : "@ai-sdk/openai-compatible";
|
|
322
|
+
return `${JSON.stringify(
|
|
323
|
+
{
|
|
324
|
+
$schema: "https://opencode.ai/config.json",
|
|
325
|
+
model: `trinity/${model}`,
|
|
326
|
+
provider: {
|
|
327
|
+
trinity: {
|
|
328
|
+
npm,
|
|
329
|
+
name: "Trinity",
|
|
330
|
+
options: {
|
|
331
|
+
baseURL: endpoint.replace(/\/+$/, ""),
|
|
332
|
+
apiKey
|
|
333
|
+
},
|
|
334
|
+
models: {
|
|
335
|
+
[model]: { name: model }
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
null,
|
|
341
|
+
2
|
|
342
|
+
)}
|
|
343
|
+
`;
|
|
344
|
+
}
|
|
345
|
+
function buildOpenClawConfigJson(apiKey, endpoint, model, protocol) {
|
|
346
|
+
const api = protocol === "anthropic_messages" ? "anthropic-messages" : protocol === "responses" ? "openai-responses" : "openai-completions";
|
|
347
|
+
return `${JSON.stringify(
|
|
348
|
+
{
|
|
349
|
+
models: {
|
|
350
|
+
mode: "merge",
|
|
351
|
+
providers: {
|
|
352
|
+
trinity: {
|
|
353
|
+
baseUrl: endpoint.replace(/\/+$/, ""),
|
|
354
|
+
apiKey,
|
|
355
|
+
api,
|
|
356
|
+
models: [
|
|
357
|
+
{
|
|
358
|
+
id: model,
|
|
359
|
+
name: model,
|
|
360
|
+
reasoning: false,
|
|
361
|
+
input: ["text"],
|
|
362
|
+
contextWindow: 128e3,
|
|
363
|
+
maxTokens: 8192
|
|
364
|
+
}
|
|
365
|
+
]
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
},
|
|
369
|
+
agents: {
|
|
370
|
+
defaults: {
|
|
371
|
+
model: { primary: `trinity/${model}` },
|
|
372
|
+
models: { "trinity/*": {} }
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
null,
|
|
377
|
+
2
|
|
378
|
+
)}
|
|
379
|
+
`;
|
|
380
|
+
}
|
|
381
|
+
function notesForCcSwitchApp(app, protocol) {
|
|
382
|
+
const common = [
|
|
383
|
+
"App-specific Provider\uFF08\u975E Universal\uFF09",
|
|
384
|
+
"\u5BFC\u5165\u540E\u8BF7\u5728 CC Switch \u4E2D Activate Trinity",
|
|
385
|
+
"\u52FF\u518D\u5BF9\u540C\u4E00\u5DE5\u5177\u8DD1 trinity-config --type \u76F4\u8FDE\uFF0C\u4EE5\u514D\u4E92\u76F8\u8986\u76D6",
|
|
386
|
+
"\u6A21\u578B\u5217\u8868\u4EE5\u8BE5 API Key Call Allowlist \u4E3A\u51C6"
|
|
387
|
+
];
|
|
388
|
+
switch (app) {
|
|
389
|
+
case "claude":
|
|
390
|
+
return [
|
|
391
|
+
...common,
|
|
392
|
+
"API Format = Anthropic Messages\uFF08\u9ED8\u8BA4\uFF09",
|
|
393
|
+
"Endpoint \u4E0D\u5E26 /v1",
|
|
394
|
+
protocol !== "anthropic_messages" ? `\u8B66\u544A: \u5F53\u524D\u62E9\u4F18\u534F\u8BAE\u4E3A ${protocol}\uFF0CClaude \u69FD\u4ECD\u6309 Messages \u5199\u5165\uFF1B\u82E5\u6A21\u578B\u65E0 Messages \u8BF7\u6362\u6A21\u578B` : ""
|
|
395
|
+
].filter(Boolean).join("\uFF1B");
|
|
396
|
+
case "codex":
|
|
397
|
+
return [
|
|
398
|
+
...common,
|
|
399
|
+
"wire_api=responses\uFF1B\u8BF7\u5173\u95ED Needs Local Routing\uFF08\u76F4\u8FDE Trinity Responses\uFF09",
|
|
400
|
+
"Endpoint \u586B\u5E26 /v1 \u7684\u524D\u7F00\uFF0C\u907F\u514D\u5199\u6210 \u2026/v1/v1"
|
|
401
|
+
].join("\uFF1B");
|
|
402
|
+
case "opencode":
|
|
403
|
+
return [...common, `\u534F\u8BAE: ${protocol}`].join("\uFF1B");
|
|
404
|
+
case "openclaw":
|
|
405
|
+
return [...common, `\u534F\u8BAE: ${protocol}`, "\u6539\u5B8C\u8BF7\u91CD\u542F OpenClaw Gateway"].join("\uFF1B");
|
|
406
|
+
case "gemini":
|
|
407
|
+
return "\u4E0D\u652F\u6301";
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
function buildCcSwitchDeepLink(options) {
|
|
411
|
+
const root = (options.rootBaseUrl ?? TRINITY_BASE_URL).replace(/\/+$/, "");
|
|
412
|
+
const withoutV1 = root.replace(/\/v1\/?$/, "");
|
|
413
|
+
const withV1 = `${withoutV1}/v1`;
|
|
414
|
+
let endpoint;
|
|
415
|
+
let config;
|
|
416
|
+
let configFormat;
|
|
417
|
+
switch (options.app) {
|
|
418
|
+
case "claude": {
|
|
419
|
+
endpoint = withoutV1;
|
|
420
|
+
configFormat = "json";
|
|
421
|
+
config = buildClaudeConfigJson(options.apiKey, endpoint, options.model);
|
|
422
|
+
break;
|
|
423
|
+
}
|
|
424
|
+
case "codex": {
|
|
425
|
+
endpoint = withV1;
|
|
426
|
+
configFormat = "toml";
|
|
427
|
+
config = buildCodexConfigToml(options.apiKey, endpoint, options.model);
|
|
428
|
+
break;
|
|
429
|
+
}
|
|
430
|
+
case "opencode": {
|
|
431
|
+
endpoint = options.protocol === "anthropic_messages" ? withoutV1 : withV1;
|
|
432
|
+
configFormat = "json";
|
|
433
|
+
config = buildOpenCodeConfigJson(
|
|
434
|
+
options.apiKey,
|
|
435
|
+
endpoint,
|
|
436
|
+
options.model,
|
|
437
|
+
options.protocol
|
|
438
|
+
);
|
|
439
|
+
break;
|
|
440
|
+
}
|
|
441
|
+
case "openclaw": {
|
|
442
|
+
endpoint = options.protocol === "anthropic_messages" ? withoutV1 : withV1;
|
|
443
|
+
configFormat = "json";
|
|
444
|
+
config = buildOpenClawConfigJson(
|
|
445
|
+
options.apiKey,
|
|
446
|
+
endpoint,
|
|
447
|
+
options.model,
|
|
448
|
+
options.protocol
|
|
449
|
+
);
|
|
450
|
+
break;
|
|
451
|
+
}
|
|
452
|
+
case "gemini":
|
|
453
|
+
throw new Error("gemini \u4E0D\u53D7\u652F\u6301");
|
|
454
|
+
}
|
|
455
|
+
const notes = notesForCcSwitchApp(options.app, options.protocol);
|
|
456
|
+
const params = new URLSearchParams();
|
|
457
|
+
params.set("resource", "provider");
|
|
458
|
+
params.set("app", options.app);
|
|
459
|
+
params.set("name", TRINITY_CCSWITCH_PROVIDER_NAME);
|
|
460
|
+
params.set("endpoint", endpoint);
|
|
461
|
+
params.set("apiKey", options.apiKey);
|
|
462
|
+
params.set("homepage", "https://trinitydesk.ai");
|
|
463
|
+
params.set("model", options.model);
|
|
464
|
+
if (options.app === "claude") {
|
|
465
|
+
params.set("sonnetModel", options.model);
|
|
466
|
+
params.set("haikuModel", options.model);
|
|
467
|
+
}
|
|
468
|
+
params.set("notes", notes);
|
|
469
|
+
params.set("config", encodeConfigBase64(config));
|
|
470
|
+
params.set("configFormat", configFormat);
|
|
471
|
+
if (options.enabled !== false) {
|
|
472
|
+
params.set("enabled", "true");
|
|
473
|
+
}
|
|
474
|
+
return {
|
|
475
|
+
url: `ccswitch://v1/import?${params.toString()}`,
|
|
476
|
+
endpoint,
|
|
477
|
+
notes,
|
|
478
|
+
configFormat
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
function ccSwitchImportDir() {
|
|
482
|
+
return path.join(os.homedir(), ".cc-switch", "trinity-imports");
|
|
483
|
+
}
|
|
484
|
+
function persistCcSwitchDeepLink(app, url) {
|
|
485
|
+
const dir = ccSwitchImportDir();
|
|
486
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
487
|
+
const stamp = (/* @__PURE__ */ new Date()).toISOString().replace(/[:.]/g, "-");
|
|
488
|
+
const base = path.join(dir, `trinity-${app}-${stamp}`);
|
|
489
|
+
const urlFile = `${base}.url`;
|
|
490
|
+
const txtFile = `${base}.txt`;
|
|
491
|
+
fs.writeFileSync(
|
|
492
|
+
urlFile,
|
|
493
|
+
`[InternetShortcut]\r
|
|
494
|
+
URL=${url}\r
|
|
495
|
+
`,
|
|
496
|
+
"utf8"
|
|
497
|
+
);
|
|
498
|
+
fs.writeFileSync(txtFile, `${url}
|
|
499
|
+
`, "utf8");
|
|
500
|
+
return { urlFile, txtFile };
|
|
501
|
+
}
|
|
502
|
+
async function openCcSwitchDeepLink(url) {
|
|
503
|
+
const platform = process.platform;
|
|
504
|
+
if (platform === "win32") {
|
|
505
|
+
await execa("cmd", ["/c", "start", "", url], {
|
|
506
|
+
windowsHide: true,
|
|
507
|
+
reject: false
|
|
508
|
+
});
|
|
509
|
+
return;
|
|
510
|
+
}
|
|
511
|
+
if (platform === "darwin") {
|
|
512
|
+
await execa("open", [url], { reject: false });
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
await execa("xdg-open", [url], { reject: false });
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// src/merge-claude-env.ts
|
|
519
|
+
import fs2 from "fs";
|
|
520
|
+
import os2 from "os";
|
|
521
|
+
import path2 from "path";
|
|
181
522
|
function claudeSettingsPath() {
|
|
182
|
-
return
|
|
523
|
+
return path2.join(os2.homedir(), ".claude", "settings.json");
|
|
183
524
|
}
|
|
184
525
|
function mergeClaudeEnv(claudeModel, fastModel, baseUrl) {
|
|
185
526
|
const filePath = claudeSettingsPath();
|
|
186
|
-
if (!
|
|
527
|
+
if (!fs2.existsSync(filePath)) {
|
|
187
528
|
return;
|
|
188
529
|
}
|
|
189
|
-
const raw =
|
|
530
|
+
const raw = fs2.readFileSync(filePath, "utf8");
|
|
190
531
|
let settings;
|
|
191
532
|
try {
|
|
192
533
|
settings = JSON.parse(raw);
|
|
@@ -199,8 +540,8 @@ function mergeClaudeEnv(claudeModel, fastModel, baseUrl) {
|
|
|
199
540
|
ANTHROPIC_MODEL: claudeModel,
|
|
200
541
|
ANTHROPIC_SMALL_FAST_MODEL: fastModel
|
|
201
542
|
};
|
|
202
|
-
|
|
203
|
-
|
|
543
|
+
fs2.mkdirSync(path2.dirname(filePath), { recursive: true });
|
|
544
|
+
fs2.writeFileSync(filePath, `${JSON.stringify(settings, null, 2)}
|
|
204
545
|
`, "utf8");
|
|
205
546
|
}
|
|
206
547
|
|
|
@@ -366,7 +707,7 @@ function protocolLabel(protocol) {
|
|
|
366
707
|
}
|
|
367
708
|
|
|
368
709
|
// src/zcf.ts
|
|
369
|
-
import { execa } from "execa";
|
|
710
|
+
import { execa as execa2 } from "execa";
|
|
370
711
|
function sharedZcfArgs(verbose) {
|
|
371
712
|
return [
|
|
372
713
|
"zcf",
|
|
@@ -405,7 +746,7 @@ async function runZcfInit(options) {
|
|
|
405
746
|
args.push("--api-haiku-model", options.fastModel);
|
|
406
747
|
args.push("--api-sonnet-model", options.primaryModel);
|
|
407
748
|
}
|
|
408
|
-
await
|
|
749
|
+
await execa2("npx", ["-y", ...args], {
|
|
409
750
|
stdio: options.verbose ? "inherit" : "pipe",
|
|
410
751
|
reject: true,
|
|
411
752
|
timeout: 18e4
|
|
@@ -581,11 +922,12 @@ async function promptToolType(initial) {
|
|
|
581
922
|
const value = await p.select({
|
|
582
923
|
message: "\u8981\u914D\u7F6E\u54EA\u4E2A\u5DE5\u5177\uFF1F",
|
|
583
924
|
options: [
|
|
584
|
-
{ value: "claude", label: "Claude Code" },
|
|
585
|
-
{ value: "codex", label: "Codex CLI" },
|
|
586
|
-
{ value: "opencode", label: "OpenCode" },
|
|
587
|
-
{ value: "openclaw", label: "OpenClaw" },
|
|
588
|
-
{ value: "zcode", label: "ZCode" }
|
|
925
|
+
{ value: "claude", label: "Claude Code\uFF08\u76F4\u8FDE\uFF09" },
|
|
926
|
+
{ value: "codex", label: "Codex CLI\uFF08\u76F4\u8FDE\uFF09" },
|
|
927
|
+
{ value: "opencode", label: "OpenCode\uFF08\u76F4\u8FDE\uFF09" },
|
|
928
|
+
{ value: "openclaw", label: "OpenClaw\uFF08\u76F4\u8FDE\uFF09" },
|
|
929
|
+
{ value: "zcode", label: "ZCode" },
|
|
930
|
+
{ value: "ccswitch", label: "CC Switch\uFF08\u6309 App \u69FD\u4F4D\u5BFC\u5165\uFF09" }
|
|
589
931
|
]
|
|
590
932
|
});
|
|
591
933
|
if (p.isCancel(value)) {
|
|
@@ -594,13 +936,31 @@ async function promptToolType(initial) {
|
|
|
594
936
|
}
|
|
595
937
|
return value;
|
|
596
938
|
}
|
|
597
|
-
async function
|
|
939
|
+
async function promptCcSwitchApps(initial) {
|
|
940
|
+
if (initial && initial.length > 0) {
|
|
941
|
+
return initial;
|
|
942
|
+
}
|
|
943
|
+
const value = await p.multiselect({
|
|
944
|
+
message: "\u8981\u5199\u5165 CC Switch \u7684\u54EA\u4E9B App \u69FD\u4F4D\uFF1F\uFF08\u975E Universal\uFF09",
|
|
945
|
+
options: CC_SWITCH_SUPPORTED_APPS.map((app) => ({
|
|
946
|
+
value: app,
|
|
947
|
+
label: app
|
|
948
|
+
})),
|
|
949
|
+
required: true
|
|
950
|
+
});
|
|
951
|
+
if (p.isCancel(value)) {
|
|
952
|
+
p.cancel("\u5DF2\u53D6\u6D88");
|
|
953
|
+
process.exit(0);
|
|
954
|
+
}
|
|
955
|
+
return value;
|
|
956
|
+
}
|
|
957
|
+
async function promptModel(type, app, initial) {
|
|
598
958
|
if (initial?.trim()) {
|
|
599
959
|
return initial.trim();
|
|
600
960
|
}
|
|
601
|
-
const fallback = defaultModelForType(type);
|
|
961
|
+
const fallback = defaultModelForType(type, app);
|
|
602
962
|
const value = await p.text({
|
|
603
|
-
message: `${toolLabel(type)} \u9ED8\u8BA4 model_code`,
|
|
963
|
+
message: `${toolLabel(type, app)} \u9ED8\u8BA4 model_code`,
|
|
604
964
|
placeholder: fallback,
|
|
605
965
|
initialValue: fallback,
|
|
606
966
|
validate: (input) => {
|
|
@@ -613,8 +973,8 @@ async function promptModel(type, initial) {
|
|
|
613
973
|
}
|
|
614
974
|
return String(value).trim();
|
|
615
975
|
}
|
|
616
|
-
function recommendedHint(
|
|
617
|
-
switch (
|
|
976
|
+
function recommendedHint(protocolTool, recommended) {
|
|
977
|
+
switch (protocolTool) {
|
|
618
978
|
case "claude":
|
|
619
979
|
return recommended.claude;
|
|
620
980
|
case "codex":
|
|
@@ -627,6 +987,13 @@ function recommendedHint(toolType, recommended) {
|
|
|
627
987
|
return recommended.zcode;
|
|
628
988
|
}
|
|
629
989
|
}
|
|
990
|
+
function protocolToolFor(type, app) {
|
|
991
|
+
if (type === "ccswitch") {
|
|
992
|
+
if (!app) throw new Error("ccswitch \u7F3A\u5C11 --app");
|
|
993
|
+
return protocolToolForCcSwitchApp(app);
|
|
994
|
+
}
|
|
995
|
+
return type;
|
|
996
|
+
}
|
|
630
997
|
async function run() {
|
|
631
998
|
let opts;
|
|
632
999
|
try {
|
|
@@ -645,13 +1012,38 @@ async function run() {
|
|
|
645
1012
|
}
|
|
646
1013
|
p.intro(pc.bgCyan(pc.black(` ${PACKAGE_NAME} v${PACKAGE_VERSION} `)));
|
|
647
1014
|
const toolType = await promptToolType(opts.type);
|
|
1015
|
+
const ccApps = toolType === "ccswitch" ? await promptCcSwitchApps(opts.apps) : void 0;
|
|
1016
|
+
if (ccApps) {
|
|
1017
|
+
for (const app of ccApps) {
|
|
1018
|
+
try {
|
|
1019
|
+
assertCcSwitchAppSupported(app);
|
|
1020
|
+
} catch (error) {
|
|
1021
|
+
console.error(pc.red(error instanceof Error ? error.message : String(error)));
|
|
1022
|
+
return 1;
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
const primaryApp = ccApps?.[0];
|
|
648
1027
|
const apiKey = await promptApiKey(opts.apiKey);
|
|
649
|
-
let model = opts.model?.trim() ? opts.model.trim() : opts.apiKey ? resolveModel(toolType) : await promptModel(toolType);
|
|
1028
|
+
let model = opts.model?.trim() ? opts.model.trim() : opts.apiKey ? resolveModel(toolType, void 0, primaryApp) : await promptModel(toolType, primaryApp);
|
|
650
1029
|
const apiRoot = rootBaseUrl(opts.baseUrl);
|
|
651
|
-
p.log.info(
|
|
1030
|
+
p.log.info(
|
|
1031
|
+
`\u5DE5\u5177: ${toolLabel(toolType, primaryApp)}` + (ccApps && ccApps.length > 1 ? `\uFF08${ccApps.join(",")}\uFF09` : "") + ` \xB7 \u6A21\u578B: ${model}`
|
|
1032
|
+
);
|
|
1033
|
+
if (toolType === "ccswitch") {
|
|
1034
|
+
p.note(
|
|
1035
|
+
[
|
|
1036
|
+
"\u5C06\u751F\u6210 App-specific Provider Deep Link\uFF08\u975E Universal\uFF09",
|
|
1037
|
+
"\u5BFC\u5165\u540E\u8BF7\u5728\u5BF9\u5E94 App \u4E0B Activate\u300CTrinity\u300D",
|
|
1038
|
+
"\u8BF7\u52FF\u540C\u65F6\u5BF9\u672C\u5DE5\u5177\u518D\u8DD1 --type \u76F4\u8FDE\uFF0C\u4EE5\u514D\u914D\u7F6E\u4E92\u76F8\u8986\u76D6"
|
|
1039
|
+
].join("\n"),
|
|
1040
|
+
"CC Switch"
|
|
1041
|
+
);
|
|
1042
|
+
}
|
|
652
1043
|
const spinner2 = p.spinner();
|
|
653
1044
|
let verifiedModelIds;
|
|
654
1045
|
let verifyFailed = false;
|
|
1046
|
+
const protocolToolHint = protocolToolFor(toolType, primaryApp);
|
|
655
1047
|
if (!opts.skipVerify) {
|
|
656
1048
|
spinner2.start("\u9A8C\u8BC1 Trinity API \u8FDE\u901A\u6027\u2026");
|
|
657
1049
|
const result = await verifyTrinityApi(apiKey, apiRoot);
|
|
@@ -663,7 +1055,7 @@ async function run() {
|
|
|
663
1055
|
return 1;
|
|
664
1056
|
}
|
|
665
1057
|
const recommended = pickRecommendedModels(verifiedModelIds);
|
|
666
|
-
const hint = recommendedHint(
|
|
1058
|
+
const hint = recommendedHint(protocolToolHint, recommended);
|
|
667
1059
|
const allowed = pickAllowedDefaultModel(model, verifiedModelIds, [
|
|
668
1060
|
hint,
|
|
669
1061
|
recommended.claude,
|
|
@@ -671,7 +1063,7 @@ async function run() {
|
|
|
671
1063
|
recommended.opencode,
|
|
672
1064
|
recommended.openclaw,
|
|
673
1065
|
recommended.zcode,
|
|
674
|
-
defaultModelForType(toolType)
|
|
1066
|
+
defaultModelForType(toolType, primaryApp)
|
|
675
1067
|
]);
|
|
676
1068
|
if (!allowed) {
|
|
677
1069
|
p.outro(pc.red("\u65E0\u6CD5\u5728\u8BE5 API Key \u7684\u53EF\u7528\u751F\u6587\u6A21\u578B\u4E2D\u9009\u51FA\u9ED8\u8BA4\u6A21\u578B"));
|
|
@@ -700,11 +1092,112 @@ async function run() {
|
|
|
700
1092
|
"\u63D0\u793A"
|
|
701
1093
|
);
|
|
702
1094
|
}
|
|
1095
|
+
if (toolType === "ccswitch" && ccApps) {
|
|
1096
|
+
const saved = [];
|
|
1097
|
+
for (const app of ccApps) {
|
|
1098
|
+
spinner2.start(`\u751F\u6210 CC Switch Deep Link\uFF08${app}\uFF09\u2026`);
|
|
1099
|
+
let appModel = model;
|
|
1100
|
+
let protocolRes2;
|
|
1101
|
+
try {
|
|
1102
|
+
protocolRes2 = await resolveProtocol({
|
|
1103
|
+
tool: protocolToolForCcSwitchApp(app),
|
|
1104
|
+
apiKey,
|
|
1105
|
+
model: appModel,
|
|
1106
|
+
rootBaseUrl: apiRoot,
|
|
1107
|
+
skipFetch: opts.skipVerify
|
|
1108
|
+
});
|
|
1109
|
+
} catch (firstError) {
|
|
1110
|
+
const fallback = defaultModelForCcSwitchApp(app);
|
|
1111
|
+
const canRetry = fallback !== appModel && (!verifiedModelIds || verifiedModelIds.includes(fallback));
|
|
1112
|
+
if (!canRetry) {
|
|
1113
|
+
spinner2.stop(pc.red(`${app} \u534F\u8BAE\u89E3\u6790\u5931\u8D25`));
|
|
1114
|
+
console.error(
|
|
1115
|
+
pc.red(
|
|
1116
|
+
firstError instanceof Error ? firstError.message : String(firstError)
|
|
1117
|
+
)
|
|
1118
|
+
);
|
|
1119
|
+
p.note(
|
|
1120
|
+
`\u591A App \u5171\u7528\u4E00\u4E2A --model \u65F6\uFF0C\u8BF7\u786E\u4FDD\u6A21\u578B\u534F\u8BAE\u5339\u914D\u5404\u69FD\u4F4D\uFF1B\u6216\u5206\u5F00\u6267\u884C\u4E0D\u540C --app / --model`,
|
|
1121
|
+
"\u63D0\u793A"
|
|
1122
|
+
);
|
|
1123
|
+
return 1;
|
|
1124
|
+
}
|
|
1125
|
+
try {
|
|
1126
|
+
protocolRes2 = await resolveProtocol({
|
|
1127
|
+
tool: protocolToolForCcSwitchApp(app),
|
|
1128
|
+
apiKey,
|
|
1129
|
+
model: fallback,
|
|
1130
|
+
rootBaseUrl: apiRoot,
|
|
1131
|
+
skipFetch: opts.skipVerify
|
|
1132
|
+
});
|
|
1133
|
+
p.note(
|
|
1134
|
+
`${app} \u69FD\uFF1A\u6A21\u578B ${appModel} \u4E0D\u517C\u5BB9\uFF0C\u5DF2\u6539\u7528 ${fallback}`,
|
|
1135
|
+
"\u6A21\u578B"
|
|
1136
|
+
);
|
|
1137
|
+
appModel = fallback;
|
|
1138
|
+
} catch (error) {
|
|
1139
|
+
spinner2.stop(pc.red(`${app} \u534F\u8BAE\u89E3\u6790\u5931\u8D25`));
|
|
1140
|
+
console.error(
|
|
1141
|
+
pc.red(error instanceof Error ? error.message : String(error))
|
|
1142
|
+
);
|
|
1143
|
+
return 1;
|
|
1144
|
+
}
|
|
1145
|
+
}
|
|
1146
|
+
const protocol2 = protocolRes2.protocol;
|
|
1147
|
+
try {
|
|
1148
|
+
const link = buildCcSwitchDeepLink({
|
|
1149
|
+
app,
|
|
1150
|
+
apiKey,
|
|
1151
|
+
rootBaseUrl: apiRoot,
|
|
1152
|
+
model: appModel,
|
|
1153
|
+
protocol: protocol2
|
|
1154
|
+
});
|
|
1155
|
+
const files = persistCcSwitchDeepLink(app, link.url);
|
|
1156
|
+
saved.push(files.urlFile);
|
|
1157
|
+
spinner2.stop(
|
|
1158
|
+
`\u5DF2\u751F\u6210 ${app}\uFF1A${protocolLabel(protocol2)} \u2192 ${link.endpoint}`
|
|
1159
|
+
);
|
|
1160
|
+
p.note(link.notes, `${app} \u6CE8\u610F`);
|
|
1161
|
+
p.log.info(`Deep Link \u5DF2\u4FDD\u5B58: ${files.txtFile}`);
|
|
1162
|
+
if (link.url.length > 2e3) {
|
|
1163
|
+
p.note(
|
|
1164
|
+
"Deep Link \u8F83\u957F\uFF0C\u82E5\u7CFB\u7EDF\u65E0\u6CD5\u5524\u8D77\uFF0C\u8BF7\u53CC\u51FB\u843D\u76D8\u7684 .url \u6587\u4EF6\u5BFC\u5165",
|
|
1165
|
+
"\u63D0\u793A"
|
|
1166
|
+
);
|
|
1167
|
+
}
|
|
1168
|
+
if (!opts.printOnly) {
|
|
1169
|
+
await openCcSwitchDeepLink(link.url);
|
|
1170
|
+
p.log.info("\u5DF2\u5C1D\u8BD5\u5524\u8D77 CC Switch \u5BFC\u5165\u5BF9\u8BDD\u6846\uFF08\u82E5\u672A\u5F39\u51FA\u8BF7\u53CC\u51FB .url \u6587\u4EF6\uFF09");
|
|
1171
|
+
} else {
|
|
1172
|
+
p.log.info(link.url);
|
|
1173
|
+
}
|
|
1174
|
+
} catch (error) {
|
|
1175
|
+
spinner2.stop(pc.red(`${app} Deep Link \u5931\u8D25`));
|
|
1176
|
+
console.error(pc.red(error instanceof Error ? error.message : String(error)));
|
|
1177
|
+
return 1;
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
if (verifyFailed) {
|
|
1181
|
+
p.outro(pc.yellow("\u914D\u7F6E\u5B8C\u6210\uFF08\u9A8C\u8BC1\u672A\u901A\u8FC7\uFF09"));
|
|
1182
|
+
return 1;
|
|
1183
|
+
}
|
|
1184
|
+
p.note(
|
|
1185
|
+
[
|
|
1186
|
+
"\u5728 CC Switch \u5BFC\u5165\u786E\u8BA4\u6846\u4E2D\u6838\u5BF9\u540E Confirm",
|
|
1187
|
+
"\u5207\u6362\u5230\u5BF9\u5E94 App \u9875\u7B7E\uFF0CActivate\u300CTrinity\u300D",
|
|
1188
|
+
`\u843D\u76D8\u6587\u4EF6: ${saved.join(" | ")}`,
|
|
1189
|
+
opts.printOnly ? "\u5DF2 --print-only\uFF0C\u672A\u81EA\u52A8\u6253\u5F00\u5E94\u7528" : "\u82E5\u672A\u5F39\u7A97\uFF1A\u53CC\u51FB\u4E0A\u8FF0 .url\uFF0C\u6216\u68C0\u67E5 ccswitch:// \u534F\u8BAE\u6CE8\u518C"
|
|
1190
|
+
].join("\n"),
|
|
1191
|
+
"\u4E0B\u4E00\u6B65"
|
|
1192
|
+
);
|
|
1193
|
+
p.outro(pc.green("\u5B8C\u6210"));
|
|
1194
|
+
return 0;
|
|
1195
|
+
}
|
|
703
1196
|
spinner2.start("\u89E3\u6790\u6A21\u578B\u534F\u8BAE\u2026");
|
|
704
1197
|
let protocolRes;
|
|
705
1198
|
try {
|
|
706
1199
|
protocolRes = await resolveProtocol({
|
|
707
|
-
tool: toolType,
|
|
1200
|
+
tool: protocolToolFor(toolType),
|
|
708
1201
|
apiKey,
|
|
709
1202
|
model,
|
|
710
1203
|
rootBaseUrl: apiRoot,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "trinity-config",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "一键把 Trinity API 接入 Claude Code、Codex、OpenCode、OpenClaw、ZCode",
|
|
3
|
+
"version": "1.3.0",
|
|
4
|
+
"description": "一键把 Trinity API 接入 Claude Code、Codex、OpenCode、OpenClaw、ZCode、CC Switch",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"bin": {
|
|
@@ -31,6 +31,8 @@
|
|
|
31
31
|
"codex",
|
|
32
32
|
"opencode",
|
|
33
33
|
"openclaw",
|
|
34
|
+
"zcode",
|
|
35
|
+
"cc-switch",
|
|
34
36
|
"cli",
|
|
35
37
|
"ai-gateway",
|
|
36
38
|
"zcf"
|