dsh-fatfish-suite 0.0.0-stage → 0.1.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,24 @@
1
+ # Changelog
2
+
3
+ ## 0.1.1 — 2026-11-02
4
+
5
+ - 依赖锁到 `dsh-fatfish@0.5.1`:0.5.0 在本代 DSH NEXT 宿主上装载失败(配置校验与 `command` 注入两处硬伤),
6
+ 套装挂着它等于三件里最要紧的那件装不上。
7
+ - 修复装载硬伤:`command` 只在 agent 上下文的子作用域提供,写进 `inject` 会让整枚插件永远 `pending`,
8
+ 不写直接读又会被宿主抛 `cannot get property "command" without inject`。改成 try/catch 按需取——
9
+ 取不到只少 `fatfish.suite` 这一条命令,两个只读状态工具照常装载。
10
+ - `fatfish_suite_status` 的套装自身版本回退值同步为 `0.1.1`。
11
+
12
+ ## 0.1.0 — 2026-10-30
13
+
14
+ 首个版本。把这几天的三件能力打成一个市场可安装的套装。
15
+
16
+ - 新增 `fatfish_suite_status`:只读检查 `dsh-fatfish` / `dsh-fatfish-hands` / `dsh-quota-guard`
17
+ 是否安装、是否通过 `cordis.patch.yml` 挂载、版本是否与套装要求一致。
18
+ - 新增 `fatfish_suite_guide`:按主题返回用法与安全边界(总览 / 记忆 / 浏览器 / 额度 / 查毒 /
19
+ 独立桌面版 / 安装卸载),只返回说明文字,不执行动作。
20
+ - 新增 `fatfish.suite` 命令:在 DSH 命令面板里直接看套装状态。
21
+ - `cordis.patch.yml` 一次插入三件:人设、之手、额度护栏。额度护栏保持默认只记账不拦截。
22
+ - 依赖锁定为 `dsh-fatfish@0.5.0`、`dsh-fatfish-hands@0.1.3`、`dsh-quota-guard@0.1.3`,
23
+ 套装自身不联网、不读聊天、不执行命令。
24
+ - 明确「套装与三件套二选一」,避免重复挂载。
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 dsh-fatfish contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,3 +1,124 @@
1
- # Temporary Holding Version
1
+ # dsh-fatfish-suite · 大肥鱼套装
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ 一条命令,把大肥鱼这几天的三件能力一起装进 DSH:
4
+
5
+ | 同伴包 | 它负责什么 | 版本 |
6
+ | --- | --- | --- |
7
+ | [`dsh-fatfish`](https://www.npmjs.com/package/dsh-fatfish) | 四档人设、时段与情绪、本地记忆、只读查毒与可更新病毒库、七个小动作 | 0.5.1 |
8
+ | [`dsh-fatfish-hands`](https://www.npmjs.com/package/dsh-fatfish-hands) | 用专用 Edge 真上网:读正文、点链接、搜索、截图;另带只读电脑状态 | 0.1.3 |
9
+ | [`dsh-quota-guard`](https://www.npmjs.com/package/dsh-quota-guard) | 模型用量账本、每日/每分钟限额、免费账号轮换 | 0.1.3 |
10
+
11
+ 套装本身不联网、不读聊天、不执行命令;它只做两件事:把三件挂进 DSH,以及提供两个只读工具
12
+ `fatfish_suite_status`(装齐了没)和 `fatfish_suite_guide`(怎么用、边界在哪)。
13
+
14
+ ## 安装
15
+
16
+ 在 DSH 插件市场搜 `fatfish`,或者:
17
+
18
+ ```bash
19
+ dsh plugin --profile desktop add dsh-fatfish-suite
20
+ ```
21
+
22
+ 装完重启 DSH。设置 → 插件里能看到三个条目:
23
+
24
+ - **大肥鱼**:人设、记忆、查毒、动作;
25
+ - **大肥鱼之手**:首次调用会自动起一个专用 Edge 窗口;
26
+ - **额度护栏**:默认只记账,不拦请求。
27
+
28
+ > 套装和三件套**二选一**。已经单独装过其中任何一个,再装套装会出现重复挂载;
29
+ > 请先卸掉单独装的包,或者只装三件套、不装套装。
30
+
31
+ 本地目录安装(还没发 npm 时):
32
+
33
+ ```bash
34
+ node scripts/install-to-dsh.mjs --suite
35
+ ```
36
+
37
+ 它会把套装和三个同伴复制进 `~/.dsh/profiles/desktop/node_modules/`,
38
+ 只把 `dsh-fatfish-suite` 写进 profile 的 `bundles`,避免重复挂载;改之前留 `.bak-<时间戳>` 备份。
39
+
40
+ ## 装完能干什么
41
+
42
+ - **聊天有性格**:好脾气 / 毒舌 / 犯困 / 自定义;按早晚调整语气,按时间算精力与心情。
43
+ - **记得住**:名字、喜好、习惯、生日记在本机 `~/.dsh/fatfish/memory.json`;能召回、能遗忘。
44
+ - **会查毒**:进程名、命令行、开机启动项、常用目录文件哈希;只报告,不删文件、不杀进程。
45
+ - **会上网**:读页面正文和链接,点编号链接、搜索、截图;不靠像素坐标猜位置。
46
+ - **看得到电脑**:内存、开机时长、CPU、最占内存的进程;只读。
47
+ - **管得住额度**:每次模型调用记 token 与耗时,可按天/按分钟设上限,免费账号之间自动切换。
48
+
49
+ ## 默认免费优先
50
+
51
+ 套装不配置任何付费开关,也不会自动充值或自动切到付费账号:
52
+
53
+ - 额度护栏默认所有限额为 `0`(只记账,不拦);没配单价的模型会标 `priced: false`,
54
+ `costCny: 0` **不代表免费**。
55
+ - 要限额,在 DSH 用户层 `cordis.patch.yml` 覆盖 `id: llm-guard`:
56
+
57
+ ```yaml
58
+ - id: llm-guard
59
+ name: dsh-quota-guard
60
+ config:
61
+ limits:
62
+ dailyTokens: 2000000
63
+ dailyRequests: 1500
64
+ perMinuteRequests: 30
65
+ warnAt: 0.8
66
+ onExceed: warn # 先用 warn 观察一周,再考虑 block
67
+ ```
68
+
69
+ - 要用付费模型,必须自己改配置,并先算清楚单价与预算;套装不会替你做这个决定。
70
+
71
+ ## 红线(写在各插件内核里,配置关不掉)
72
+
73
+ - **不自动回复私聊**:可以读聊天记录与通讯录,但回复必须由主人发出。
74
+ - **不代付**:支付、网购、收银台、网银页面拒绝打开、点击与输入;付款由主人完成。
75
+ - **不碰日常浏览器**:之手只使用独立配置 `~/.dsh/fatfish-hands/edge-profile`,
76
+ 不读日常 Edge 的登录态、书签、历史。
77
+ - **不下载**:默认拒绝,只允许 `http/https`,`file://` 一律拒绝。
78
+ - **不记敏感信息**:密码、验证码、证件号、银行卡、手机号、住址、API Key 一律拒收。
79
+ - **不上传**:无遥测、无云端账号;唯一外发是病毒库订阅和主人自己配置的模型调用。
80
+ - **查毒不处置**:只报告;重要场合请用专业安全软件复扫。
81
+
82
+ ## 配置在哪
83
+
84
+ | 内容 | 位置 |
85
+ | --- | --- |
86
+ | 人设 / 记忆 / 查毒选项 | DSH 用户层 `cordis.patch.yml` 的 `id: dsh-fatfish` |
87
+ | Edge 选项 | `~/.dsh/fatfish-hands.config.json` |
88
+ | 额度限额与账号池 | DSH 用户层 `cordis.patch.yml` 的 `id: llm-guard` |
89
+ | 记忆与查毒缓存 | `~/.dsh/fatfish/` |
90
+ | 浏览器配置与截图 | `~/.dsh/fatfish-hands/` |
91
+ | 用量账本 | `~/.dsh/llm-guard/usage.json` |
92
+
93
+ 删掉对应目录即清空那一部分数据;卸载套装不会自动删这些目录。
94
+
95
+ ## 与桌面完整版的关系
96
+
97
+ 电脑上的「大肥鱼陪伴」独立程序是完整版:独立窗口、桌宠气泡、聊天存档、自动备份、
98
+ 加密保险库、本地 OpenAI 兼容中转。套装是 DSH 插件形态,两者不共享进程:
99
+
100
+ - 套装不会自动读独立版的记忆,也不会替它回复私聊;
101
+ - 想日常陪伴与本地中转,用独立程序;
102
+ - 想让 DSH 里的 agent 上网、查毒、管额度,用套装。
103
+
104
+ ## 卸载
105
+
106
+ ```bash
107
+ dsh plugin --profile desktop remove dsh-fatfish-suite
108
+ dsh plugin --profile desktop remove dsh-fatfish dsh-fatfish-hands dsh-quota-guard
109
+ ```
110
+
111
+ 然后按需删 `~/.dsh/fatfish*`、`~/.dsh/llm-guard`。卸载不会删除你的聊天记录或桌面版数据。
112
+
113
+ ## 开发
114
+
115
+ ```bash
116
+ node dsh-fatfish-suite/test/plugin.mjs # 套装契约:工具注册、状态、指南、卸载
117
+ node dsh-fatfish/test/plugin.mjs # 人设契约
118
+ node dsh-fatfish-hands/test/plugin.mjs # 之手契约(不开浏览器)
119
+ node dsh-quota-guard/test/*.test.js # 额度护栏离线测试
120
+ ```
121
+
122
+ ## License
123
+
124
+ MIT
package/SECURITY.md ADDED
@@ -0,0 +1,52 @@
1
+ # 安全说明
2
+
3
+ ## 报告问题
4
+
5
+ 发现安全问题**不要**公开开 issue。用仓库的 GitHub Security Advisories 私下报告,
6
+ 或直接联系维护者。写清楚:复现步骤、影响版本、可能后果。48 小时内回复。
7
+
8
+ ## 威胁模型
9
+
10
+ 套装本身是**元包**:它不联网、不读聊天、不执行命令、不写文件,只负责把三个同伴插件
11
+ 挂进 DSH,并提供两个只读工具。真正的能力与风险都在同伴包里,各自有独立的安全说明:
12
+
13
+ - `dsh-fatfish`:人设、本地记忆、只读查毒;
14
+ - `dsh-fatfish-hands`:专用 Edge 上网、只读电脑状态;
15
+ - `dsh-quota-guard`:模型用量账本、限额、账号轮换。
16
+
17
+ 套装要防的是**误装带来的权限叠加**:用户以为自己只装了一个聊天插件,实际同时获得了
18
+ 浏览器操作、电脑状态读取和模型调用记账能力。
19
+
20
+ ## 硬边界
21
+
22
+ | 能力 | 限制 | 实现位置 |
23
+ | --- | --- | --- |
24
+ | 套装自身网络 | 完全无网络请求 | `lib/index.js` 只读本地文件 |
25
+ | 套装自身写入 | 不写文件、不建目录、不改配置 | `lib/index.js` |
26
+ | 状态检查 | 只读 `package.json` 与自己的 `cordis.patch.yml` | `fatfish_suite_status` |
27
+ | 说明工具 | 只返回静态文字,不执行任何动作 | `fatfish_suite_guide` |
28
+ | 能力来源 | 全部来自三个同伴包,各自的红线独立生效 | 见各包 `SECURITY.md` |
29
+ | 重复挂载 | 文档明确「套装与三件套二选一」;自检检查 patch 覆盖关系 | README / 上架自检 |
30
+
31
+ **不提供**:执行 shell、读任意文件内容、读剪贴板、发消息、改系统设置、下载、支付。
32
+
33
+ ## 数据落在哪
34
+
35
+ 套装自身不落任何数据。同伴包的数据位置:
36
+
37
+ | 内容 | 路径 |
38
+ | --- | --- |
39
+ | 记忆与查毒缓存 | `~/.dsh/fatfish/` |
40
+ | Edge 配置与截图 | `~/.dsh/fatfish-hands/` |
41
+ | 用量账本 | `~/.dsh/llm-guard/usage.json` |
42
+ | 配置 | DSH 用户层 `cordis.patch.yml` |
43
+
44
+ ## 安装前请确认
45
+
46
+ - 你接受「浏览器操作 + 电脑状态读取 + 模型用量记账」这三项能力同时存在;
47
+ - 你已经装过其中某个同伴包时,先卸载它,避免重复挂载;
48
+ - 额度护栏默认只记账不拦截;要防费用失控,请自己配置 `limits`,先用 `warn` 观察。
49
+
50
+ ## 支持版本
51
+
52
+ 只对最新发布版本提供安全修复。
@@ -0,0 +1,40 @@
1
+ # ============================================================================
2
+ # dsh-fatfish-suite —— 大肥鱼套装 bundle patch
3
+ #
4
+ # 装这一个包,等于同时挂上三件:
5
+ # dsh-fatfish 大肥鱼:人设 / 时段与情绪 / 本地记忆 / 只读查毒 / 小动作
6
+ # dsh-fatfish-hands 大肥鱼之手:专用 Edge 上网 / 读页面 / 截图 / 只读电脑状态
7
+ # dsh-quota-guard 额度护栏:用量账本 / 每日限额 / 免费账号轮换
8
+ #
9
+ # ⚠️ 套装和三件套二选一。已经单独装过其中任何一个,再装套装会出现重复挂载,
10
+ # 请先 `dsh plugin remove` 掉单独装的包,或者别装套装。
11
+ #
12
+ # 想改人设/记忆/查毒选项:在用户层 cordis.patch.yml 覆盖 id: dsh-fatfish。
13
+ # 想设限额:覆盖 id: llm-guard,给 limits.dailyTokens / dailyRequests 赋值。
14
+ # ============================================================================
15
+
16
+ - insert:
17
+ - id: dsh-fatfish
18
+ name: dsh-fatfish
19
+ config:
20
+ mode: normal
21
+ custom: ''
22
+ enableTimeAwareness: true
23
+ enableMood: true
24
+ memory:
25
+ enabled: true
26
+ autoCapture: true
27
+ maxFacts: 300
28
+ security:
29
+ enabled: true
30
+ feedUrl: https://gitee.com/akiba-yuzuki_0/dsh-fatfish/raw/master/signatures.json
31
+ autoUpdate: true
32
+ updateHours: 12
33
+
34
+ - id: dsh-fatfish-hands
35
+ name: dsh-fatfish-hands
36
+
37
+ - id: llm-guard
38
+ name: dsh-quota-guard
39
+ config:
40
+ enabled: true
package/lib/index.js ADDED
@@ -0,0 +1,291 @@
1
+ /**
2
+ * dsh-fatfish-suite —— 大肥鱼套装入口
3
+ *
4
+ * 一个包装齐三件:人设/记忆/查毒、Edge 上网、额度护栏。
5
+ * 本包自己不联网、不读聊天、不执行命令,只做两件事:
6
+ * 1. 通过 cordis.patch.yml 把三个同伴插件挂进 DSH;
7
+ * 2. 提供两个只读工具,让人和 agent 都能看清「套装现在装齐了没、各自能干什么」。
8
+ */
9
+ import fs from 'node:fs'
10
+ import path from 'node:path'
11
+ import { fileURLToPath } from 'node:url'
12
+
13
+ export const name = 'fatfish-suite'
14
+ export const inject = ['tools']
15
+
16
+ const HERE = path.dirname(fileURLToPath(import.meta.url))
17
+ const ROOT = path.resolve(HERE, '..')
18
+
19
+ export const COMPANIONS = Object.freeze([
20
+ {
21
+ name: 'dsh-fatfish',
22
+ title: '大肥鱼',
23
+ role: '人设 / 时段与情绪 / 本地记忆 / 只读查毒 / 小动作',
24
+ boundary: '记忆拒收密码与 Key;查毒只报告,不删文件不杀进程',
25
+ },
26
+ {
27
+ name: 'dsh-fatfish-hands',
28
+ title: '大肥鱼之手',
29
+ role: '专用 Edge 上网 / 读正文与链接 / 截图 / 只读电脑状态',
30
+ boundary: '支付、网银、登录、下载硬拦截;不碰日常浏览器的账号与历史',
31
+ },
32
+ {
33
+ name: 'dsh-quota-guard',
34
+ title: '额度护栏',
35
+ role: '模型用量账本 / 每日与每分钟限额 / 免费账号轮换',
36
+ boundary: '默认只记账不拦;单价未知时明确标记 priced=false,不假装免费',
37
+ },
38
+ ])
39
+
40
+ const TOPICS = ['overview', 'memory', 'browser', 'quota', 'security', 'desktop', 'install']
41
+
42
+ const GUIDE = {
43
+ overview: [
44
+ '大肥鱼套装 = 三个 DSH 插件,装一次一起挂上:',
45
+ ' · 大肥鱼:人格、时段、情绪、本地记忆、只读查毒、七个小动作。',
46
+ ' · 大肥鱼之手:用专用 Edge 读网页、点链接、搜索、截图,另带只读电脑状态。',
47
+ ' · 额度护栏:记录模型用量,可按天/按分钟设上限,免费账号之间自动轮换。',
48
+ '',
49
+ '默认免费优先:套装不配置任何付费开关,也不自动充值。要用付费模型,必须自己改配置并清楚代价。',
50
+ '红线写在各自插件内核里:不自动回复私聊,不代付,不点支付页,不上传聊天或文件。',
51
+ ].join('\n'),
52
+ memory: [
53
+ '本地记忆:~/.dsh/fatfish/memory.json',
54
+ ' · 对话里自动抽取名字、喜好、习惯、生日;也可用 fatfish_memory_save 手动记。',
55
+ ' · fatfish_memory_recall 按关键词召回,fatfish_memory_forget 按 id 删除。',
56
+ ' · 密码、验证码、证件号、银行卡、手机号、住址、API Key 一律拒收。',
57
+ ' · 没有「清空全部」,删一条必须给出 id 或足够具体的描述。',
58
+ ].join('\n'),
59
+ browser: [
60
+ '大肥鱼之手使用独立 Edge 配置:~/.dsh/fatfish-hands/edge-profile',
61
+ ' · 读页面文字与链接,不靠截图猜坐标;第一次调用会自动起一个 Edge 窗口。',
62
+ ' · 支付、网购、银行、收银台、验证码页:只读,拒绝点击和输入。',
63
+ ' · 页面有密码框时拒绝输入;需要登录请主人自己完成。',
64
+ ' · 下载默认拒绝,只允许 http/https,file:// 一律拒绝。',
65
+ ' · fatfish_pc_status 只读电脑状态,不结束进程、不改设置。',
66
+ ].join('\n'),
67
+ quota: [
68
+ '额度护栏默认只记账,不拦请求:',
69
+ ' · 账本:~/.dsh/llm-guard/usage.json,只记模型、token、耗时、费用估算。',
70
+ ' · 在 DSH 用户层 cordis.patch.yml 给 id: llm-guard 加 limits,例如 dailyTokens / dailyRequests。',
71
+ ' · onExceed 先建议用 warn 观察一周,再切 block,避免误拦长任务。',
72
+ ' · 没配单价的模型显示 priced=false,costCny=0 不代表免费。',
73
+ ' · 账号池只用主人自己放进去的免费账号;插件不自动充值、不自动换付费账号。',
74
+ ].join('\n'),
75
+ security: [
76
+ '查毒是特征匹配,不是完整杀毒引擎:',
77
+ ' · 检查进程名、命令行、启动项和常用目录里的可执行文件哈希。',
78
+ ' · 只读:不删文件、不杀进程、不改注册表。',
79
+ ' · 病毒库可用 HTTPS 订阅更新,默认每 12 小时检查一次。',
80
+ ' · 发现可疑项先看建议,再决定是否用专业安全软件复扫。',
81
+ ].join('\n'),
82
+ desktop: [
83
+ '套装是 DSH 插件形态;电脑上的「大肥鱼陪伴」独立程序是完整版:',
84
+ ' · 独立窗口、桌宠气泡、聊天存档、自动备份、加密保险库、本地 OpenAI 兼容中转。',
85
+ ' · 两者不共享进程;DSH 套装不会自动读独立版的记忆,也不会替它回复私聊。',
86
+ ' · 想让 agent 干重活,用套装里的手和护栏;想日常陪伴与本地中转,用独立程序。',
87
+ ' · 独立程序的中转只监听 127.0.0.1,Key 只存在本机,不写进插件配置。',
88
+ ].join('\n'),
89
+ install: [
90
+ '安装与卸载:',
91
+ ' · DSH:dsh plugin --profile desktop add dsh-fatfish-suite',
92
+ ' · 卸载:dsh plugin --profile desktop remove dsh-fatfish-suite,再按需删三个同伴包。',
93
+ ' · 套装和三件套二选一:已经单独装了某个插件,再装套装会出现重复挂载。',
94
+ ' · 本机目录安装:node scripts/install-to-dsh.mjs --suite(只把套装写进 bundles)。',
95
+ ' · 改完配置重启 DSH,或在 profile 的 cordis.patch.yml 追加 "# reload" 触发热重载。',
96
+ ].join('\n'),
97
+ }
98
+
99
+ function manifestOf(pkgName) {
100
+ const candidates = [
101
+ path.join(ROOT, '..', pkgName, 'package.json'),
102
+ path.join(ROOT, 'node_modules', pkgName, 'package.json'),
103
+ path.join(process.cwd(), 'node_modules', pkgName, 'package.json'),
104
+ ]
105
+ for (const file of candidates) {
106
+ try {
107
+ return JSON.parse(fs.readFileSync(file, 'utf8'))
108
+ } catch {}
109
+ }
110
+ return null
111
+ }
112
+
113
+ function expectedVersions() {
114
+ const self = manifestOf('dsh-fatfish-suite')
115
+ return (self && self.dependencies) || {}
116
+ }
117
+
118
+ function mountedNames() {
119
+ try {
120
+ const yml = fs.readFileSync(path.join(ROOT, 'cordis.patch.yml'), 'utf8')
121
+ return [...yml.matchAll(/^\s+name:\s*['"]?([^'"\s#]+)/gm)].map((m) => m[1])
122
+ } catch {
123
+ return []
124
+ }
125
+ }
126
+
127
+ export function suiteStatus() {
128
+ const expected = expectedVersions()
129
+ const mounts = mountedNames()
130
+ const companions = COMPANIONS.map((c) => {
131
+ const manifest = manifestOf(c.name)
132
+ const want = expected[c.name] || manifest?.version || ''
133
+ const version = manifest?.version || ''
134
+ return {
135
+ name: c.name,
136
+ title: c.title,
137
+ role: c.role,
138
+ boundary: c.boundary,
139
+ installed: Boolean(manifest),
140
+ version,
141
+ expected: want,
142
+ mounted: mounts.includes(c.name),
143
+ ok: Boolean(manifest) && mounts.includes(c.name) && (!want || version === want),
144
+ }
145
+ })
146
+ const self = manifestOf('dsh-fatfish-suite')
147
+ return {
148
+ ok: true,
149
+ suite: { name: 'dsh-fatfish-suite', version: self?.version || '0.1.1' },
150
+ companions,
151
+ allInstalled: companions.every((c) => c.installed),
152
+ allMounted: companions.every((c) => c.mounted),
153
+ missing: companions.filter((c) => !c.installed).map((c) => c.name),
154
+ unmounted: companions.filter((c) => !c.mounted).map((c) => c.name),
155
+ versionMismatch: companions.filter((c) => c.installed && c.expected && c.version !== c.expected)
156
+ .map((c) => `${c.name} 装的是 ${c.version},套装要求 ${c.expected}`),
157
+ }
158
+ }
159
+
160
+ function statusView(s) {
161
+ const lines = [`大肥鱼套装 ${s.suite.version}`]
162
+ for (const c of s.companions) {
163
+ const mark = c.ok ? '✓' : '✗'
164
+ const state = !c.installed ? '未安装' : (!c.mounted ? '已安装但没挂载' : `v${c.version}`)
165
+ lines.push(` ${mark} ${c.title}(${c.name})· ${state}`)
166
+ lines.push(` ${c.role}`)
167
+ }
168
+ if (s.allInstalled && s.allMounted && !s.versionMismatch.length) {
169
+ lines.push('三件都齐了。用 fatfish_suite_guide 看每件的用法与边界。')
170
+ } else {
171
+ if (s.missing.length) lines.push(`缺:${s.missing.join(' / ')} —— 重新安装套装,或单独装这些包。`)
172
+ if (s.unmounted.length) lines.push(`没挂载:${s.unmounted.join(' / ')} —— 检查 cordis.patch.yml 的 insert 段。`)
173
+ if (s.versionMismatch.length) lines.push(`版本不一致:${s.versionMismatch.join(';')}。`)
174
+ }
175
+ return lines.join('\n')
176
+ }
177
+
178
+ function guideView(topic) {
179
+ const key = TOPICS.includes(topic) ? topic : 'overview'
180
+ return { ok: true, topic: key, text: GUIDE[key] }
181
+ }
182
+
183
+ const text = (s) => [{ type: 'text', text: s }]
184
+
185
+ const STATUS_SCHEMA = {
186
+ type: 'object',
187
+ properties: {
188
+ ok: { type: 'boolean' },
189
+ suite: {
190
+ type: 'object',
191
+ properties: { name: { type: 'string' }, version: { type: 'string' } },
192
+ },
193
+ companions: {
194
+ type: 'array',
195
+ items: {
196
+ type: 'object',
197
+ properties: {
198
+ name: { type: 'string' },
199
+ title: { type: 'string' },
200
+ role: { type: 'string' },
201
+ boundary: { type: 'string' },
202
+ installed: { type: 'boolean' },
203
+ version: { type: 'string' },
204
+ expected: { type: 'string' },
205
+ mounted: { type: 'boolean' },
206
+ ok: { type: 'boolean' },
207
+ },
208
+ },
209
+ },
210
+ allInstalled: { type: 'boolean' },
211
+ allMounted: { type: 'boolean' },
212
+ missing: { type: 'array', items: { type: 'string' } },
213
+ unmounted: { type: 'array', items: { type: 'string' } },
214
+ versionMismatch: { type: 'array', items: { type: 'string' } },
215
+ },
216
+ }
217
+
218
+ export const TOOLS = [
219
+ {
220
+ name: 'fatfish_suite_status',
221
+ description: '查看大肥鱼套装三件(大肥鱼 / 大肥鱼之手 / 额度护栏)是否装齐、是否挂载、版本是否对得上。只读,不联网。',
222
+ parameters: { type: 'object', properties: {}, additionalProperties: false },
223
+ output: {
224
+ schema: STATUS_SCHEMA,
225
+ render: (_args, v) => text(v && v.ok ? statusView(v) : '大肥鱼套装状态读取失败。'),
226
+ },
227
+ execute: async () => {
228
+ try {
229
+ return suiteStatus()
230
+ } catch (e) {
231
+ return { ok: false, error: String(e?.message || e) }
232
+ }
233
+ },
234
+ },
235
+ {
236
+ name: 'fatfish_suite_guide',
237
+ description: '查大肥鱼套装的用法与安全边界:总览、记忆、浏览器、额度、查毒、独立桌面版、安装卸载。只返回说明文字,不执行动作。',
238
+ parameters: {
239
+ type: 'object',
240
+ properties: {
241
+ topic: { type: 'string', enum: TOPICS, description: '想了解的部分,默认 overview' },
242
+ },
243
+ additionalProperties: false,
244
+ },
245
+ output: {
246
+ schema: {
247
+ type: 'object',
248
+ properties: {
249
+ ok: { type: 'boolean' },
250
+ topic: { type: 'string' },
251
+ text: { type: 'string' },
252
+ },
253
+ },
254
+ render: (_args, v) => text(v?.text || '没有这条说明。'),
255
+ },
256
+ execute: async (args) => guideView(String(args?.topic || 'overview')),
257
+ },
258
+ ]
259
+
260
+ export function apply(ctx) {
261
+ const disposers = []
262
+ for (const tool of TOOLS) {
263
+ disposers.push(ctx.tools.register(tool))
264
+ }
265
+ ctx.effect(() => () => {
266
+ for (const d of disposers) {
267
+ try { d() } catch {}
268
+ }
269
+ })
270
+
271
+ // command 只在 agent 上下文的子作用域提供:写进 inject 会让整枚插件永远 pending,
272
+ // 根作用域直接读又会被宿主抛 cannot get property,所以按需取、取不到就跳过斜杠命令。
273
+ let command = null
274
+ try {
275
+ command = ctx.command
276
+ } catch {}
277
+
278
+ if (command) {
279
+ command('fatfish.suite', '查看大肥鱼套装三件是否装齐、挂载与版本', async () => {
280
+ const s = suiteStatus()
281
+ return statusView(s)
282
+ })
283
+ }
284
+
285
+ try {
286
+ const s = suiteStatus()
287
+ console.log(`[fatfish-suite] ${s.allInstalled && s.allMounted ? '三件已挂载' : `缺 ${s.missing.concat(s.unmounted).join('/') || '版本不一致'}`}`)
288
+ } catch {}
289
+ }
290
+
291
+ export const _internal = { manifestOf, mountedNames, expectedVersions, statusView, guideView, TOPICS }
package/package.json CHANGED
@@ -1,6 +1,68 @@
1
1
  {
2
2
  "name": "dsh-fatfish-suite",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "0.1.1",
4
+ "description": "大肥鱼套装:一次装齐人格与本地记忆、专用 Edge 上网之手、模型额度护栏。三件各自带硬红线,默认免费优先,不上传聊天与文件。",
5
+ "keywords": [
6
+ "dsh",
7
+ "dsh-plugin",
8
+ "deepseek-harness",
9
+ "fatfish",
10
+ "大肥鱼",
11
+ "suite",
12
+ "bundle",
13
+ "persona",
14
+ "browser",
15
+ "quota"
16
+ ],
17
+ "type": "module",
18
+ "main": "lib/index.js",
19
+ "exports": {
20
+ ".": "./lib/index.js",
21
+ "./package.json": "./package.json"
22
+ },
23
+ "files": [
24
+ "lib",
25
+ "cordis.patch.yml",
26
+ "README.md",
27
+ "CHANGELOG.md",
28
+ "SECURITY.md",
29
+ "LICENSE"
30
+ ],
31
+ "scripts": {
32
+ "test": "node test/plugin.mjs"
33
+ },
34
+ "engines": {
35
+ "node": ">=22",
36
+ "dsh": ">=0.2.0"
37
+ },
38
+ "dependencies": {
39
+ "dsh-fatfish": "0.5.1",
40
+ "dsh-fatfish-hands": "0.1.3",
41
+ "dsh-quota-guard": "0.1.3"
42
+ },
43
+ "peerDependencies": {
44
+ "@deepseek-ai/cordis": "^4.0.2",
45
+ "@deepseek-ai/dsh-commands": "^0.1.2-rc.1 || ^0.1.7-rc.2 || ^0.2.0-rc.1",
46
+ "@deepseek-ai/dsh-llm": ">=0.0.1-rc.0",
47
+ "@deepseek-ai/schemastery": "^3.18.4"
48
+ },
49
+ "repository": {
50
+ "type": "git",
51
+ "url": "git+https://github.com/yellow-yel/dsh-fatfish.git",
52
+ "directory": "dsh-fatfish-suite"
53
+ },
54
+ "homepage": "https://github.com/yellow-yel/dsh-fatfish/tree/master/dsh-fatfish-suite#readme",
55
+ "bugs": {
56
+ "url": "https://github.com/yellow-yel/dsh-fatfish/issues"
57
+ },
58
+ "publishConfig": {
59
+ "access": "public",
60
+ "registry": "https://registry.npmjs.org/"
61
+ },
62
+ "dsh": {
63
+ "bundle": {
64
+ "patch": "./cordis.patch.yml"
65
+ }
66
+ },
67
+ "license": "MIT"
68
+ }