@shgroup/dsh-serenity-hooks 1.25.9 → 1.25.10

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.25.9",
3
+ "version": "1.25.10",
4
4
  "main": "lib/index.js",
5
5
  "description": "宁静号 ACC harness(Native Cordis 插件):真实 DSH 工具 cc_fs/session/acc_msm/eap/neat/cce/handyman/session_rebuild/skiff_admin + 拦截缝机械约束(safe-mode/路径守卫)+ 高级设定面板(双端口网关/账号管理)+ Skiff 认知子集角色(实验性)。适配 DSH 公开版(0.1.0-rc,deepseek-ai/deepseek-harness)。",
6
6
  "engines": {
package/lib/index.js CHANGED
@@ -647,7 +647,8 @@ function readSkiffRoles(root, paths = DEFAULT_SERENITY_CONFIG_PATHS) {
647
647
  keeper: role.trajectory.keeper === true,
648
648
  rebuild: role.trajectory.rebuild === true
649
649
  } : void 0,
650
- systemPrompt: typeof role.systemPrompt === "string" ? role.systemPrompt : void 0
650
+ systemPrompt: typeof role.systemPrompt === "string" ? role.systemPrompt : void 0,
651
+ systemPromptFile: typeof role.systemPromptFile === "string" ? role.systemPromptFile : void 0
651
652
  });
652
653
  }
653
654
  } catch {}
@@ -672,6 +673,32 @@ function roleMsmWhitelist(role) {
672
673
  return new Set(role?.msms ?? []);
673
674
  }
674
675
  /**
676
+ * 解析角色的系统提示词全文(v1.25.10,S142 用户:超长提示词 JSON 内嵌不可读):
677
+ * ① `systemPromptFile` 存在 → 读取文件内容(**推荐配置方法**;相对 CCC 根,
678
+ * 路径逃逸拒绝(resolveInside)+ BOM 剥除(readUtf8)+ 存在性校验)
679
+ * ② 否则 → 内嵌 `systemPrompt`(兼容旧配置)
680
+ * ③ 都无 → 空字符串
681
+ * 文件缺失/逃逸 → 抛错(调用方 catch 降级 + validate 报 issue)。
682
+ * 懒读取:readSkiffRoles 不读文件(guards/seams 每次工具调用查询的热路径零 IO),
683
+ * 仅在本函数(创建 agent / validate / list 时)读取。
684
+ */
685
+ function resolveRoleSystemPrompt(root, role) {
686
+ if (!role) return "";
687
+ const file = role.systemPromptFile?.trim();
688
+ if (file) {
689
+ const abs = resolveInside(root, file);
690
+ if (!existsSync(abs)) throw new Error(`skiff role "${role.systemPrompt ?? "(unnamed)"}": systemPromptFile "${file}" not found (resolved: ${abs})`);
691
+ return readUtf8(abs).trim();
692
+ }
693
+ return role.systemPrompt ?? "";
694
+ }
695
+ /** 角色系统提示词来源(validate/list 展示用) */
696
+ function systemPromptSource(role) {
697
+ if (role?.systemPromptFile?.trim()) return "file";
698
+ if (role?.systemPrompt?.trim()) return "inline";
699
+ return "none";
700
+ }
701
+ /**
675
702
  * Skiff 基础提示词(dsp 只给这部分;CCC 的 systemPrompt 段由调用方拼接):
676
703
  * 身份 + 可用 MSM/工具清单 + 调用协议 + 边界声明。动态生成(清单来自角色白名单)。
677
704
  */
@@ -694,22 +721,20 @@ function buildSkiffBasePrompt(roleName, role) {
694
721
  }
695
722
  //#endregion
696
723
  //#region src/skiff-registry.ts
697
- /**
698
- * skiff-registry.ts — Skiff 会话注册表(sessionId → role;零 DSH 依赖,可被任何 seams 安全 import)
699
- *
700
- * F4b 会话映射:Skiff agent 创建时注册(skiff-core),guards/seams 按 sessionId 查角色。
701
- * 独立成模块的原因:guards.ts 等拦截缝需要查角色而不引入 skiff-core 的运行时依赖
702
- * (skiff-core 依赖 @deepseek-ai/dsh-llm,测试/装配级联成本高)——注册表本身纯内存 Map。
703
- *
704
- * 生命周期:进程内存态;连接/页面关闭时 unregister;进程重启自然清空(skiff 会话不复存在)。
705
- */
706
724
  const skiffSessions = /* @__PURE__ */ new Map();
