dsh-session-conductor 1.3.4 → 1.3.5

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 CHANGED
@@ -137,10 +137,24 @@ allowBuilds:
137
137
 
138
138
  ### 真实后端预览页
139
139
 
140
- 改 UI 后免重启查看效果:
140
+ 改 UI 后免重启查看效果 —— **预览能力已移出本插件**,统一用独立插件 `dsh-useful-tools` 的 `preview` / `minihost` 工具。
141
141
 
142
- - **快照模式(推荐,免重启)**:`bash tools/preview-snapshot.sh` → 生成 `assets/preview-*.html`(内嵌生成时真实后端响应),file:// 打开即可查看,无 CORS、无假数据
143
- - **DSH 同源路由**:重启后访问 `/api/session-conductor/preview/settings`(或 `/panel`),同源实时 fetch
142
+ **最短三行(实测可用;本仓库没有 `assets/preview.spec.mjs` 也能出页面)**:
143
+
144
+ ```
145
+ minihost { action: "start", plugin: "<插件根>", port: 31177 } # ① 后端模拟
146
+ preview { action: "gen", plugin: "<插件根>" } # ② 前端预览页(无 spec 自动用默认垫片)
147
+ preview { action: "serve", file: "<插件根>/assets/preview.html", backend: "http://127.0.0.1:31177" } # ③ 前端接后端
148
+ ```
149
+
150
+ **几个容易写错的点**:
151
+
152
+ - `gen` 默认产物是 `<插件根>/assets/preview.html`(会写进仓库)⇒ 不想入库就传 `out`(如 `out: "/tmp/sc-preview.html"`),并让 `serve` 的 `file` 指向同一路径。本仓库已把该产物加进 `.gitignore`。
153
+ - `serve` 默认端口 **31188**,显式传 `port` 才用你给的。
154
+ - `backend` 可指向 minihost 的端口(`/api/*` 反代到模拟后端),也可指向**真实 DSH 后端**。
155
+ - 显式传 `spec` 但文件不存在会**直接报错**(不静默降级)—— 故意的,避免指错文件还生成一个看不懂的页面。
156
+ - 停止:`minihost { action: "stop", port: 31177 }` + `preview { action: "stop", port: 31200 }`;状态:两者都用 `action: "status"`。
157
+ - **截图**(README 配图)改走 **browser 插件的 `browser_screenshot`**;「自包含快照」形态不做(理由见 `dsh-useful-tools` 的 `docs/NOT-DONE.md`)。
144
158
 
145
159
  ### 聊天框指令:`/model-switch`
146
160
 
@@ -221,7 +235,6 @@ allowBuilds:
221
235
  | `/templates/dir` | GET | 目录浏览 |
222
236
  | `/auto-rename-model` | GET | 自动重命名模型(透传官方 modelCatalog) |
223
237
  | `/i18n` | GET | 语言包(zh/en 外置 JSON) |
224
- | `/preview/settings` `/preview/panel` | GET | 真实后端预览页(同源服务) |
225
238
 
226
239
  示例:
227
240
 
package/lib/apply.js CHANGED
@@ -234,35 +234,11 @@ export async function apply(ctx, config = {}) {
234
234
  },
235
235
  });
236
236
 
237
- // ---------- GET /api/session-conductor/preview/<settings|panel> ----------
238
- // 真实后端预览页:单文件 html(assets/preview-*.html)经本路由同源服务,浏览器从 DSH 反代地址
239
- // 打开即同源 fetch /api/*(file:// 双击会被 CORS 拦——DSH API 不带 Access-Control-Allow-Origin)。
240
- // 用 kind:"exact" 枚举两个预览(DSH 的 kind:"prefix" 实测 401 不生效)
241
- const PREVIEW_FILES = {
242
- settings: new URL("../../assets/preview-settings.html", import.meta.url),
243
- panel: new URL("../../assets/preview-panel.html", import.meta.url),
244
- };
245
- const servePreview = async (req, res, name) => {
246
- try {
247
- if ((req.method ?? "GET") !== "GET") {
248
- return send(res, 405, { ok: false, error: { code: "METHOD", message: "Method Not Allowed" } });
249
- }
250
- const file = PREVIEW_FILES[name];
251
- if (!file) return send(res, 404, { ok: false, error: { code: "NOT_FOUND", message: "未知预览: " + name } });
252
- const html = readFileSync(file, "utf8");
253
- res.writeHead(200, { "Content-Type": "text/html; charset=utf-8" });
254
- return res.end(html);
255
- } catch (error) {
256
- return send(res, 500, { ok: false, error: { code: "INTERNAL", message: String(error?.message ?? error) } });
257
- }
258
- };
259
- for (const name of ["settings", "panel"]) {
260
- webServer.register({
261
- kind: "exact",
262
- path: "/api/session-conductor/preview/" + name,
263
- handler: (req, res) => servePreview(req, res, name),
264
- });
265
- }
237
+ // ---------- 预览页已移出本插件 ----------
238
+ // 原先这里用 /api/session-conductor/preview/<settings|panel> 同源服务 assets/preview-*.html
239
+ // (那两份 html 由已移除的 tools/preview-snapshot.sh 生成)。现在预览能力统一由独立插件
240
+ // dsh-useful-tools 的 `preview` 工具提供:gen 生成 + serve 带 backend 反代真实后端,
241
+ // 效果等价且本插件不必再托管静态页,故路由与产物一并移除。
266
242
 
