dsh-plugin-litellm-bridge 2.0.5 → 2.0.7
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.
|
@@ -484,7 +484,11 @@ window.__ModuleLoader__.load({
|
|
|
484
484
|
(Array.isArray(test.steps) ? test.steps : []).map((s, i) => h('div', {
|
|
485
485
|
key: i, style: { display: 'flex', gap: 8, padding: '4px 0', alignItems: 'baseline', flexWrap: 'wrap' },
|
|
486
486
|
},
|
|
487
|
-
|
|
487
|
+
// 【血案 2】这里原来是 { style: s?.ok ? S.ok : S.err } —— 三元的结果
|
|
488
|
+
// 依然是**颜色字符串**,style 收到字符串就抛 React #62。
|
|
489
|
+
// 上一轮我只修了上面的 test.ok 分支,漏了这个三元形态,
|
|
490
|
+
// 所以「点测试连通性」依旧白屏。必须包成 { color: ... }。
|
|
491
|
+
h('span', { style: { color: s?.ok ? S.ok : S.err } }, s?.ok ? '✓' : '✗'),
|
|
488
492
|
h('span', { style: { minWidth: 110 } }, safeText(s?.name)),
|
|
489
493
|
h('span', { style: { ...S.mono, opacity: 0.6 } }, safeText(s?.path)),
|
|
490
494
|
h('span', { style: { ...S.mono, opacity: 0.85, marginLeft: 'auto', textAlign: 'right', wordBreak: 'break-all' } },
|
|
@@ -592,8 +596,16 @@ window.__ModuleLoader__.load({
|
|
|
592
596
|
: h('div', { style: { opacity: 0.6 } }, '加载中…'),
|
|
593
597
|
);
|
|
594
598
|
}
|
|
595
|
-
|
|
596
|
-
|
|
599
|
+
// 【防御】prof 可能是空对象或残缺结构。
|
|
600
|
+
// 先判断存在性再往下渲染,否则后面读 prof.agents[at] 会抛 TypeError。
|
|
601
|
+
const prof = draft?.[pid];
|
|
602
|
+
if (!prof || typeof prof !== 'object') {
|
|
603
|
+
return h('div', { style: S.notice('warn') },
|
|
604
|
+
`profile「${pid}」的数据不完整(缺少 agents 配置)。`,
|
|
605
|
+
h('div', { style: { ...S.hint } },
|
|
606
|
+
'可能来自旧版本的状态文件。可以在上方点击「+ 新建」创建新 profile,' +
|
|
607
|
+
'或删除当前 profile 后重建。'));
|
|
608
|
+
}
|
|
597
609
|
|
|
598
610
|
const setAgent = (at, patch) =>
|
|
599
611
|
setDraft((d) => {
|
|
@@ -746,7 +758,10 @@ window.__ModuleLoader__.load({
|
|
|
746
758
|
|
|
747
759
|
// ---- 三条链:root / coder / research ----
|
|
748
760
|
AGENT_TYPES.map((at) => {
|
|
749
|
-
|
|
761
|
+
// 【防御】cfg 可能缺失(旧版 state.json 结构不全 / 宿主返回残缺)。
|
|
762
|
+
// 直接读 cfg.primary 会抛 TypeError,进而让整页崩掉。
|
|
763
|
+
const cfg = prof?.agents?.[at]
|
|
764
|
+
|| { label: at, primary: '', timeoutMs: 600000, fallbacks: [] };
|
|
750
765
|
const isSub = at !== 'root';
|
|
751
766
|
const groupLabel = at === 'root' ? 'root · 主代理降级链'
|
|
752
767
|
: at === 'coder' ? 'coder · 子代理降级链(Coder)'
|
|
@@ -1271,12 +1286,47 @@ window.__ModuleLoader__.load({
|
|
|
1271
1286
|
);
|
|
1272
1287
|
}
|
|
1273
1288
|
|
|
1274
|
-
/**
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1289
|
+
/**
|
|
1290
|
+
* 错误边界 —— 必须是**真正的 React class 错误边界**。
|
|
1291
|
+
*
|
|
1292
|
+
* 【为什么之前那版是无效的】
|
|
1293
|
+
* 原来写的是:
|
|
1294
|
+
* function Guard({ title, children }) {
|
|
1295
|
+
* try { return children(); } catch (err) { ... }
|
|
1296
|
+
* }
|
|
1297
|
+
* 用法:h(Guard, {}, () => h(RouteTab, {...}))
|
|
1298
|
+
*
|
|
1299
|
+
* 问题:children() 只是**创建元素**(h() 是纯函数,返回一个普通对象),
|
|
1300
|
+
* 此时并不会渲染 RouteTab。真正的渲染发生在 Guard 返回之后、React 内部。
|
|
1301
|
+
* 所以 RouteTab 抛的异常**根本不在这个 try 里**,catch 永远抓不到,
|
|
1302
|
+
* React 直接向上冒泡 → 整个设置页空白(连错误框都没有)。
|
|
1303
|
+
* 这正是「点路由配置后整页全空、什么都不显示」的原因。
|
|
1304
|
+
*
|
|
1305
|
+
* 正确做法:class 组件的 getDerivedStateFromError / componentDidCatch,
|
|
1306
|
+
* 这是 React 唯一能捕获子组件渲染异常的机制。
|
|
1307
|
+
*/
|
|
1308
|
+
class Guard extends React.Component {
|
|
1309
|
+
constructor(props) {
|
|
1310
|
+
super(props);
|
|
1311
|
+
this.state = { error: null };
|
|
1312
|
+
}
|
|
1313
|
+
static getDerivedStateFromError(error) {
|
|
1314
|
+
return { error };
|
|
1315
|
+
}
|
|
1316
|
+
componentDidCatch(error, info) {
|
|
1317
|
+
// 打到控制台便于排查(浏览器 F12)
|
|
1318
|
+
try {
|
|
1319
|
+
console.error('[litellm-bridge] 渲染异常:', error, info?.componentStack);
|
|
1320
|
+
} catch { /* ignore */ }
|
|
1321
|
+
}
|
|
1322
|
+
render() {
|
|
1323
|
+
if (this.state.error) {
|
|
1324
|
+
return h(ErrorBox, { title: this.props.title, error: this.state.error });
|
|
1325
|
+
}
|
|
1326
|
+
// children 既可能是元素也可能是函数,两种都支持
|
|
1327
|
+
return typeof this.props.children === 'function'
|
|
1328
|
+
? this.props.children()
|
|
1329
|
+
: this.props.children;
|
|
1280
1330
|
}
|
|
1281
1331
|
}
|
|
1282
1332
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-plugin-litellm-bridge",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.7",
|
|
4
4
|
"description": "LiteLLM gateway bridge for DSH: assemble root / coder / research fallback chains from the DSH model pool and hand the order to a LiteLLM gateway that executes retries and fallbacks. The plugin performs no routing itself.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dsh",
|