@shgroup/dsh-serenity-hooks 1.46.0 → 1.47.0
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 +3 -3
- package/dsh.plugin.json +1 -1
- package/lib/client.js +45 -34
- package/lib/cro-turns.d.ts +3 -3
- package/lib/host/access.d.ts +11 -1
- package/lib/host/contract.d.ts +2 -2
- package/lib/index.d.ts +20 -0
- package/lib/index.js +726 -69
- package/lib/{trajectory-bound-BPWKkzJC.js → message-source-Boc-AbHs.js} +7 -1
- package/lib/message-source.d.ts +28 -0
- package/lib/output-guard-seam.d.ts +9 -0
- package/lib/seams/context.d.ts +1 -1
- package/lib/{settings-section-CIuyoSOX.js → settings-section-DTJW4smh.js} +52 -66
- package/lib/settings-section.d.ts +84 -42
- package/lib/unattended-ops.d.ts +247 -0
- package/lib/unattended-seam.d.ts +49 -0
- package/lib/{wake-scheduler-DF-YWcX5.js → wake-scheduler-DdaRNofO.js} +10 -12
- package/package.json +52 -52
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
> **一句话**:装上这个插件,你在电脑上给 AI 划一块自己的工作区(就是一个普通目录),
|
|
4
4
|
> AI 在里面干活时就有了**记忆、纪律、工具和边界**——中途换模型、重启电脑、第二天再来,都能接着干。
|
|
5
5
|
>
|
|
6
|
-
> 适用 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(下称 DSH)0.1.
|
|
6
|
+
> 适用 [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)(下称 DSH)0.1.7-rc.1 及以上。
|
|
7
7
|
> 想了解背后的想法(为什么叫"认知容器"),看 [docs/cognitive-container-theory.md](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/docs/cognitive-container-theory.md);本文只讲**能干什么、怎么用**。
|
|
8
8
|
|
|
9
9
|
**几个词先说明白**(后面都用这几个词,不再解释):
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
|
|
33
33
|
## 2. 快速开始(2 分钟)
|
|
34
34
|
|
|
35
|
-
前置:Node ≥ 20(或 bun)、DSH 0.1.
|
|
35
|
+
前置:Node ≥ 20(或 bun)、DSH 0.1.7-rc.1 及以上。
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
38
|
# 1. 装插件(自动加入 DSH 的 web profile)
|
|
@@ -423,4 +423,4 @@ pnpm build # 打包(lib/index.js + client.js)
|
|
|
423
423
|
|
|
424
424
|
MIT(见 [LICENSE](https://github.com/tellmewhattodo/dsh-serenity-plugin/blob/master/LICENSE))
|
|
425
425
|
|
|
426
|
-
> **版本**:v1.
|
|
426
|
+
> **版本**:v1.47.0 | **前置**:DSH 0.1.7-rc.1+ / Node ≥ 20 或 bun | **测试**:107 个文件 / 1679 个用例
|
package/dsh.plugin.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "dsh-serenity-hooks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.47.0",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"description": "宁静号 ACC harness(Native Cordis 插件):给 DSH 装一个「AI 工作区」——11 个工具(container_fs/container_trajectory/dashboard/container_git/msm/praxis/handyman/localstore/container_admin/im-bridge/acc-diag;后两个按配置条件出现)+ 机械约束(安全模式/工作区围墙/密钥守卫)+ 轨迹日志与原地重建 + 网页登录入口/微信桥/子角色/对外问答页/trajectory 唤醒注册表。适配 DSH 0.1.5-rc.2(deepseek-ai/deepseek-harness)。",
|
|
6
6
|
"engines": {
|
package/lib/client.js
CHANGED
|
@@ -208,7 +208,7 @@ window.__ModuleLoader__.load({
|
|
|
208
208
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: cx("sp-switchThumb") })
|
|
209
209
|
})
|
|
210
210
|
] }),
|
|
211
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
211
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconChevronDownOutlineMedium, {
|
|
212
212
|
size: 12,
|
|
213
213
|
className: cx("sp-chev")
|
|
214
214
|
})
|
|
@@ -289,7 +289,7 @@ window.__ModuleLoader__.load({
|
|
|
289
289
|
disabled: busy,
|
|
290
290
|
onClick: () => void toggle(!status.safeModeOn),
|
|
291
291
|
children: [
|
|
292
|
-
status.safeModeOn && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.
|
|
292
|
+
status.safeModeOn && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_deepseek_ai_dsh_client_ui_primitives.IconWarningOutlineMedium, {
|
|
293
293
|
size: 14,
|
|
294
294
|
className: cx("sp-toggleIcon")
|
|
295
295
|
}),
|
|
@@ -4672,8 +4672,6 @@ Instruction-following style:
|
|
|
4672
4672
|
}
|
|
4673
4673
|
//#endregion
|
|
4674
4674
|
//#region src/client/SettingsSection.tsx
|
|
4675
|
-
/** 降级提示文案(旧 RC 白名单时引导去宁静号面板) */
|
|
4676
|
-
const DEGRADE_NOTE = "当前运行版本未暴露 serenity-hooks 配置(旧 RC 白名单)。请升级 DSH 或使用会话头部 Serenity 状态栏。";
|
|
4677
4675
|
/** 开关(官方 settings 语言:label 右置 toggle,--dsw-alias-* token) */
|
|
4678
4676
|
function Toggle(props) {
|
|
4679
4677
|
const { checked, disabled, onChange } = props;
|
|
@@ -4791,32 +4789,20 @@ Instruction-following style:
|
|
|
4791
4789
|
}
|
|
4792
4790
|
/** dsh 原生设置面板:serenity-hooks 配置页(官方 settings 设计语言,多级标题) */
|
|
4793
4791
|
function SettingsSection(props) {
|
|
4794
|
-
const {
|
|
4795
|
-
const
|
|
4796
|
-
(0, react.useEffect)(() => {
|
|
4797
|
-
return scope.subscribe(() => setSnapshot(scope.getSnapshot()));
|
|
4798
|
-
}, [scope]);
|
|
4799
|
-
const value = snapshot.value;
|
|
4800
|
-
const ready = snapshot.status === "ready";
|
|
4792
|
+
const { set, useSerenitySettings } = props;
|
|
4793
|
+
const value = useSerenitySettings((s) => s).value;
|
|
4801
4794
|
const toggle = (field, on) => {
|
|
4802
|
-
|
|
4795
|
+
set(field, on);
|
|
4803
4796
|
};
|
|
4804
4797
|
const setThreshold = (v) => {
|
|
4805
|
-
|
|
4798
|
+
set("rebuildThresholdK", Math.min(4e3, Math.max(50, Math.round(v))));
|
|
4806
4799
|
};
|
|
4807
4800
|
const setSkiffPort = (v) => {
|
|
4808
|
-
|
|
4801
|
+
set("skiffDebugPort", Math.min(65535, Math.max(1024, Math.round(v))));
|
|
4809
4802
|
};
|
|
4810
4803
|
const setAcpPort = (v) => {
|
|
4811
|
-
|
|
4804
|
+
set("acpHttpPort", Math.min(65535, Math.max(1024, Math.round(v))));
|
|
4812
4805
|
};
|
|
4813
|
-
if (!ready) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4814
|
-
className: "ss-section",
|
|
4815
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4816
|
-
className: "ss-degrade",
|
|
4817
|
-
children: DEGRADE_NOTE
|
|
4818
|
-
})
|
|
4819
|
-
});
|
|
4820
4806
|
const gatewayOn = value?.gatewayEnabled ?? false;
|
|
4821
4807
|
const rebuildOn = value?.rebuildEnabled ?? true;
|
|
4822
4808
|
const thresholdK = value?.rebuildThresholdK ?? 400;
|
|
@@ -4826,12 +4812,14 @@ Instruction-following style:
|
|
|
4826
4812
|
const acpPort = value?.acpHttpPort ?? 3100;
|
|
4827
4813
|
const publicAskOn = value?.publicAskEnabled ?? false;
|
|
4828
4814
|
const croOn = value?.croEnabled ?? true;
|
|
4815
|
+
const unattendedOn = value?.unattendedEnabled ?? false;
|
|
4829
4816
|
const [openGateway, setOpenGateway] = (0, react.useState)(false);
|
|
4830
4817
|
const [openRebuild, setOpenRebuild] = (0, react.useState)(false);
|
|
4831
4818
|
const [openSkiff, setOpenSkiff] = (0, react.useState)(false);
|
|
4832
4819
|
const [openAcp, setOpenAcp] = (0, react.useState)(false);
|
|
4833
4820
|
const [openPublicAsk, setOpenPublicAsk] = (0, react.useState)(false);
|
|
4834
4821
|
const [openCro, setOpenCro] = (0, react.useState)(false);
|
|
4822
|
+
const [openUnattended, setOpenUnattended] = (0, react.useState)(false);
|
|
4835
4823
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4836
4824
|
className: "ss-section",
|
|
4837
4825
|
children: [
|
|
@@ -4902,6 +4890,27 @@ Instruction-following style:
|
|
|
4902
4890
|
})
|
|
4903
4891
|
}) })
|
|
4904
4892
|
}),
|
|
4893
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Group, {
|
|
4894
|
+
title: "无人值守",
|
|
4895
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("li", { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RowCard, {
|
|
4896
|
+
title: "无人值守代理回复",
|
|
4897
|
+
desc: "你走开后,会话被模型停下且无人应答时,由 ACC 代你回一句让它自己收束(默认关)",
|
|
4898
|
+
expandable: true,
|
|
4899
|
+
open: openUnattended,
|
|
4900
|
+
onToggle: setOpenUnattended,
|
|
4901
|
+
control: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Toggle, {
|
|
4902
|
+
checked: unattendedOn,
|
|
4903
|
+
onChange: (on) => toggle("unattendedEnabled", on)
|
|
4904
|
+
}),
|
|
4905
|
+
detail: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4906
|
+
className: "ss-detailStack",
|
|
4907
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
4908
|
+
className: "ss-detailIntro",
|
|
4909
|
+
children: "无人值守代理回复(unattended proxy)\n· 作用:你发完任务就走开,模型干一段停下来又没人接话 ⇒ 会话就挂住了;\n 本机制由 ACC 注入一条“代理用户”的结构化回复,让它自己接着干\n· 收束方式:每轮给一个验证码;只有四种明确收束才放过 —— 干完了 / 已通知你并停下等你 /\n 需确认但可自决(按最保守可逆的做并记理由)/ 撞上“不可代批”的事(立刻停并写待办)\n· 身份:代理消息会自报“无人值守代理 · 非本人”,不会被当成你说的话\n· 不适用:有 CRO 自编程唤起程序的轨迹(它自己会叫自己)、对外面与微信桥会话、子代理会话\n· 默认关:它把“人”从回路里拿掉,失败是静默的 ⇒ 只在你要离开时才开\n· 配套:你自己用 send-later 给自己排的“定时叫醒”(现在约每 2 小时一次)会改成“很久才叫一次”(6–12 小时);\n 平时“接着干”的活交给本机制 —— ⚠️ 只在本机制上线之后才这么改,否则中间会出现没人管的空档\n· 本版现状:机制已实现(开关 + 注入行为 + 流水);⚠️ 尚未部署 ⇒ 现在拨开关不会生效,等发布后生效"
|
|
4910
|
+
})
|
|
4911
|
+
})
|
|
4912
|
+
}) })
|
|
4913
|
+
}),
|
|
4905
4914
|
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Group, {
|
|
4906
4915
|
title: "外部能力",
|
|
4907
4916
|
children: [
|
|
@@ -5147,19 +5156,16 @@ Instruction-following style:
|
|
|
5147
5156
|
"slots",
|
|
5148
5157
|
"conversation",
|
|
5149
5158
|
"sessions",
|
|
5150
|
-
"
|
|
5159
|
+
"configForms"
|
|
5151
5160
|
];
|
|
5152
|
-
/**
|
|
5153
|
-
const
|
|
5154
|
-
namespace: "serenity-hooks",
|
|
5155
|
-
decode: (section) => section !== null && typeof section === "object" ? section : void 0
|
|
5156
|
-
};
|
|
5161
|
+
/** 设置页命名空间 = profile 条目 id(与 host 侧 `SERENITY_SETTINGS_NS` 同值;单一真相源在 host 侧常量,此处只作字面量引用) */
|
|
5162
|
+
const SERENITY_SETTINGS_NS = "serenity-hooks";
|
|
5157
5163
|
function apply(ctx) {
|
|
5158
5164
|
ctx.inject([
|
|
5159
5165
|
"slots",
|
|
5160
5166
|
"conversation",
|
|
5161
5167
|
"sessions",
|
|
5162
|
-
"
|
|
5168
|
+
"configForms"
|
|
5163
5169
|
], (scope) => {
|
|
5164
5170
|
scope.effect(() => scope.slots.register({
|
|
5165
5171
|
name: "conversation.session.header.actions",
|
|
@@ -5182,14 +5188,19 @@ Instruction-following style:
|
|
|
5182
5188
|
order: 110,
|
|
5183
5189
|
inject: () => ({ uploadFile: (file, sessionId) => uploadFile(file, sessionId) })
|
|
5184
5190
|
}, FileFallbackDock), "serenity: file fallback dock");
|
|
5185
|
-
const
|
|
5186
|
-
scope.effect(() => scope.slots.register({
|
|
5191
|
+
const serenityForm = scope.configForms.get(SERENITY_SETTINGS_NS);
|
|
5192
|
+
scope.effect(() => scope.configForms.whileServed([SERENITY_SETTINGS_NS], () => scope.slots.inject("settings.section", () => scope.slots.register({
|
|
5187
5193
|
name: "settings.section",
|
|
5188
|
-
id:
|
|
5194
|
+
id: SERENITY_SETTINGS_NS,
|
|
5189
5195
|
order: 90,
|
|
5190
5196
|
label: () => "Serenity",
|
|
5191
|
-
inject: () => ({
|
|
5192
|
-
|
|
5197
|
+
inject: () => ({
|
|
5198
|
+
hooks: { serenitySettings: serenityForm },
|
|
5199
|
+
set: (field, value) => {
|
|
5200
|
+
serenityForm.set(field, value).catch((_error) => {});
|
|
5201
|
+
}
|
|
5202
|
+
})
|
|
5203
|
+
}, SettingsSection))), "serenity: simple settings section");
|
|
5193
5204
|
});
|
|
5194
5205
|
}
|
|
5195
5206
|
//#endregion
|
package/lib/cro-turns.d.ts
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*
|
|
13
13
|
* | 事件 | 动作 | 出处 |
|
|
14
14
|
* |---|---|---|
|
|
15
|
-
* | `agent/
|
|
15
|
+
* | `agent/created` | 标记「在跑」 | `host/contract.ts`(dsp 已在 `seams/context.ts` 订阅)。⚠️ v0.1.7 前名为 `agent/session-start`;新事件 `@mode = serial` ⇒ 处理函数须快速返回 |
|
|
16
16
|
* | `agent/turn-stopping` | 清除标记 | `host/contract.ts:277`(dsp 已在 `rebuild.ts:442` 等 4 处订阅) |
|
|
17
17
|
* | `agent/disposed` | **清该载体的项** | `host/contract.ts:280` |
|
|
18
18
|
* | `session/disposed` | **清该载体的项** | `host/contract.ts:283` |
|
|
@@ -52,7 +52,7 @@ import type { Context } from 'cordis';
|
|
|
52
52
|
import type { Agent } from '@deepseek-ai/dsh-agent';
|
|
53
53
|
/** 一次「在跑」记录的 TTL(见文件头的方向性判据) */
|
|
54
54
|
export declare const TURN_TTL_MS: number;
|
|
55
|
-
/** 标记「在跑」(`agent/
|
|
55
|
+
/** 标记「在跑」(`agent/created` + `agent/status=running` 调用) */
|
|
56
56
|
export declare function markTurnRunning(sessionId: string, nowMs: number, turn?: number | null): void;
|
|
57
57
|
/** 清除「在跑」(`turn-stopping` / disposed 调用) */
|
|
58
58
|
export declare function clearTurnRunning(sessionId: string): void;
|
|
@@ -82,7 +82,7 @@ export declare function __resetCroTurnsForTest(): void;
|
|
|
82
82
|
* 装配追踪(`index.ts` apply 调用):订阅四个既有事件 + 拆卸。
|
|
83
83
|
*
|
|
84
84
|
* **为什么订阅四个而不是两个**(R↓):
|
|
85
|
-
* · 前两个(`
|
|
85
|
+
* · 前两个(`agent/created` / `turn-stopping`)负责**语义**——"在不在跑";
|
|
86
86
|
* · 后两个(`agent/disposed` / `session/disposed`)负责**生命周期**——
|
|
87
87
|
* 载体没了必须清项,否则表按载体只增(本模块的头号风险)。
|
|
88
88
|
*
|
package/lib/host/access.d.ts
CHANGED
|
@@ -55,8 +55,18 @@ interface HostWebServer {
|
|
|
55
55
|
register?: (registration: unknown) => unknown;
|
|
56
56
|
port?: number;
|
|
57
57
|
}
|
|
58
|
+
/** `ctx.settings`(v0.1.7 起为 `SettingsForms`:按条目 Config 投影表单 + 页策略) */
|
|
58
59
|
interface HostSettings {
|
|
59
|
-
|
|
60
|
+
/** 页策略(本插件用它关掉自动生成页;v0.1.7 前无此成员) */
|
|
61
|
+
configure?: (presentation: {
|
|
62
|
+
auto?: boolean;
|
|
63
|
+
}, owner?: unknown) => unknown;
|
|
64
|
+
/** 读各条目表单(含 live 值 / 用户层);保留可选读取,供诊断面取证 */
|
|
65
|
+
describe?: (options?: {
|
|
66
|
+
redactSecrets?: boolean;
|
|
67
|
+
}) => unknown;
|
|
68
|
+
/** 写一个条目的 config(宿主负责落 profile 文档 + 校验) */
|
|
69
|
+
update?: (ns: string, patch: object, expectedRevision?: number) => Promise<void>;
|
|
60
70
|
}
|
|
61
71
|
/** `ctx.web`(injected;v1.30.12:fetch provider 注册通道) */
|
|
62
72
|
interface HostWeb {
|
package/lib/host/contract.d.ts
CHANGED
|
@@ -55,14 +55,14 @@ interface HostEventContract {
|
|
|
55
55
|
* 在名字写错/宿主改名时**编译失败**(v1.30.7,review F-04/F-05)。
|
|
56
56
|
* 该 import 为 type-only,编译期擦除,不产生运行时依赖。
|
|
57
57
|
*/
|
|
58
|
-
export declare const HOST_EVENT_NAMES: readonly ["agent/
|
|
58
|
+
export declare const HOST_EVENT_NAMES: readonly ["agent/created", "agent/pre-step", "agent/turn-stopping", "agent/status", "agent/inbox/inserted", "agent/inbox/claimed", "agent/disposed", "session/event", "session/created", "session/disposed", "settings/document-updated", "tools/pre-execute", "tools/post-execute", "system-prompt/assemble"];
|
|
59
59
|
type HostEventName = (typeof HOST_EVENT_NAMES)[number];
|
|
60
60
|
/**
|
|
61
61
|
* dsp 订阅的宿主事件清单(与 HOST_EVENT_NAMES 同源;impact/site 供 health 报告与文档)。
|
|
62
62
|
*/
|
|
63
63
|
export declare const HOST_EVENTS: readonly HostEventContract[];
|
|
64
64
|
/** dsp 被验证过的宿主版本范围(与 package.json peerDependencies 同源,单一真相源) */
|
|
65
|
-
export declare const REQUIRED_HOST_RANGE = "^0.1.
|
|
65
|
+
export declare const REQUIRED_HOST_RANGE = "^0.1.7-rc.1";
|
|
66
66
|
interface HostContractIssue {
|
|
67
67
|
id: string;
|
|
68
68
|
kind: 'service' | 'member' | 'version';
|
package/lib/index.d.ts
CHANGED
|
@@ -82,6 +82,26 @@ export interface Config {
|
|
|
82
82
|
visionPatch?: {
|
|
83
83
|
enabled?: boolean;
|
|
84
84
|
};
|
|
85
|
+
/** F1 双端口网关总开关(面板层;部署层同义键 = `gateway.enabled`) */
|
|
86
|
+
gatewayEnabled?: boolean;
|
|
87
|
+
/** F2 超限重建总开关(面板层;部署层同义键 = `rebuild.enabled`) */
|
|
88
|
+
rebuildEnabled?: boolean;
|
|
89
|
+
/** F2 触发阈值(K token;面板层;部署层同义键 = `rebuild.thresholdK`) */
|
|
90
|
+
rebuildThresholdK?: number;
|
|
91
|
+
/** F4 Skiff 调试服务总开关(面板层;部署层同义键 = `skiff.enabled`) */
|
|
92
|
+
skiffEnabled?: boolean;
|
|
93
|
+
/** F4 Skiff 调试端口(面板层;部署层同义键 = `skiff.debugPort`) */
|
|
94
|
+
skiffDebugPort?: number;
|
|
95
|
+
/** F4c ACP HTTP 端点总开关(面板层;部署层同义键 = `acp.enabled`) */
|
|
96
|
+
acpEnabled?: boolean;
|
|
97
|
+
/** F4c ACP HTTP 端口(面板层;部署层同义键 = `acp.httpPort`) */
|
|
98
|
+
acpHttpPort?: number;
|
|
99
|
+
/** F4d 建议问答页总开关(面板层;无部署层同义键) */
|
|
100
|
+
publicAskEnabled?: boolean;
|
|
101
|
+
/** CRO(轨迹自编程唤起)总闸(面板层;无部署层同义键;缺省开) */
|
|
102
|
+
croEnabled?: boolean;
|
|
103
|
+
/** 无人值守代理回复总闸(面板层;无部署层同义键;缺省关) */
|
|
104
|
+
unattendedEnabled?: boolean;
|
|
85
105
|
}
|
|
86
106
|
export declare const Config: z<Config>;
|
|
87
107
|
export declare function apply(ctx: Context, config: Config): void;
|