@shgroup/dsh-serenity-hooks 1.20.0 → 1.20.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/dsh.plugin.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "id": "dsh-serenity-hooks",
3
- "version": "1.20.0",
3
+ "version": "1.20.2",
4
4
  "main": "lib/index.js",
5
5
  "description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 cc_fs/session/acc_msm/eap/neat/cce/loop + 拦截缝机械约束(safe-mode/路径守卫)。适配 DSH 公开版(0.1.0-rc,deepseek-ai/deepseek-harness)。私有(dsh-external 组织)。",
6
6
  "engines": {
package/lib/client.js CHANGED
@@ -259,6 +259,7 @@ window.__ModuleLoader__.load({
259
259
  const { uploadImage, getDraftFiles, resendText } = props;
260
260
  const [state, setState] = (0, react.useState)("idle");
261
261
  const [paths, setPaths] = (0, react.useState)([]);
262
+ const [errorText, setErrorText] = (0, react.useState)(null);
262
263
  const handlingRef = (0, react.useRef)(false);
263
264
  const promptError = session?.promptError?.error;
264
265
  const imageIds = input?.imageIds ?? [];
@@ -273,7 +274,7 @@ window.__ModuleLoader__.load({
273
274
  const files = await getDraftFiles(String(sessionId), imageIds);
274
275
  if (files.length === 0) throw new Error("no draft image files");
275
276
  const saved = [];
276
- for (const file of files) saved.push(await uploadImage(file));
277
+ for (const file of files) saved.push(await uploadImage(file, String(sessionId)));
277
278
  const note = saved.map((p) => `用户提供了图片在 ${p}`).join("\n");
278
279
  const draft = input?.draft ?? "";
279
280
  const text = draft === "" ? note : `${draft}\n${note}`;
@@ -281,7 +282,9 @@ window.__ModuleLoader__.load({
281
282
  setPaths(saved);
282
283
  setState("done");
283
284
  } catch (err) {
284
- console.warn(`[serenity] image fallback failed: ${String(err?.message ?? err)}`);
285
+ const message = String(err?.message ?? err);
286
+ console.warn(`[serenity] image fallback failed: ${message}`);
287
+ setErrorText(message);
285
288
  setState("error");
286
289
  } finally {
287
290
  handlingRef.current = false;
@@ -310,10 +313,10 @@ window.__ModuleLoader__.load({
310
313
  "data-state": "done",
311
314
  children: paths.map((p) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", { children: p }, p))
312
315
  });
313
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
316
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
314
317
  className: "serenity-image-fallback",
315
318
  "data-state": "error",
316
- children: "图片保存失败,请重试"
319
+ children: ["图片保存失败:", errorText ?? "未知错误"]
317
320
  });
318
321
  }
319
322
  //#endregion
@@ -330,8 +333,11 @@ window.__ModuleLoader__.load({
330
333
  return btoa(binary);
331
334
  });
332
335
  }
333
- /** 上传一张图片到 CCC _tmp/images_from_user/,返回相对路径(如 _tmp/images_from_user/xxx.png) */
334
- async function uploadImage(file) {
336
+ /**
337
+ * 上传一张图片到 CCC _tmp/images_from_user/,返回相对路径(如 _tmp/images_from_user/xxx.png)。
338
+ * sessionId 必传:node half 经会话 header.cwd 解析 CCC 根(进程 cwd 不可靠)。
339
+ */
340
+ async function uploadImage(file, sessionId) {
335
341
  const data = await fileToBase64(file);
336
342
  const res = await fetch(UPLOAD_PATH, {
337
343
  method: "POST",
@@ -340,6 +346,7 @@ window.__ModuleLoader__.load({
340
346
  "x-serenity-ui": "1"
341
347
  },
342
348
  body: JSON.stringify({
349
+ sessionId,
343
350
  mediaType: file.type,
344
351
  name: file.name,
345
352
  data
@@ -349,11 +356,17 @@ window.__ModuleLoader__.load({
349
356
  if (!res.ok || typeof body.path !== "string") throw new Error(`serenity image upload failed: ${body.error ?? res.status}`);
350
357
  return body.path;
351
358
  }
352
- /** 取 rail 图片的浏览器 File(conversation.draftImages,session-scoped;类型宽松访问——IConversation 类型面未含 draftImages) */
353
- async function getDraftFiles(ctx, sessionId, ids) {
354
- const draftImages = (ctx.sessions.scope(sessionId)?.conversation)?.draftImages;
355
- if (draftImages === void 0) return [];
356
- return (draftImages(ids) ?? []).map((a) => a.file);
359
+ /**
360
+ * rail 图片的浏览器 File。
361
+ * conversation.draftImages root singleton 的公开方法(读 controller 的 draftAttachments Map,
362
+ * 与调用 ctx 的作用域无关)——直接 ctx.get('conversation')
363
+ * ⚠️ 必须作为方法调用(conversation.draftImages(ids)):解构取出再调会丢失 this
364
+ * (draftImages 内部读 this.draftAttachments → "Cannot read properties of undefined")。
365
+ */
366
+ async function getDraftFiles(ctx, _sessionId, ids) {
367
+ const conversation = ctx.get?.("conversation");
368
+ if (conversation?.draftImages === void 0) return [];
369
+ return (conversation.draftImages(ids) ?? []).map((a) => a.file);
357
370
  }
358
371
  /** 纯文本重发(绕过图片门禁——不含 image part,模型永不触发 MODEL_DOES_NOT_SUPPORT_IMAGES) */
359
372
  async function resendText(ctx, sessionId, text) {
@@ -388,7 +401,7 @@ window.__ModuleLoader__.load({
388
401
  id: "serenity-image-fallback",
389
402
  order: 100,
390
403
  inject: () => ({
391
- uploadImage: (file) => uploadImage(file),
404
+ uploadImage: (file, sessionId) => uploadImage(file, sessionId),
392
405
  getDraftFiles: (sessionId, ids) => getDraftFiles(scope, sessionId, ids),
393
406
  resendText: (sessionId, text) => resendText(scope, sessionId, text)
394
407
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.20.0",
3
+ "version": "1.20.2",
4
4
  "description": "宁静号 ACC harness — Native Cordis 插件(DeepSeek Harness 运行时)。真实 DSH 工具注册(cc_fs/session/acc_msm 等 9 工具)+ 拦截缝机械约束(safe-mode/路径守卫/会话落盘)+ 系统提示词注入(ACC/CCE/Constraints/SKILL/Session 五块)。适配 DSH 公开版(deepseek-ai/deepseek-harness 0.1.0-rc)。",
5
5
  "license": "MIT",
6
6
  "repository": {