@morehao/dsh-skills-console 0.5.0 → 0.5.2
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 +27 -3
- package/client.js +688 -300
- package/lib/core/intro-store.js +156 -0
- package/lib/core/intro.js +430 -0
- package/lib/core/paths.js +2 -0
- package/lib/core/remote.js +103 -1
- package/lib/core/service.js +477 -1
- package/lib/index.js +16 -0
- package/lib/routes.js +50 -2
- package/package.json +1 -1
package/lib/routes.js
CHANGED
|
@@ -73,6 +73,11 @@ function matchRoute(method, pathname) {
|
|
|
73
73
|
if (segments[0] === 'skills' && segments.length === 3 && segments[2] === 'files' && method === 'GET') {
|
|
74
74
|
return { name: 'skill.files', params: { name: decodeURIComponent(segments[1]) } };
|
|
75
75
|
}
|
|
76
|
+
// 技能介绍(模型生成):GET 只读缓存,POST 才真正调模型
|
|
77
|
+
if (segments[0] === 'skills' && segments.length === 3 && segments[2] === 'intro') {
|
|
78
|
+
if (method === 'GET') return { name: 'skill.intro.get', params: { name: decodeURIComponent(segments[1]) } };
|
|
79
|
+
if (method === 'POST') return { name: 'skill.intro.generate', params: { name: decodeURIComponent(segments[1]) } };
|
|
80
|
+
}
|
|
76
81
|
if (segments[0] === 'skills' && segments.length === 3 && segments[2] === 'adopt' && method === 'POST') {
|
|
77
82
|
return { name: 'skill.adopt', params: { name: decodeURIComponent(segments[1]) } };
|
|
78
83
|
}
|
|
@@ -97,6 +102,13 @@ function matchRoute(method, pathname) {
|
|
|
97
102
|
if (segments.length === 3 && segments[2] === 'refresh' && method === 'POST') {
|
|
98
103
|
return { name: 'subscriptions.refresh', params: { id: decodeURIComponent(segments[1]) } };
|
|
99
104
|
}
|
|
105
|
+
// 订阅候选的介绍:路径由服务端按快照反查,客户端只给订阅 id + 条目名
|
|
106
|
+
if (segments.length === 5 && segments[2] === 'entries' && segments[4] === 'intro') {
|
|
107
|
+
const id = decodeURIComponent(segments[1]);
|
|
108
|
+
const entryName = decodeURIComponent(segments[3]);
|
|
109
|
+
if (method === 'GET') return { name: 'subscription.intro.get', params: { id, name: entryName } };
|
|
110
|
+
if (method === 'POST') return { name: 'subscription.intro.generate', params: { id, name: entryName } };
|
|
111
|
+
}
|
|
100
112
|
}
|
|
101
113
|
|
|
102
114
|
if (segments[0] === 'updates') {
|
|
@@ -129,13 +141,24 @@ export function createRoutes({ service, logger }) {
|
|
|
129
141
|
return;
|
|
130
142
|
}
|
|
131
143
|
|
|
144
|
+
// 客户端断开(关抽屉 / 关页面)就取消模型调用:摘要是一次性辅助请求,没必要跑完再丢。
|
|
145
|
+
// 测试里的 fake res 没有 on/off,所以要按能力探测。
|
|
146
|
+
const abort = new AbortController();
|
|
147
|
+
const onClose = () => {
|
|
148
|
+
if (!res.writableEnded) abort.abort();
|
|
149
|
+
};
|
|
150
|
+
if (typeof res.on === 'function') res.on('close', onClose);
|
|
151
|
+
|
|
132
152
|
try {
|
|
133
153
|
service.reloadState();
|
|
134
154
|
const body = method === 'GET' ? {} : await readBody(req);
|
|
135
155
|
const query = Object.fromEntries(url.searchParams.entries());
|
|
136
|
-
const result = await dispatch(route, { body, query, service });
|
|
156
|
+
const result = await dispatch(route, { body, query, service, signal: abort.signal });
|
|
157
|
+
// 生成期间客户端可能已经走了:往已关闭的响应写会抛 ERR_STREAM_WRITE_AFTER_END
|
|
158
|
+
if (res.writableEnded || res.destroyed) return;
|
|
137
159
|
sendJson(res, 200, result);
|
|
138
160
|
} catch (error) {
|
|
161
|
+
if (res.writableEnded || res.destroyed) return;
|
|
139
162
|
if (error instanceof StateReadOnlyError) {
|
|
140
163
|
sendJson(res, 409, {
|
|
141
164
|
ok: false,
|
|
@@ -152,11 +175,13 @@ export function createRoutes({ service, logger }) {
|
|
|
152
175
|
}
|
|
153
176
|
logger('route.error', { message: error?.message, stack: String(error?.stack || '').slice(0, 800) });
|
|
154
177
|
sendJson(res, 500, { ok: false, code: 'error.skills.internal', message: error?.message || 'internal error' });
|
|
178
|
+
} finally {
|
|
179
|
+
if (typeof res.off === 'function') res.off('close', onClose);
|
|
155
180
|
}
|
|
156
181
|
};
|
|
157
182
|
}
|
|
158
183
|
|
|
159
|
-
async function dispatch(route, { body, query, service }) {
|
|
184
|
+
async function dispatch(route, { body, query, service, signal = null }) {
|
|
160
185
|
switch (route.name) {
|
|
161
186
|
case 'state': {
|
|
162
187
|
const state = await service.getState({ cwd: query.cwd || body.cwd, workspace: query.workspace });
|
|
@@ -180,6 +205,29 @@ async function dispatch(route, { body, query, service }) {
|
|
|
180
205
|
return service.listSkillBody({ name: route.params.name, path: query.path });
|
|
181
206
|
case 'skill.files':
|
|
182
207
|
return service.listSkillFiles({ name: route.params.name });
|
|
208
|
+
case 'skill.intro.get':
|
|
209
|
+
return service.getSkillIntro({ name: route.params.name, lang: query.lang });
|
|
210
|
+
case 'subscription.intro.get':
|
|
211
|
+
return service.getRemoteIntro({
|
|
212
|
+
subscriptionId: route.params.id,
|
|
213
|
+
name: route.params.name,
|
|
214
|
+
lang: query.lang,
|
|
215
|
+
});
|
|
216
|
+
case 'subscription.intro.generate':
|
|
217
|
+
return service.generateRemoteIntro({
|
|
218
|
+
subscriptionId: route.params.id,
|
|
219
|
+
name: route.params.name,
|
|
220
|
+
lang: body.lang ?? query.lang,
|
|
221
|
+
force: body.force === true,
|
|
222
|
+
signal,
|
|
223
|
+
});
|
|
224
|
+
case 'skill.intro.generate':
|
|
225
|
+
return service.generateSkillIntro({
|
|
226
|
+
name: route.params.name,
|
|
227
|
+
lang: body.lang ?? query.lang,
|
|
228
|
+
force: body.force === true,
|
|
229
|
+
signal,
|
|
230
|
+
});
|
|
183
231
|
case 'skill.adopt':
|
|
184
232
|
return service.adopt({ name: route.params.name });
|
|
185
233
|
case 'skill.mode':
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@morehao/dsh-skills-console",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "统一管理本地技能的安装、更新、删除与接入,让同一份技能在多个 Agent 间复用。A skill manager for DeepSeek Harness: install, update, remove, link and toggle agent skills.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "morehao <morehao@qq.com>",
|