@peterwangze/claude-trigger-router 1.0.2 → 1.0.4
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 +6 -4
- package/config/trigger.example.yaml +1 -1
- package/dist/cli.js +143 -43
- package/dist/cli.js.map +3 -3
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -30,8 +30,8 @@ ctr setup
|
|
|
30
30
|
`ctr setup` 会:
|
|
31
31
|
|
|
32
32
|
- 优先检查当前配置是否可直接复用
|
|
33
|
-
- 检测旧版 `~/.ccr/config.yaml` 并优先提供迁移
|
|
34
|
-
-
|
|
33
|
+
- 检测旧版 `~/.ccr/config.yaml` 或 `~/.claude-code-router/config.yaml` 并优先提供迁移
|
|
34
|
+
- 在需要新建时,先确认接入方式与 provider 预设,再带出默认模型和默认模型 ID 供确认
|
|
35
35
|
- 只生成最小可用配置(`Models + Router.default`),高级路由稍后再补
|
|
36
36
|
- 保存配置后启动服务并进入 Claude Code
|
|
37
37
|
|
|
@@ -245,7 +245,7 @@ Models:
|
|
|
245
245
|
|
|
246
246
|
## `/ui` 可以做什么
|
|
247
247
|
|
|
248
|
-
访问 `http://127.0.0.1:
|
|
248
|
+
访问 `http://127.0.0.1:5678/ui` 后,可以直接:
|
|
249
249
|
|
|
250
250
|
- 编辑 `Models` 草稿
|
|
251
251
|
- 预览 compiled model map
|
|
@@ -262,7 +262,7 @@ Models:
|
|
|
262
262
|
如果你还在使用旧的 `Providers + provider,model` 配置:
|
|
263
263
|
|
|
264
264
|
- 当前版本仍然兼容旧格式
|
|
265
|
-
- `ctr setup` 会优先尝试迁移旧 `ccr` 配置
|
|
265
|
+
- `ctr setup` 会优先尝试迁移旧 `ccr` / `claude-code-router` 配置
|
|
266
266
|
- 路由字段推荐逐步改成直接引用 `Models[].id`
|
|
267
267
|
|
|
268
268
|
迁移后的核心变化是:
|
|
@@ -279,6 +279,8 @@ Models:
|
|
|
279
279
|
```bash
|
|
280
280
|
ctr setup
|
|
281
281
|
ctr init
|
|
282
|
+
ctr version
|
|
283
|
+
ctr upgrade
|
|
282
284
|
ctr start
|
|
283
285
|
ctr start --daemon
|
|
284
286
|
ctr stop
|
package/dist/cli.js
CHANGED
|
@@ -32,7 +32,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
32
32
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
33
33
|
|
|
34
34
|
// src/constants.ts
|
|
35
|
-
var import_os, import_path, CONFIG_DIR, CONFIG_FILE, CONFIG_FILE_JSON, CONFIG_FILE_YML, HOME_DIR, PID_FILE, GOVERNANCE_TRACE_FILE, GOVERNANCE_TRACE_ARCHIVE_DIR, GOVERNANCE_EXPORT_HISTORY_FILE, GOVERNANCE_SNAPSHOT_DIR, GOVERNANCE_SCHEDULE_FILE,
|
|
35
|
+
var import_os, import_path, CONFIG_DIR, CONFIG_FILE, CONFIG_FILE_JSON, CONFIG_FILE_YML, HOME_DIR, PID_FILE, GOVERNANCE_TRACE_FILE, GOVERNANCE_TRACE_ARCHIVE_DIR, GOVERNANCE_EXPORT_HISTORY_FILE, GOVERNANCE_SNAPSHOT_DIR, GOVERNANCE_SCHEDULE_FILE, DEFAULT_CONFIG2, DEFAULT_TRIGGER_CONFIG, DEFAULT_SMART_ROUTER_CONFIG, DEFAULT_GOVERNANCE_CONFIG;
|
|
36
36
|
var init_constants = __esm({
|
|
37
37
|
"src/constants.ts"() {
|
|
38
38
|
"use strict";
|
|
@@ -49,9 +49,9 @@ var init_constants = __esm({
|
|
|
49
49
|
GOVERNANCE_EXPORT_HISTORY_FILE = (0, import_path.join)(CONFIG_DIR, "governance-metrics-export-history.json");
|
|
50
50
|
GOVERNANCE_SNAPSHOT_DIR = (0, import_path.join)(CONFIG_DIR, "governance-metric-snapshots");
|
|
51
51
|
GOVERNANCE_SCHEDULE_FILE = (0, import_path.join)(CONFIG_DIR, "governance-metric-schedules.json");
|
|
52
|
-
|
|
52
|
+
DEFAULT_CONFIG2 = {
|
|
53
53
|
HOST: "127.0.0.1",
|
|
54
|
-
PORT:
|
|
54
|
+
PORT: 5678,
|
|
55
55
|
LOG: true,
|
|
56
56
|
LOG_LEVEL: "debug",
|
|
57
57
|
API_TIMEOUT_MS: 6e5,
|
|
@@ -775,7 +775,7 @@ function validateConfig(config) {
|
|
|
775
775
|
function normalizeAndValidateConfig(config = {}) {
|
|
776
776
|
const normalizedConfig = deepMerge(
|
|
777
777
|
{
|
|
778
|
-
...
|
|
778
|
+
...DEFAULT_CONFIG2,
|
|
779
779
|
Router: {
|
|
780
780
|
default: ""
|
|
781
781
|
},
|
|
@@ -1404,6 +1404,7 @@ var CONTEXT_ALIGNMENT_PROMPT, ContextAlignmentService, contextAlignmentService;
|
|
|
1404
1404
|
var init_context_alignment = __esm({
|
|
1405
1405
|
"src/governance/context-alignment.ts"() {
|
|
1406
1406
|
"use strict";
|
|
1407
|
+
init_constants();
|
|
1407
1408
|
init_log();
|
|
1408
1409
|
init_message_ir();
|
|
1409
1410
|
init_anthropic();
|
|
@@ -1432,7 +1433,7 @@ Do not include markdown fences.`;
|
|
|
1432
1433
|
buildPrompt(text, previousModel, nextModel) {
|
|
1433
1434
|
return CONTEXT_ALIGNMENT_PROMPT.replace("{previousModel}", previousModel).replace("{nextModel}", nextModel).replace("{request}", text);
|
|
1434
1435
|
}
|
|
1435
|
-
async summarizeTransition(text, previousModel, nextModel, config, port =
|
|
1436
|
+
async summarizeTransition(text, previousModel, nextModel, config, port = DEFAULT_CONFIG2.PORT, fetchFn, apiKey, timeoutMs) {
|
|
1436
1437
|
if (!config.enabled || !config.summarizer_model || !text.trim()) {
|
|
1437
1438
|
return null;
|
|
1438
1439
|
}
|
|
@@ -1656,6 +1657,7 @@ var SemanticRouter, semanticRouter;
|
|
|
1656
1657
|
var init_semantic_router = __esm({
|
|
1657
1658
|
"src/governance/semantic-router.ts"() {
|
|
1658
1659
|
"use strict";
|
|
1660
|
+
init_constants();
|
|
1659
1661
|
init_log();
|
|
1660
1662
|
init_message_ir();
|
|
1661
1663
|
init_anthropic();
|
|
@@ -1714,7 +1716,7 @@ Return JSON only:
|
|
|
1714
1716
|
analyze(text, config) {
|
|
1715
1717
|
return this.analyzeEmbedding(text, config);
|
|
1716
1718
|
}
|
|
1717
|
-
async analyzeWithClassifier(text, config, port =
|
|
1719
|
+
async analyzeWithClassifier(text, config, port = DEFAULT_CONFIG2.PORT, fetchFn, apiKey, timeoutMs) {
|
|
1718
1720
|
if (!config?.enabled || config.mode !== "classifier" || !config.prototypes || Object.keys(config.prototypes).length === 0) {
|
|
1719
1721
|
return this.analyzeEmbedding(text, config);
|
|
1720
1722
|
}
|
|
@@ -1778,6 +1780,7 @@ var SHADOW_VERIFIER_PROMPT, ShadowSupervisor, shadowSupervisor;
|
|
|
1778
1780
|
var init_shadow_supervisor = __esm({
|
|
1779
1781
|
"src/governance/shadow-supervisor.ts"() {
|
|
1780
1782
|
"use strict";
|
|
1783
|
+
init_constants();
|
|
1781
1784
|
init_log();
|
|
1782
1785
|
init_message_ir();
|
|
1783
1786
|
init_anthropic();
|
|
@@ -1852,7 +1855,7 @@ If no issue is found, return:
|
|
|
1852
1855
|
}
|
|
1853
1856
|
});
|
|
1854
1857
|
}
|
|
1855
|
-
async inspectWithVerifier(payload, config, port =
|
|
1858
|
+
async inspectWithVerifier(payload, config, port = DEFAULT_CONFIG2.PORT, fetchFn, apiKey, timeoutMs) {
|
|
1856
1859
|
const text = extractText(payload).trim();
|
|
1857
1860
|
if (!config.enabled || !config.verifier_model || !text) {
|
|
1858
1861
|
return this.inspect(payload, config);
|
|
@@ -3527,7 +3530,7 @@ function isServiceRunning() {
|
|
|
3527
3530
|
function savePid(pid, port) {
|
|
3528
3531
|
const info = {
|
|
3529
3532
|
pid,
|
|
3530
|
-
port: port ??
|
|
3533
|
+
port: port ?? DEFAULT_CONFIG2.PORT,
|
|
3531
3534
|
startTime: (/* @__PURE__ */ new Date()).toISOString()
|
|
3532
3535
|
};
|
|
3533
3536
|
(0, import_fs4.writeFileSync)(PID_FILE, JSON.stringify(info, null, 2), "utf-8");
|
|
@@ -3537,7 +3540,7 @@ function readServiceInfo() {
|
|
|
3537
3540
|
try {
|
|
3538
3541
|
const content = (0, import_fs4.readFileSync)(PID_FILE, "utf-8").trim();
|
|
3539
3542
|
if (/^\d+$/.test(content)) {
|
|
3540
|
-
return { pid: parseInt(content, 10), port:
|
|
3543
|
+
return { pid: parseInt(content, 10), port: DEFAULT_CONFIG2.PORT, startTime: "" };
|
|
3541
3544
|
}
|
|
3542
3545
|
return JSON.parse(content);
|
|
3543
3546
|
} catch {
|
|
@@ -4130,6 +4133,7 @@ var init_intent = __esm({
|
|
|
4130
4133
|
"src/trigger/intent.ts"() {
|
|
4131
4134
|
"use strict";
|
|
4132
4135
|
import_lru_cache6 = require("lru-cache");
|
|
4136
|
+
init_constants();
|
|
4133
4137
|
init_log();
|
|
4134
4138
|
intentCache = new import_lru_cache6.LRUCache({
|
|
4135
4139
|
max: 500,
|
|
@@ -4198,7 +4202,7 @@ Important: Respond ONLY with the JSON, no additional text.`;
|
|
|
4198
4202
|
* @param fetchFn fetch 函数(用于发起 API 请求)
|
|
4199
4203
|
* @returns 意图识别结果
|
|
4200
4204
|
*/
|
|
4201
|
-
async detectIntent(text, config, port =
|
|
4205
|
+
async detectIntent(text, config, port = DEFAULT_CONFIG2.PORT, fetchFn, apiKey, timeoutMs) {
|
|
4202
4206
|
if (!config.llm_intent_recognition) {
|
|
4203
4207
|
return {
|
|
4204
4208
|
intent: "general",
|
|
@@ -4286,6 +4290,7 @@ var init_smart_router = __esm({
|
|
|
4286
4290
|
"src/trigger/smart-router.ts"() {
|
|
4287
4291
|
"use strict";
|
|
4288
4292
|
import_lru_cache7 = require("lru-cache");
|
|
4293
|
+
init_constants();
|
|
4289
4294
|
init_log();
|
|
4290
4295
|
init_message_ir();
|
|
4291
4296
|
init_anthropic();
|
|
@@ -4349,11 +4354,11 @@ Important:
|
|
|
4349
4354
|
*
|
|
4350
4355
|
* @param text 请求文本
|
|
4351
4356
|
* @param config SmartRouter 配置
|
|
4352
|
-
* @param port 本地服务端口(默认
|
|
4357
|
+
* @param port 本地服务端口(默认 5678)
|
|
4353
4358
|
* @param fetchFn 可注入的 fetch 函数(用于测试)
|
|
4354
4359
|
* @returns 选择结果,失败时返回 null
|
|
4355
4360
|
*/
|
|
4356
|
-
async selectModel(text, config, port =
|
|
4361
|
+
async selectModel(text, config, port = DEFAULT_CONFIG2.PORT, fetchFn, apiKey, timeoutMs) {
|
|
4357
4362
|
if (!config.enabled) {
|
|
4358
4363
|
return null;
|
|
4359
4364
|
}
|
|
@@ -4428,6 +4433,7 @@ var init_selector = __esm({
|
|
|
4428
4433
|
init_intent();
|
|
4429
4434
|
init_smart_router();
|
|
4430
4435
|
init_log();
|
|
4436
|
+
init_constants();
|
|
4431
4437
|
init_session_store();
|
|
4432
4438
|
init_semantic_router();
|
|
4433
4439
|
init_compile();
|
|
@@ -4484,7 +4490,7 @@ var init_selector = __esm({
|
|
|
4484
4490
|
* @param config 触发配置
|
|
4485
4491
|
* @returns 分析结果
|
|
4486
4492
|
*/
|
|
4487
|
-
async selectModel(req, config, port =
|
|
4493
|
+
async selectModel(req, config, port = DEFAULT_CONFIG2.PORT, smartRouterConfig, governanceConfig, apiKey, timeoutMs) {
|
|
4488
4494
|
const startTime = Date.now();
|
|
4489
4495
|
const appConfig = req.appConfig;
|
|
4490
4496
|
if (!config.enabled) {
|
|
@@ -4683,10 +4689,11 @@ var init_trigger = __esm({
|
|
|
4683
4689
|
init_selector();
|
|
4684
4690
|
init_analyzer();
|
|
4685
4691
|
init_log();
|
|
4692
|
+
init_constants();
|
|
4686
4693
|
TriggerRouter = class {
|
|
4687
4694
|
config = null;
|
|
4688
4695
|
appConfig = null;
|
|
4689
|
-
port =
|
|
4696
|
+
port = DEFAULT_CONFIG2.PORT;
|
|
4690
4697
|
smartRouterConfig = void 0;
|
|
4691
4698
|
governanceConfig = void 0;
|
|
4692
4699
|
apiKey;
|
|
@@ -4699,7 +4706,7 @@ var init_trigger = __esm({
|
|
|
4699
4706
|
init(appConfig) {
|
|
4700
4707
|
this.appConfig = appConfig;
|
|
4701
4708
|
this.config = appConfig.TriggerRouter || this.getDefaultConfig();
|
|
4702
|
-
this.port = appConfig.PORT ||
|
|
4709
|
+
this.port = appConfig.PORT || DEFAULT_CONFIG2.PORT;
|
|
4703
4710
|
this.smartRouterConfig = appConfig.SmartRouter;
|
|
4704
4711
|
this.governanceConfig = appConfig.Governance;
|
|
4705
4712
|
this.apiKey = appConfig.APIKEY;
|
|
@@ -5171,7 +5178,7 @@ async function run(options = {}) {
|
|
|
5171
5178
|
HOST = "127.0.0.1";
|
|
5172
5179
|
logWarn("\u26A0\uFE0F API key is not set. HOST is forced to 127.0.0.1.");
|
|
5173
5180
|
}
|
|
5174
|
-
const port = options.port ?? config.PORT ??
|
|
5181
|
+
const port = options.port ?? config.PORT ?? DEFAULT_CONFIG.PORT;
|
|
5175
5182
|
savePid(process.pid, port);
|
|
5176
5183
|
process.on("SIGINT", () => {
|
|
5177
5184
|
log("Received SIGINT, cleaning up...");
|
|
@@ -5882,7 +5889,7 @@ function decideSetupBranch(input2) {
|
|
|
5882
5889
|
ensureNoLegacyAction(legacyConfigAction);
|
|
5883
5890
|
return { kind: "reuse_current" };
|
|
5884
5891
|
}
|
|
5885
|
-
if (currentConfigAction === "overwrite") {
|
|
5892
|
+
if (currentConfigAction === "overwrite" || currentConfigAction === "fresh") {
|
|
5886
5893
|
return ensureLegacyFlow(detection, legacyConfigAction);
|
|
5887
5894
|
}
|
|
5888
5895
|
return invalidAction();
|
|
@@ -6083,50 +6090,58 @@ function readStructuredConfigFile(filePath) {
|
|
|
6083
6090
|
}
|
|
6084
6091
|
return import_js_yaml.default.load(content);
|
|
6085
6092
|
}
|
|
6086
|
-
async function
|
|
6087
|
-
const
|
|
6088
|
-
const
|
|
6089
|
-
|
|
6093
|
+
async function readLegacyConfig(deps = {}) {
|
|
6094
|
+
const baseHomeDir = deps.homeDir || (0, import_os3.homedir)();
|
|
6095
|
+
const exists = deps.exists || import_fs6.existsSync;
|
|
6096
|
+
const readConfig = deps.readConfig || readStructuredConfigFile;
|
|
6097
|
+
const overridePath = process.env.CTR_SETUP_LEGACY_CONFIG_PATH;
|
|
6098
|
+
const candidatePaths = overridePath ? [overridePath] : [
|
|
6099
|
+
(0, import_path6.join)(baseHomeDir, ".ccr", "config.yaml"),
|
|
6100
|
+
(0, import_path6.join)(baseHomeDir, ".claude-code-router", "config.yaml")
|
|
6101
|
+
];
|
|
6102
|
+
const legacyPath = candidatePaths.find((filePath) => exists(filePath));
|
|
6103
|
+
if (!legacyPath) {
|
|
6090
6104
|
return { kind: "missing" };
|
|
6091
6105
|
}
|
|
6092
6106
|
try {
|
|
6093
6107
|
return {
|
|
6094
6108
|
kind: "found",
|
|
6095
|
-
path:
|
|
6096
|
-
|
|
6097
|
-
config: readStructuredConfigFile(currentPath) ?? {}
|
|
6109
|
+
path: legacyPath,
|
|
6110
|
+
config: readConfig(legacyPath)
|
|
6098
6111
|
};
|
|
6099
6112
|
} catch (error) {
|
|
6100
6113
|
return {
|
|
6101
|
-
kind: "
|
|
6102
|
-
path:
|
|
6103
|
-
format: currentPath.endsWith(".json") ? "json" : currentPath.endsWith(".yml") ? "yml" : "yaml",
|
|
6114
|
+
kind: "read_error",
|
|
6115
|
+
path: legacyPath,
|
|
6104
6116
|
error: error instanceof Error ? error.message : String(error)
|
|
6105
6117
|
};
|
|
6106
6118
|
}
|
|
6107
6119
|
}
|
|
6108
|
-
async function
|
|
6109
|
-
const
|
|
6110
|
-
|
|
6120
|
+
async function readCurrentConfig() {
|
|
6121
|
+
const candidates = [CONFIG_FILE, CONFIG_FILE_YML, CONFIG_FILE_JSON];
|
|
6122
|
+
const currentPath = candidates.find((filePath) => (0, import_fs6.existsSync)(filePath));
|
|
6123
|
+
if (!currentPath) {
|
|
6111
6124
|
return { kind: "missing" };
|
|
6112
6125
|
}
|
|
6113
6126
|
try {
|
|
6114
6127
|
return {
|
|
6115
6128
|
kind: "found",
|
|
6116
|
-
path:
|
|
6117
|
-
|
|
6129
|
+
path: currentPath,
|
|
6130
|
+
format: currentPath.endsWith(".json") ? "json" : currentPath.endsWith(".yml") ? "yml" : "yaml",
|
|
6131
|
+
config: readStructuredConfigFile(currentPath) ?? {}
|
|
6118
6132
|
};
|
|
6119
6133
|
} catch (error) {
|
|
6120
6134
|
return {
|
|
6121
|
-
kind: "
|
|
6122
|
-
path:
|
|
6135
|
+
kind: "parse_error",
|
|
6136
|
+
path: currentPath,
|
|
6137
|
+
format: currentPath.endsWith(".json") ? "json" : currentPath.endsWith(".yml") ? "yml" : "yaml",
|
|
6123
6138
|
error: error instanceof Error ? error.message : String(error)
|
|
6124
6139
|
};
|
|
6125
6140
|
}
|
|
6126
6141
|
}
|
|
6127
6142
|
async function probeService() {
|
|
6128
|
-
const healthy = await waitForService(
|
|
6129
|
-
return healthy ? { kind: "self_healthy", port:
|
|
6143
|
+
const healthy = await waitForService(DEFAULT_CONFIG2.PORT, 500);
|
|
6144
|
+
return healthy ? { kind: "self_healthy", port: DEFAULT_CONFIG2.PORT } : { kind: "none" };
|
|
6130
6145
|
}
|
|
6131
6146
|
async function enterClaudeCode() {
|
|
6132
6147
|
const cliModule = await Promise.resolve().then(() => (init_cli(), cli_exports));
|
|
@@ -6161,7 +6176,10 @@ function mapValidCurrentConfigChoice(choice) {
|
|
|
6161
6176
|
if (choice === "overwrite" || choice === "\u68C0\u67E5\u5E76\u8C03\u6574\u5F53\u524D\u914D\u7F6E") {
|
|
6162
6177
|
return "overwrite";
|
|
6163
6178
|
}
|
|
6164
|
-
if (choice === "
|
|
6179
|
+
if (choice === "fresh" || choice === "\u653E\u5F03\u5F53\u524D\u914D\u7F6E\uFF0C\u91CD\u65B0\u5F00\u59CB") {
|
|
6180
|
+
return "fresh";
|
|
6181
|
+
}
|
|
6182
|
+
if (choice === "cancel") {
|
|
6165
6183
|
return "cancel";
|
|
6166
6184
|
}
|
|
6167
6185
|
throw new Error("invalid current config action");
|
|
@@ -6276,8 +6294,15 @@ function toDraftFromConfig(config) {
|
|
|
6276
6294
|
}
|
|
6277
6295
|
};
|
|
6278
6296
|
}
|
|
6297
|
+
function toSuggestedModelId(providerName, model, preset) {
|
|
6298
|
+
const presetDefinition = getProviderPreset(preset);
|
|
6299
|
+
if (presetDefinition?.suggested_id) {
|
|
6300
|
+
return presetDefinition.suggested_id;
|
|
6301
|
+
}
|
|
6302
|
+
const source = model || providerName || "model";
|
|
6303
|
+
return source.toLowerCase().replace(/[^a-z0-9]+/g, "_").replace(/^_+|_+$/g, "") || "model";
|
|
6304
|
+
}
|
|
6279
6305
|
async function buildFreshConfig(io) {
|
|
6280
|
-
const modelId = await io.input("\u9ED8\u8BA4\u6A21\u578B ID");
|
|
6281
6306
|
const connectMode = await io.choose("\u8FD9\u4E2A\u6A21\u578B\u63A5\u5230\u54EA\u91CC\uFF1F", ["\u4F7F\u7528\u5E38\u89C1\u63A5\u5165\u6A21\u677F", "\u624B\u52A8\u586B\u5199\u63A5\u53E3"]);
|
|
6282
6307
|
let preset = "custom";
|
|
6283
6308
|
let providerName = "provider";
|
|
@@ -6292,7 +6317,9 @@ async function buildFreshConfig(io) {
|
|
|
6292
6317
|
apiBaseUrl = await io.input("API Base URL");
|
|
6293
6318
|
}
|
|
6294
6319
|
const apiKey = await io.input("API Key");
|
|
6295
|
-
const
|
|
6320
|
+
const presetDefinition = getProviderPreset(preset);
|
|
6321
|
+
const model = await io.input("\u4E0A\u6E38\u6A21\u578B\u540D", presetDefinition?.default_model ?? "");
|
|
6322
|
+
const modelId = await io.input("\u9ED8\u8BA4\u6A21\u578B ID", toSuggestedModelId(providerName, model, preset));
|
|
6296
6323
|
const capabilityMode = await io.choose("\u662F\u5426\u914D\u7F6E capability \u63D0\u793A", ["\u4FDD\u6301\u9ED8\u8BA4", "\u914D\u7F6E capability \u63D0\u793A"]);
|
|
6297
6324
|
const draft = buildMinimalConfig({
|
|
6298
6325
|
providers: [
|
|
@@ -6364,7 +6391,7 @@ function createDefaultDeps(io = createConsoleIO()) {
|
|
|
6364
6391
|
executeStart,
|
|
6365
6392
|
executeReload: executeRestart,
|
|
6366
6393
|
executeRestart,
|
|
6367
|
-
verifyHealth: () => waitForService(
|
|
6394
|
+
verifyHealth: () => waitForService(DEFAULT_CONFIG2.PORT, 5e3),
|
|
6368
6395
|
enterClaudeCode,
|
|
6369
6396
|
io
|
|
6370
6397
|
};
|
|
@@ -6494,6 +6521,14 @@ __export(cli_exports, {
|
|
|
6494
6521
|
runClaudeCode: () => runClaudeCode
|
|
6495
6522
|
});
|
|
6496
6523
|
module.exports = __toCommonJS(cli_exports);
|
|
6524
|
+
function getPackageInfo() {
|
|
6525
|
+
const content = (0, import_fs7.readFileSync)(PACKAGE_JSON_PATH, "utf-8");
|
|
6526
|
+
const pkg = JSON.parse(content);
|
|
6527
|
+
return {
|
|
6528
|
+
name: pkg.name ?? "@peterwangze/claude-trigger-router",
|
|
6529
|
+
version: pkg.version ?? "unknown"
|
|
6530
|
+
};
|
|
6531
|
+
}
|
|
6497
6532
|
function getArgs() {
|
|
6498
6533
|
return process.argv.slice(2);
|
|
6499
6534
|
}
|
|
@@ -6531,7 +6566,7 @@ function getPort() {
|
|
|
6531
6566
|
}
|
|
6532
6567
|
} catch {
|
|
6533
6568
|
}
|
|
6534
|
-
return
|
|
6569
|
+
return DEFAULT_CONFIG2.PORT;
|
|
6535
6570
|
}
|
|
6536
6571
|
function isDaemonMode() {
|
|
6537
6572
|
return hasArg("--daemon", "-d");
|
|
@@ -6549,18 +6584,22 @@ Claude Trigger Router - \u667A\u80FD\u89E6\u53D1\u8DEF\u7531\u5668
|
|
|
6549
6584
|
stop \u505C\u6B62\u540E\u53F0\u670D\u52A1
|
|
6550
6585
|
restart \u91CD\u542F\u540E\u53F0\u670D\u52A1
|
|
6551
6586
|
status \u67E5\u770B\u670D\u52A1\u8FD0\u884C\u72B6\u6001\uFF08PID\u3001\u7AEF\u53E3\u3001\u542F\u52A8\u65F6\u95F4\uFF09
|
|
6587
|
+
version \u67E5\u770B\u5F53\u524D\u5B89\u88C5\u7248\u672C\u4E0E\u5305\u4FE1\u606F
|
|
6588
|
+
upgrade \u67E5\u770B\u5347\u7EA7\u5230\u6700\u65B0 npm \u7248\u672C\u7684\u6307\u5F15
|
|
6552
6589
|
code \u901A\u8FC7\u8DEF\u7531\u5668\u8FD0\u884C Claude Code\uFF08\u9700\u5148\u542F\u52A8\u670D\u52A1\uFF09
|
|
6553
6590
|
ui \u6253\u5F00\u7BA1\u7406 API \u8BF4\u660E\u9875\uFF08Web UI \u5F00\u53D1\u4E2D\uFF09
|
|
6554
6591
|
help \u663E\u793A\u6B64\u5E2E\u52A9\u4FE1\u606F
|
|
6555
6592
|
|
|
6556
6593
|
\u9009\u9879\uFF1A
|
|
6557
|
-
--port, -p \u6307\u5B9A\u76D1\u542C\u7AEF\u53E3\uFF08\u9ED8\u8BA4\
|
|
6594
|
+
--port, -p \u6307\u5B9A\u76D1\u542C\u7AEF\u53E3\uFF08\u9ED8\u8BA4\uFF1A5678\uFF09
|
|
6558
6595
|
--daemon, -d \u4EE5\u540E\u53F0\u65B9\u5F0F\u8FD0\u884C\uFF08\u914D\u5408 start/restart \u4F7F\u7528\uFF09
|
|
6559
6596
|
--force \u5F3A\u5236\u8986\u76D6\u5DF2\u6709\u914D\u7F6E\uFF08\u914D\u5408 init \u4F7F\u7528\uFF09
|
|
6560
6597
|
|
|
6561
6598
|
\u4F7F\u7528\u793A\u4F8B\uFF1A
|
|
6562
6599
|
ctr setup # \u590D\u7528\u5F53\u524D\u914D\u7F6E / \u8FC1\u79FB\u65E7\u914D\u7F6E / \u65B0\u5EFA\u6700\u5C0F\u914D\u7F6E
|
|
6563
6600
|
ctr init # \u521D\u59CB\u5316\u6700\u5C0F\u914D\u7F6E\u6A21\u677F
|
|
6601
|
+
ctr version # \u67E5\u770B\u5F53\u524D\u5B89\u88C5\u7248\u672C
|
|
6602
|
+
ctr upgrade # \u67E5\u770B\u5347\u7EA7\u5230\u6700\u65B0\u7248\u672C\u7684\u547D\u4EE4
|
|
6564
6603
|
ctr start # \u524D\u53F0\u542F\u52A8\uFF08\u63A8\u8350\u9996\u6B21\u4F7F\u7528\uFF0C\u4FBF\u4E8E\u67E5\u770B\u65E5\u5FD7\uFF09
|
|
6565
6604
|
ctr start --daemon # \u540E\u53F0\u542F\u52A8
|
|
6566
6605
|
ctr status # \u67E5\u770B\u670D\u52A1\u72B6\u6001
|
|
@@ -6577,6 +6616,58 @@ Claude Trigger Router - \u667A\u80FD\u89E6\u53D1\u8DEF\u7531\u5668
|
|
|
6577
6616
|
\u66F4\u591A\u4FE1\u606F\uFF1Ahttps://github.com/peterwangze/claude-trigger-router
|
|
6578
6617
|
`);
|
|
6579
6618
|
}
|
|
6619
|
+
async function getLatestPackageVersion(timeoutMs = 1500) {
|
|
6620
|
+
try {
|
|
6621
|
+
const response = await fetch(PACKAGE_REGISTRY_LATEST_URL, {
|
|
6622
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
6623
|
+
});
|
|
6624
|
+
if (!response.ok) {
|
|
6625
|
+
return null;
|
|
6626
|
+
}
|
|
6627
|
+
const payload = await response.json();
|
|
6628
|
+
return typeof payload.version === "string" ? payload.version : null;
|
|
6629
|
+
} catch {
|
|
6630
|
+
return null;
|
|
6631
|
+
}
|
|
6632
|
+
}
|
|
6633
|
+
function isNewerVersion(current, latest) {
|
|
6634
|
+
const currentParts = current.split(".").map((part) => Number.parseInt(part, 10));
|
|
6635
|
+
const latestParts = latest.split(".").map((part) => Number.parseInt(part, 10));
|
|
6636
|
+
const length = Math.max(currentParts.length, latestParts.length);
|
|
6637
|
+
for (let index = 0; index < length; index += 1) {
|
|
6638
|
+
const currentValue = Number.isFinite(currentParts[index]) ? currentParts[index] : 0;
|
|
6639
|
+
const latestValue = Number.isFinite(latestParts[index]) ? latestParts[index] : 0;
|
|
6640
|
+
if (latestValue > currentValue) {
|
|
6641
|
+
return true;
|
|
6642
|
+
}
|
|
6643
|
+
if (latestValue < currentValue) {
|
|
6644
|
+
return false;
|
|
6645
|
+
}
|
|
6646
|
+
}
|
|
6647
|
+
return false;
|
|
6648
|
+
}
|
|
6649
|
+
async function printVersion() {
|
|
6650
|
+
const pkg = getPackageInfo();
|
|
6651
|
+
const latestVersion = await getLatestPackageVersion();
|
|
6652
|
+
console.log(`Package: ${pkg.name}`);
|
|
6653
|
+
console.log(`Version: ${pkg.version}`);
|
|
6654
|
+
console.log(`Latest: ${latestVersion ?? "unavailable"}`);
|
|
6655
|
+
if (latestVersion && isNewerVersion(pkg.version, latestVersion)) {
|
|
6656
|
+
console.log(`Upgrade: npm install -g ${pkg.name}@latest`);
|
|
6657
|
+
}
|
|
6658
|
+
console.log(`NPM: ${PACKAGE_PAGE_URL}`);
|
|
6659
|
+
}
|
|
6660
|
+
function printUpgradeGuidance() {
|
|
6661
|
+
const pkg = getPackageInfo();
|
|
6662
|
+
console.log(`\u5F53\u524D\u5B89\u88C5\u7248\u672C\uFF1A${pkg.version}`);
|
|
6663
|
+
console.log(`\u5305\u540D\uFF1A${pkg.name}`);
|
|
6664
|
+
console.log("\u5347\u7EA7\u5230\u6700\u65B0\u7248\u672C\uFF1A");
|
|
6665
|
+
console.log(` npm install -g ${pkg.name}@latest`);
|
|
6666
|
+
console.log("\u8BF7\u5728\u5F53\u524D ctr \u8FDB\u7A0B\u5916\u6267\u884C\u5347\u7EA7\u547D\u4EE4\uFF0C\u907F\u514D\u81EA\u5347\u7EA7\u65F6\u5360\u7528\u5F53\u524D\u6587\u4EF6\u3002");
|
|
6667
|
+
console.log("\u5982\u679C\u4F60\u6700\u521D\u662F\u901A\u8FC7 GitHub \u6E90\u5B89\u88C5\uFF0C\u8BF7\u7EE7\u7EED\u4F7F\u7528\u539F\u5B89\u88C5\u6765\u6E90\uFF0C\u5F53\u524D\u547D\u4EE4\u4E0D\u4F1A\u81EA\u52A8\u5207\u6362\u6765\u6E90\u3002");
|
|
6668
|
+
console.log("\u5168\u5C40\u5B89\u88C5\u5728\u67D0\u4E9B\u73AF\u5883\u4E0B\u53EF\u80FD\u9700\u8981\u7BA1\u7406\u5458/root \u6743\u9650\u3002");
|
|
6669
|
+
console.log(`NPM: ${PACKAGE_PAGE_URL}`);
|
|
6670
|
+
}
|
|
6580
6671
|
function initConfig2() {
|
|
6581
6672
|
const force = hasArg("--force");
|
|
6582
6673
|
const existingConfig = [CONFIG_FILE, CONFIG_FILE_YML, CONFIG_FILE_JSON].find(import_fs7.existsSync);
|
|
@@ -6763,6 +6854,12 @@ async function main() {
|
|
|
6763
6854
|
case "status":
|
|
6764
6855
|
showStatus();
|
|
6765
6856
|
break;
|
|
6857
|
+
case "version":
|
|
6858
|
+
await printVersion();
|
|
6859
|
+
break;
|
|
6860
|
+
case "upgrade":
|
|
6861
|
+
printUpgradeGuidance();
|
|
6862
|
+
break;
|
|
6766
6863
|
case "restart":
|
|
6767
6864
|
restartService();
|
|
6768
6865
|
break;
|
|
@@ -6785,7 +6882,7 @@ async function main() {
|
|
|
6785
6882
|
process.exit(command ? 1 : 0);
|
|
6786
6883
|
}
|
|
6787
6884
|
}
|
|
6788
|
-
var import_child_process2, import_path7, import_openurl, import_fs7;
|
|
6885
|
+
var import_child_process2, import_path7, import_openurl, import_fs7, PACKAGE_JSON_PATH, PACKAGE_PAGE_URL, PACKAGE_REGISTRY_LATEST_URL;
|
|
6789
6886
|
var init_cli = __esm({
|
|
6790
6887
|
"src/cli.ts"() {
|
|
6791
6888
|
import_child_process2 = require("child_process");
|
|
@@ -6797,6 +6894,9 @@ var init_cli = __esm({
|
|
|
6797
6894
|
init_constants();
|
|
6798
6895
|
init_service_health();
|
|
6799
6896
|
init_setup2();
|
|
6897
|
+
PACKAGE_JSON_PATH = (0, import_path7.join)(__dirname, "..", "package.json");
|
|
6898
|
+
PACKAGE_PAGE_URL = "https://www.npmjs.com/package/@peterwangze/claude-trigger-router";
|
|
6899
|
+
PACKAGE_REGISTRY_LATEST_URL = "https://registry.npmjs.org/@peterwangze%2Fclaude-trigger-router/latest";
|
|
6800
6900
|
if (process.env.CTR_SKIP_MAIN !== "1") {
|
|
6801
6901
|
main().catch((error) => {
|
|
6802
6902
|
console.error("Error:", error);
|