@modesto_ma/dsh-channels 0.5.0-beta.4 → 0.5.0-beta.6
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 +49 -28
- package/docs/attachment-pipeline-v2.md +1 -1
- package/docs/feishu-onboarding.md +6 -5
- package/lib/client.js +1874 -1510
- package/lib/client.js.map +1 -1
- package/lib/index.js +736 -353
- package/lib/index.js.map +1 -1
- package/package.json +2 -2
- package/src/client/api.ts +45 -2
- package/src/client/avatar.tsx +36 -0
- package/src/client/icon.tsx +25 -0
- package/src/client/index.ts +78 -23
- package/src/client/number-field.ts +97 -0
- package/src/client/origin-cache.ts +45 -0
- package/src/client/origin.tsx +201 -0
- package/src/client/panel/access-tab.tsx +90 -21
- package/src/client/panel/advanced-tab.tsx +59 -68
- package/src/client/panel/connection-tab.tsx +147 -164
- package/src/client/panel/credentials-card.tsx +124 -87
- package/src/client/panel/fields-tab.tsx +27 -0
- package/src/client/panel/index.tsx +77 -54
- package/src/client/panel/profiles.ts +73 -0
- package/src/client/panel/shared.tsx +358 -253
- package/src/client/panel/whitelist.tsx +203 -0
- package/src/client/panel/wiki-tab.tsx +33 -39
- package/src/client/styles.ts +132 -92
- package/src/domain.ts +42 -0
- package/src/feishu/scopes.ts +2 -1
- package/src/feishu-channel.ts +87 -0
- package/src/index.ts +1 -1
- package/src/routing/inbound.ts +13 -5
- package/src/service.ts +146 -3
- package/src/session/routes.ts +45 -4
- package/src/settings/contract.ts +265 -152
- package/src/settings/routes.ts +47 -0
- package/src/settings/surface.ts +201 -197
- package/src/client/panel/access-card.tsx +0 -329
- package/src/client/panel/analyze-token-card.tsx +0 -70
- package/src/client/panel/model-tab.tsx +0 -23
- package/src/client/panel/sessions-tab.tsx +0 -24
- package/src/client/panel/workspace-tab.tsx +0 -24
package/README.md
CHANGED
|
@@ -13,7 +13,8 @@ DeepSeek Harness(DSH)飞书渠道插件:**一个 dsh 实例对应一个飞
|
|
|
13
13
|
- **结构化提问**:模型调用 `ask_user_question` 时,插件监听主机 `user-questions/request` 瀑布并发一张问答卡(每个问题一组选项按钮,多选先勾选再「提交本题选择」),答案回填给模型;主机自带的应答者只有 Web 客户端,没有本插件时纯飞书会话会以 `NO_PROVIDER` 失败。超时(`questionTimeoutMs`,默认 5 分钟)或回合取消时本轮提问失败(fail-closed);没有可选项的问题直接提示用文字作答,**阻塞期间普通文本回复即作为该问题的自由文本答案**(同时支持多选后的自定义文本)
|
|
14
14
|
- **准入与授权(默认开启)**:**管理员不受白名单限制**(私聊、任意群聊——包括尚未授权的群——都能直接发起会话);其他人私聊只收到一条固定提示(`/userid` 例外),群聊需要「群已授权 + 用户在全局白名单」两层同时命中。机器人被拉进群后私聊管理员发**群信息卡**(未授权群附授权按钮,用于放行白名单用户);已授权群里未授权用户 @ 会触发用户授权卡。授权入口:飞书 `/auth` 命令、授权卡、Web 设置面板;管理员 user_id 在面板配置(私聊 `/userid` 获取),**留空时自动使用飞书应用所有者**
|
|
15
15
|
- 全部基于飞书官方 SDK [`@larksuiteoapi/node-sdk`](https://www.npmjs.com/package/@larksuiteoapi/node-sdk)(WebSocket 长连接,免公网)
|
|
16
|
-
- **Web 设置面板**:Web
|
|
16
|
+
- **Web 设置面板**:Web/桌面端左侧栏 **飞书渠道** 入口(主区整页),顶部状态头 + 7 个标签页(连接 / 会话 / 模型 / 附件与工具 / 访问授权 / 知识库 / 高级);凭据不完整时插件不连接、面板显示三步引导,填写保存后自动连接(保存写入本机覆盖文件,部分字段需重连生效);详见下文「Web 设置面板」章节
|
|
17
|
+
- **对话里的飞书来源**:从飞书发起的会话在 Web/桌面端对话标题旁多一个来源按钮(群名或「飞书私聊」),点开在右侧栏「飞书来源」标签页查看群聊/私聊、话题、发起人、开始与最近活跃时间,并可跳回飞书;其他会话不显示;详见下文「对话里的飞书来源」章节
|
|
17
18
|
|
|
18
19
|
设计与可行性论证见 [docs/feasibility-and-design.md](docs/feasibility-and-design.md);工作区粒度与会话隔离的取舍见 [docs/workspace-isolation-design.md](docs/workspace-isolation-design.md);入站附件管线(存储 / 清单 / 工具 / 引用与历史 / 降级 / 隐私边界)见 [docs/attachment-pipeline-v2.md](docs/attachment-pipeline-v2.md)。
|
|
19
20
|
|
|
@@ -39,6 +40,8 @@ DeepSeek Harness(DSH)飞书渠道插件:**一个 dsh 实例对应一个飞
|
|
|
39
40
|
|
|
40
41
|
`/new` 是 `/renew` 的别名。`/help` 由命令注册表按分组生成,新增命令只需在注册表里加一行。
|
|
41
42
|
|
|
43
|
+
不在上面命令表中的 `/` 开头消息(如 `/guanxiang …`)不由插件处理,而是和普通消息一样经过准入后作为 prompt 交给 DSH,由 DSH 展开对应的用户可调用 skill;没有同名 skill 时按普通文本处理。
|
|
44
|
+
|
|
42
45
|
**飞书原生斜杠指令面板**(可选,`slashCommandPanel: true` 开启,默认关闭;部分企业不允许应用添加斜杠指令):开启后每次连上飞书,插件在后台调用 `application/v7/app_slash_commands` 把命令注册表同步到飞书原生面板,用户在聊天框输入 `/` 即可直接选择命令(飞书客户端有约 5 分钟缓存)。同步是全量对齐且幂等:缺的创建、描述变了的原地更新、注册表里已没有的或重复的删除(别名不单独列出),注册表不变时再次连接不产生任何写操作;超时(30 秒)或断开后不再发起新的写操作。需要可选权限 `application:app_slash_command:read`(读取现有命令)与 `application:app_slash_command:write`(增删改),两项只在开启时列入权限自检。关闭时插件不读写面板。同步失败只影响面板列表,直接输入命令照常可用;失败原因显示在 Web 设置「连接」页并打印一条 warn。
|
|
43
46
|
|
|
44
47
|
## 流式卡片
|
|
@@ -59,9 +62,9 @@ DeepSeek Harness(DSH)飞书渠道插件:**一个 dsh 实例对应一个飞
|
|
|
59
62
|
- 第二行:`📊 上下文 {tokens}/{window} ({占比}) · 📩 输入 {n} · 📨 输出 {n} · ⚡ 缓存命中 {pct}`。占比 = 上下文 tokens / 窗口(<10% 保留一位小数,≥10% 取整);没有窗口时只显示 tokens
|
|
60
63
|
- 输入/输出为 session 累计口径;模型、推理强度、缓存命中按**当前轮次**,本轮在请求头产生前失败时模型/缓存命中显示 `—`、推理强度省略,不会沿用上一轮
|
|
61
64
|
|
|
62
|
-
## Web
|
|
65
|
+
## Web 设置面板(左侧栏 → 飞书渠道)
|
|
63
66
|
|
|
64
|
-
包内含可选的浏览器半区(`lib/client.js`,DSH client module):在 Web
|
|
67
|
+
包内含可选的浏览器半区(`lib/client.js`,DSH client module):在 Web/桌面端左侧栏注册「飞书渠道」全局入口(`sidebar.panellist`),点击后在主区打开整页面板(`main` 槽)。宿主没有 `webServer` 服务(headless profile)时不加载面板,飞书通道本身不受影响。
|
|
65
68
|
|
|
66
69
|
**连接时机**:启用插件时**不会无条件连接飞书**。插件启动先读取 profile 配置与 Web 覆盖,再检查 `appId` / `appSecret` 两个凭据引用能否解析出值:
|
|
67
70
|
|
|
@@ -69,30 +72,33 @@ DeepSeek Harness(DSH)飞书渠道插件:**一个 dsh 实例对应一个飞
|
|
|
69
72
|
- **凭据不完整** → 插件正常加载、**不建连接**、不报错,面板显示「待配置」与三步引导;在「连接」标签页填好两项凭据并保存后自动连接。
|
|
70
73
|
- **连接失败**(凭据错误、网络等)→ 记录在面板状态卡,插件保持加载;修好凭据或网络后点「重试」。
|
|
71
74
|
|
|
72
|
-
|
|
75
|
+
**面板结构**:顶部固定状态头(标题、阶段徽标:待配置 / 未连接 / 连接中 / 已连接 / 连接失败、插件版本、运行时长、刷新按钮),下方按标签页分区。每一项是单列一行:名称 + 一句话说明 + 控件,两值选项用开关,较长的说明收在「详情」里;数值项按显示单位输入(天 / 秒 / ms / 条 / 字节,字节项旁显示 MiB 读数)。
|
|
73
76
|
|
|
74
77
|
| 标签页 | 内容 |
|
|
75
78
|
| --- | --- |
|
|
76
|
-
| 连接 |
|
|
77
|
-
|
|
|
78
|
-
| 模型 |
|
|
79
|
-
|
|
|
80
|
-
| 访问授权 |
|
|
81
|
-
| 知识库 |
|
|
82
|
-
| 高级 |
|
|
79
|
+
| 连接 | 状态块(当前阶段唯一的操作按钮:连接 / 重试 / 重启连接,连接后显示话题路由 / 活动会话 / 在途回复 / Bot open_id 尾号)、自检(权限缺口可展开逐项开通、斜杠指令面板同步结果)、飞书应用凭据(更换 / 移除);未配置时显示三步引导,有需重连才生效的已保存项时顶部显示「重启连接」横幅 |
|
|
80
|
+
| 会话 | 「触发」:私聊、普通群需要 @、话题被拒时降级为会话级(均为开关);「工作区」:工作区根目录、话题工作目录隔离方式(`topicIsolation`);「话题与卡片」:话题过期(`routeTtlMs`,按天)、审批 / 提问卡片等待(`approvalTimeoutMs` / `questionTimeoutMs`,按秒)、流式刷新与状态行保活间隔;「飞书侧功能」:首次私聊引导、斜杠指令面板同步、权限切换 |
|
|
81
|
+
| 模型 | 服务商、模型、推理档位、单次输出上限(`maxTokens`,留空使用模型默认)、Agent 预设 |
|
|
82
|
+
| 附件与工具 | 「入站附件」:接收图片和文件、使用 DSH 原生附件库(开关,关闭则存到话题目录 `attachments/`)、图片预取、首轮话题历史;「工具」:`feishu_attachment_fetch` / `feishu_topic_messages` / `feishu_send_file` 开关;「限额与超时」:预取上限、读取附件上限与超时、读取话题消息超时、引用摘录与历史超时(共 8 项,默认收起,有改动或错误时自动展开) |
|
|
83
|
+
| 访问授权 | 待处理申请(置顶,一键授权 / 忽略)、调试模式(`accessMode`,开关)、管理员 user_id、申请有效期;已授权群 / 用户白名单(添加表单默认收起) |
|
|
84
|
+
| 知识库 | 知识库读 / 写开关(`feishuTools.wikiRead` / `feishuTools.wikiWrite`)、可访问范围 `wikiRoots`(每条链接一个输入框,逐条校验);「可使用的人」:知识库白名单增删(与用户白名单独立,等同 `/auth wiki add|remove`) |
|
|
85
|
+
| 高级 | 日志分析接口(监听地址 `analyzeListen` 与访问令牌)、SDK 日志级别、Web 覆盖文件路径与「恢复 profile 配置」 |
|
|
86
|
+
|
|
87
|
+
**调试模式**:「访问授权 → 调试模式」打开即 `accessMode: open`,所有人都能和机器人聊天;打开期间面板顶部常驻黄色警告。默认关闭(`guarded`)。
|
|
83
88
|
|
|
84
|
-
**入站附件与模型工具(v2
|
|
89
|
+
**入站附件与模型工具(v2)**:「附件与工具」标签页的字段与 profile 配置同名、写入同一 Web 覆盖文件(`$DSH_HOME/dsh-channels/settings.json`):
|
|
85
90
|
|
|
86
|
-
-
|
|
87
|
-
-
|
|
91
|
+
- **入站附件**:附件接收(`acceptAttachments`)、入站附件存储后端(`attachmentStore`:开关打开为 DSH 原生附件库,关闭为话题目录 `attachments/`)、触发消息图片预取(`prefetchImages`)、首轮话题历史条数(`historyBootstrapLimit`)。
|
|
92
|
+
- **工具**:`feishu_attachment_fetch`(`feishuTools.attachmentFetch`)、`feishu_topic_messages`(`feishuTools.topicMessages`)、`feishu_send_file`(`feishuTools.sendFile`)开关。
|
|
93
|
+
- **限额与超时**:预取单图 / 总量 / 整段超时(`prefetchImageMaxBytes` / `prefetchTotalMaxBytes` / `prefetchTimeoutMs`)、读取附件资源数 / 字节预算 / 超时(`feishuTools.attachmentFetchMaxResources` / `attachmentFetchMaxBytes` / `attachmentFetchTimeoutMs`)、读取话题消息超时(`feishuTools.topicMessagesTimeoutMs`)、被动引用 / 历史读取预算(`promptContextTimeoutMs`)。
|
|
88
94
|
|
|
89
95
|
`feishuTools.*` 是嵌套配置:面板只把改动过的子键写进覆盖层,其余子键保持原值(Web 覆盖或 profile 配置),不会因部分保存变成未定义。字段默认值、边界与降级规则见下文配置示例和 [docs/attachment-pipeline-v2.md](docs/attachment-pipeline-v2.md)。
|
|
90
96
|
|
|
91
97
|
**连接状态**:阶段徽标(待配置 / 未连接 / 连接中 / 已连接 / 连接失败)、飞书长连接状态、Bot open_id 尾号、运行时长、话题路由数 / 活动会话 / 在途回复、最近一次连接失败原因;每 5 秒自动刷新,也可手动刷新或**重启飞书连接**(会断开当前长连接并中断进行中的回复)。徽标不是健康时会额外显示「健康判定」原因——健康等级由宿主**所有 Cordis fiber** 折叠而来,因此「降级」也可能来自其它插件入口仍在等待依赖/加载(与飞书通道无关),原因行会列出对应插件名;「连接失败」只针对飞书连接本身,插件入口保持加载。
|
|
92
98
|
|
|
93
|
-
**飞书应用凭据**:在「连接 → 飞书应用凭据」卡片里填写 **App ID / App Secret** 并保存,值经宿主 `ctx.credentials` 写入 DSH 凭据库(默认 `$DSH_HOME/.credentials.yaml` 的 `refs:` 段,仍遵循凭据层的解析优先级),面板只显示「已配置 /
|
|
99
|
+
**飞书应用凭据**:在「连接 → 飞书应用凭据」卡片里填写 **App ID / App Secret** 并保存,值经宿主 `ctx.credentials` 写入 DSH 凭据库(默认 `$DSH_HOME/.credentials.yaml` 的 `refs:` 段,仍遵循凭据层的解析优先级),面板只显示「已配置 / 未配置」与来源,**永不回显已存值**。两项齐全且通道未运行时保存后自动建立连接;已连接时保存只提示重连;只填了一项时保存成功但**不会连接**(状态保持「待配置」),补齐另一项后自动连接。每项凭据一行,点「更换」展开输入框,已存值可以单独「移除」;行内显示的是凭据**引用名**(profile 配置里的 `appId` / `appSecret`),换引用名仍需改 profile 配置。「高级 → 日志分析接口 → 访问令牌」用同样方式写入令牌,保存或移除后下一次接口请求即生效,不会重连飞书。
|
|
94
100
|
|
|
95
|
-
|
|
101
|
+
**统一保存**:除连接类操作外,可编辑字段共用一个跨标签页的草稿;有未保存改动时页面底部浮出保存栏(「N 项未保存」、其中需重连的项数、「放弃 / 保存」),没有改动时不显示。只提交改动过的字段,标注「需重连」的项在下次连接时生效;保存后「连接」标签页顶部横幅列出待生效项并提供一键重连。
|
|
96
102
|
|
|
97
103
|
**模型选择器**:模型与推理在面板里是**独立的「模型」标签页**:宿主 LLM 服务可用时,`provider` / `model` / `reasoningEffort` 与 `agentPreset` 渲染为**下拉选择**而不是手填:provider 来自 `ctx.llm.listProviders()`,model 来自所选 provider 的 `listModels()`,推理档位来自 `resolveModelInfo(provider, model).reasoning.efforts`,Agent 预设来自 `agentPresets.list()`。每个选择器的首项是「留空 = 部署默认 / 适配器默认 / roster 默认」,有部署默认模型(`agentDefaultModel`)或 roster 默认预设时会在标签里带上具体值。选择按依赖级联:先选 provider 才会加载 model,选了 model 才会加载推理档位;宿主暂时无法枚举的项(服务未挂载、适配器查询失败/超时)自动退回原来的自由文本框,已保存但当前列表里没有的值会作为「当前配置,不在宿主机列表中」选项保留,不会在打开面板时被静默改掉。级联查询走只读的 `GET /dsh-channels/catalog?provider=…&model=…`(Host 侧短 TTL 缓存,单次查询 4 秒上限)。`provider` 与 `model` 在宿主侧是一条完整的请求路由,因此面板保存时要求**两者同时设置或同时留空**,不允许只选一半。
|
|
98
104
|
|
|
@@ -100,9 +106,9 @@ DeepSeek Harness(DSH)飞书渠道插件:**一个 dsh 实例对应一个飞
|
|
|
100
106
|
|
|
101
107
|
**可视化选择工作区根目录**:输入框旁的「选择目录…」按钮会调用**宿主机的系统目录选择框**(macOS 的 NSOpenPanel / Windows 的文件夹对话框),选中后把绝对路径填进草稿,仍需点「保存更改」才落盘。该能力转发自宿主可选的 `ctx.directoryPicker` 服务:桌面端/本机 GUI 会话(native 后端)提供按钮;headless、远程或 SSH 会话没有可服务的显示会话(browse 后端),面板不显示按钮、保留手写输入,插件在缺少该服务的旧宿主上照常加载。选择框打开期间请求保持挂起;取消是正常结果,不会报错。
|
|
102
108
|
|
|
103
|
-
**访问授权**:「访问授权」标签页集中管理准入:管理员 user_id(私聊 `/userid`
|
|
109
|
+
**访问授权**:「访问授权」标签页集中管理准入:管理员 user_id(私聊 `/userid` 获取)、调试模式、授权申请有效期;「已授权群」「已授权用户」列表支持增删(群 ID 可从入群群信息卡或 `/groupid` 获得,用户 user_id 可用 `/userid` 查看);「待处理申请」可一键授权/忽略。白名单只约束非管理员:管理员在任何私聊/群聊都直接放行。管理员留空时自动使用飞书应用所有者(连接时通过「获取应用信息」接口查询),管理员设置下方的「当前管理员」一行会注明“应用所有者”;`guarded` 且既未配置管理员、也查不到应用所有者时,标签页顶部会红字提示“当前会拒绝所有对话”并附上查询失败原因。管理员、群和用户白名单、待处理申请、知识库白名单在每次进入页面时实时读取飞书头像和名字(`GET /dsh-channels/profiles?users=…&chats=…`,每类最多 200 个,Host 侧缓存 30 秒):用户需要 `contact:user.base:readonly` 且在应用的通讯录权限范围内,群需要 `im:chat:readonly`;读不到时显示授权时记下的名字或 ID,并在标签页顶部注明失败原因。授权白名单与申请记录保存在插件 `storageDomain`(`channels_routes_v2` 域),重启后保留;未建立飞书连接时白名单尚未加载,标签页会提示「连接建立后加载授权列表」并禁用写操作。
|
|
104
110
|
|
|
105
|
-
**配置层级**:`configSchema` 默认值 < profile `cordis.patch.yml` 的 `config` < Web 面板覆盖。面板只把可编辑字段写入 `$DSH_HOME/dsh-channels/settings.json`;「高级 →
|
|
111
|
+
**配置层级**:`configSchema` 默认值 < profile `cordis.patch.yml` 的 `config` < Web 面板覆盖。面板只把可编辑字段写入 `$DSH_HOME/dsh-channels/settings.json`;「高级 → 恢复 profile 配置」确认后删除该文件并回落到 profile 配置。`baseDir` 与 `topicIsolation` 在「会话 → 工作区」编辑(只影响之后新建的话题);话题过期、审批 / 提问卡片等待与 `maxTokens` 保存后立即生效,不需要重连。凭据**值**在「连接 → 飞书应用凭据」编辑,凭据**引用名**(`appId` / `appSecret` 配置项)仍由 profile 配置决定。已移除的目录清理配置 `workspaceRetention` / `workspaceRetentionAuto` 与覆盖文件路径配置 `settingsFile` 若仍留在 profile 或覆盖文件中会被静默忽略,面板下次保存时从覆盖文件中去掉。
|
|
106
112
|
|
|
107
113
|
**为什么落在插件自己的文件而不是 profile 的 `cordis.patch.yml`?** DSH 提供官方 `ctx.configEditor.edit()`,可以安全写 profile patch(完整 Config 校验、保留注释与 `!!js`、原子替换、失败回滚、与 HMR 串行);但它是「完整配置编辑」通道——本插件的 Config 是 zod,没有 schemastery `.volatile()` 标记,普通字段写入会触发 Loader 重载插件,等于每次保存都断开并重连飞书;而且该服务只在有 `profileContext` 的启动器(桌面端 / `dsh web`)存在。`$DSH_HOME/<plugin>/` 是 DSH 插件保存运行时数据的惯例(如 dsh-pet 的 `$DSH_HOME/dsh-pet/`),因此面板偏好写入 `$DSH_HOME/dsh-channels/settings.json`:保存即生效(需重连字段除外)、可一键清除回退、不依赖 `profileContext`;profile 的 `cordis.patch.yml` 继续作为部署级基础配置层。若将来要求「所有配置统一进 profile」,迁移路径是改用 `ctx.configEditor.edit()` 并接受保存触发插件重载。
|
|
108
114
|
|
|
@@ -116,6 +122,18 @@ pnpm verify:host # 以纯 ESM 导入 Host bundle,检查 Cordis 插件面
|
|
|
116
122
|
pnpm verify:client # 用 __ModuleLoader__ shim 做 loader 冒烟
|
|
117
123
|
```
|
|
118
124
|
|
|
125
|
+
## 对话里的飞书来源
|
|
126
|
+
|
|
127
|
+
从飞书发起的会话(话题、会话级降级、`/renew` 新开的会话、日志平台分析话题)在 Web/桌面端对话标题旁会出现一个来源按钮:群聊显示群名,私聊显示「私聊 · 对方姓名」(读不到姓名时为「飞书私聊」)。点击后在右侧栏打开「飞书来源」标签页,内容包括:
|
|
128
|
+
|
|
129
|
+
- **标题**:群聊为群头像和群名,私聊为对方头像和姓名;
|
|
130
|
+
- **来源**:私聊 / 群聊 / 群聊 · 话题;群名读不到时显示群 ID;
|
|
131
|
+
- **发起人**:头像、姓名 + `user_id`(日志平台分析话题显示请求人,并注明群内成员都可以继续);
|
|
132
|
+
- **开始于 / 最近活跃**:飞书侧已经换到新会话(`/renew`、`/new`)或路由过期后,「最近活跃」换成「状态:飞书侧已切换到新会话或已过期」;
|
|
133
|
+
- **在飞书中打开**(飞书 applink 打开对应聊天)与「刷新」。
|
|
134
|
+
|
|
135
|
+
Web 里直接新建的会话不显示按钮。来源在 Host 侧按会话 id 持久保存(存储表 `session_origins`,路由过期后仍可查;升级前已有的路由在启动时补写)。群名、群头像、姓名与头像在每次打开「飞书来源」标签页时实时读取(Host 侧缓存 30 秒,标题旁按钮与标签页同时打开只查一次):群用 `im:chat:readonly`,用户优先用通讯录 `contact:user.base:readonly`,缺失时群聊从群成员列表查姓名(没有头像),私聊只显示 `user_id`。接口为 `GET /dsh-channels/session-origin?sessionId=…`,与设置面板一样需要 DSH 登录。右侧栏不可用的宿主(如 headless)不注册这部分。
|
|
136
|
+
|
|
119
137
|
## 发布
|
|
120
138
|
|
|
121
139
|
版本号由 semantic-release 按 Conventional Commits 计算,**只在手动触发时发布**;推送到 `main` / `dev` 只跑检查,可以先累积多笔提交。
|
|
@@ -185,16 +203,19 @@ src/
|
|
|
185
203
|
├── health.ts # 健康快照与卡片
|
|
186
204
|
├── session-export.ts # 逻辑日志导出
|
|
187
205
|
├── feishu-channel.ts # 官方 SDK Channel 适配(可注入 stub)
|
|
188
|
-
├── client/ #
|
|
189
|
-
│ ├── index.ts # client 插件入口:
|
|
206
|
+
├── client/ # 浏览器半区:左侧栏「飞书渠道」主区页面(构建到 lib/client.js)
|
|
207
|
+
│ ├── index.ts # client 插件入口:sidebar.panellist + main 注册、飞书来源(右侧栏标签 + 会话头部入口)+ 样式
|
|
208
|
+
│ ├── origin.tsx # 对话里的飞书来源:会话头部按钮与右侧栏标签页
|
|
209
|
+
│ ├── origin-cache.ts # 按会话缓存的来源查询
|
|
190
210
|
│ ├── panel/ # 页面外壳 + 七个标签页
|
|
191
211
|
│ │ ├── index.tsx # 加载 / 5s 状态轮询 / 全局草稿 / catalog 级联 / 顶部状态头 / Tab
|
|
192
|
-
│ │ ├── shared.tsx #
|
|
193
|
-
│ │ ├── connection-tab.tsx # 连接:三步引导 /
|
|
194
|
-
│ │ ├── credentials-card.tsx #
|
|
195
|
-
│ │ ├──
|
|
196
|
-
│ │ ├──
|
|
197
|
-
│ │ └──
|
|
212
|
+
│ │ ├── shared.tsx # 行 / 开关 / 分组 / 保存栏等渲染原语、阶段徽标、草稿校验
|
|
213
|
+
│ │ ├── connection-tab.tsx # 连接:三步引导 / 状态块 / 自检 / 待生效提醒 / 凭据
|
|
214
|
+
│ │ ├── credentials-card.tsx # 凭据行:更换 / 移除(不回显),App 凭据与分析接口令牌共用
|
|
215
|
+
│ │ ├── fields-tab.tsx # 会话 / 模型 / 附件与工具:纯字段分组页
|
|
216
|
+
│ │ ├── access-tab.tsx / wiki-tab.tsx / advanced-tab.tsx
|
|
217
|
+
│ │ └── whitelist.tsx # 白名单与待处理申请列表
|
|
218
|
+
│ ├── number-field.ts # 数值字段显示单位换算、上下界校验、字节读数
|
|
198
219
|
│ ├── catalog.ts # 选择器目录折叠:Host 字段 + 实时目录 → 表单字段
|
|
199
220
|
│ ├── api.ts # 同源 /dsh-channels/* 请求封装
|
|
200
221
|
│ └── styles.ts # 语义 token 样式(注入一次)
|
|
@@ -298,13 +319,13 @@ FEISHU_APP_ID: cli_xxxxxxxx
|
|
|
298
319
|
FEISHU_APP_SECRET: xxxxxxxx
|
|
299
320
|
```
|
|
300
321
|
|
|
301
|
-
也可以不手改文件:安装并在 Web
|
|
322
|
+
也可以不手改文件:安装并在 Web 左侧栏打开 **飞书渠道**,在「飞书应用凭据」卡片填入 App ID / App Secret 保存即可(值同样写进该凭据库)。
|
|
302
323
|
|
|
303
324
|
文件必须仅属主可读(dsh 强制校验,否则拒绝启动):`chmod 600 $DSH_HOME/.credentials.yaml`。解析优先级:进程环境变量 > `.credentials.yaml` > `<cwd>/.env` > `$DSH_HOME/.env`(由 `dsh-credentials-local` 提供,热加载)。配置里只写引用名,明文密钥会被 schema 拒绝。改动凭据后:Web 面板保存会即时写入,未连接时自动建立连接、已连接时提示重连;手改 `.credentials.yaml` 由凭据层热加载,但正在运行的连接不会自动使用新值,需在面板点「重启飞书连接」。
|
|
304
325
|
|
|
305
326
|
验证组合(不启动服务):`DSH_HOME=$DSH_HOME pnpm dsh web --dump-config | grep dsh-channels`
|
|
306
327
|
|
|
307
|
-
启动成功标志(控制台):`[dsh-channels] feishu long connection established, bot open_id: ou_xxx`;凭据不完整时不会连接,日志会提示缺少的凭据引用(如 `飞书应用凭据未配置完整(缺少 FEISHU_APP_SECRET…)`),打开 Web
|
|
328
|
+
启动成功标志(控制台):`[dsh-channels] feishu long connection established, bot open_id: ou_xxx`;凭据不完整时不会连接,日志会提示缺少的凭据引用(如 `飞书应用凭据未配置完整(缺少 FEISHU_APP_SECRET…)`),打开 Web 左侧栏 **飞书渠道 → 连接** 补齐即可。
|
|
308
329
|
|
|
309
330
|
宿主 profile 已内置所需服务(agent-loop、llm-deepseek、session 持久化、storage-domain、workspace、working-directory);web profile 默认组合还包含 DSH 原生附件库 `dsh-attachment-local` 与 `dsh-tools`(`ctx.attachments` / `ctx.tools`)。缺少原生附件库时入站附件自动回退 archive 后端(见「行为与降级」)。推荐确认 `dsh-token-meter` 已启用(卡片上下文占用显示)。Git worktree 隔离模式额外依赖可选的 `@deepseek-ai/dsh-experimental-worktree` 实验插件,缺失时自动回退为普通话题子目录。
|
|
310
331
|
|
|
@@ -214,7 +214,7 @@ native 后端下,准入通过后由 `inboundAttachmentState` 做**不下载的
|
|
|
214
214
|
|
|
215
215
|
## 11. 配置项全景
|
|
216
216
|
|
|
217
|
-
下表为 v2 相关配置(默认值 / 边界以 [src/config.ts](../src/config.ts) 为准)。Web
|
|
217
|
+
下表为 v2 相关配置(默认值 / 边界以 [src/config.ts](../src/config.ts) 为准)。Web 面板「左侧栏 → 飞书渠道 → 附件与工具」把它们分为「入站附件」(`FieldGroup = attachments`)、「工具」(`tools`)与默认收起的「限额与超时」(`limits`)三组;`feishuTools.*` 在覆盖层中仍写成嵌套对象,保存时只合并被修改的子键。
|
|
218
218
|
|
|
219
219
|
| 配置项 | 默认 | 边界 / 说明 | 面板分组 |
|
|
220
220
|
| --- | --- | --- | --- |
|
|
@@ -26,7 +26,8 @@
|
|
|
26
26
|
| `im:resource`(获取与上传图片或文件资源,**可选**;`im:resource:upload` 亦可) | 模型用 `feishu_send_file` 把生成的图片/文件发给用户;不开通时该工具返回可读错误 |
|
|
27
27
|
| `im:message:update`(更新消息卡片) | 流式卡片刷新(patch) |
|
|
28
28
|
| `wiki:wiki`、`docx:document`(只读可用对应的 `:readonly` 权限),电子表格 `sheets:spreadsheet:read` / `sheets:spreadsheet:write_only`,多维表格 `base:table:read`、`base:field:read`、`base:record:read` / `base:record:create`、`base:record:update`、`base:record:delete`(**可选**;旧版 `sheets:spreadsheet` / `bitable:app` 对新版接口不生效) | 知识库工具(`feishuTools.wikiRead` / `wikiWrite` + `wikiRoots`):浏览知识库,读取/新建/修改飞书文档、电子表格、多维表格;应用还需是目标知识空间的成员 |
|
|
29
|
-
| `im:chat:readonly` 一类(获取群信息) |
|
|
29
|
+
| `im:chat:readonly` 一类(获取群信息) | 入群通知卡展示群名/成员数;Web 设置页和对话「飞书来源」显示群名、群头像,并在缺少通讯录权限时从群成员列表读取发起人姓名(具体 scope 以控制台要求为准) |
|
|
30
|
+
| `contact:user.base:readonly`(获取用户基本信息,**可选**) | Web 设置页(管理员、白名单、待处理申请、知识库用户)和对话「飞书来源」显示用户真实姓名与头像;还要求用户在应用的「通讯录权限范围」内(最简单是选全部成员)。缺失时显示授权时记下的名字或 user_id,「飞书来源」的群聊发起人退回群成员列表取名字(没有头像) |
|
|
30
31
|
| 「获取应用信息」一类(如 `admin:app.info:readonly` / `application:application:self_manage`,**可选**,以控制台要求为准) | 未配置 `adminUserId` 时连接后自动把应用所有者设为管理员;不便申请时跳过即可,按 3.3 手动设置管理员 |
|
|
31
32
|
| `application:app_slash_command:read` 与 `application:app_slash_command:write`(读取/管理应用斜杠指令,可选,仅 `slashCommandPanel: true` 时需要) | 连接后把插件命令同步到飞书原生斜杠指令面板(输入 `/` 时列出,客户端约 5 分钟后刷新);缺失时只是面板没有列表,直接输入命令不受影响 |
|
|
32
33
|
|
|
@@ -174,14 +175,14 @@ chmod 600 $DSH_HOME/.credentials.yaml
|
|
|
174
175
|
| `feishuTools.topicMessagesTimeoutMs` | `20000` | 单次 `feishu_topic_messages` 整段超时(1000–120000 ms) |
|
|
175
176
|
| `loggerLevel` | `info` | 官方 SDK 日志级别 |
|
|
176
177
|
|
|
177
|
-
> **面板与配置位置**:v2
|
|
178
|
+
> **面板与配置位置**:v2 附件配置在 Web 面板「左侧栏 → 飞书渠道 → 附件与工具」:`acceptAttachments` / `attachmentStore` / `prefetchImages` / `historyBootstrapLimit` 在「入站附件」组,`feishuTools.*` 开关在「工具」组,各项字节上限与超时在「限额与超时」组;保存写入同一 Web 覆盖文件,`feishuTools.*` 按子键合并(不会把未修改子键写空)。直接写 profile 补丁层同样生效,面板覆盖优先。其中 `feishuTools.topicMessages=false` 只关闭模型工具,被动的引用/历史 prompt 摘录仍生效;要完全关闭首轮历史请设 `historyBootstrapLimit: 0`。archive 后端下 `feishu_attachment_fetch` 不挂载,`feishu_topic_messages` 仍可读取历史文本,但工具描述会提示附件不可取。
|
|
178
179
|
|
|
179
180
|
### 3.3 初始化管理员与授权(默认准入)
|
|
180
181
|
|
|
181
182
|
插件默认 `accessMode: 'guarded'`:**没有管理员时,所有对话都会被拒绝**(这是 fail-closed 的安全默认值)。如果应用开通了可选的「获取应用信息」权限,留空 `adminUserId` 时连接后会自动把应用所有者设为管理员(Web「访问授权」页显示“已自动使用应用所有者”),可以跳过下面第 1–2 步;没开通或查询失败时按以下顺序手动设置:
|
|
182
183
|
|
|
183
184
|
1. 启动 dsh 后在飞书**私聊机器人**发送 `/userid`(未配置管理员时任何私聊用户都可以用,只回固定文本,不建会话)→ 复制返回的 user_id;
|
|
184
|
-
2. 打开 Web
|
|
185
|
+
2. 打开 Web 左侧栏 **飞书渠道 → 访问授权**,把它填进「管理员 user_id」并保存(立即生效);也可以直接写 profile 的 `adminUserId`;
|
|
185
186
|
3. 现在管理员私聊机器人即可正常对话。**其他用户私聊会收到一条固定提示**(“非管理员禁用私聊功能哦…”),不会建会话;
|
|
186
187
|
4. **给群授权**(三种入口任选;目的是放行**非管理员**,管理员本人在任何群都能直接对话):
|
|
187
188
|
- 机器人被拉进群 → 管理员私聊收到**群信息卡**(群名/`chat_id`/成员数/邀请人)→ 点「授权本群」;
|
|
@@ -233,7 +234,7 @@ DSH_HOME=$DSH_HOME pnpm dsh web # 默认 http://127.0.0.1:3080
|
|
|
233
234
|
| `feishu_topic_messages 未挂载:宿主 tools 服务不可用(会话继续)` | 缺 `tools` 服务:话题读取工具不注册 |
|
|
234
235
|
| `adopted N legacy staged attachment(s) into …; the one-time _staging migration is deprecated and will be removed after one release cycle` | 旧版 `_staging` 遗留文件被一次性迁入话题目录;按 D12,该兼容路径在 v2 发布后的下一个 minor 版本移除,可据此清理旧数据 |
|
|
235
236
|
|
|
236
|
-
**未配置凭据(不是启动失败)**:日志会提示 `飞书应用凭据未配置完整(缺少 FEISHU_APP_…)`,插件照常加载但**不连接**;打开 Web
|
|
237
|
+
**未配置凭据(不是启动失败)**:日志会提示 `飞书应用凭据未配置完整(缺少 FEISHU_APP_…)`,插件照常加载但**不连接**;打开 Web 左侧栏 **飞书渠道 → 连接**,按三步引导填写 App ID / App Secret 并保存后自动连接。
|
|
237
238
|
|
|
238
239
|
**常见连接失败**(插件保持加载,面板「连接」标签页显示原因,可重试):
|
|
239
240
|
|
|
@@ -340,7 +341,7 @@ DSH_HOME=$DSH_HOME pnpm dsh web # 默认 http://127.0.0.1:3080
|
|
|
340
341
|
| D4 | 关闭附件接收 | 面板关闭 `acceptAttachments` 后发纯附件 / 文件+文字 | 纯附件:无回复/无登记/无下载;文件+文字:只以文字触发,附件不保存不登记 | ⏳ 待手测(自动测试覆盖) |
|
|
341
342
|
| E1 | 权限缺失·读取 | 临时移除 `im:message:readonly`(或让 `im:message.group_msg` 未审批)后发布版本,发引用消息/在群内 @ | 普通对话正常;引用/历史块静默省略;首次降级一条 warn;显式 `feishu_topic_messages` 返回可读 `PERMISSION_DENIED`;恢复权限并重发版本后恢复 | ⏳ 待手测(用户已决定跳过;自动测试覆盖 throw/resolved 两种降级) |
|
|
342
343
|
| E2 | 权限缺失·下载 | 临时移除消息资源读取相关 scope,让模型 fetch 一个文件 | 工具逐资源返回可读失败(403/权限说明),回合不崩;archive 下则加 `No` 并回纯文字失败提示 | ⏳ 待手测(自动测试覆盖) |
|
|
343
|
-
| F1 | 面板配置 | 在 Web
|
|
344
|
+
| F1 | 面板配置 | 在 Web 「附件与工具」依次修改存储后端、预取开关/上限、登记 TTL/容量、两个工具开关与上限并保存,新建会话验证生效 | 面板读写与帮助文案正确;嵌套 `feishuTools.*` 只改被改子键;旧值不丢;保存后入站行为即时按新配置判定、工具挂载对新会话生效;非法值被拒 | ⏳ 待手测 + 自动测试(settings 覆盖) |
|
|
344
345
|
|
|
345
346
|
**记录要求**:每个「待手测」项执行后,在 `acceptance.md` 对应 AC 下写「操作 / 实际结果 / 结论 / 环境(构建 SHA、profile、日期)」;失败的项保留原文与日志摘录,修复后复测再更新。`historyBootstrapLimit: 0`、非本 route 负向、`acceptAttachments=false` 等用户已决定跳过真机的项,标注「自动测试覆盖,用户决定跳过真机」,不要写成已验证。
|
|
346
347
|
|