dsh-agentic-router 1.4.0 → 1.4.1
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/dsh/index.js +26 -11
- package/package.json +2 -2
package/dsh/index.js
CHANGED
|
@@ -38,6 +38,22 @@ const KNN_GRADUATION = 30 // k-NN 毕业经验线
|
|
|
38
38
|
const SETTLE_DELAY_MS = 45000 // 反馈结算窗口:回合结束 45s 后查询 messageFeedback
|
|
39
39
|
const SWEEP_MS = 15000 // 结算轮询周期
|
|
40
40
|
|
|
41
|
+
// 同步兜底档位表:从 DEFAULT_PRICES 已知的 provider→model 推导档位,
|
|
42
|
+
// 让插件在 llm.listModels 异步加载完成之前也能立即决策与切换(不 await、不延期)。
|
|
43
|
+
// 加载完成后由 refreshModelTiers 用权威目录覆盖。
|
|
44
|
+
function fallbackTiers() {
|
|
45
|
+
const tiers = { fast: [], mid: [], strong: [] }
|
|
46
|
+
const providers = []
|
|
47
|
+
for (const provider of Object.keys(DEFAULT_PRICES)) {
|
|
48
|
+
if (provider === '*') continue
|
|
49
|
+
const models = Object.keys(DEFAULT_PRICES[provider] || {})
|
|
50
|
+
if (!models.length) continue
|
|
51
|
+
providers.push({ provider, models })
|
|
52
|
+
for (const n of models) tiers[tierOf(n)].push(provider + '/' + n)
|
|
53
|
+
}
|
|
54
|
+
return { providers, tiers }
|
|
55
|
+
}
|
|
56
|
+
|
|
41
57
|
function freshState() {
|
|
42
58
|
return {
|
|
43
59
|
mode: 'shadow',
|
|
@@ -45,7 +61,7 @@ function freshState() {
|
|
|
45
61
|
decisions: [],
|
|
46
62
|
forced: null,
|
|
47
63
|
pending: new Map(),
|
|
48
|
-
modelTiers:
|
|
64
|
+
modelTiers: fallbackTiers(),
|
|
49
65
|
turnDecision: {},
|
|
50
66
|
openTurns: new Map(),
|
|
51
67
|
pendingFeedback: [],
|
|
@@ -287,11 +303,9 @@ export function apply(ctx, config = {}) {
|
|
|
287
303
|
|
|
288
304
|
// ---- 决策流水线(inbox 与 request 兜底共用) ----
|
|
289
305
|
// 返回 { key, td, record, target };已决策过本回合则返回 null。
|
|
290
|
-
//
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
try { await tiersReady } catch (e) { /* keep null */ }
|
|
294
|
-
}
|
|
306
|
+
// 必须同步执行:档位表用 fallbackTiers() 兜底(见 freshState),
|
|
307
|
+
// 不 await、不延期——否则追加 header 会落到 prompt 组装之后,被 loop 覆盖。
|
|
308
|
+
function decideAndRecord(payload, text, current, provider, source) {
|
|
295
309
|
const key = fullKey(payload)
|
|
296
310
|
if (state.turnDecision[key]) return null
|
|
297
311
|
const cls = classify(text)
|
|
@@ -377,14 +391,14 @@ export function apply(ctx, config = {}) {
|
|
|
377
391
|
// ---- 事件挂载 ----
|
|
378
392
|
// 回合开始(prompt 组装之前):捕获用户消息并决策,active 模式立即应用切换。
|
|
379
393
|
// 这是主路径——零延迟,回合第一步就按目标模型执行。
|
|
380
|
-
ctx.on('agent/inbox/claimed',
|
|
394
|
+
ctx.on('agent/inbox/claimed', (payload) => {
|
|
381
395
|
try {
|
|
382
396
|
const session = sessionOf(payload)
|
|
383
397
|
const text = extractText(payload && payload.message)
|
|
384
398
|
if (!text) return
|
|
385
399
|
const current = session ? currentModel(session) : null
|
|
386
400
|
const provider = session ? currentProvider(session) : ''
|
|
387
|
-
const r =
|
|
401
|
+
const r = decideAndRecord(payload, text, current, provider, 'inbox')
|
|
388
402
|
if (!r) return
|
|
389
403
|
applyDecision(session, r.key, r.td, r.record, r.target)
|
|
390
404
|
commitRecord(r.record)
|
|
@@ -428,7 +442,7 @@ export function apply(ctx, config = {}) {
|
|
|
428
442
|
const text = state.pending.get(pkey) || ''
|
|
429
443
|
state.pending.delete(pkey)
|
|
430
444
|
const provider = typeof cfg.provider === 'string' ? cfg.provider : ''
|
|
431
|
-
const r =
|
|
445
|
+
const r = decideAndRecord(payload, text, model, provider, 'request')
|
|
432
446
|
if (r) {
|
|
433
447
|
r.td.needsApply = state.mode === 'active' && r.target && r.target !== r.td.currentModel
|
|
434
448
|
commitRecord(r.record)
|
|
@@ -571,10 +585,11 @@ export function apply(ctx, config = {}) {
|
|
|
571
585
|
ctx.on('agent/turn-stopping', (payload) => finalize(payload, 'clean-close'))
|
|
572
586
|
ctx.on('agent/error', (payload) => finalize(payload, 'error'))
|
|
573
587
|
|
|
574
|
-
//
|
|
588
|
+
// 权威档位表异步加载,就绪后覆盖同步兜底表(fallbackTiers 保证首回合即可决策)。
|
|
589
|
+
// 仅在刷新成功时覆盖,避免把兜底表清成 null。
|
|
575
590
|
const tiersReady = refreshModelTiers(llm)
|
|
576
591
|
tiersReady.then((t) => {
|
|
577
|
-
state.modelTiers = t
|
|
592
|
+
if (t) state.modelTiers = t
|
|
578
593
|
log('model tiers: ' + JSON.stringify(t))
|
|
579
594
|
}).catch((e) => log('model tiers refresh failed: ' + String(e)))
|
|
580
595
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-agentic-router",
|
|
3
|
-
"version": "1.4.
|
|
4
|
-
"description": "DeepSeek Harness plugin: learning agentic router — rule + UCB + LinUCB + k-NN experts under an EXP3 meta-selector, with a durable quality-reward flywheel and REAL model switching via the session request-header precedence chain (v1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
4
|
+
"description": "DeepSeek Harness plugin: learning agentic router — rule + UCB + LinUCB + k-NN experts under an EXP3 meta-selector, with a durable quality-reward flywheel and REAL model switching via the session request-header precedence chain (v1.4.1, cold-start fix)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "lhl",
|