@peterwangze/claude-trigger-router 1.12.0 → 1.13.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 +11 -7
- package/config/trigger.smart-router.advanced.yaml +214 -0
- package/config/trigger.smart-router.yaml +21 -138
- package/dist/cli.js +358 -0
- package/dist/cli.js.map +4 -4
- package/docs/configuration-guide.md +7 -2
- package/docs/release-notes-v1.13.0.md +49 -0
- package/docs/releasing.md +10 -2
- package/package.json +2 -1
package/dist/cli.js
CHANGED
|
@@ -14059,6 +14059,8 @@ function createDefaultDeps(io = createConsoleIO()) {
|
|
|
14059
14059
|
}
|
|
14060
14060
|
function printRoutingNextSteps(io) {
|
|
14061
14061
|
io.info("\u4F60\u53EF\u4EE5\u6309\u9700\u7EE7\u7EED\u914D\u7F6E\u8DEF\u7531\u80FD\u529B\uFF1A");
|
|
14062
|
+
io.info(' - \u5148\u8FD0\u884C ctr doctor --route-preview --route-text "\u4F60\u7684\u8BF7\u6C42"\uFF0C\u786E\u8BA4\u672C\u6B21\u4F1A\u547D\u4E2D\u54EA\u4E2A\u69FD\u4F4D\u6216 SmartRouter \u8DEF\u5F84');
|
|
14063
|
+
io.info(" - \u57FA\u7840\u8DEF\u7531\u987A\u5E8F\uFF1A\u663E\u5F0F\u4E0A\u6E38\u6A21\u578B -> longContext -> background -> think -> webSearch -> default");
|
|
14062
14064
|
io.info(" - SmartRouter.rules\uFF1A\u9002\u5408\u9AD8\u786E\u5B9A\u6027\u4EFB\u52A1\uFF0C\u628A\u67B6\u6784\u8BBE\u8BA1\u3001\u4EE3\u7801\u5BA1\u67E5\u7B49\u8BF7\u6C42\u56FA\u5B9A\u5207\u5230\u6307\u5B9A\u6A21\u578B");
|
|
14063
14065
|
io.info(" - SmartRouter candidates\uFF1A\u9002\u5408\u6A21\u7CCA\u4EFB\u52A1\uFF0C\u5728\u5019\u9009\u6A21\u578B\u4E4B\u95F4\u81EA\u52A8\u9009\u62E9\u66F4\u5408\u9002\u7684\u6A21\u578B");
|
|
14064
14066
|
io.info(" - \u914D\u7F6E\u6A21\u677F\u53C2\u8003\uFF1Aconfig/trigger.advanced.yaml");
|
|
@@ -14244,6 +14246,294 @@ var init_setup2 = __esm({
|
|
|
14244
14246
|
}
|
|
14245
14247
|
});
|
|
14246
14248
|
|
|
14249
|
+
// src/router/route-preview.ts
|
|
14250
|
+
function resolveDisplayModel(config, ref) {
|
|
14251
|
+
if (!ref) {
|
|
14252
|
+
return {};
|
|
14253
|
+
}
|
|
14254
|
+
const resolved = resolveModelReference(config, ref);
|
|
14255
|
+
return {
|
|
14256
|
+
model: ref,
|
|
14257
|
+
resolved
|
|
14258
|
+
};
|
|
14259
|
+
}
|
|
14260
|
+
function extractRuleMatch(text, rules) {
|
|
14261
|
+
const sortedRules = rules.filter((rule) => rule.enabled !== false).sort((a, b) => (b.priority || 0) - (a.priority || 0));
|
|
14262
|
+
for (const rule of sortedRules) {
|
|
14263
|
+
for (const pattern of rule.patterns ?? []) {
|
|
14264
|
+
const result = patternMatcher.match(text, pattern);
|
|
14265
|
+
if (!result.matched) {
|
|
14266
|
+
continue;
|
|
14267
|
+
}
|
|
14268
|
+
const detail = result.matchedKeyword ? `keyword "${result.matchedKeyword}"` : result.regexMatch ? `regex "${pattern.pattern}"` : pattern.type;
|
|
14269
|
+
return { rule, detail };
|
|
14270
|
+
}
|
|
14271
|
+
}
|
|
14272
|
+
return void 0;
|
|
14273
|
+
}
|
|
14274
|
+
function buildSemanticCandidates(rules, config) {
|
|
14275
|
+
const defaultThreshold = config.semantic?.threshold;
|
|
14276
|
+
const prototypes = config.semantic?.prototypes ?? {};
|
|
14277
|
+
return rules.filter((rule) => rule.enabled !== false).map((rule) => {
|
|
14278
|
+
const prototype = rule.semantic_profile?.prototype ?? prototypes[rule.name] ?? rule.description;
|
|
14279
|
+
if (!prototype || rule.semantic_profile?.enabled === false) {
|
|
14280
|
+
return void 0;
|
|
14281
|
+
}
|
|
14282
|
+
return {
|
|
14283
|
+
intent: rule.name,
|
|
14284
|
+
prototype,
|
|
14285
|
+
threshold: rule.semantic_profile?.threshold ?? defaultThreshold,
|
|
14286
|
+
rule
|
|
14287
|
+
};
|
|
14288
|
+
}).filter((item) => Boolean(item));
|
|
14289
|
+
}
|
|
14290
|
+
function previewBasicRouter(config, input3) {
|
|
14291
|
+
const steps = [];
|
|
14292
|
+
const warnings = [];
|
|
14293
|
+
const registry = buildModelRegistry(config);
|
|
14294
|
+
const tokenCount = input3.tokenCount ?? 0;
|
|
14295
|
+
const longContextThreshold = config.Router.longContextThreshold || 6e4;
|
|
14296
|
+
const explicit = resolveModelReference(config, input3.model);
|
|
14297
|
+
if (explicit && explicit.includes(",")) {
|
|
14298
|
+
steps.push({
|
|
14299
|
+
label: "Explicit model",
|
|
14300
|
+
status: "matched",
|
|
14301
|
+
detail: `\u8BF7\u6C42\u6A21\u578B "${input3.model}" \u5DF2\u89E3\u6790\u4E3A\u4E0A\u6E38\u5F15\u7528\uFF0C\u57FA\u7840\u69FD\u4F4D\u4E0D\u4F1A\u518D\u8986\u76D6\u3002`
|
|
14302
|
+
});
|
|
14303
|
+
return {
|
|
14304
|
+
input: input3,
|
|
14305
|
+
finalModel: explicit,
|
|
14306
|
+
finalModelRef: input3.model,
|
|
14307
|
+
source: "explicit_model",
|
|
14308
|
+
steps,
|
|
14309
|
+
warnings
|
|
14310
|
+
};
|
|
14311
|
+
}
|
|
14312
|
+
if (tokenCount > longContextThreshold && config.Router.longContext) {
|
|
14313
|
+
const model = resolveDisplayModel(config, config.Router.longContext);
|
|
14314
|
+
steps.push({
|
|
14315
|
+
label: "Router.longContext",
|
|
14316
|
+
status: "matched",
|
|
14317
|
+
detail: `tokenCount ${tokenCount} > threshold ${longContextThreshold}\uFF0C\u4F18\u5148\u4F7F\u7528\u957F\u4E0A\u4E0B\u6587\u69FD\u4F4D\u3002`
|
|
14318
|
+
});
|
|
14319
|
+
return {
|
|
14320
|
+
input: input3,
|
|
14321
|
+
finalModel: model.resolved,
|
|
14322
|
+
finalModelRef: model.model,
|
|
14323
|
+
source: "basic_long_context",
|
|
14324
|
+
steps,
|
|
14325
|
+
warnings
|
|
14326
|
+
};
|
|
14327
|
+
}
|
|
14328
|
+
steps.push({
|
|
14329
|
+
label: "Router.longContext",
|
|
14330
|
+
status: config.Router.longContext ? "info" : "skipped",
|
|
14331
|
+
detail: config.Router.longContext ? `\u5F53\u524D tokenCount ${tokenCount} \u672A\u8D85\u8FC7 threshold ${longContextThreshold}\uFF1B\u771F\u5B9E\u8FD0\u884C\u8FD8\u4F1A\u5728\u6700\u7EC8\u5B9A\u6A21\u540E\u68C0\u67E5 safe_input/context_window\u3002` : "\u672A\u914D\u7F6E Router.longContext\uFF0C\u5927\u4E0A\u4E0B\u6587\u8BF7\u6C42\u4F1A\u56DE\u5230\u5F53\u524D\u9009\u4E2D\u6A21\u578B\u3002"
|
|
14332
|
+
});
|
|
14333
|
+
if (input3.model?.startsWith("claude-3-5-haiku") && config.Router.background) {
|
|
14334
|
+
const model = resolveDisplayModel(config, config.Router.background);
|
|
14335
|
+
steps.push({
|
|
14336
|
+
label: "Router.background",
|
|
14337
|
+
status: "matched",
|
|
14338
|
+
detail: "\u8BF7\u6C42\u6A21\u578B\u4EE5 claude-3-5-haiku \u5F00\u5934\uFF0C\u6309\u5F53\u524D\u57FA\u7840\u8DEF\u7531\u5B9E\u73B0\u8BC6\u522B\u4E3A\u540E\u53F0\u8BF7\u6C42\u3002"
|
|
14339
|
+
});
|
|
14340
|
+
return {
|
|
14341
|
+
input: input3,
|
|
14342
|
+
finalModel: model.resolved,
|
|
14343
|
+
finalModelRef: model.model,
|
|
14344
|
+
source: "basic_background",
|
|
14345
|
+
steps,
|
|
14346
|
+
warnings
|
|
14347
|
+
};
|
|
14348
|
+
}
|
|
14349
|
+
steps.push({
|
|
14350
|
+
label: "Router.background",
|
|
14351
|
+
status: config.Router.background ? "info" : "skipped",
|
|
14352
|
+
detail: config.Router.background ? "\u4EC5\u5F53\u8BF7\u6C42\u6A21\u578B\u4EE5 claude-3-5-haiku \u5F00\u5934\u65F6\u547D\u4E2D\uFF1B\u5982\u679C Claude Code \u540E\u53F0\u6A21\u578B\u6807\u8BC6\u53D8\u5316\uFF0C\u9700\u8981\u91CD\u65B0\u6821\u51C6\u3002" : "\u672A\u914D\u7F6E Router.background\u3002"
|
|
14353
|
+
});
|
|
14354
|
+
if (input3.thinking && config.Router.think) {
|
|
14355
|
+
const model = resolveDisplayModel(config, config.Router.think);
|
|
14356
|
+
steps.push({
|
|
14357
|
+
label: "Router.think",
|
|
14358
|
+
status: "matched",
|
|
14359
|
+
detail: "\u8BF7\u6C42\u5305\u542B thinking\uFF0C\u4F7F\u7528\u601D\u8003\u69FD\u4F4D\u3002"
|
|
14360
|
+
});
|
|
14361
|
+
return {
|
|
14362
|
+
input: input3,
|
|
14363
|
+
finalModel: model.resolved,
|
|
14364
|
+
finalModelRef: model.model,
|
|
14365
|
+
source: "basic_thinking",
|
|
14366
|
+
steps,
|
|
14367
|
+
warnings
|
|
14368
|
+
};
|
|
14369
|
+
}
|
|
14370
|
+
steps.push({
|
|
14371
|
+
label: "Router.think",
|
|
14372
|
+
status: config.Router.think ? "info" : "skipped",
|
|
14373
|
+
detail: config.Router.think ? "\u672C\u6B21\u672A\u58F0\u660E thinking\uFF1B\u5982\u679C\u540C\u65F6\u8D85\u8FC7 longContext threshold\uFF0C\u957F\u4E0A\u4E0B\u6587\u4F1A\u5148\u4E8E thinking \u547D\u4E2D\u3002" : "\u672A\u914D\u7F6E Router.think\u3002"
|
|
14374
|
+
});
|
|
14375
|
+
if (input3.webSearch && config.Router.webSearch) {
|
|
14376
|
+
const model = resolveDisplayModel(config, config.Router.webSearch);
|
|
14377
|
+
steps.push({
|
|
14378
|
+
label: "Router.webSearch",
|
|
14379
|
+
status: "matched",
|
|
14380
|
+
detail: "\u8BF7\u6C42\u5305\u542B web_search \u5DE5\u5177\uFF0C\u4F7F\u7528\u8054\u7F51\u641C\u7D22\u69FD\u4F4D\u3002"
|
|
14381
|
+
});
|
|
14382
|
+
return {
|
|
14383
|
+
input: input3,
|
|
14384
|
+
finalModel: model.resolved,
|
|
14385
|
+
finalModelRef: model.model,
|
|
14386
|
+
source: "basic_web_search",
|
|
14387
|
+
steps,
|
|
14388
|
+
warnings
|
|
14389
|
+
};
|
|
14390
|
+
}
|
|
14391
|
+
steps.push({
|
|
14392
|
+
label: "Router.webSearch",
|
|
14393
|
+
status: config.Router.webSearch ? "info" : "skipped",
|
|
14394
|
+
detail: config.Router.webSearch ? "\u672C\u6B21\u672A\u58F0\u660E web_search\uFF1B\u5982\u679C\u540C\u65F6\u8D85\u8FC7 longContext threshold\uFF0C\u957F\u4E0A\u4E0B\u6587\u4F1A\u5148\u4E8E webSearch \u547D\u4E2D\u3002" : "\u672A\u914D\u7F6E Router.webSearch\u3002"
|
|
14395
|
+
});
|
|
14396
|
+
const defaultModel = resolveDisplayModel(config, config.Router.default);
|
|
14397
|
+
if (!defaultModel.resolved || !getCompiledModelRef(config, defaultModel.resolved)) {
|
|
14398
|
+
warnings.push(`Router.default "${config.Router.default}" \u672A\u89E3\u6790\u5230\u53EF\u7528\u6A21\u578B\u3002`);
|
|
14399
|
+
}
|
|
14400
|
+
steps.push({
|
|
14401
|
+
label: "Router.default",
|
|
14402
|
+
status: defaultModel.resolved ? "matched" : "warning",
|
|
14403
|
+
detail: defaultModel.resolved ? "\u524D\u7F6E\u69FD\u4F4D\u5747\u672A\u547D\u4E2D\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u6A21\u578B\u3002" : "Router.default \u672A\u89E3\u6790\u5230\u53EF\u7528\u6A21\u578B\u3002"
|
|
14404
|
+
});
|
|
14405
|
+
if (defaultModel.model && !registry.modelMap[defaultModel.model] && !defaultModel.model.includes(",")) {
|
|
14406
|
+
warnings.push(`Router.default "${defaultModel.model}" \u4E0D\u5728 Models/Providers/Registration \u4E2D\u3002`);
|
|
14407
|
+
}
|
|
14408
|
+
return {
|
|
14409
|
+
input: input3,
|
|
14410
|
+
finalModel: defaultModel.resolved,
|
|
14411
|
+
finalModelRef: defaultModel.model,
|
|
14412
|
+
source: defaultModel.resolved ? "basic_default" : "unresolved",
|
|
14413
|
+
steps,
|
|
14414
|
+
warnings
|
|
14415
|
+
};
|
|
14416
|
+
}
|
|
14417
|
+
function previewRoute(config, input3) {
|
|
14418
|
+
const smartRouterConfig = deriveRuntimeSmartRouterConfig(config, config);
|
|
14419
|
+
const text = input3.text.trim();
|
|
14420
|
+
const smartRouterEnabled = Boolean(smartRouterConfig?.enabled);
|
|
14421
|
+
const rules = smartRouterConfig?.rules ?? [];
|
|
14422
|
+
if (smartRouterEnabled && smartRouterConfig && text) {
|
|
14423
|
+
const ruleMatch = extractRuleMatch(text, rules);
|
|
14424
|
+
if (ruleMatch) {
|
|
14425
|
+
const model = resolveDisplayModel(config, ruleMatch.rule.model);
|
|
14426
|
+
return {
|
|
14427
|
+
input: input3,
|
|
14428
|
+
finalModel: model.resolved,
|
|
14429
|
+
finalModelRef: model.model,
|
|
14430
|
+
source: "smart_rule",
|
|
14431
|
+
confidence: 1,
|
|
14432
|
+
ruleName: ruleMatch.rule.name,
|
|
14433
|
+
steps: [
|
|
14434
|
+
{
|
|
14435
|
+
label: "SmartRouter.rules",
|
|
14436
|
+
status: "matched",
|
|
14437
|
+
detail: `\u547D\u4E2D\u89C4\u5219 "${ruleMatch.rule.name}"\uFF08${ruleMatch.detail}\uFF09\uFF0C\u4F1A\u5728\u57FA\u7840 Router \u524D\u9009\u5B9A\u6A21\u578B\u3002`
|
|
14438
|
+
}
|
|
14439
|
+
],
|
|
14440
|
+
warnings: []
|
|
14441
|
+
};
|
|
14442
|
+
}
|
|
14443
|
+
const semanticCandidates = buildSemanticCandidates(rules, smartRouterConfig);
|
|
14444
|
+
if (smartRouterConfig.semantic?.enabled && smartRouterConfig.semantic.mode !== "classifier" && semanticCandidates.length) {
|
|
14445
|
+
const result = semanticRouter.analyzeCandidates(
|
|
14446
|
+
text,
|
|
14447
|
+
semanticCandidates.map((candidate) => ({
|
|
14448
|
+
intent: candidate.intent,
|
|
14449
|
+
prototype: candidate.prototype,
|
|
14450
|
+
threshold: candidate.threshold
|
|
14451
|
+
})),
|
|
14452
|
+
smartRouterConfig.semantic.threshold
|
|
14453
|
+
);
|
|
14454
|
+
if (result) {
|
|
14455
|
+
const candidate = semanticCandidates.find((item) => item.intent === result.intent);
|
|
14456
|
+
const model = resolveDisplayModel(config, candidate?.rule.model);
|
|
14457
|
+
return {
|
|
14458
|
+
input: input3,
|
|
14459
|
+
finalModel: model.resolved,
|
|
14460
|
+
finalModelRef: model.model,
|
|
14461
|
+
source: "semantic_match",
|
|
14462
|
+
confidence: result.confidence,
|
|
14463
|
+
ruleName: result.intent,
|
|
14464
|
+
steps: [
|
|
14465
|
+
{
|
|
14466
|
+
label: "SmartRouter.semantic",
|
|
14467
|
+
status: "matched",
|
|
14468
|
+
detail: `\u8BED\u4E49 prototype \u547D\u4E2D "${result.intent}"\uFF0Cconfidence=${result.confidence.toFixed(3)}\u3002`
|
|
14469
|
+
}
|
|
14470
|
+
],
|
|
14471
|
+
warnings: []
|
|
14472
|
+
};
|
|
14473
|
+
}
|
|
14474
|
+
}
|
|
14475
|
+
if (smartRouterConfig.router_model && (smartRouterConfig.candidates?.length ?? 0) >= 2) {
|
|
14476
|
+
const model = resolveDisplayModel(config, smartRouterConfig.router_model);
|
|
14477
|
+
return {
|
|
14478
|
+
input: input3,
|
|
14479
|
+
finalModel: void 0,
|
|
14480
|
+
finalModelRef: void 0,
|
|
14481
|
+
source: "smart_router_pending",
|
|
14482
|
+
steps: [
|
|
14483
|
+
{
|
|
14484
|
+
label: "SmartRouter.router_model",
|
|
14485
|
+
status: "info",
|
|
14486
|
+
detail: `\u672A\u547D\u4E2D\u786E\u5B9A\u6027\u89C4\u5219\uFF1B\u771F\u5B9E\u8BF7\u6C42\u4F1A\u5148\u8C03\u7528 router_model "${smartRouterConfig.router_model}"\uFF08${model.resolved ?? "\u672A\u89E3\u6790"}\uFF09\u5728 ${smartRouterConfig.candidates?.length ?? 0} \u4E2A\u5019\u9009\u4E2D\u9009\u62E9\uFF0C\u4F1A\u589E\u52A0\u9996\u5305\u524D\u7B49\u5F85\u3002`
|
|
14487
|
+
},
|
|
14488
|
+
{
|
|
14489
|
+
label: "Basic Router fallback",
|
|
14490
|
+
status: "info",
|
|
14491
|
+
detail: "\u5982\u679C SmartRouter \u8C03\u7528\u5931\u8D25\u6216\u8FD4\u56DE\u65E0\u6548\u6A21\u578B\uFF0C\u8BF7\u6C42\u4F1A\u7EE7\u7EED\u8FDB\u5165\u57FA\u7840 Router fallback\u3002"
|
|
14492
|
+
}
|
|
14493
|
+
],
|
|
14494
|
+
warnings: [
|
|
14495
|
+
"doctor route preview \u4E0D\u4F1A\u8C03\u7528 SmartRouter LLM\uFF1B\u8FD9\u91CC\u5C55\u793A\u7684\u662F\u5F85\u51B3\u7B56\u8DEF\u5F84\uFF0C\u4E0D\u4EE3\u8868\u6700\u7EC8\u5019\u9009\u9009\u62E9\u3002"
|
|
14496
|
+
]
|
|
14497
|
+
};
|
|
14498
|
+
}
|
|
14499
|
+
}
|
|
14500
|
+
const basic = previewBasicRouter(config, input3);
|
|
14501
|
+
if (smartRouterEnabled) {
|
|
14502
|
+
basic.steps.unshift({
|
|
14503
|
+
label: "SmartRouter",
|
|
14504
|
+
status: "skipped",
|
|
14505
|
+
detail: "SmartRouter \u5DF2\u542F\u7528\uFF0C\u4F46\u672C\u6B21\u672A\u547D\u4E2D\u89C4\u5219/\u8BED\u4E49\uFF0C\u4E14\u6CA1\u6709\u53EF\u7528 router_model+candidates \u515C\u5E95\u3002"
|
|
14506
|
+
});
|
|
14507
|
+
}
|
|
14508
|
+
return basic;
|
|
14509
|
+
}
|
|
14510
|
+
function formatRoutePreview(result) {
|
|
14511
|
+
const lines = [
|
|
14512
|
+
`\u8DEF\u7531\u9884\u6F14\uFF1A${result.input.text || "<empty>"}`,
|
|
14513
|
+
`\u9884\u8BA1\u6765\u6E90\uFF1A${result.source}${result.ruleName ? ` (${result.ruleName})` : ""}`,
|
|
14514
|
+
`\u9884\u8BA1\u6A21\u578B\uFF1A${result.finalModelRef ?? "-"}${result.finalModel ? ` -> ${result.finalModel}` : ""}`
|
|
14515
|
+
];
|
|
14516
|
+
if (result.confidence !== void 0) {
|
|
14517
|
+
lines.push(`\u7F6E\u4FE1\u5EA6\uFF1A${result.confidence.toFixed(3)}`);
|
|
14518
|
+
}
|
|
14519
|
+
for (const step of result.steps) {
|
|
14520
|
+
lines.push(`- [${step.status}] ${step.label}: ${step.detail}`);
|
|
14521
|
+
}
|
|
14522
|
+
for (const warning of result.warnings) {
|
|
14523
|
+
lines.push(`! ${warning}`);
|
|
14524
|
+
}
|
|
14525
|
+
return lines;
|
|
14526
|
+
}
|
|
14527
|
+
var init_route_preview = __esm({
|
|
14528
|
+
"src/router/route-preview.ts"() {
|
|
14529
|
+
"use strict";
|
|
14530
|
+
init_compile();
|
|
14531
|
+
init_matcher();
|
|
14532
|
+
init_config();
|
|
14533
|
+
init_semantic_router();
|
|
14534
|
+
}
|
|
14535
|
+
});
|
|
14536
|
+
|
|
14247
14537
|
// src/doctor/index.ts
|
|
14248
14538
|
function collectCompatibilityPreviewDiagnostics(model) {
|
|
14249
14539
|
const registry = buildModelRegistry({
|
|
@@ -14311,6 +14601,18 @@ function collectCompatibilityPreviewDiagnostics(model) {
|
|
|
14311
14601
|
function hasArg(flag) {
|
|
14312
14602
|
return process.argv.slice(2).includes(flag);
|
|
14313
14603
|
}
|
|
14604
|
+
function readArgValue(flag) {
|
|
14605
|
+
const args = process.argv.slice(2);
|
|
14606
|
+
const index = args.indexOf(flag);
|
|
14607
|
+
if (index < 0) {
|
|
14608
|
+
return void 0;
|
|
14609
|
+
}
|
|
14610
|
+
const value = args[index + 1];
|
|
14611
|
+
if (!value || value.startsWith("--")) {
|
|
14612
|
+
return void 0;
|
|
14613
|
+
}
|
|
14614
|
+
return value;
|
|
14615
|
+
}
|
|
14314
14616
|
function createConsoleIO2() {
|
|
14315
14617
|
if (process.env.CTR_DOCTOR_FORCE_SCRIPTED_INPUT === "1") {
|
|
14316
14618
|
const scriptedInput = (0, import_fs10.readFileSync)(0, "utf-8");
|
|
@@ -14896,6 +15198,57 @@ function reportRouterSlotSummary(config, registry, deps) {
|
|
|
14896
15198
|
deps.io.info("\u957F\u4E0A\u4E0B\u6587\u63D0\u793A\uFF1ARouter.longContext \u7684 context_window_tokens \u4E0D\u9AD8\u4E8E Router.default\uFF1B\u8BF7\u786E\u8BA4\u5B83\u786E\u5B9E\u662F\u957F\u4E0A\u4E0B\u6587\u6A21\u578B\u3002");
|
|
14897
15199
|
}
|
|
14898
15200
|
}
|
|
15201
|
+
function buildDoctorRoutePreviewInputs() {
|
|
15202
|
+
const customText = readArgValue("--route-text");
|
|
15203
|
+
if (customText) {
|
|
15204
|
+
return [{
|
|
15205
|
+
text: customText,
|
|
15206
|
+
model: readArgValue("--route-model") ?? "claude-3-5-sonnet",
|
|
15207
|
+
thinking: hasArg("--route-thinking"),
|
|
15208
|
+
webSearch: hasArg("--route-web-search"),
|
|
15209
|
+
tokenCount: Number(readArgValue("--route-tokens")) || void 0
|
|
15210
|
+
}];
|
|
15211
|
+
}
|
|
15212
|
+
return [
|
|
15213
|
+
{
|
|
15214
|
+
text: "\u65E5\u5E38\u4EE3\u7801\u4FEE\u6539\u548C\u89E3\u91CA",
|
|
15215
|
+
model: "claude-3-5-sonnet",
|
|
15216
|
+
tokenCount: 1e3
|
|
15217
|
+
},
|
|
15218
|
+
{
|
|
15219
|
+
text: "\u8BF7\u6DF1\u5165\u5206\u6790\u8FD9\u4E2A\u590D\u6742\u8BBE\u8BA1\u95EE\u9898",
|
|
15220
|
+
model: "claude-3-5-sonnet",
|
|
15221
|
+
thinking: true,
|
|
15222
|
+
tokenCount: 1e3
|
|
15223
|
+
},
|
|
15224
|
+
{
|
|
15225
|
+
text: "\u957F\u6587\u6863\u5168\u6587\u603B\u7ED3",
|
|
15226
|
+
model: "claude-3-5-sonnet",
|
|
15227
|
+
tokenCount: 12e4
|
|
15228
|
+
},
|
|
15229
|
+
{
|
|
15230
|
+
text: "\u9700\u8981\u8054\u7F51\u641C\u7D22\u8D44\u6599",
|
|
15231
|
+
model: "claude-3-5-sonnet",
|
|
15232
|
+
webSearch: true,
|
|
15233
|
+
tokenCount: 1e3
|
|
15234
|
+
},
|
|
15235
|
+
{
|
|
15236
|
+
text: "\u540E\u53F0\u8F7B\u91CF\u4EFB\u52A1",
|
|
15237
|
+
model: "claude-3-5-haiku",
|
|
15238
|
+
tokenCount: 1e3
|
|
15239
|
+
}
|
|
15240
|
+
];
|
|
15241
|
+
}
|
|
15242
|
+
function reportRoutePreview(config, deps) {
|
|
15243
|
+
deps.io.info("\u8DEF\u7531\u9884\u6F14\uFF1A\u6839\u636E\u5F53\u524D\u914D\u7F6E\u9884\u4F30\u8BF7\u6C42\u4F1A\u547D\u4E2D\u54EA\u4E2A\u6A21\u578B\uFF1B\u4E0D\u4F1A\u8C03\u7528\u4E0A\u6E38\u6A21\u578B\u6216 SmartRouter LLM\u3002");
|
|
15244
|
+
for (const input3 of buildDoctorRoutePreviewInputs()) {
|
|
15245
|
+
const result = previewRoute(config, input3);
|
|
15246
|
+
for (const line of formatRoutePreview(result)) {
|
|
15247
|
+
deps.io.info(line);
|
|
15248
|
+
}
|
|
15249
|
+
}
|
|
15250
|
+
deps.io.info("\u8DEF\u7531\u9884\u6F14\u63D0\u793A\uFF1A\u771F\u5B9E\u8FD0\u884C\u4ECD\u4F1A\u5728\u6700\u7EC8\u5B9A\u6A21\u540E\u6267\u884C context window guard\u3001\u6A21\u578B\u6C60 fallback\u3001\u8FDC\u7A0B\u4E2D\u8F6C\u548C\u6D41\u5F0F\u6CBB\u7406\u3002");
|
|
15251
|
+
}
|
|
14899
15252
|
function createDefaultDeps2(io = createConsoleIO2()) {
|
|
14900
15253
|
return {
|
|
14901
15254
|
readLegacyConfig,
|
|
@@ -14956,6 +15309,9 @@ async function runDoctorCli(customDeps) {
|
|
|
14956
15309
|
await reportRuntimeServiceContext(normalized.config, deps);
|
|
14957
15310
|
const registry = buildModelRegistry(normalized.config);
|
|
14958
15311
|
reportRouterSlotSummary(normalized.config, registry, deps);
|
|
15312
|
+
if (hasArg("--route-preview")) {
|
|
15313
|
+
reportRoutePreview(normalized.config, deps);
|
|
15314
|
+
}
|
|
14959
15315
|
for (const model of normalized.config.Models ?? []) {
|
|
14960
15316
|
const compiledModel = registry.modelMap[model.id];
|
|
14961
15317
|
if (!compiledModel) {
|
|
@@ -15043,6 +15399,7 @@ var init_doctor = __esm({
|
|
|
15043
15399
|
init_service_health();
|
|
15044
15400
|
init_templates();
|
|
15045
15401
|
init_api_keys();
|
|
15402
|
+
init_route_preview();
|
|
15046
15403
|
ROUTER_SLOT_DIAGNOSTICS = [
|
|
15047
15404
|
{
|
|
15048
15405
|
key: "default",
|
|
@@ -15193,6 +15550,7 @@ Claude Trigger Router - \u667A\u80FD\u89E6\u53D1\u8DEF\u7531\u5668
|
|
|
15193
15550
|
\u4F7F\u7528\u793A\u4F8B\uFF1A
|
|
15194
15551
|
ctr setup # \u590D\u7528\u5F53\u524D\u914D\u7F6E / \u8FC1\u79FB\u65E7\u914D\u7F6E / \u65B0\u5EFA\u6700\u5C0F\u914D\u7F6E
|
|
15195
15552
|
ctr doctor # \u8BCA\u65AD\u914D\u7F6E / \u4FEE\u590D\u683C\u5F0F\u95EE\u9898 / \u6309\u9700\u63A2\u6D4B\u6A21\u578B\u53EF\u7528\u6027
|
|
15553
|
+
ctr doctor --route-preview --route-text "\u8BF7\u505A\u67B6\u6784\u8BBE\u8BA1" # \u9884\u6F14\u5F53\u524D\u8BF7\u6C42\u4F1A\u8D70\u54EA\u4E2A\u6A21\u578B
|
|
15196
15554
|
ctr eval --tasks # \u67E5\u770B\u56FA\u5B9A\u8BC4\u6D4B\u4EFB\u52A1\u3001prompt \u548C rubric
|
|
15197
15555
|
ctr eval --input results.json # \u7528\u56FA\u5B9A\u4EFB\u52A1\u96C6 rubric \u8BC4\u6D4B\u591A\u6A21\u578B\u8F93\u51FA\u7ED3\u679C
|
|
15198
15556
|
ctr eval --run --models "sonnet;haiku" # \u81EA\u52A8\u8C03\u7528 CTR /v1/messages \u540E\u8BC4\u6D4B
|