dsh-skill-hub 0.3.11 → 0.3.12
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 +1 -1
- package/README.zh.md +1 -1
- package/lib/index.js +37 -2
- package/lib/types/error-text.d.ts +4 -1
- package/package.json +34 -29
- package/src/error-text.test.ts +45 -0
- package/src/error-text.ts +44 -2
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ dsh plugin --profile web add dsh-skill-hub
|
|
|
24
24
|
# restart dsh web → Settings → 技能 → Market → scan → import
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
Requires `Node ^22.19 || >=24` + dsh web (`0.1.5-
|
|
27
|
+
Requires `Node ^22.19 || >=24` + dsh web (`0.1.5-rc.2`, `0.1.x` forward compatible).
|
|
28
28
|
|
|
29
29
|
## Features
|
|
30
30
|
|
package/README.zh.md
CHANGED
package/lib/index.js
CHANGED
|
@@ -108,10 +108,45 @@ function isProjectSource(source) {
|
|
|
108
108
|
* 错误文案收敛:宿主各处把 unknown 异常转成一行可读文字。原先这条表达式
|
|
109
109
|
* 在宿主侧内联了 22 次(`error instanceof Error ? error.message : String(error)`),
|
|
110
110
|
* 现在统一走这里。浏览器半有自己的 `helpers.errorMessage`,两半互不引用。
|
|
111
|
+
*
|
|
112
|
+
* Error 的 `cause` 链(undici 的 `fetch failed`、AggregateError 的多地址
|
|
113
|
+
* 失败、TLS 证书错误等)以括号附录带出,避免只剩笼统的顶层 message。
|
|
111
114
|
*/
|
|
112
|
-
/**
|
|
115
|
+
/** cause 链最大展开深度,防自引用/超深链。 */
|
|
116
|
+
const MAX_CAUSE_DEPTH = 4;
|
|
117
|
+
/** 合成一条 cause 细节;code 已在 message 里则不重复。 */
|
|
118
|
+
function causeDetail(message, code) {
|
|
119
|
+
const text = message.trim();
|
|
120
|
+
if (code === "") return text;
|
|
121
|
+
if (text === "") return "[" + code + "]";
|
|
122
|
+
return text.includes(code) ? text : text + " [" + code + "]";
|
|
123
|
+
}
|
|
124
|
+
/** 深度受限地收集 cause 链细节(AggregateError 展开其 errors)。 */
|
|
125
|
+
function collectCauseDetails(cause, depth, seen, out) {
|
|
126
|
+
if (depth > MAX_CAUSE_DEPTH || cause === null || cause === void 0 || seen.has(cause)) return;
|
|
127
|
+
seen.add(cause);
|
|
128
|
+
if (cause instanceof Error) {
|
|
129
|
+
const errors = cause.errors;
|
|
130
|
+
if (Array.isArray(errors)) for (const item of errors) collectCauseDetails(item, depth + 1, seen, out);
|
|
131
|
+
const rawCode = cause.code;
|
|
132
|
+
const code = typeof rawCode === "string" ? rawCode : "";
|
|
133
|
+
const detail = causeDetail(cause.message, code);
|
|
134
|
+
if (detail !== "") out.push(detail);
|
|
135
|
+
collectCauseDetails(cause.cause, depth + 1, seen, out);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
const detail = causeDetail(String(cause), "");
|
|
139
|
+
if (detail !== "") out.push(detail);
|
|
140
|
+
}
|
|
141
|
+
/** 从 unknown 异常取出可读文案;非 Error 值用 String 兜底,cause 附在括号里。 */
|
|
113
142
|
function errorText(error) {
|
|
114
|
-
|
|
143
|
+
if (!(error instanceof Error)) return String(error);
|
|
144
|
+
const details = [];
|
|
145
|
+
collectCauseDetails(error.cause, 1, /* @__PURE__ */ new Set(), details);
|
|
146
|
+
for (let index = details.length - 1; index >= 0; index -= 1) if (details[index] === error.message || details.indexOf(details[index]) !== index) details.splice(index, 1);
|
|
147
|
+
if (details.length === 0) return error.message;
|
|
148
|
+
const suffix = details.join("; ");
|
|
149
|
+
return error.message === "" ? suffix : error.message + " (" + suffix + ")";
|
|
115
150
|
}
|
|
116
151
|
//#endregion
|
|
117
152
|
//#region src/store/paths.ts
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* 错误文案收敛:宿主各处把 unknown 异常转成一行可读文字。原先这条表达式
|
|
3
3
|
* 在宿主侧内联了 22 次(`error instanceof Error ? error.message : String(error)`),
|
|
4
4
|
* 现在统一走这里。浏览器半有自己的 `helpers.errorMessage`,两半互不引用。
|
|
5
|
+
*
|
|
6
|
+
* Error 的 `cause` 链(undici 的 `fetch failed`、AggregateError 的多地址
|
|
7
|
+
* 失败、TLS 证书错误等)以括号附录带出,避免只剩笼统的顶层 message。
|
|
5
8
|
*/
|
|
6
|
-
/** 从 unknown 异常取出可读文案;非 Error 值用 String
|
|
9
|
+
/** 从 unknown 异常取出可读文案;非 Error 值用 String 兜底,cause 附在括号里。 */
|
|
7
10
|
export declare function errorText(error: unknown): string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dsh-skill-hub",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.12",
|
|
4
4
|
"description": "In-GUI skill hub for DeepSeek Harness (dsh): browse the full local skill catalog from the official ctx.skills registry (every root + third-party providers), toggle skills on/off, inspect bodies, surface frontmatter diagnostics, and scaffold new skills — plus a codex-style skill market (built-in catalog, upstream update checks, one-click update-all) with tracked source sync. The full manager beyond the read-only dsh-skill-manager browser.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -69,7 +69,10 @@
|
|
|
69
69
|
"0.1.2-alpha.5",
|
|
70
70
|
"0.1.2-rc.1",
|
|
71
71
|
"0.1.3-alpha.2",
|
|
72
|
-
"0.1.5-alpha.1"
|
|
72
|
+
"0.1.5-alpha.1",
|
|
73
|
+
"0.1.5-alpha.2",
|
|
74
|
+
"0.1.5-rc.1",
|
|
75
|
+
"0.1.5-rc.2"
|
|
73
76
|
]
|
|
74
77
|
},
|
|
75
78
|
"capability": {
|
|
@@ -91,19 +94,19 @@
|
|
|
91
94
|
},
|
|
92
95
|
"peerDependencies": {
|
|
93
96
|
"@deepseek-ai/cordis": "^4.0.1 || ^4.0.2",
|
|
94
|
-
"@deepseek-ai/dsh-client-connection": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
95
|
-
"@deepseek-ai/dsh-client-locale": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
96
|
-
"@deepseek-ai/dsh-client-runtime": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
97
|
-
"@deepseek-ai/dsh-client-store": ">=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
98
|
-
"@deepseek-ai/dsh-client-ui-input-trigger": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
99
|
-
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
100
|
-
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
101
|
-
"@deepseek-ai/dsh-host-webserver": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
102
|
-
"@deepseek-ai/dsh-session": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
103
|
-
"@deepseek-ai/dsh-session-query": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
104
|
-
"@deepseek-ai/dsh-settings": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
105
|
-
"@deepseek-ai/dsh-skill": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
106
|
-
"@deepseek-ai/dsh-system-prompt": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0",
|
|
97
|
+
"@deepseek-ai/dsh-client-connection": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
98
|
+
"@deepseek-ai/dsh-client-locale": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
99
|
+
"@deepseek-ai/dsh-client-runtime": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
100
|
+
"@deepseek-ai/dsh-client-store": ">=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
101
|
+
"@deepseek-ai/dsh-client-ui-input-trigger": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
102
|
+
"@deepseek-ai/dsh-client-ui-settings": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
103
|
+
"@deepseek-ai/dsh-client-ui-slots": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
104
|
+
"@deepseek-ai/dsh-host-webserver": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
105
|
+
"@deepseek-ai/dsh-session": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
106
|
+
"@deepseek-ai/dsh-session-query": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
107
|
+
"@deepseek-ai/dsh-settings": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
108
|
+
"@deepseek-ai/dsh-skill": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
109
|
+
"@deepseek-ai/dsh-system-prompt": ">=0.1.0-rc.7 <0.2.0-0 || >=0.1.1-rc.2 <0.2.0-0 || >=0.1.2-alpha.2 <0.2.0-0 || >=0.1.2-alpha.3 <0.2.0-0 || >=0.1.2-alpha.4 <0.2.0-0 || >=0.1.2-alpha.5 <0.2.0-0 || >=0.1.2-rc.1 <0.2.0-0 || >=0.1.3-alpha.2 <0.2.0-0 || >=0.1.5-alpha.1 <0.2.0-0 || >=0.1.5-alpha.2 <0.2.0-0 || >=0.1.5-rc.1 <0.2.0-0 || >=0.1.5-rc.2 <0.2.0-0",
|
|
107
110
|
"react": "^18.2.0",
|
|
108
111
|
"react-dom": "^18.2.0"
|
|
109
112
|
},
|
|
@@ -117,30 +120,32 @@
|
|
|
117
120
|
},
|
|
118
121
|
"devDependencies": {
|
|
119
122
|
"@deepseek-ai/cordis": "^4.0.2",
|
|
120
|
-
"@deepseek-ai/dsh-client-connection": "^0.1.5-
|
|
121
|
-
"@deepseek-ai/dsh-client-locale": "^0.1.5-
|
|
122
|
-
"@deepseek-ai/dsh-client-store": "^0.1.5-
|
|
123
|
-
"@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.5-
|
|
124
|
-
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-
|
|
125
|
-
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.5-
|
|
126
|
-
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-
|
|
127
|
-
"@deepseek-ai/dsh-host-webserver": "^0.1.5-
|
|
128
|
-
"@deepseek-ai/dsh-session": "^0.1.5-
|
|
129
|
-
"@deepseek-ai/dsh-session-query": "^0.1.5-
|
|
130
|
-
"@deepseek-ai/dsh-settings": "^0.1.5-
|
|
131
|
-
"@deepseek-ai/dsh-skill": "^0.1.5-
|
|
132
|
-
"@deepseek-ai/dsh-system-prompt": "^0.1.5-
|
|
123
|
+
"@deepseek-ai/dsh-client-connection": "^0.1.5-rc.2",
|
|
124
|
+
"@deepseek-ai/dsh-client-locale": "^0.1.5-rc.2",
|
|
125
|
+
"@deepseek-ai/dsh-client-store": "^0.1.5-rc.2",
|
|
126
|
+
"@deepseek-ai/dsh-client-ui-input-trigger": "^0.1.5-rc.2",
|
|
127
|
+
"@deepseek-ai/dsh-client-ui-settings": "^0.1.5-rc.2",
|
|
128
|
+
"@deepseek-ai/dsh-client-ui-settings-plugins": "^0.1.5-rc.2",
|
|
129
|
+
"@deepseek-ai/dsh-client-ui-slots": "^0.1.5-rc.2",
|
|
130
|
+
"@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.2",
|
|
131
|
+
"@deepseek-ai/dsh-session": "^0.1.5-rc.2",
|
|
132
|
+
"@deepseek-ai/dsh-session-query": "^0.1.5-rc.2",
|
|
133
|
+
"@deepseek-ai/dsh-settings": "^0.1.5-rc.2",
|
|
134
|
+
"@deepseek-ai/dsh-skill": "^0.1.5-rc.2",
|
|
135
|
+
"@deepseek-ai/dsh-system-prompt": "^0.1.5-rc.2",
|
|
133
136
|
"@types/js-yaml": "^4.0.9",
|
|
134
137
|
"@types/node": "^22.20.0",
|
|
135
138
|
"@types/react": "~18.3.1",
|
|
136
139
|
"@types/react-dom": "^18.3.5",
|
|
140
|
+
"immer": "^10.2.0",
|
|
137
141
|
"lightningcss": "1.32.0",
|
|
138
142
|
"react": "^18.3.1",
|
|
139
143
|
"react-dom": "^18.3.1",
|
|
140
144
|
"schemastery": "^3.18.0",
|
|
141
145
|
"tsdown": "0.22.2",
|
|
142
146
|
"typescript": "~5.7.2",
|
|
143
|
-
"vitest": "^3.0.0"
|
|
147
|
+
"vitest": "^3.0.0",
|
|
148
|
+
"zustand": "~4.4.7"
|
|
144
149
|
},
|
|
145
150
|
"files": [
|
|
146
151
|
"lib/**/*.js",
|
package/src/error-text.test.ts
CHANGED
|
@@ -16,4 +16,49 @@ describe('errorText', () => {
|
|
|
16
16
|
it('uses an empty message when the Error has none', () => {
|
|
17
17
|
expect(errorText(new Error(''))).toBe('')
|
|
18
18
|
})
|
|
19
|
+
|
|
20
|
+
it('appends a cause message to a fetch failure', () => {
|
|
21
|
+
const error = new TypeError('fetch failed', { cause: new Error('getaddrinfo ENOTFOUND api.github.com') })
|
|
22
|
+
expect(errorText(error)).toBe('fetch failed (getaddrinfo ENOTFOUND api.github.com)')
|
|
23
|
+
})
|
|
24
|
+
|
|
25
|
+
it('appends an error code when the cause message does not contain it', () => {
|
|
26
|
+
const cause = Object.assign(new Error('Connect Timeout Error'), { code: 'UND_ERR_CONNECT_TIMEOUT' })
|
|
27
|
+
expect(errorText(new TypeError('fetch failed', { cause }))).toBe('fetch failed (Connect Timeout Error [UND_ERR_CONNECT_TIMEOUT])')
|
|
28
|
+
})
|
|
29
|
+
|
|
30
|
+
it('does not duplicate a code already present in the cause message', () => {
|
|
31
|
+
const cause = Object.assign(new Error('getaddrinfo ENOTFOUND api.github.com'), { code: 'ENOTFOUND' })
|
|
32
|
+
expect(errorText(new TypeError('fetch failed', { cause }))).toBe('fetch failed (getaddrinfo ENOTFOUND api.github.com)')
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
it('walks nested cause chains', () => {
|
|
36
|
+
const inner = new Error('inner reason')
|
|
37
|
+
const outer = new Error('outer', { cause: inner })
|
|
38
|
+
expect(errorText(new TypeError('fetch failed', { cause: outer }))).toBe('fetch failed (outer; inner reason)')
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
it('expands an AggregateError cause', () => {
|
|
42
|
+
const cause = new AggregateError([
|
|
43
|
+
new Error('connect ECONNREFUSED 127.0.0.1:443'),
|
|
44
|
+
new Error('connect ECONNREFUSED [::1]:443'),
|
|
45
|
+
])
|
|
46
|
+
expect(errorText(new TypeError('fetch failed', { cause }))).toBe('fetch failed (connect ECONNREFUSED 127.0.0.1:443; connect ECONNREFUSED [::1]:443)')
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
it('stops at self-referencing cause chains', () => {
|
|
50
|
+
const error = new Error('fetch failed')
|
|
51
|
+
error.cause = error
|
|
52
|
+
expect(errorText(error)).toBe('fetch failed')
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
it('stringifies non-Error causes', () => {
|
|
56
|
+
const error = new Error('fetch failed')
|
|
57
|
+
error.cause = 'socket closed'
|
|
58
|
+
expect(errorText(error)).toBe('fetch failed (socket closed)')
|
|
59
|
+
})
|
|
60
|
+
|
|
61
|
+
it('returns the cause detail alone when the top message is empty', () => {
|
|
62
|
+
expect(errorText(new Error('', { cause: new Error('boom') }))).toBe('boom')
|
|
63
|
+
})
|
|
19
64
|
})
|
package/src/error-text.ts
CHANGED
|
@@ -2,9 +2,51 @@
|
|
|
2
2
|
* 错误文案收敛:宿主各处把 unknown 异常转成一行可读文字。原先这条表达式
|
|
3
3
|
* 在宿主侧内联了 22 次(`error instanceof Error ? error.message : String(error)`),
|
|
4
4
|
* 现在统一走这里。浏览器半有自己的 `helpers.errorMessage`,两半互不引用。
|
|
5
|
+
*
|
|
6
|
+
* Error 的 `cause` 链(undici 的 `fetch failed`、AggregateError 的多地址
|
|
7
|
+
* 失败、TLS 证书错误等)以括号附录带出,避免只剩笼统的顶层 message。
|
|
5
8
|
*/
|
|
6
9
|
|
|
7
|
-
/**
|
|
10
|
+
/** cause 链最大展开深度,防自引用/超深链。 */
|
|
11
|
+
const MAX_CAUSE_DEPTH = 4
|
|
12
|
+
|
|
13
|
+
/** 合成一条 cause 细节;code 已在 message 里则不重复。 */
|
|
14
|
+
function causeDetail(message: string, code: string): string {
|
|
15
|
+
const text = message.trim()
|
|
16
|
+
if (code === '') return text
|
|
17
|
+
if (text === '') return '[' + code + ']'
|
|
18
|
+
return text.includes(code) ? text : text + ' [' + code + ']'
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** 深度受限地收集 cause 链细节(AggregateError 展开其 errors)。 */
|
|
22
|
+
function collectCauseDetails(cause: unknown, depth: number, seen: Set<unknown>, out: string[]): void {
|
|
23
|
+
if (depth > MAX_CAUSE_DEPTH || cause === null || cause === undefined || seen.has(cause)) return
|
|
24
|
+
seen.add(cause)
|
|
25
|
+
if (cause instanceof Error) {
|
|
26
|
+
const errors = (cause as { errors?: unknown }).errors
|
|
27
|
+
if (Array.isArray(errors)) {
|
|
28
|
+
for (const item of errors) collectCauseDetails(item, depth + 1, seen, out)
|
|
29
|
+
}
|
|
30
|
+
const rawCode: unknown = (cause as { code?: unknown }).code
|
|
31
|
+
const code = typeof rawCode === 'string' ? rawCode : ''
|
|
32
|
+
const detail = causeDetail(cause.message, code)
|
|
33
|
+
if (detail !== '') out.push(detail)
|
|
34
|
+
collectCauseDetails(cause.cause, depth + 1, seen, out)
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
const detail = causeDetail(String(cause), '')
|
|
38
|
+
if (detail !== '') out.push(detail)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/** 从 unknown 异常取出可读文案;非 Error 值用 String 兜底,cause 附在括号里。 */
|
|
8
42
|
export function errorText(error: unknown): string {
|
|
9
|
-
|
|
43
|
+
if (!(error instanceof Error)) return String(error)
|
|
44
|
+
const details: string[] = []
|
|
45
|
+
collectCauseDetails(error.cause, 1, new Set(), details)
|
|
46
|
+
for (let index = details.length - 1; index >= 0; index -= 1) {
|
|
47
|
+
if (details[index] === error.message || details.indexOf(details[index]) !== index) details.splice(index, 1)
|
|
48
|
+
}
|
|
49
|
+
if (details.length === 0) return error.message
|
|
50
|
+
const suffix = details.join('; ')
|
|
51
|
+
return error.message === '' ? suffix : error.message + ' (' + suffix + ')'
|
|
10
52
|
}
|