267
243
  // ---------- GET /api/session-conductor/list ----------
268
244
  webServer.register({
@@ -262,11 +262,18 @@ export function contentOf(text) {
262
262
  return [{ type: "text", text: String(text) }];
263
263
  }
264
264
 
265
- /** 投递一条消息到目标会话(走本体官方 prompt;目标空闲时会被 resume 唤醒)。 */
266
- export function deliverPrompt(sc, { sessionId, text, mode, requestId }) {
265
+ /**
266
+ * 投递一条消息到目标会话(走本体官方 prompt;目标空闲时会被 resume 唤醒)。
267
+ *
268
+ * 【为什么自动加发送者标记】本体 prompt 只带正文,接收方看不到「这条是谁发的」——实测出现过
269
+ * 「A 会话投递的消息,B 会话以为是当前这一方发的」。这里统一在正文头部加一行
270
+ * `【来自会话 <sessionId>】`,id 由调用方从 `currentSessionId(exec.agent)` 取,**不需要 AI 自己写**。
271
+ */
272
+ export function deliverPrompt(sc, { sessionId, text, mode, requestId, from }) {
273
+ const body = from ? `【来自会话 ${from}】\n${String(text ?? "")}` : String(text ?? "");
267
274
  // 本体签名是 prompt(request, signal):signal 必传(内部会 throwIfAborted)。
268
275
  return sc.prompt(
269
- { requestId, sessionId, mode, content: contentOf(text) },
276
+ { requestId, sessionId, mode, content: contentOf(body) },
270
277
  AbortSignal.timeout(PROMPT_TIMEOUT_MS),
271
278
  );
272
279
  }
@@ -236,7 +236,7 @@ function registerSendToSession(ctx, defineTool, tools) {
236
236
  if (isInFlight(requestId)) return `投递失败:同一 requestId 正在投递中(${requestId})`;
237
237
  markInFlight(requestId);
238
238
  try {
239
- await deliverPrompt(sc, { sessionId: to, text, mode, requestId });
239
+ await deliverPrompt(sc, { sessionId: to, text, mode, requestId, from });
240
240
  logMessaging(ctx, `跨会话投递 ${from ?? "?"} → ${to}(mode=${mode} requestId=${requestId} hops=${hops})`);
241
241
  return `已投递到 ${to}(mode=${mode} | requestId=${requestId})。`
242
242
  + (mode === "steer"
@@ -341,7 +341,7 @@ function registerCreateSession(ctx, defineTool, tools) {
341
341
  }
342
342
  if (text.trim()) {
343
343
  try {
344
- await deliverPrompt(sc, { sessionId, text, mode: "queue", requestId: newRequestId() });
344
+ await deliverPrompt(sc, { sessionId, text, mode: "queue", requestId: newRequestId(), from: currentSessionId(exec?.agent) });
345
345
  } catch (error) {
346
346
  notes.push(`⚠️ 会话已建,但初始消息未投递(${mapPromptError(error)}:${shortError(error)})`);
347
347
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dsh-session-conductor",
3
- "version": "1.3.4",
3
+ "version": "1.3.5",
4
4
  "description": "DSH session management enhancement: archive/restore sessions, batch & conditional delete, AI auto-rename, interrupted-session auto-resume, release idle sessions, workspace grouping, undo last message, repair damaged session logs, value analysis, full-text search, per-member model switching (list_models / set_member_model), and plan/closing template injection (system-prompt + context).",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",