dsh-plugin-feihualing 1.0.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 ADDED
@@ -0,0 +1,108 @@
1
+ # dsh-plugin-feihualing —— 飞花令游戏插件
2
+
3
+ DeepSeek Harness 飞花令游戏插件:**简易 / 古法严格**双模式,游戏状态(令字、得分、已使用诗句、剩余提示次数)由插件**按会话独立维护**;插件自身不向主聊天输出流写入任何内容,所有播报由模型根据工具返回值完成。
4
+
5
+ ## 玩法
6
+
7
+ ### 关键词指令(直接对插件说)
8
+
9
+ | 指令 | 作用 |
10
+ | --- | --- |
11
+ | 开始飞花令 / 开始游戏 | 开启一局(关键词默认简易模式) |
12
+ | 结束飞花令 / 结束游戏 / 停止飞花令 | 结束对局并结算 |
13
+ | 换字 | 更换令字(得分与已用诗句保留) |
14
+ | 提示 | 消耗 1 次提示次数,给出参考诗句 |
15
+ | 认输 | 认输并结算 |
16
+ | 暂停 | 手动暂停并保存现场 |
17
+ | 继续飞花令 / 继续游戏 | 从暂停处继续 |
18
+
19
+ 非指令的普通消息若**包含令字**,会被当作诗句尝试自动判定;不含令字的消息视为聊天,直接忽略。
20
+
21
+ ### 判定规则
22
+
23
+ - **simple 简易**:诗句(4–48 字)任意位置包含令字即可,得分 +1;重复诗句无效。
24
+ - **ancient 古法严格**:令字必须位于本轮指定位置(第 1 字 → 第 7 字循环);位置不符或诗句过短无效。
25
+
26
+ ### 模型工具
27
+
28
+ | 工具 | 说明 |
29
+ | --- | --- |
30
+ | `feihualing_start` | 开始/重新开始对局,可选参数 `mode: simple \| ancient` |
31
+ | `feihualing_status` | 查询状态:模式、令字、得分、已用诗句、剩余提示次数、最近判定等 |
32
+ | `feihualing_stop` | 结束对局并结算 |
33
+
34
+ ### 自动暂停(保存现场)
35
+
36
+ 检测到 shell / 文件写入类工具调用(`bash`、`pwsh`、`shell`、`write`、`edit` 等,可配置 `autoPause` 关闭)时,游戏自动暂停,现场写入快照文件;宿主重启后同一会话可通过「继续飞花令」恢复。手动暂停同样保存现场。
37
+
38
+ ## 配置
39
+
40
+ 在 profile 的 `cordis.yml` 对应条目下配置(缺省值如下):
41
+
42
+ ```yaml
43
+ - id: feihualing
44
+ name: dsh-plugin-feihualing
45
+ config:
46
+ enable: true # 总开关
47
+ maxHintCount: 3 # 每局最大提示次数(0-10 整数)
48
+ autoPause: true # shell/文件写入工具调用时自动暂停
49
+ ```
50
+
51
+ ## 安装
52
+
53
+ > 本插件是 **DSH bundle**,安装到 profile 即自动挂载(id `feihualing`),运行时零第三方依赖。需已装 `dsh` CLI(或桌面版)、Node.js ≥ 20、pnpm ≥ 10;下文 profile 以 `desktop` 为例,替换为你实际的 profile(见 `$DSH_HOME/profiles/`)。
54
+
55
+ ### 从 GitHub 直接安装(推荐)
56
+
57
+ ```bash
58
+ dsh plugin --profile desktop add github:zhaoxuejie/dsh-plugin-feihualing
59
+ ```
60
+
61
+ - git 安装拿到的是源码,包的 `prepare` 脚本会在安装时自动执行 `pnpm run build` 生成 `lib/`,无需手动构建;
62
+ - pnpm ≥ 10 默认拒绝执行 git 依赖的 `prepare`,首次会失败:请在该 profile 目录的 `pnpm-workspace.yaml` 加入白名单后重跑上面的命令:
63
+
64
+ ```yaml
65
+ allowBuilds:
66
+ dsh-plugin-feihualing: true
67
+ ```
68
+
69
+ > ⚠️ 允许构建 = 允许安装时在您机器上执行该包代码,仅对信任的源码开启;更稳妥的是固定 commit:`github:zhaoxuejie/dsh-plugin-feihualing#<sha>`。
70
+
71
+ ### 克隆源码本地安装
72
+
73
+ ```bash
74
+ git clone https://github.com/zhaoxuejie/dsh-plugin-feihualing.git
75
+ cd dsh-plugin-feihualing
76
+ pnpm install && pnpm run build
77
+ dsh plugin --profile desktop add . # 在仓库根目录执行
78
+ ```
79
+
80
+ ### 或经 npm / tarball 安装(预构建,免白名单)
81
+
82
+ ```bash
83
+ dsh plugin --profile desktop add dsh-plugin-feihualing # 已发布 npm 时
84
+ dsh plugin --profile desktop add ./dsh-plugin-feihualing-1.0.0.tgz # 或 pnpm pack 产物
85
+ ```
86
+
87
+ ### 验证与卸载
88
+
89
+ ```bash
90
+ dsh --profile desktop --dump-config # 应能看到 "# == dsh-plugin-feihualing" 层
91
+ dsh --profile desktop # 启动后对模型说「开始飞花令」即可开局
92
+
93
+ dsh plugin --profile desktop remove dsh-plugin-feihualing # 卸载并清理快照
94
+ ```
95
+
96
+ 可选配置(提示次数、自动暂停等)见上方「配置」章节。
97
+
98
+ ## 文件读写安全(白名单)
99
+
100
+ - 快照目录固定为 `$DSH_HOME/storages/dsh-plugin-feihualing`(`DSH_HOME` 环境变量优先,否则 `~/.dsh`)。
101
+ - 所有读写经 `assertSnapshotPath()` 校验:会话 id 仅允许 `[A-Za-z0-9._-]{1,64}`、防目录穿越、文件大小上限 64 KB、内容逐字段校验;白名单目录以外的任何路径一律拒绝。
102
+ - 插件卸载时清空全部会话内存状态并删除白名单目录内全部快照(无残留)。
103
+
104
+ ## 其它说明
105
+
106
+ - 不使用定时器、无后台任务;会话之间状态完全隔离。
107
+ - 事件映射(需求名 → 本 Harness 实际事件):`user:message → user/message`、`turn:before → turn/start`、`turn:after → turn/end`、`tool:before → tool/call`、`plugin:unload → Cordis fiber dispose(ctx.effect 清理 + 字面量事件兜底)`。
108
+ - 不做侧边 UI 面板(按需求仅工具与事件逻辑);游戏状态经 `feihualing_status` 返回给模型播报。
@@ -0,0 +1,10 @@
1
+ # dsh-plugin-feihualing bundle patch:向 profile 插入一行 Loader 条目。
2
+ #
3
+ # 说明:DeepSeek Harness 生态里,插件包通过 package.json 的
4
+ # `dsh.bundle.patch` 指向本文件;安装器将 `- insert:` 块合并进
5
+ # profile 的 cordis.yml。此处保持“纯 insert”(id + name),
6
+ # 配置项交由用户按需在 profile 的 cordis.yml 条目 config 中覆写,
7
+ # 缺省值由插件代码与 cordis.yml 的 config schema 提供。
8
+ - insert:
9
+ - id: feihualing
10
+ name: dsh-plugin-feihualing
package/cordis.yml ADDED
@@ -0,0 +1,71 @@
1
+ # ============================================================
2
+ # dsh-plugin-feihualing 插件元配置
3
+ # ============================================================
4
+ name: dsh-plugin-feihualing
5
+ version: 1.0.0
6
+ description: >-
7
+ 飞花令游戏插件(简易 / 古法严格双模式)。
8
+ 支持关键词指令(开始飞花令、结束飞花令、换字、提示、认输、暂停、继续飞花令)、
9
+ 3 个模型工具(feihualing_start / feihualing_status / feihualing_stop)、
10
+ 按会话隔离的游戏状态(令字、得分、已用诗句、剩余提示次数),
11
+ 以及检测到 shell / 文件写入类工具调用时自动暂停并保存现场。
12
+ author: feihualing
13
+
14
+ # ------------------------------------------------------------
15
+ # Loader 条目(安装器写入 profile cordis.yml 时使用的形态)
16
+ # ------------------------------------------------------------
17
+ entry:
18
+ id: feihualing
19
+ name: dsh-plugin-feihualing
20
+ inject: [tools]
21
+
22
+ # ------------------------------------------------------------
23
+ # 配置 Schema(运行时在插件代码内同样执行严格校验)
24
+ # ------------------------------------------------------------
25
+ config:
26
+ enable:
27
+ type: boolean
28
+ default: true
29
+ description: 插件总开关;false 时完全不注册任何逻辑
30
+ maxHintCount:
31
+ type: integer
32
+ default: 3
33
+ min: 0
34
+ max: 10
35
+ description: 每局最大提示次数(剩余提示次数初始值)
36
+ autoPause:
37
+ type: boolean
38
+ default: true
39
+ description: >-
40
+ 自动暂停开关;为 true 时,检测到 shell / 文件写入类工具调用
41
+ (bash、pwsh、write、edit 等)自动暂停游戏并保存现场
42
+
43
+ # ------------------------------------------------------------
44
+ # UI 声明:按需求不做侧边面板,仅工具与事件逻辑
45
+ # ------------------------------------------------------------
46
+ ui:
47
+ sidePanel: false
48
+ note: 游戏状态通过 feihualing_status 工具返回给模型,由模型自然语言播报
49
+
50
+ # ------------------------------------------------------------
51
+ # 能力与安全声明
52
+ # ------------------------------------------------------------
53
+ capabilities:
54
+ provides:
55
+ - tool: feihualing_start
56
+ - tool: feihualing_status
57
+ - tool: feihualing_stop
58
+ listens:
59
+ - user:message # 实际映射到 Harness 会话事件 user/message
60
+ - turn:before # 实际映射到 Harness 会话事件 turn/start
61
+ - turn:after # 实际映射到 Harness 会话事件 turn/end
62
+ - tool:before # 实际映射到 Harness 会话事件 tool/call
63
+ - plugin:unload # 实际映射到 Cordis fiber dispose(ctx.effect 清理)
64
+
65
+ permissions:
66
+ filesystem:
67
+ whitelist:
68
+ - $DSH_HOME/storages/dsh-plugin-feihualing/**
69
+ note: 仅允许在快照白名单目录内读写;路径穿越、非法文件名一律拒绝
70
+ network: [] # 不使用网络
71
+ timers: none # 不使用定时器
package/lib/index.d.ts ADDED
@@ -0,0 +1,155 @@
1
+ /**
2
+ * ============================================================
3
+ * dsh-plugin-feihualing —— 飞花令游戏插件(DeepSeek Harness / Cordis)
4
+ * ============================================================
5
+ *
6
+ * 功能总览
7
+ * 1. 游戏模式:simple(简易,诗句任意位置包含令字即可)、
8
+ * ancient(古法严格,令字必须出现在本轮指定位置,按第 1 字到第 7 字循环)。
9
+ * 2. 关键词指令(真实用户消息中识别):开始飞花令、结束飞花令、换字、提示、
10
+ * 认输、暂停、继续飞花令。
11
+ * 3. 每个会话独立的内存游戏状态:令字、得分、usedPoems(已使用诗句集合)、
12
+ * 剩余提示次数等;会话之间互不共享,插件卸载时全部清空。
13
+ * 4. 自动暂停:监听工具调用事件,检测到 shell / 文件写入类工具(bash、pwsh、
14
+ * write、edit 等)调用时自动暂停游戏并把现场快照写入白名单目录。
15
+ * 5. 注册 3 个模型工具:feihualing_start、feihualing_status、feihualing_stop。
16
+ * 插件自身不向主聊天流输出任何内容——游戏播报由模型根据工具返回值完成,
17
+ * 从而不污染主聊天输出流(框架规则 7)。
18
+ * 6. 配置项:enable(总开关)、maxHintCount(最大提示次数)、autoPause(自动暂停开关)。
19
+ *
20
+ * Harness 事件映射(需求事件名 → 本 Harness 实际事件)
21
+ * user:message → 会话事件 user/message(仅处理 source.kind === 'user' 的真实输入)
22
+ * turn:before → 会话事件 turn/start
23
+ * turn:after → 会话事件 turn/end
24
+ * tool:before → 会话事件 tool/call(工具调用落盘,执行前可见)
25
+ * plugin:unload → Cordis fiber dispose:用 ctx.effect 清理函数实现(同时保留
26
+ * 字面量 'plugin:unload' 监听作为兼容兜底)
27
+ *
28
+ * 文件读写安全
29
+ * 快照根目录固定为 $DSH_HOME/storages/dsh-plugin-feihualing(白名单)。
30
+ * 所有读写先经过 assertSnapshotPath() 校验:会话 id 仅允许
31
+ * [A-Za-z0-9._-]{1,64}、路径拼接后必须仍位于白名单根目录内(防目录穿越)、
32
+ * 快照文件大小上限 64KB、内容逐字段校验。
33
+ *
34
+ * 约束
35
+ * 不使用定时器、无后台任务、不引入任何第三方 npm 运行时依赖
36
+ * (唯一运行时 import 是 Harness 原生包 @deepseek-ai/dsh-tools)。
37
+ */
38
+ import type { ToolDefinition } from '@deepseek-ai/dsh-tools';
39
+ /** 插件在 Loader 中的显示名。 */
40
+ export declare const name = "feihualing";
41
+ /** 依赖注入:等待 Harness 的 tools 服务就绪后再加载本插件。 */
42
+ export declare const inject: string[];
43
+ /** 游戏模式:simple 简易 / ancient 古法严格。 */
44
+ export type GameMode = 'simple' | 'ancient';
45
+ /** 游戏阶段:idle 无对局 / running 进行中 / paused 已暂停 / finished 已结束。 */
46
+ export type GamePhase = 'idle' | 'running' | 'paused' | 'finished';
47
+ /** 插件配置(与 cordis.yml 的 config schema 一一对应)。 */
48
+ export interface FeihualingConfig {
49
+ /** 总开关;false 时插件不注册任何逻辑。 */
50
+ enable: boolean;
51
+ /** 每局最大提示次数(剩余提示次数的初始值),0-10 的整数。 */
52
+ maxHintCount: number;
53
+ /** 自动暂停开关;检测到 shell/文件写入类工具调用时自动暂停并保存现场。 */
54
+ autoPause: boolean;
55
+ }
56
+ /** 单个会话的飞花令游戏状态(会话隔离的最小业务单元)。 */
57
+ export interface GameState {
58
+ /** 所属会话 id(状态与快照都以它为键)。 */
59
+ sessionId: string;
60
+ /** 当前阶段。 */
61
+ phase: GamePhase;
62
+ /** 游戏模式。 */
63
+ mode: GameMode;
64
+ /** 当前令字(单个汉字)。 */
65
+ lingzi: string;
66
+ /** 得分(每句有效诗句 +1)。 */
67
+ score: number;
68
+ /** 总尝试次数(含无效尝试,供统计展示)。 */
69
+ attempts: number;
70
+ /** 已使用诗句集合(展示形式,保留原文;去重基于 usedNormalized)。 */
71
+ usedPoems: string[];
72
+ /** 已使用诗句的规范化文本(用于去重判定,与 usedPoems 平行索引)。 */
73
+ usedNormalized: string[];
74
+ /** 剩余提示次数。 */
75
+ hintsLeft: number;
76
+ /** 古法模式当前要求的令字位置(1 起,1-7 循环)。 */
77
+ requiredPosition: number;
78
+ /** 暂停原因;未暂停时为空字符串。 */
79
+ pausedReason: string;
80
+ /** 最近一次事件/判定描述(模型经 status 工具读取后播报)。 */
81
+ lastEvent: string;
82
+ /** 开局时间戳(毫秒)。 */
83
+ startedAt: number;
84
+ /** 最近更新时间戳(毫秒)。 */
85
+ updatedAt: number;
86
+ }
87
+ /** 磁盘快照文件格式(v1,字段校验见 validateSnapshot)。 */
88
+ export interface SnapshotFile {
89
+ /** 快照格式版本,当前恒为 1。 */
90
+ version: 1;
91
+ /** 写入方插件标识。 */
92
+ plugin: 'dsh-plugin-feihualing';
93
+ /** 所属会话 id。 */
94
+ sessionId: string;
95
+ /** 保存时间戳(毫秒)。 */
96
+ savedAt: number;
97
+ /** 游戏状态现场。 */
98
+ state: GameState;
99
+ }
100
+ /** 对局进行中的阶段(start 工具返回值的 phase 取值,不含 idle)。 */
101
+ export type ActivePhase = 'running' | 'paused' | 'finished';
102
+ /** feihualing_start 工具返回值。 */
103
+ export interface StartResult {
104
+ /** 是否本次调用实际开启了对局(已在进行中时为 false)。 */
105
+ started: boolean;
106
+ phase: ActivePhase;
107
+ mode: GameMode;
108
+ lingzi: string;
109
+ score: number;
110
+ hintsLeft: number;
111
+ /** 面向模型的播报文案。 */
112
+ message: string;
113
+ }
114
+ /** feihualing_status 工具返回值(可选字段缺省表示不适用/无,与工具 JSON Schema 对齐)。 */
115
+ export interface StatusResult {
116
+ phase: GamePhase;
117
+ mode?: GameMode;
118
+ lingzi?: string;
119
+ score: number;
120
+ attempts: number;
121
+ /** 已使用诗句列表(快照副本,防止外部修改内部状态)。 */
122
+ usedPoems: string[];
123
+ hintsLeft: number;
124
+ /** 古法模式要求的令字位置;非古法或 idle 时缺省。 */
125
+ requiredPosition?: number;
126
+ pausedReason?: string;
127
+ lastEvent: string;
128
+ /** 当前会话最近的轮次号(来自 turn/start、turn/end 事件)。 */
129
+ turn: number;
130
+ }
131
+ /** feihualing_stop 工具返回值。 */
132
+ export interface StopResult {
133
+ stopped: boolean;
134
+ finalScore: number;
135
+ usedCount: number;
136
+ message: string;
137
+ }
138
+ /** 本插件消费的 Harness Context 最小子集(严格 TS 类型)。 */
139
+ export interface Context {
140
+ /** 注册事件监听,返回注销函数;随插件 fiber 卸载自动注销。 */
141
+ on(eventName: string, listener: (...args: any[]) => unknown): () => void;
142
+ /** 注册卸载清理:execute() 返回的 disposer 在插件卸载时执行。 */
143
+ effect(execute: () => (() => void) | void, label?: string): void;
144
+ /** Harness 工具注册表(tools 服务,由 inject: ['tools'] 保证可用)。 */
145
+ tools: {
146
+ register(definition: ToolDefinition): void;
147
+ };
148
+ /** 可选日志器;缺失时退回 console。 */
149
+ logger?: {
150
+ info(...args: unknown[]): void;
151
+ warn(...args: unknown[]): void;
152
+ error(...args: unknown[]): void;
153
+ };
154
+ }
155
+ export declare function apply(ctx: Context, rawConfig?: Partial<FeihualingConfig>): void;
package/lib/index.js ADDED
@@ -0,0 +1,851 @@
1
+ /**
2
+ * ============================================================
3
+ * dsh-plugin-feihualing —— 飞花令游戏插件(DeepSeek Harness / Cordis)
4
+ * ============================================================
5
+ *
6
+ * 功能总览
7
+ * 1. 游戏模式:simple(简易,诗句任意位置包含令字即可)、
8
+ * ancient(古法严格,令字必须出现在本轮指定位置,按第 1 字到第 7 字循环)。
9
+ * 2. 关键词指令(真实用户消息中识别):开始飞花令、结束飞花令、换字、提示、
10
+ * 认输、暂停、继续飞花令。
11
+ * 3. 每个会话独立的内存游戏状态:令字、得分、usedPoems(已使用诗句集合)、
12
+ * 剩余提示次数等;会话之间互不共享,插件卸载时全部清空。
13
+ * 4. 自动暂停:监听工具调用事件,检测到 shell / 文件写入类工具(bash、pwsh、
14
+ * write、edit 等)调用时自动暂停游戏并把现场快照写入白名单目录。
15
+ * 5. 注册 3 个模型工具:feihualing_start、feihualing_status、feihualing_stop。
16
+ * 插件自身不向主聊天流输出任何内容——游戏播报由模型根据工具返回值完成,
17
+ * 从而不污染主聊天输出流(框架规则 7)。
18
+ * 6. 配置项:enable(总开关)、maxHintCount(最大提示次数)、autoPause(自动暂停开关)。
19
+ *
20
+ * Harness 事件映射(需求事件名 → 本 Harness 实际事件)
21
+ * user:message → 会话事件 user/message(仅处理 source.kind === 'user' 的真实输入)
22
+ * turn:before → 会话事件 turn/start
23
+ * turn:after → 会话事件 turn/end
24
+ * tool:before → 会话事件 tool/call(工具调用落盘,执行前可见)
25
+ * plugin:unload → Cordis fiber dispose:用 ctx.effect 清理函数实现(同时保留
26
+ * 字面量 'plugin:unload' 监听作为兼容兜底)
27
+ *
28
+ * 文件读写安全
29
+ * 快照根目录固定为 $DSH_HOME/storages/dsh-plugin-feihualing(白名单)。
30
+ * 所有读写先经过 assertSnapshotPath() 校验:会话 id 仅允许
31
+ * [A-Za-z0-9._-]{1,64}、路径拼接后必须仍位于白名单根目录内(防目录穿越)、
32
+ * 快照文件大小上限 64KB、内容逐字段校验。
33
+ *
34
+ * 约束
35
+ * 不使用定时器、无后台任务、不引入任何第三方 npm 运行时依赖
36
+ * (唯一运行时 import 是 Harness 原生包 @deepseek-ai/dsh-tools)。
37
+ */
38
+ import { defineTool } from '@deepseek-ai/dsh-tools';
39
+ import * as fs from 'node:fs';
40
+ import * as os from 'node:os';
41
+ import * as path from 'node:path';
42
+ /** 插件在 Loader 中的显示名。 */
43
+ export const name = 'feihualing';
44
+ /** 依赖注入:等待 Harness 的 tools 服务就绪后再加载本插件。 */
45
+ export const inject = ['tools'];
46
+ // ============================================================
47
+ // 模块级常量(纯数据,无任何状态与副作用)
48
+ // ============================================================
49
+ const PLUGIN_ID = 'dsh-plugin-feihualing';
50
+ /** 快照格式版本。 */
51
+ const SNAPSHOT_VERSION = 1;
52
+ /** 快照文件大小上限(字节),防止恶意/损坏文件拖垮读取。 */
53
+ const MAX_SNAPSHOT_BYTES = 64 * 1024;
54
+ /** 诗句尝试的最小/最大长度(规范化后字符数)。 */
55
+ const MIN_LINE_CHARS = 4;
56
+ const MAX_LINE_CHARS = 48;
57
+ /** 古法令字位置循环上限(第 1 字 → 第 7 字 → 第 1 字)。 */
58
+ const MAX_ANCIENT_POSITION = 7;
59
+ /**
60
+ * 提示诗句库:令字 → 常见古诗词名句(仅用于“提示”功能,不参与判定;
61
+ * 判定只查“含令字 + 未重复 + 古法位置”,因此插件不依赖任何古诗数据库)。
62
+ * 全部为公有领域经典诗句。
63
+ */
64
+ const POEM_BANK = Object.freeze({
65
+ 花: ['花间一壶酒', '感时花溅泪', '人面桃花相映红', '霜叶红于二月花', '花落知多少', '春城无处不飞花'],
66
+ 月: ['床前明月光', '举头望明月', '海上生明月', '月落乌啼霜满天', '月是故乡明', '明月几时有'],
67
+ 风: ['夜来风雨声', '春风又绿江南岸', '风吹草低见牛羊', '二月春风似剪刀', '春风不度玉门关', '长风破浪会有时'],
68
+ 雪: ['窗含西岭千秋雪', '独钓寒江雪', '柴门闻犬吠,风雪夜归人', '北风吹雁雪纷纷', '雪上空留马行处', '北风卷地白草折,胡天八月即飞雪'],
69
+ 山: ['白日依山尽', '山重水复疑无路', '轻舟已过万重山', '空山不见人', '千山鸟飞绝', '会当凌绝顶,一览众山小'],
70
+ 水: ['抽刀断水水更流', '桃花潭水深千尺', '一江春水向东流', '山重水复疑无路', '行到水穷处'],
71
+ 云: ['黄河远上白云间', '只在此山中,云深不知处', '白云生处有人家', '行到水穷处,坐看云起时', '众鸟高飞尽,孤云独去闲'],
72
+ 雨: ['清明时节雨纷纷', '好雨知时节', '天街小雨润如酥', '巴山夜雨涨秋池', '山色空蒙雨亦奇'],
73
+ 春: ['春眠不觉晓', '春来江水绿如蓝', '春城无处不飞花', '春蚕到死丝方尽', '野火烧不尽,春风吹又生', '春风又绿江南岸'],
74
+ 秋: ['空山新雨后,天气晚来秋', '湖光秋月两相和', '自古逢秋悲寂寥', '春种一粒粟,秋收万颗子'],
75
+ 人: ['人生得意须尽欢', '人生自古谁无死', '人闲桂花落', '举杯邀明月,对影成三人', '路上行人欲断魂'],
76
+ 酒: ['花间一壶酒', '葡萄美酒夜光杯', '借问酒家何处有', '劝君更尽一杯酒', '对酒当歌'],
77
+ 夜: ['夜来风雨声', '忽如一夜春风来', '巴山夜雨涨秋池', '葡萄美酒夜光杯'],
78
+ 江: ['孤帆远影碧空尽,唯见长江天际流', '春来江水绿如蓝', '春风又绿江南岸', '一江春水向东流', '天门中断楚江开'],
79
+ 日: ['白日依山尽', '日照香炉生紫烟', '千里江陵一日还', '映日荷花别样红', '锄禾日当午'],
80
+ 星: ['星垂平野阔', '迢迢牵牛星', '危楼高百尺,手可摘星辰', '微微风簇浪,散作满河星'],
81
+ });
82
+ /** 开局/换字时随机抽取的令字池(即提示诗句库的键)。 */
83
+ const LINGZI_POOL = Object.keys(POEM_BANK);
84
+ const KEYWORDS = [
85
+ { action: 'stop', test: (t) => t.includes('结束飞花令') || t.includes('结束游戏') || t.includes('停止飞花令') },
86
+ { action: 'start', test: (t) => t.includes('开始飞花令') || t.includes('开始游戏') },
87
+ { action: 'resume', test: (t) => t.includes('继续飞花令') || t.includes('继续游戏') },
88
+ { action: 'pause', test: (t) => t.includes('暂停') },
89
+ { action: 'surrender', test: (t) => t.includes('认输') },
90
+ { action: 'swap', test: (t) => t.includes('换字') },
91
+ { action: 'hint', test: (t) => t.includes('提示') },
92
+ ];
93
+ /**
94
+ * 危险工具名集合(自动暂停触发条件):
95
+ * shell 类(bash/pwsh/shell 等)与文件写入类(write/edit/file_write)。
96
+ * 工具名先剥掉 "tool:" 前缀并转小写再匹配;本插件自己的 feihualing_* 工具除外。
97
+ */
98
+ const DANGEROUS_TOOL_NAMES = new Set([
99
+ 'bash', 'shell', 'sh', 'zsh', 'cmd', 'pwsh', 'powershell', 'subprocess', 'terminal',
100
+ 'write', 'edit', 'file_write',
101
+ ]);
102
+ // ============================================================
103
+ // 模块级纯函数(无状态、无副作用,仅做文本/路径处理)
104
+ // ============================================================
105
+ /**
106
+ * 规范化一行文本:去除空白与常见中英文标点,仅保留汉字/字母/数字。
107
+ * 用于关键词匹配与诗句去重比较。
108
+ */
109
+ function normalizeLine(raw) {
110
+ return raw.replace(/[\s,。!?、;:""''()《》〈〉【】\[\]·,.!?;:'"()\-—…]+/gu, '');
111
+ }
112
+ /**
113
+ * 从 user/message 事件的 content 中提取纯文本。
114
+ * 兼容字符串、文本块({ type: 'text'|'input_text', text })等形态。
115
+ */
116
+ function extractText(content) {
117
+ if (typeof content === 'string')
118
+ return content;
119
+ if (!Array.isArray(content))
120
+ return '';
121
+ let out = '';
122
+ for (const part of content) {
123
+ if (typeof part === 'string') {
124
+ out += part;
125
+ }
126
+ else if (part !== null && typeof part === 'object') {
127
+ const block = part;
128
+ if (typeof block.text === 'string')
129
+ out += block.text;
130
+ }
131
+ }
132
+ return out;
133
+ }
134
+ /** 归一化工具名:去掉 "tool:" 前缀并转小写。 */
135
+ function normalizeToolName(raw) {
136
+ if (typeof raw !== 'string')
137
+ return '';
138
+ return raw.replace(/^tool:/, '').toLowerCase();
139
+ }
140
+ /** 统一错误信息提取(catch 变量在 strict 模式下为 unknown)。 */
141
+ function errorMessage(error) {
142
+ return error instanceof Error ? error.message : String(error);
143
+ }
144
+ /** 去掉文本首尾空白(用于展示时压缩用户输入的换行/空格)。 */
145
+ function trimDisplay(raw) {
146
+ return raw.trim().replace(/\s+/gu, ' ').slice(0, MAX_LINE_CHARS);
147
+ }
148
+ // ============================================================
149
+ // 插件入口(所有状态与业务逻辑都在 apply 内部,无模块级可变状态)
150
+ // ============================================================
151
+ export function apply(ctx, rawConfig) {
152
+ // ---------- 1. 配置解析与严格校验(非法配置直接抛错拒绝加载) ----------
153
+ const config = resolveConfig(rawConfig);
154
+ /** 统一日志出口:优先 Harness logger,缺失时退回 console。 */
155
+ const log = (level, ...args) => {
156
+ try {
157
+ const target = ctx.logger ?? console;
158
+ target[level](...args);
159
+ }
160
+ catch {
161
+ /* 日志失败不影响游戏逻辑 */
162
+ }
163
+ };
164
+ // 总开关关闭:不注册任何事件监听与工具,插件整体空转。
165
+ if (!config.enable) {
166
+ log('info', `[${PLUGIN_ID}] enable=false,插件未启用`);
167
+ return;
168
+ }
169
+ // ---------- 2. 会话隔离的游戏状态表(仅存在于本 apply 闭包内) ----------
170
+ // 每个会话(session.id)一份独立 GameState;卸载时全部清空(见 cleanup)。
171
+ const games = new Map();
172
+ /** 各会话最近轮次号(来自 turn/start、turn/end 事件,用于状态展示)。 */
173
+ const lastTurns = new Map();
174
+ // ---------- 3. 快照白名单根目录:$DSH_HOME/storages/dsh-plugin-feihualing ----------
175
+ const dataDir = resolveDataDir();
176
+ /**
177
+ * 快照路径白名单校验(安全关键代码)。
178
+ * 校验三步:
179
+ * 1) 会话 id 必须是严格文件名形式([A-Za-z0-9._-]{1,64}),杜绝 ../ 等穿越字符;
180
+ * 2) path.resolve 后的最终路径必须与“白名单根目录 + 固定文件名”的拼接结果
181
+ * 完全一致(等价于拒绝任何穿越);
182
+ * 3) 最终路径必须位于白名单根目录之内(双保险前缀校验)。
183
+ * @throws 路径非法时抛出异常,调用方负责拦截。
184
+ */
185
+ function assertSnapshotPath(sessionId) {
186
+ if (!/^[A-Za-z0-9._-]{1,64}$/.test(sessionId)) {
187
+ throw new Error(`非法会话 id(仅允许 [A-Za-z0-9._-]{1,64}): ${JSON.stringify(sessionId)}`);
188
+ }
189
+ const root = path.resolve(dataDir);
190
+ const fileName = `snapshot-${sessionId}.json`;
191
+ const target = path.resolve(root, fileName);
192
+ if (target !== path.join(root, fileName)) {
193
+ throw new Error(`快照路径越界被拒绝: ${target}`);
194
+ }
195
+ if (!target.startsWith(root + path.sep)) {
196
+ throw new Error(`快照路径不在白名单目录内: ${target}`);
197
+ }
198
+ return target;
199
+ }
200
+ /** 保存现场:把会话游戏状态写入白名单目录内的快照文件(同步、原子性足够)。 */
201
+ function saveSnapshot(sessionId, state) {
202
+ try {
203
+ const file = assertSnapshotPath(sessionId);
204
+ fs.mkdirSync(dataDir, { recursive: true });
205
+ const snapshot = {
206
+ version: SNAPSHOT_VERSION,
207
+ plugin: PLUGIN_ID,
208
+ sessionId,
209
+ savedAt: Date.now(),
210
+ state: { ...state, usedPoems: [...state.usedPoems], usedNormalized: [...state.usedNormalized] },
211
+ };
212
+ fs.writeFileSync(file, JSON.stringify(snapshot, null, 2), 'utf8');
213
+ log('info', `[${PLUGIN_ID}] 会话 ${sessionId}: 现场已保存到 ${file}`);
214
+ }
215
+ catch (error) {
216
+ log('warn', `[${PLUGIN_ID}] 会话 ${sessionId}: 保存现场失败: ${errorMessage(error)}`);
217
+ }
218
+ }
219
+ /** 删除指定会话的快照文件(对局结束/认输/开局后调用;不存在则忽略)。 */
220
+ function deleteSnapshot(sessionId) {
221
+ try {
222
+ fs.unlinkSync(assertSnapshotPath(sessionId));
223
+ }
224
+ catch {
225
+ /* 文件不存在等一律忽略 */
226
+ }
227
+ }
228
+ /**
229
+ * 从快照恢复现场(例如宿主重启后同一会话继续)。
230
+ * 文件缺失、超限、JSON 损坏或字段校验失败时返回 undefined。
231
+ */
232
+ function restoreSnapshot(sessionId) {
233
+ let file;
234
+ try {
235
+ file = assertSnapshotPath(sessionId);
236
+ }
237
+ catch {
238
+ return undefined;
239
+ }
240
+ try {
241
+ const stat = fs.statSync(file);
242
+ if (stat.size > MAX_SNAPSHOT_BYTES) {
243
+ log('warn', `[${PLUGIN_ID}] 会话 ${sessionId}: 快照超过大小上限,已忽略`);
244
+ return undefined;
245
+ }
246
+ const parsed = JSON.parse(fs.readFileSync(file, 'utf8'));
247
+ const snapshot = validateSnapshot(parsed, sessionId);
248
+ if (snapshot === null)
249
+ return undefined;
250
+ log('info', `[${PLUGIN_ID}] 会话 ${sessionId}: 已从快照恢复现场(${snapshot.state.phase})`);
251
+ return snapshot.state;
252
+ }
253
+ catch {
254
+ return undefined;
255
+ }
256
+ }
257
+ /** 读取会话现场:内存优先,缺失时尝试从快照恢复(恢复后写入内存表)。 */
258
+ function ensureState(sessionId) {
259
+ const existing = games.get(sessionId);
260
+ if (existing)
261
+ return existing;
262
+ const restored = restoreSnapshot(sessionId);
263
+ if (restored)
264
+ games.set(sessionId, restored);
265
+ return restored;
266
+ }
267
+ // ---------- 4. 游戏引擎(纯内存状态机) ----------
268
+ /** 随机抽取令字;与 exclude 相同时重抽(最多重试几次,不用定时器)。 */
269
+ function pickLingzi(exclude) {
270
+ for (let attempt = 0; attempt < 8; attempt++) {
271
+ const lingzi = LINGZI_POOL[Math.floor(Math.random() * LINGZI_POOL.length)];
272
+ if (lingzi !== exclude)
273
+ return lingzi;
274
+ }
275
+ return LINGZI_POOL[0];
276
+ }
277
+ /** 创建一局新游戏。 */
278
+ function createGame(sessionId, mode) {
279
+ const lingzi = pickLingzi('');
280
+ const modeText = mode === 'ancient' ? '古法严格' : '简易';
281
+ return {
282
+ sessionId,
283
+ phase: 'running',
284
+ mode,
285
+ lingzi,
286
+ score: 0,
287
+ attempts: 0,
288
+ usedPoems: [],
289
+ usedNormalized: [],
290
+ hintsLeft: config.maxHintCount,
291
+ requiredPosition: 1,
292
+ pausedReason: '',
293
+ lastEvent: `飞花令开始!模式:${modeText},令字「${lingzi}」,剩余提示 ${config.maxHintCount} 次` + (mode === 'ancient' ? '(古法要求令字位于第 1 字)' : ''),
294
+ startedAt: Date.now(),
295
+ updatedAt: Date.now(),
296
+ };
297
+ }
298
+ /** 暂停游戏并记录原因(不负责写盘,由调用方决定是否保存现场)。 */
299
+ function pauseGame(state, reason) {
300
+ state.phase = 'paused';
301
+ state.pausedReason = reason;
302
+ state.lastEvent = `游戏已暂停:${reason}`;
303
+ state.updatedAt = Date.now();
304
+ }
305
+ /** 结束对局:置为 finished、清理暂停原因、删除快照文件。 */
306
+ function finishGame(sessionId, state, message) {
307
+ state.phase = 'finished';
308
+ state.pausedReason = '';
309
+ state.lastEvent = message;
310
+ state.updatedAt = Date.now();
311
+ deleteSnapshot(sessionId);
312
+ }
313
+ /**
314
+ * 诗句尝试判定(核心规则)。
315
+ * 尝试门槛:规范化后必须包含令字,否则视为普通聊天、不判定;
316
+ * 判定顺序:长度 → 去重 → 古法位置;全部通过则得分 +1。
317
+ */
318
+ function attemptPoem(state, rawText) {
319
+ const line = normalizeLine(rawText);
320
+ // 不含令字的消息不视为诗句尝试(普通聊天直接忽略)
321
+ if (!line.includes(state.lingzi))
322
+ return;
323
+ if (line.length < MIN_LINE_CHARS || line.length > MAX_LINE_CHARS) {
324
+ state.attempts += 1;
325
+ state.lastEvent = `「${trimDisplay(rawText)}」长度不符(需 ${MIN_LINE_CHARS}-${MAX_LINE_CHARS} 字),本次无效`;
326
+ state.updatedAt = Date.now();
327
+ return;
328
+ }
329
+ if (state.usedNormalized.includes(line)) {
330
+ state.attempts += 1;
331
+ state.lastEvent = `「${trimDisplay(rawText)}」已使用过,本次无效`;
332
+ state.updatedAt = Date.now();
333
+ return;
334
+ }
335
+ // 古法严格模式:令字必须位于本轮指定位置(第 1 字到第 7 字循环)
336
+ if (state.mode === 'ancient') {
337
+ const pos = state.requiredPosition;
338
+ if (line.length < pos) {
339
+ state.attempts += 1;
340
+ state.lastEvent = `「${trimDisplay(rawText)}」不足 ${pos} 字:古法要求令字「${state.lingzi}」位于第 ${pos} 字`;
341
+ state.updatedAt = Date.now();
342
+ return;
343
+ }
344
+ if (line[pos - 1] !== state.lingzi) {
345
+ state.attempts += 1;
346
+ state.lastEvent = `位置不符:「${trimDisplay(rawText)}」第 ${pos} 字应为令字「${state.lingzi}」`;
347
+ state.updatedAt = Date.now();
348
+ return;
349
+ }
350
+ }
351
+ // 判定通过:得分 +1,诗句入已使用集合,古法推进要求位置
352
+ state.attempts += 1;
353
+ state.score += 1;
354
+ state.usedPoems.push(trimDisplay(rawText));
355
+ state.usedNormalized.push(line);
356
+ if (state.mode === 'ancient') {
357
+ state.requiredPosition = (state.requiredPosition % MAX_ANCIENT_POSITION) + 1;
358
+ }
359
+ state.lastEvent = `判定有效!「${trimDisplay(rawText)}」得分 +1(当前 ${state.score} 分)`;
360
+ state.updatedAt = Date.now();
361
+ }
362
+ /** “提示”指令:消耗一次提示次数,从内置诗句库挑一句未使用的示例。 */
363
+ function consumeHint(state) {
364
+ if (state.hintsLeft <= 0) {
365
+ state.lastEvent = '提示次数已用完';
366
+ state.updatedAt = Date.now();
367
+ return;
368
+ }
369
+ state.hintsLeft -= 1;
370
+ const bank = POEM_BANK[state.lingzi] ?? [];
371
+ const candidate = bank.find((entry) => !state.usedNormalized.includes(normalizeLine(entry)));
372
+ const positionNote = state.mode === 'ancient' ? `(古法:令字「${state.lingzi}」需位于第 ${state.requiredPosition} 字)` : '';
373
+ state.lastEvent = candidate
374
+ ? `提示${positionNote}:例如「${candidate}」(仅作参考,请自行创作)`
375
+ : `提示${positionNote}:请说出一句包含「${state.lingzi}」的诗句`;
376
+ state.updatedAt = Date.now();
377
+ }
378
+ /** 关键词指令处理(无对局时除 start 外一律忽略)。 */
379
+ function applyCommand(sessionId, action) {
380
+ const existing = ensureState(sessionId);
381
+ switch (action) {
382
+ case 'start': {
383
+ // 关键词默认开启简易模式;模型如需古法模式可通过 feihualing_start 工具指定
384
+ const next = createGame(sessionId, 'simple');
385
+ if (existing)
386
+ next.lastEvent = `已重新开局(先前的对局已被替换):${next.lastEvent}`;
387
+ games.set(sessionId, next);
388
+ deleteSnapshot(sessionId); // 旧对局的暂停快照随新开局失效
389
+ return;
390
+ }
391
+ case 'stop':
392
+ if (existing)
393
+ finishGame(sessionId, existing, `游戏结束:最终得分 ${existing.score},共使用诗句 ${existing.usedPoems.length} 句`);
394
+ return;
395
+ case 'surrender':
396
+ if (existing)
397
+ finishGame(sessionId, existing, `玩家认输:最终得分 ${existing.score},共使用诗句 ${existing.usedPoems.length} 句`);
398
+ return;
399
+ case 'pause':
400
+ if (existing && existing.phase === 'running') {
401
+ pauseGame(existing, '玩家手动暂停');
402
+ saveSnapshot(sessionId, existing); // 手动暂停同样保存现场
403
+ }
404
+ return;
405
+ case 'resume':
406
+ if (existing && existing.phase === 'paused') {
407
+ existing.phase = 'running';
408
+ existing.pausedReason = '';
409
+ existing.lastEvent = '游戏继续';
410
+ existing.updatedAt = Date.now();
411
+ deleteSnapshot(sessionId); // 快照与“已暂停”一一对应,恢复运行后移除
412
+ }
413
+ return;
414
+ case 'swap':
415
+ if (existing && (existing.phase === 'running' || existing.phase === 'paused')) {
416
+ existing.lingzi = pickLingzi(existing.lingzi);
417
+ existing.requiredPosition = 1; // 古法位置从头循环
418
+ existing.lastEvent = `令字已更换为「${existing.lingzi}」`;
419
+ existing.updatedAt = Date.now();
420
+ }
421
+ return;
422
+ case 'hint':
423
+ if (existing && (existing.phase === 'running' || existing.phase === 'paused')) {
424
+ consumeHint(existing);
425
+ }
426
+ return;
427
+ }
428
+ }
429
+ // ---------- 5. 事件监听(Harness 原生事件;随插件 fiber 卸载自动注销) ----------
430
+ /**
431
+ * session/event:所有会话提交事件的统一入口(untagged 监听器全局可见)。
432
+ * 载荷为 (session, event),据此实现需求中的 user:message / turn:before /
433
+ * turn:after / tool:before 四类监听(映射关系见文件头注释)。
434
+ */
435
+ ctx.on('session/event', (session, event) => {
436
+ try {
437
+ if (session === null || typeof session !== 'object' || typeof session.id !== 'string')
438
+ return;
439
+ const sessionId = session.id;
440
+ switch (event?.type) {
441
+ // user:message —— 关键词指令 + 诗句尝试判定
442
+ case 'user/message': {
443
+ const data = event.data;
444
+ if (data === null || typeof data !== 'object')
445
+ return;
446
+ const message = data;
447
+ if (message.role !== 'user')
448
+ return;
449
+ // 只处理真实用户输入;压缩摘要等系统产生的 user/message 一律忽略
450
+ const source = message.source;
451
+ if (source?.kind !== 'user')
452
+ return;
453
+ const text = extractText(message.content);
454
+ if (text.trim().length === 0)
455
+ return;
456
+ const normalized = normalizeLine(text);
457
+ // 关键词指令优先级最高
458
+ const keyword = KEYWORDS.find((entry) => entry.test(normalized));
459
+ if (keyword) {
460
+ applyCommand(sessionId, keyword.action);
461
+ return;
462
+ }
463
+ // 非指令且游戏进行中 → 按诗句尝试判定
464
+ const state = ensureState(sessionId);
465
+ if (state && state.phase === 'running')
466
+ attemptPoem(state, text);
467
+ return;
468
+ }
469
+ // tool:before —— 自动暂停(shell / 文件写入类工具调用)
470
+ case 'tool/call': {
471
+ if (!config.autoPause)
472
+ return;
473
+ const data = event.data;
474
+ const toolName = normalizeToolName(data?.name);
475
+ if (toolName === '' || toolName.startsWith('feihualing'))
476
+ return; // 本插件工具不触发
477
+ if (!DANGEROUS_TOOL_NAMES.has(toolName))
478
+ return;
479
+ const state = ensureState(sessionId);
480
+ if (!state || state.phase !== 'running')
481
+ return;
482
+ pauseGame(state, `检测到 ${toolName} 工具调用,自动暂停`);
483
+ saveSnapshot(sessionId, state); // 自动暂停:保存现场(需求 4)
484
+ log('info', `[${PLUGIN_ID}] 会话 ${sessionId}: 因工具 ${toolName} 自动暂停并保存现场`);
485
+ return;
486
+ }
487
+ // turn:before / turn:after —— 记录轮次(供状态展示)
488
+ case 'turn/start':
489
+ case 'turn/end': {
490
+ const data = event.data;
491
+ if (typeof data?.turn === 'number')
492
+ lastTurns.set(sessionId, data.turn);
493
+ return;
494
+ }
495
+ default:
496
+ return;
497
+ }
498
+ }
499
+ catch (error) {
500
+ // 事件监听异常不允许影响宿主事件流
501
+ log('warn', `[${PLUGIN_ID}] session/event 处理异常: ${errorMessage(error)}`);
502
+ }
503
+ });
504
+ // ---------- 6. 注册 3 个模型工具(不向主聊天流输出任何内容) ----------
505
+ /** 从工具执行上下文解析会话 id(无 agent 会话时拒绝执行)。 */
506
+ function requireSessionId(exec) {
507
+ const sessionId = exec.agent?.session?.id;
508
+ if (typeof sessionId !== 'string' || sessionId.length === 0) {
509
+ throw new Error('飞花令工具必须在 agent 会话中调用');
510
+ }
511
+ return sessionId;
512
+ }
513
+ /** 构造 status 工具返回(usedPoems 返回副本,防止外部修改内部状态)。 */
514
+ function buildStatus(state, sessionId) {
515
+ if (!state) {
516
+ return {
517
+ phase: 'idle',
518
+ score: 0,
519
+ attempts: 0,
520
+ usedPoems: [],
521
+ hintsLeft: 0,
522
+ lastEvent: '当前会话没有进行中的飞花令游戏',
523
+ turn: lastTurns.get(sessionId) ?? 0,
524
+ };
525
+ }
526
+ return {
527
+ phase: state.phase,
528
+ mode: state.mode,
529
+ lingzi: state.lingzi,
530
+ score: state.score,
531
+ attempts: state.attempts,
532
+ usedPoems: [...state.usedPoems],
533
+ hintsLeft: state.hintsLeft,
534
+ // 可选字段缺省即不返回,与工具 JSON Schema(additionalProperties: false)对齐
535
+ ...(state.mode === 'ancient' ? { requiredPosition: state.requiredPosition } : {}),
536
+ ...(state.pausedReason === '' ? {} : { pausedReason: state.pausedReason }),
537
+ lastEvent: state.lastEvent,
538
+ turn: lastTurns.get(sessionId) ?? 0,
539
+ };
540
+ }
541
+ /** status 的文本渲染(工具结果在 UI 中的一句话摘要)。 */
542
+ function renderStatusText(value) {
543
+ if (value.phase === 'idle')
544
+ return '当前没有进行中的飞花令游戏';
545
+ const modeText = value.mode === 'ancient' ? '古法严格' : '简易';
546
+ const base = `模式:${modeText}|令字「${value.lingzi ?? '?'}」|得分 ${value.score}|已用诗句 ${value.usedPoems.length} 句|剩余提示 ${value.hintsLeft} 次`;
547
+ const posText = value.mode === 'ancient' && value.requiredPosition !== undefined ? `|令字需位于第 ${value.requiredPosition} 字` : '';
548
+ if (value.phase === 'paused')
549
+ return `游戏已暂停(${value.pausedReason ?? '原因未知'})。${base}${posText}`;
550
+ if (value.phase === 'finished')
551
+ return `游戏已结束。${base}`;
552
+ return `游戏进行中。${base}${posText}。最近判定:${value.lastEvent || '无'}`;
553
+ }
554
+ ctx.tools.register(defineTool({
555
+ name: 'feihualing_start',
556
+ description: '开始(或重新开始)一场飞花令游戏。当用户说「开始飞花令」「开始游戏」等指令时应调用本工具;' +
557
+ '游戏状态由插件按会话维护,调用后请以返回值中的 message 为准,用自然语言向用户宣布开局信息(模式、令字、剩余提示次数)。',
558
+ parameters: {
559
+ mode: {
560
+ type: 'string',
561
+ // 可选参数:省略 required 标记(Harness 约定 required 只能为 true,不存在则视为可选)
562
+ enum: ['simple', 'ancient'],
563
+ description: '游戏模式:simple=简易飞花令(诗句任意位置包含令字即可);ancient=古法严格飞花令(令字必须位于本轮指定位置,位置按第 1 字到第 7 字循环)。缺省为 simple。',
564
+ },
565
+ },
566
+ output: {
567
+ schema: {
568
+ type: 'object',
569
+ additionalProperties: false,
570
+ properties: {
571
+ started: { type: 'boolean', required: true },
572
+ phase: { type: 'string', required: true, enum: ['running', 'paused', 'finished'] },
573
+ mode: { type: 'string', required: true, enum: ['simple', 'ancient'] },
574
+ lingzi: { type: 'string', required: true },
575
+ score: { type: 'integer', required: true },
576
+ hintsLeft: { type: 'integer', required: true },
577
+ message: { type: 'string', required: true },
578
+ },
579
+ },
580
+ render: (_args, value) => [{ type: 'text', text: value.message }],
581
+ },
582
+ async execute(args, exec) {
583
+ const sessionId = requireSessionId(exec);
584
+ const requestedMode = args.mode === 'ancient' ? 'ancient' : 'simple';
585
+ const existing = ensureState(sessionId);
586
+ // 已有进行中的对局 → 幂等返回现状,不重复开局
587
+ if (existing && existing.phase === 'running') {
588
+ const result = {
589
+ started: false,
590
+ phase: 'running',
591
+ mode: existing.mode,
592
+ lingzi: existing.lingzi,
593
+ score: existing.score,
594
+ hintsLeft: existing.hintsLeft,
595
+ message: `游戏已在进行中(模式:${existing.mode === 'ancient' ? '古法严格' : '简易'},令字「${existing.lingzi}」),无需重复开始`,
596
+ };
597
+ return result;
598
+ }
599
+ const state = createGame(sessionId, requestedMode);
600
+ if (existing)
601
+ state.lastEvent = `已重新开局(先前的对局已被替换):${state.lastEvent}`;
602
+ games.set(sessionId, state);
603
+ deleteSnapshot(sessionId);
604
+ const result = {
605
+ started: true,
606
+ phase: 'running', // createGame 恒定以 running 开局
607
+ mode: state.mode,
608
+ lingzi: state.lingzi,
609
+ score: state.score,
610
+ hintsLeft: state.hintsLeft,
611
+ message: state.lastEvent,
612
+ };
613
+ return result;
614
+ },
615
+ presentCall: (args) => ({ card: 'generic', title: '开始飞花令', kind: 'other', rawInput: args }),
616
+ }));
617
+ ctx.tools.register(defineTool({
618
+ name: 'feihualing_status',
619
+ description: '查询当前会话的飞花令游戏状态(模式、令字、得分、已使用诗句、剩余提示次数、最近判定结果等)。' +
620
+ '当用户提交诗句或发出游戏指令(换字/提示/认输/暂停/继续飞花令等)后,插件已在后台完成判定;' +
621
+ '请先调用本工具获取最新状态与最近判定(lastEvent),再据此以自然语言回复用户。',
622
+ parameters: {},
623
+ output: {
624
+ schema: {
625
+ type: 'object',
626
+ additionalProperties: false,
627
+ properties: {
628
+ phase: { type: 'string', required: true, enum: ['idle', 'running', 'paused', 'finished'] },
629
+ mode: { type: 'string', enum: ['simple', 'ancient'] },
630
+ lingzi: { type: 'string' },
631
+ score: { type: 'integer', required: true },
632
+ attempts: { type: 'integer', required: true },
633
+ usedPoems: { type: 'array', required: true, items: { type: 'string' } },
634
+ hintsLeft: { type: 'integer', required: true },
635
+ requiredPosition: { type: 'integer' },
636
+ pausedReason: { type: 'string' },
637
+ lastEvent: { type: 'string', required: true },
638
+ turn: { type: 'integer', required: true },
639
+ },
640
+ },
641
+ render: (_args, value) => [{ type: 'text', text: renderStatusText(value) }],
642
+ },
643
+ async execute(_args, exec) {
644
+ const sessionId = requireSessionId(exec);
645
+ return buildStatus(ensureState(sessionId), sessionId);
646
+ },
647
+ presentCall: () => ({ card: 'generic', title: '查询飞花令状态', kind: 'other', rawInput: null }),
648
+ }));
649
+ ctx.tools.register(defineTool({
650
+ name: 'feihualing_stop',
651
+ description: '结束当前会话的飞花令游戏(含「结束飞花令」「认输」语义的收尾)。' +
652
+ '调用后返回最终得分与已使用诗句数量,请以自然语言向用户播报结算结果。',
653
+ parameters: {},
654
+ output: {
655
+ schema: {
656
+ type: 'object',
657
+ additionalProperties: false,
658
+ properties: {
659
+ stopped: { type: 'boolean', required: true },
660
+ finalScore: { type: 'integer', required: true },
661
+ usedCount: { type: 'integer', required: true },
662
+ message: { type: 'string', required: true },
663
+ },
664
+ },
665
+ render: (_args, value) => [{ type: 'text', text: value.message }],
666
+ },
667
+ async execute(_args, exec) {
668
+ const sessionId = requireSessionId(exec);
669
+ const state = ensureState(sessionId);
670
+ if (!state || state.phase === 'finished') {
671
+ const result = {
672
+ stopped: false,
673
+ finalScore: 0,
674
+ usedCount: 0,
675
+ message: '当前没有进行中的飞花令游戏',
676
+ };
677
+ return result;
678
+ }
679
+ finishGame(sessionId, state, `游戏结束:最终得分 ${state.score},共使用诗句 ${state.usedPoems.length} 句`);
680
+ const result = {
681
+ stopped: true,
682
+ finalScore: state.score,
683
+ usedCount: state.usedPoems.length,
684
+ message: state.lastEvent,
685
+ };
686
+ return result;
687
+ },
688
+ presentCall: () => ({ card: 'generic', title: '结束飞花令', kind: 'other', rawInput: null }),
689
+ }));
690
+ // ---------- 7. 卸载生命周期(需求:处理 plugin:unload,卸载后无残留) ----------
691
+ /** 是否已执行过清理(幂等保护:effect 与 plugin:unload 可能先后触发)。 */
692
+ let disposed = false;
693
+ /**
694
+ * 卸载清理:
695
+ * 1. 清空全部会话的游戏状态与轮次记录(内存状态无残留);
696
+ * 2. 删除白名单目录内全部快照文件(磁盘现场无残留);
697
+ * 3. 事件监听由 Cordis 随 fiber 卸载自动注销(ctx.on 挂载的 effect)。
698
+ */
699
+ const cleanup = () => {
700
+ if (disposed)
701
+ return;
702
+ disposed = true;
703
+ games.clear();
704
+ lastTurns.clear();
705
+ try {
706
+ for (const fileName of fs.readdirSync(dataDir)) {
707
+ // 只删除本插件命名空间的快照文件,白名单目录内其它内容一律不动
708
+ if (!/^snapshot-[A-Za-z0-9._-]{1,64}\.json$/.test(fileName))
709
+ continue;
710
+ fs.unlinkSync(path.join(dataDir, fileName));
711
+ }
712
+ }
713
+ catch {
714
+ /* 目录不存在等情况一律忽略 */
715
+ }
716
+ log('info', `[${PLUGIN_ID}] 插件已卸载:全部会话状态与快照已清空`);
717
+ };
718
+ // 主卸载路径:Cordis fiber dispose 时执行(即需求中的 plugin:unload 语义)
719
+ ctx.effect(() => cleanup, 'dsh-plugin-feihualing: unload cleanup');
720
+ // 兼容兜底:若宿主额外派发字面量 'plugin:unload' 事件同样执行清理(幂等)
721
+ ctx.on('plugin:unload', cleanup);
722
+ log('info', `[${PLUGIN_ID}] 已加载(enable=${String(config.enable)}, maxHintCount=${config.maxHintCount}, autoPause=${String(config.autoPause)},快照目录:${dataDir})`);
723
+ }
724
+ // ============================================================
725
+ // 模块级辅助函数(apply 的支撑工具,无状态)
726
+ // ============================================================
727
+ /** 配置解析与严格校验;非法值抛错拒绝加载(与 cordis.yml 的 config schema 一致)。 */
728
+ function resolveConfig(raw) {
729
+ const candidate = raw ?? {};
730
+ const enable = candidate.enable ?? true;
731
+ const maxHintCount = candidate.maxHintCount ?? 3;
732
+ const autoPause = candidate.autoPause ?? true;
733
+ if (typeof enable !== 'boolean') {
734
+ throw new TypeError('dsh-plugin-feihualing: config.enable 必须是布尔值');
735
+ }
736
+ if (typeof autoPause !== 'boolean') {
737
+ throw new TypeError('dsh-plugin-feihualing: config.autoPause 必须是布尔值');
738
+ }
739
+ if (typeof maxHintCount !== 'number' || !Number.isInteger(maxHintCount) || maxHintCount < 0 || maxHintCount > 10) {
740
+ throw new TypeError('dsh-plugin-feihualing: config.maxHintCount 必须是 0-10 的整数');
741
+ }
742
+ return { enable, maxHintCount, autoPause };
743
+ }
744
+ /**
745
+ * 解析快照白名单根目录:$DSH_HOME/storages/dsh-plugin-feihualing。
746
+ * 与 @deepseek-ai/dsh-home-paths 的约定一致:DSH_HOME 环境变量优先
747
+ * (支持 ~ 前缀展开),否则使用 ~/.dsh。
748
+ */
749
+ function resolveDataDir() {
750
+ const envHome = process.env.DSH_HOME;
751
+ const home = envHome !== undefined && envHome.trim().length > 0
752
+ ? path.resolve(envHome.trim().replace(/^~(?=[\\/])/, os.homedir()))
753
+ : path.join(os.homedir(), '.dsh');
754
+ return path.join(home, 'storages', PLUGIN_ID);
755
+ }
756
+ /**
757
+ * 快照内容逐字段校验(读取自磁盘的数据一律视为不可信)。
758
+ * 校验通过返回规范化 SnapshotFile,否则返回 null。
759
+ */
760
+ function validateSnapshot(raw, sessionId) {
761
+ if (raw === null || typeof raw !== 'object')
762
+ return null;
763
+ const snapshot = raw;
764
+ if (snapshot.version !== SNAPSHOT_VERSION)
765
+ return null;
766
+ if (snapshot.plugin !== PLUGIN_ID)
767
+ return null;
768
+ if (snapshot.sessionId !== sessionId)
769
+ return null;
770
+ if (typeof snapshot.savedAt !== 'number')
771
+ return null;
772
+ const rawState = snapshot.state;
773
+ if (rawState === null || typeof rawState !== 'object')
774
+ return null;
775
+ const st = rawState;
776
+ if (st.sessionId !== sessionId)
777
+ return null;
778
+ const rawPhase = st.phase;
779
+ if (typeof rawPhase !== 'string')
780
+ return null;
781
+ const phase = rawPhase;
782
+ if (phase !== 'running' && phase !== 'paused' && phase !== 'finished')
783
+ return null;
784
+ const rawMode = st.mode;
785
+ if (typeof rawMode !== 'string')
786
+ return null;
787
+ const mode = rawMode;
788
+ if (mode !== 'simple' && mode !== 'ancient')
789
+ return null;
790
+ if (typeof st.lingzi !== 'string' || st.lingzi.length === 0)
791
+ return null;
792
+ if (typeof st.score !== 'number' || !Number.isFinite(st.score))
793
+ return null;
794
+ if (typeof st.attempts !== 'number' || !Number.isFinite(st.attempts))
795
+ return null;
796
+ if (typeof st.hintsLeft !== 'number' || !Number.isFinite(st.hintsLeft))
797
+ return null;
798
+ if (typeof st.requiredPosition !== 'number' || !Number.isInteger(st.requiredPosition) || st.requiredPosition < 1)
799
+ return null;
800
+ if (typeof st.pausedReason !== 'string')
801
+ return null;
802
+ if (typeof st.lastEvent !== 'string')
803
+ return null;
804
+ if (typeof st.startedAt !== 'number')
805
+ return null;
806
+ if (typeof st.updatedAt !== 'number')
807
+ return null;
808
+ const rawPoems = st.usedPoems;
809
+ if (!Array.isArray(rawPoems))
810
+ return null;
811
+ const usedPoems = [];
812
+ for (const item of rawPoems) {
813
+ if (typeof item !== 'string')
814
+ return null;
815
+ usedPoems.push(item);
816
+ }
817
+ const rawNormalized = st.usedNormalized;
818
+ if (!Array.isArray(rawNormalized))
819
+ return null;
820
+ const usedNormalized = [];
821
+ for (const item of rawNormalized) {
822
+ if (typeof item !== 'string')
823
+ return null;
824
+ usedNormalized.push(item);
825
+ }
826
+ if (usedNormalized.length > 10000)
827
+ return null;
828
+ return {
829
+ version: SNAPSHOT_VERSION,
830
+ plugin: PLUGIN_ID,
831
+ sessionId,
832
+ savedAt: snapshot.savedAt,
833
+ state: {
834
+ sessionId,
835
+ phase,
836
+ mode,
837
+ lingzi: st.lingzi,
838
+ score: st.score,
839
+ attempts: st.attempts,
840
+ usedPoems,
841
+ usedNormalized,
842
+ hintsLeft: st.hintsLeft,
843
+ requiredPosition: st.requiredPosition,
844
+ pausedReason: st.pausedReason,
845
+ lastEvent: st.lastEvent,
846
+ startedAt: st.startedAt,
847
+ updatedAt: st.updatedAt,
848
+ },
849
+ };
850
+ }
851
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,61 @@
1
+ {
2
+ "name": "dsh-plugin-feihualing",
3
+ "version": "1.0.0",
4
+ "description": "DeepSeek Harness 飞花令游戏插件:简易/古法严格双模式,按会话独立维护令字、得分、已用诗句与剩余提示次数;提供 feihualing_start / feihualing_status / feihualing_stop 三个工具与关键词指令,检测到 shell/文件写入类工具调用时自动暂停并保存现场。",
5
+ "type": "module",
6
+ "main": "lib/index.js",
7
+ "types": "lib/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/index.d.ts",
11
+ "default": "./lib/index.js"
12
+ },
13
+ "./package.json": "./package.json"
14
+ },
15
+ "files": [
16
+ "lib",
17
+ "cordis.yml",
18
+ "cordis.patch.yml",
19
+ "README.md"
20
+ ],
21
+ "dsh": {
22
+ "bundle": {
23
+ "patch": "./cordis.patch.yml"
24
+ }
25
+ },
26
+ "publishConfig": {
27
+ "registry": "https://registry.npmjs.org"
28
+ },
29
+ "scripts": {
30
+ "prepare": "pnpm run build",
31
+ "build": "tsc -p tsconfig.json",
32
+ "typecheck": "tsc -p tsconfig.json --noEmit"
33
+ },
34
+ "keywords": [
35
+ "deepseek",
36
+ "deepseek-harness",
37
+ "dsh",
38
+ "dsh-plugin",
39
+ "cordis",
40
+ "feihualing",
41
+ "game"
42
+ ],
43
+ "license": "MIT",
44
+ "engines": {
45
+ "node": ">=20"
46
+ },
47
+ "peerDependencies": {
48
+ "@deepseek-ai/dsh-tools": ">=0.1.2-alpha.1"
49
+ },
50
+ "peerDependenciesMeta": {
51
+ "@deepseek-ai/dsh-tools": {
52
+ "optional": true
53
+ }
54
+ },
55
+ "devDependencies": {
56
+ "@deepseek-ai/dsh-agent": "0.1.0-rc.6",
57
+ "@deepseek-ai/dsh-tools": ">=0.1.2-alpha.1",
58
+ "@types/node": "^22.0.0",
59
+ "typescript": "^5.4.0"
60
+ }
61
+ }