707
- /** 查 sessionId 的 Skiff 角色名(无 → null */
725
+ /** 查 sessionId 的 Skiff 角色名(无 → null)——向后兼容(guards/seams 依赖) */
708
726
  function skiffRoleFor$1(sessionId) {
727
+ return skiffSessions.get(sessionId)?.role ?? null;
728
+ }
729
+ /** 查 sessionId 的完整绑定(role + ccc;无 → null)——v1.25.10 会话追问校验 */
730
+ function skiffSessionInfo$1(sessionId) {
709
731
  return skiffSessions.get(sessionId) ?? null;
710
732
  }
711
- function registerSkiffSession$1(sessionId, role) {
712
- skiffSessions.set(sessionId, role);
733
+ function registerSkiffSession$1(sessionId, role, ccc) {
734
+ skiffSessions.set(sessionId, {
735
+ role,
736
+ ccc
737
+ });
713
738
  }
714
739
  //#endregion
715
740
  //#region src/seams/guards.ts
@@ -2357,9 +2382,17 @@ const skiffAgents = /* @__PURE__ */ new Map();
2357
2382
  function skiffRoleFor(sessionId) {
2358
2383
  return skiffRoleFor$1(sessionId);
2359
2384
  }
2360
- function registerSkiffSession(sessionId, role, agent) {
2385
+ /** sessionId 的会话绑定(role + ccc;无 → null)——v1.25.10 追问校验 */
2386
+ function skiffSessionInfo(sessionId) {
2387
+ return skiffSessionInfo$1(sessionId);
2388
+ }
2389
+ /** 查 sessionId 的活体 agent(进程内会话延续用;未注册/已清理 → undefined) */
2390
+ function getSkiffAgent(sessionId) {
2391
+ return skiffAgents.get(sessionId);
2392
+ }
2393
+ function registerSkiffSession(sessionId, role, ccc, agent) {
2361
2394
  skiffAgents.set(sessionId, agent);
2362
- registerSkiffSession$1(sessionId, role);
2395
+ registerSkiffSession$1(sessionId, role, ccc);
2363
2396
  }
2364
2397
  /** Skiff agent 挂载的 DSH preset(v1.25.3 修复:read/grep/glob 等平台工具由 preset 决定工具面;
2365
2398
  * handyman 经 composeFrom 继承父、skiff 无父上下文——直接挂 DSH 默认 standard preset;
@@ -2387,16 +2420,22 @@ async function createSkiffAgent(ctx, root, roleName, role, defaultModel) {
2387
2420
  ...model ? { agentOptions: splitModel(model) } : {}
2388
2421
  });
2389
2422
  const agent = handle.agent;
2423
+ let cccPrompt = "";
2424
+ try {
2425
+ cccPrompt = resolveRoleSystemPrompt(root, role);
2426
+ } catch (err) {
2427
+ console.warn(`[serenity-hooks] skiff 角色 "${roleName}" 系统提示词解析失败(回退仅基础段): ${String(err?.message ?? err)}`);
2428
+ }
2390
2429
  try {
2391
2430
  agent.ctx.systemPrompt.section({
2392
2431
  name: "serenity-skiff",
2393
2432
  order: -60,
2394
- text: () => [buildSkiffBasePrompt(roleName, role), role.systemPrompt ?? ""].filter(Boolean).join("\n")
2433
+ text: () => [buildSkiffBasePrompt(roleName, role), cccPrompt].filter(Boolean).join("\n")
2395
2434
  });
2396
2435
  } catch (err) {
2397
2436
  console.warn(`[serenity-hooks] skiff 系统提示词注册失败: ${String(err?.message ?? err)}`);
2398
2437
  }
2399
- registerSkiffSession(sessionId, roleName, agent);
2438
+ registerSkiffSession(sessionId, roleName, root, agent);
2400
2439
  return {
2401
2440
  handle,
2402
2441
  agent,
@@ -2478,11 +2517,12 @@ function truncate(s, n) {
2478
2517
  return s.length > n ? `${s.slice(0, n)}…` : s;
2479
2518
  }
2480
2519
  /**
2481
- * 提问一轮:followup → 等 idle → 读答案 + 本 turn 轨迹(增量 = followup 前 events 之后)。
2482
- * @param eventsStart 本轮开始前的 events 长度(0 = 全量轨迹)
2520
+ * 提问一轮:followup → 等 idle → 读答案 + 轨迹。
2521
+ * @param eventsStart 轨迹起点:显式传 0 = 全量轨迹(会话追问时页面重绘完整时间线,
2522
+ * v1.25.10 用户拍板);不传(undefined)= 本轮增量(followup 前 events 之后)
2483
2523
  */
2484
- async function askSkiff(ctx, agent, question, eventsStart = 0) {
2485
- const before = eventsStart > 0 ? eventsStart : agent.session.events.length;
2524
+ async function askSkiff(ctx, agent, question, eventsStart) {
2525
+ const before = eventsStart === void 0 ? agent.session.events.length : eventsStart;
2486
2526
  agent.followup(createUserMessage({
2487
2527
  content: [{
2488
2528
  type: "text",
@@ -6806,7 +6846,9 @@ dsp 只提供机制(双白名单强制 + 基础提示词 + 调试问答页)
6806
6846
  "msms": ["msm-a", "msm-b"], // MSM 白名单(独立):acc_msm exec 只能跑这些;register/deregister 必拒;list 只显示这些
6807
6847
  "tools": ["read","grep","glob",...], // 非 MSM 工具白名单(独立):白名单外工具一律不可用(guard 强制)
6808
6848
  "trajectory": { "session": false, "keeper": false, "rebuild": false }, // 轨迹纪律子集(缺省全关 = 完全独立)
6809
- "systemPrompt": "..." // 角色人格/认知边界/风格(CCC 完整定义;dsp 只给基础提示词)
6849
+ // 角色人格/认知边界/风格(CCC 完整定义;dsp 只给基础提示词)
6850
+ "systemPromptFile": ".opencode/skiff/<role>.md" // ★ 推荐:引用 md 文件(相对 CCC 根;超长提示词在 JSON 内嵌不可读)
6851
+ // "systemPrompt": "..." // 兼容:内嵌字符串仍可用;两者都设时 systemPromptFile 优先
6810
6852
  }
6811
6853
  } } }
6812
6854
 
@@ -6837,6 +6879,8 @@ dsp 只提供机制(双白名单强制 + 基础提示词 + 调试问答页)
6837
6879
  启停 = 人工(设置面板开关,不随插件加载自动启动);未开启零资源占用
6838
6880
  生效机制:角色配置**实时读取**(改 .opencode/serenity.json → 刷新调试页即生效);
6839
6881
  改配置后用 skiff_admin apply 做显式校验 + 应用确认(绑定 CCC + 角色清单)
6882
+ 会话追问(v1.25.10):调试页持有当前会话,追问自动续接(同会话上下文延续);
6883
+ 「新对话」按钮开新会话;进程重启后旧会话不可续(WebUI 仍可见历史)
6840
6884
  注意:skill 加载对 skiff **恒可用**(不设白名单——读知识面,无写能力)`;
6841
6885
  /** 校验当前 CCC 的 skiff 配置:roles schema 合法 / msms 均已注册 / model ∈ handyman.models / systemPrompt 非空 */
6842
6886
  function validateSkiffConfig(root) {
@@ -6852,7 +6896,11 @@ function validateSkiffConfig(root) {
6852
6896
  const hc = readHandymanConfig(root);
6853
6897
  const allowedModels = hc ? new Set(hc.models) : null;
6854
6898
  for (const [name, role] of roles) {
6855
- if (!role.systemPrompt?.trim()) issues.push(`role "${name}": systemPrompt is empty (CCC should fully define the role persona)`);
6899
+ try {
6900
+ if (!resolveRoleSystemPrompt(root, role).trim()) issues.push(`role "${name}": system prompt is empty (define systemPromptFile (recommended) or systemPrompt)`);
6901
+ } catch (err) {
6902
+ issues.push(`role "${name}": ${String(err?.message ?? err)}`);
6903
+ }
6856
6904
  for (const m of role.msms ?? []) if (!registered.has(m)) issues.push(`role "${name}": msms "${m}" is not registered in mech-registry.json`);
6857
6905
  if (role.model && allowedModels && !allowedModels.has(role.model)) issues.push(`role "${name}": model "${role.model}" not in handyman.models (${[...allowedModels].join(", ") || "(none)"})`);
6858
6906
  }
@@ -6879,7 +6927,8 @@ function listSkiffRoles(root) {
6879
6927
  keeper: role.trajectory?.keeper === true,
6880
6928
  rebuild: role.trajectory?.rebuild === true
6881
6929
  },
6882
- hasSystemPrompt: Boolean(role.systemPrompt?.trim())
6930
+ promptSource: systemPromptSource(role),
6931
+ ...role.systemPromptFile ? { systemPromptFile: role.systemPromptFile } : {}
6883
6932
  }));
6884
6933
  return {
6885
6934
  roles: items,
@@ -6914,7 +6963,7 @@ function applySkiffConfig(root) {
6914
6963
  }
6915
6964
  const skiffAdminTool = defineTool({
6916
6965
  name: "skiff_admin",
6917
- description: "Skiff (F4, experimental): CCC cognitive-subset roles (subsets of the full serenity trajectory). guide: definition tutorial (concept/role schema/cognitive MSM writing/dual whitelist/trajectory subset/examples); validate: check the CCC skiff config (roles schema legal / msms registered / model in handyman.models / systemPrompt non-empty); apply: validate then confirm the config is live (bound CCC + role list; roles are read live on every request); list: role summary (name/model/msms/tools/trajectory). Roles are defined by the CCC in .opencode/serenity.json skiff.roles; skill loading is always available to skiff sessions (not whitelisted).",
6966
+ description: "Skiff (F4, experimental): CCC cognitive-subset roles (subsets of the full serenity trajectory). guide: definition tutorial (concept/role schema/cognitive MSM writing/dual whitelist/trajectory subset/examples); validate: check the CCC skiff config (roles schema legal / msms registered / model in handyman.models / system prompt resolvable — systemPromptFile (recommended) or systemPrompt non-empty); apply: validate then confirm the config is live (bound CCC + role list; roles are read live on every request); list: role summary (name/model/msms/tools/trajectory/prompt source). Roles are defined by the CCC in .opencode/serenity.json skiff.roles; skill loading is always available to skiff sessions (not whitelisted).",
6918
6967
  parameters: { action: {
6919
6968
  type: "string",
6920
6969
  enum: [
@@ -11084,6 +11133,13 @@ function skiffDebugPage(cccs, defaultRoot, webPort) {
11084
11133
  .sub { opacity: .65; font-size: 13px; margin-bottom: 16px; }
11085
11134
  .ccc { display: inline-block; padding: 3px 10px; border-radius: 999px; background: rgba(11,168,117,.12); color: #0ba875; font-size: 12px; font-weight: 600; margin-bottom: 12px; word-break: break-all; }
11086
11135
  @media (prefers-color-scheme: dark) { .ccc { color: #3ddc9a; } }
11136
+ .sessionbar { display: flex; align-items: center; gap: 10px; margin-bottom: 4px; }
11137
+ .session-badge { font-family: ui-monospace, SFMono-Regular, monospace; font-size: 12px; padding: 3px 10px; border-radius: 999px; background: rgba(127,127,127,.12); word-break: break-all; }
11138
+ .session-badge.continued { background: rgba(11,168,117,.12); color: #0ba875; }
11139
+ @media (prefers-color-scheme: dark) { .session-badge.continued { color: #3ddc9a; } }
11140
+ button.ghost { background: transparent; color: #57606a; border: 1px solid #d0d7de; padding: 4px 12px; font-size: 12px; border-radius: 8px; cursor: pointer; margin-top: 0; }
11141
+ @media (prefers-color-scheme: dark) { button.ghost { color: #8b949e; border-color: #3a3d42; } }
11142
+ button.ghost:hover { background: rgba(127,127,127,.1); }
11087
11143
  label { font-size: 13px; font-weight: 600; display: block; margin: 12px 0 4px; }
11088
11144
  select, textarea { width: 100%; box-sizing: border-box; padding: 8px 10px; border-radius: 8px; border: 1px solid #d0d7de; background: #fff; color: inherit; font-size: 14px; }
11089
11145
  @media (prefers-color-scheme: dark) { select, textarea { background: #26282c; border-color: #3a3d42; } }
@@ -11120,14 +11176,18 @@ function skiffDebugPage(cccs, defaultRoot, webPort) {
11120
11176
  <body>
11121
11177
  <main>
11122
11178
  <h1>Skiff Debug</h1>
11123
- <div class="sub">宁静号 trajectory 子集角色问答页(v1.25.9 实验性)— 多 CCC 可切换,走 DSH agent-loop 会话核心,回答 marked 服务端渲染 + think 折叠</div>
11179
+ <div class="sub">宁静号 trajectory 子集角色问答页(v1.25.10 实验性)— 多 CCC 可切换,同会话可追问(新对话按钮开新会话),回答 marked 服务端渲染 + think 折叠</div>
11124
11180
  <div class="ccc" id="cccBadge"></div>
11181
+ <div class="sessionbar">
11182
+ <span id="sessionBadge" class="session-badge muted">(新会话)</span>
11183
+ <button id="newChat" type="button" class="ghost">新对话</button>
11184
+ </div>
11125
11185
  <label for="ccc">认知容器</label>
11126
11186
  <select id="ccc"></select>
11127
11187
  <label for="role">角色</label>
11128
11188
  <select id="role"></select>
11129
11189
  <label for="q">问题</label>
11130
- <textarea id="q" placeholder="向该角色提问…"></textarea>
11190
+ <textarea id="q" placeholder="向该角色提问…(追问直接继续输入)"></textarea>
11131
11191
  <button id="ask">提问</button>
11132
11192
  <div id="answer" class="muted">等待提问…</div>
11133
11193
  <div id="trajectory"></div>
@@ -11140,10 +11200,26 @@ const defaultRoot = document.getElementById('skiff-data').dataset.default
11140
11200
  const cccSel = document.getElementById('ccc')
11141
11201
  const roleSel = document.getElementById('role')
11142
11202
  const badge = document.getElementById('cccBadge')
11203
+ const sessionBadge = document.getElementById('sessionBadge')
11204
+ const newChatBtn = document.getElementById('newChat')
11143
11205
  const btn = document.getElementById('ask')
11144
11206
  const answer = document.getElementById('answer')
11145
11207
  const traj = document.getElementById('trajectory')
11146
11208
  const esc = (s) => String(s ?? '').replace(/[&<>"']/g, (c) => ({'&':'&amp;','<':'&lt;','>':'&gt;','"':'&quot;',"'":'&#39;'}[c]))
11209
+ let sessionId = ''
11210
+ function shortId(id) { return id.length > 24 ? id.slice(0, 18) + '…' + id.slice(-6) : id }
11211
+ function renderSessionBadge() {
11212
+ sessionBadge.textContent = sessionId ? '会话 ' + shortId(sessionId) + '(追问续接)' : '(新会话)'
11213
+ sessionBadge.className = 'session-badge' + (sessionId ? ' continued' : '')
11214
+ }
11215
+ function newConversation() {
11216
+ sessionId = ''
11217
+ renderSessionBadge()
11218
+ answer.className = 'muted'
11219
+ answer.textContent = '已开启新对话'
11220
+ traj.innerHTML = ''
11221
+ document.getElementById('q').value = ''
11222
+ }
11147
11223
  function currentCcc() {
11148
11224
  return CCCS.find((c) => c.root === cccSel.value) || (CCCS[0] || { root: '', name: '', roles: [] })
11149
11225
  }
@@ -11162,8 +11238,11 @@ function fillRoles() {
11162
11238
  ? c.roles.map((r) => '<option value="' + esc(r) + '">' + esc(r) + '</option>').join('')
11163
11239
  : '<option value="">(未配置角色)</option>'
11164
11240
  }
11165
- cccSel.addEventListener('change', fillRoles)
11241
+ cccSel.addEventListener('change', () => { fillRoles(); newConversation() })
11242
+ roleSel.addEventListener('change', () => newConversation())
11243
+ newChatBtn.addEventListener('click', newConversation)
11166
11244
  fillCccs()
11245
+ renderSessionBadge()
11167
11246
  btn.addEventListener('click', async () => {
11168
11247
  const c = currentCcc()
11169
11248
  const role = roleSel.value
@@ -11174,11 +11253,18 @@ btn.addEventListener('click', async () => {
11174
11253
  answer.textContent = '运行中…'
11175
11254
  traj.innerHTML = ''
11176
11255
  try {
11177
- const res = await fetch('/ask', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ccc: c.root, role, question: q }) })
11256
+ const res = await fetch('/ask', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ ccc: c.root, role, question: q, sessionId: sessionId || undefined }) })
11178
11257
  const data = await res.json()
11179
- if (!res.ok) throw new Error(data.error || ('HTTP ' + res.status))
11258
+ if (!res.ok) {
11259
+ // 会话不可恢复/绑定不匹配 → 前端清空 sessionId 重建(用户拍板:切换即新对话)
11260
+ sessionId = ''
11261
+ renderSessionBadge()
11262
+ throw new Error(data.error || ('HTTP ' + res.status))
11263
+ }
11180
11264
  answer.className = ''
11181
11265
  answer.innerHTML = data.answer_html || esc(data.answer || '') || '(空回答)'
11266
+ sessionId = data.sessionId || sessionId
11267
+ renderSessionBadge()
11182
11268
  renderTrajectory(data.trajectory || [], data.sessionId || '')
11183
11269
  } catch (err) {
11184
11270
  answer.className = 'err'
@@ -11288,6 +11374,7 @@ async function handle(ctx, defaultRoot, webPort, req, res) {
11288
11374
  const ccc = typeof body.ccc === "string" && body.ccc !== "" ? body.ccc : defaultRoot;
11289
11375
  const roleName = typeof body.role === "string" ? body.role : "";
11290
11376
  const question = typeof body.question === "string" ? body.question : "";
11377
+ const sessionId = typeof body.sessionId === "string" && body.sessionId !== "" ? body.sessionId : void 0;
11291
11378
  const role = readSkiffRoles(ccc).get(roleName);
11292
11379
  if (!roleName || !role) {
11293
11380
  sendJson(res, 400, { error: `unknown role: ${roleName} (ccc: ${ccc})` });
@@ -11297,11 +11384,30 @@ async function handle(ctx, defaultRoot, webPort, req, res) {
11297
11384
  sendJson(res, 400, { error: "empty question" });
11298
11385
  return;
11299
11386
  }
11300
- const result = await askSkiff(ctx, (await createSkiffAgent(ctx, ccc, roleName, role, readHandymanConfig(ccc)?.defaultModel)).agent, question);
11387
+ let agent;
11388
+ let continued = false;
11389
+ if (sessionId) {
11390
+ const info = skiffSessionInfo(sessionId);
11391
+ const live = getSkiffAgent(sessionId);
11392
+ if (!info || !live) {
11393
+ sendJson(res, 400, { error: "session is not recoverable (process restarted or session unknown) — start a new conversation" });
11394
+ return;
11395
+ }
11396
+ if (info.role !== roleName || info.ccc !== ccc) {
11397
+ sendJson(res, 400, { error: `session "${sessionId}" belongs to role "${info.role}" in another CCC — start a new conversation` });
11398
+ return;
11399
+ }
11400
+ agent = live;
11401
+ continued = true;
11402
+ }
11403
+ const hc = readHandymanConfig(ccc);
11404
+ if (!agent) agent = (await createSkiffAgent(ctx, ccc, roleName, role, hc?.defaultModel)).agent;
11405
+ const result = await askSkiff(ctx, agent, question, 0);
11301
11406
  sendJson(res, 200, {
11302
11407
  answer: result.answer,
11303
11408
  answer_html: renderSkiffMarkdown(result.answer),
11304
11409
  sessionId: result.sessionId,
11410
+ continued,
11305
11411
  trajectory: result.trajectory
11306
11412
  });
11307
11413
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@shgroup/dsh-serenity-hooks",
3
- "version": "1.25.9",
3
+ "version": "1.25.10",
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": {