@whyshu/argent-erp 0.0.0-stage → 0.2.3
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 +179 -2
- package/cordis.patch.yml +6 -0
- package/dist/client.js +614 -0
- package/package.json +55 -4
- package/presets/argent-office.patch.yml +78 -0
- package/src/data.mjs +297 -0
- package/src/index.js +123 -0
- package/src/office-guard.js +105 -0
- package/src/vendor/account-token.mjs +41 -0
- package/src/vendor/redact.mjs +37 -0
package/README.md
CHANGED
|
@@ -1,3 +1,180 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @whyshu/argent-erp(v0.2.0)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**两件东西,一个货**:
|
|
4
|
+
|
|
5
|
+
1. **DSH 会话视图插件**:会话顶部 Chat / 轨迹 旁加一个「ERP」tab,把 Argent ERP 的
|
|
6
|
+
办公室现场 / 待办 / 时间线 / 货件 / 聊一聊入口渲染进 dsh,看 ERP 不用离开当前会话;
|
|
7
|
+
2. **「六禾园办公室助理」preset**:让「和办公室聊一聊」变成一个**真正的 dsh 会话**
|
|
8
|
+
(原生 Chat,含轨迹/统计/中断),但**边界写死在 preset 里**——只聊办公室、只读 ERP、无本机能力。
|
|
9
|
+
|
|
10
|
+
> 目标不是把 ERP 后台搬空,而是把"看"和"聊"搬进会话;重编辑与写操作仍在 ERP web。
|
|
11
|
+
> ERP 业务逻辑与数据始终在 `whyshu-svr`;本包**只读**。
|
|
12
|
+
|
|
13
|
+
## 1. 结构
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
src/index.js 宿主插件:注册 /api/argent-erp/*(带账号 token 去 whyshu.com,token 不下发浏览器)
|
|
17
|
+
src/data.mjs 数据层:whoami / overview / timeline / flow / shipment / chat 历史(经 vendor/redact 脱敏)
|
|
18
|
+
src/office-guard.js 办公室会话的**工具边界**(preset 内挂载:只放行 mcp__argent__erp_*)
|
|
19
|
+
src/vendor/ account-token.mjs + redact.mjs 的**副本**(插件可发布,不能相对 import core/lib)
|
|
20
|
+
presets/argent-office.patch.yml 「六禾园办公室助理」preset 声明行(dsh 0.2.x 行式 preset)
|
|
21
|
+
dist/client.js 客户端 bundle(手写维护):注册 conversation.view(id=erp)+ 视图实现
|
|
22
|
+
test/ 客户端 bundle + preset 边界冒烟测试(纯夹具,不启 dsh、不联网)
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
`package.json#dsh.bundle.patch` 是**数组**:`[cordis.patch.yml, presets/argent-office.patch.yml]`
|
|
26
|
+
⇒ 一次 `install_bundle` 同时落「ERP 视图」与「办公室助理 preset」。
|
|
27
|
+
|
|
28
|
+
## 2. 它是「会话视图」而不是「侧栏面板」
|
|
29
|
+
|
|
30
|
+
dsh 0.2.x 的 `conversation.view` 槽 = 对话顶部那排 **Chat / 轨迹 / 统计** 的注册位。
|
|
31
|
+
本插件向该槽注册一项:
|
|
32
|
+
|
|
33
|
+
```js
|
|
34
|
+
ctx.slots.inject("conversation.view", () => ctx.slots.register({
|
|
35
|
+
name: "conversation.view",
|
|
36
|
+
id: "erp",
|
|
37
|
+
order: 5, // Chat=0,本视图=5,轨迹=10
|
|
38
|
+
label: () => "ERP",
|
|
39
|
+
inject: () => ({ sessions, workspaceNav, remote }), // 建会话 / 跳转 / 钉模型
|
|
40
|
+
}, ErpView))
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
- 纯 UI 视图**不需要**注册 `ctx.uiConversation.views.register({ target })`
|
|
44
|
+
—— 那个 registry 是"消费 Session 事件"的 target 才需要的;ERP 视图读的是自己的宿主端点。
|
|
45
|
+
- 视图随会话存在:切会话 → 视图重挂;切 tab 不丢别的 tab 状态。
|
|
46
|
+
|
|
47
|
+
## 3. 视图内容
|
|
48
|
+
|
|
49
|
+
| tab | 内容 | 数据来源(宿主端点) |
|
|
50
|
+
|---|---|---|
|
|
51
|
+
| 办公室 | KPI(待处理/在办/今日完成/执行机在线)+ 在岗员工 + 执行机 + 现场动态 | `/overview` |
|
|
52
|
+
| 待办 | `workItems`(在办优先)→ 点开货件详情(节点 + 发票状态) | `/overview` → `/shipment` |
|
|
53
|
+
| 时间线 | 最近 14 天 `/sku-flows` 按天分组 → 点开 8 节点详情 | `/timeline` → `/flow` |
|
|
54
|
+
| 货件 | 关键词搜索货件 → 点开详情 | `/shipments` → `/shipment` |
|
|
55
|
+
| 聊一聊 | **一键开「六禾园办公室助理」dsh 会话** + ERP 侧历史(只读) | 客户端 `sessions.create` |
|
|
56
|
+
|
|
57
|
+
顶部:多租户下拉(`/me/tenants`)、刷新、更新于 HH:mm、完整版 ↗。时间一律 **24 小时制**。
|
|
58
|
+
|
|
59
|
+
## 4. 「办公室聊一聊」为什么走「dsh 会话 + preset」(C 路线)
|
|
60
|
+
|
|
61
|
+
### 4.1 直接把 ERP 的 chat 塞进 dsh Chat 视图是错的
|
|
62
|
+
|
|
63
|
+
| 事实 | 证据 |
|
|
64
|
+
|---|---|
|
|
65
|
+
| ERP「办公室聊一聊」是**服务端** LLM + 工具循环:`POST /tenants/:appId/office/chat`,自定义 SSE(`meta/tool/card/proposal/delta/done`) | `whyshu-svr/admin/argent/office.js:2140-2214`;`whyshu-svr/src/routes/argentV1.js:1045-1263` |
|
|
66
|
+
| 计费在服务端(积分/钱包/成员额度) | `argentV1.js:1071-1080, 1189-1208`;`services/walletBilling.js:28-120` |
|
|
67
|
+
| 会话落 ERP:`OfficeChatSession`,`tenantId+userId` 双隔离 | `models/OfficeChatSession.js`;`services/officeChat.js:441-530` |
|
|
68
|
+
| 而 dsh Chat 视图**硬绑 target `chat`**,其 target 由 `@deepseek-ai/dsh-client-ui-chat` 独占注册、**不允许重复注册** | `node_modules/@deepseek-ai/dsh-client-ui-chat/lib/client.js:15318, 15458-15545` |
|
|
69
|
+
|
|
70
|
+
⇒ 把 ERP 的 SSE 翻译成 dsh SessionEvent = 给内核喂假事件,会污染轨迹/统计/成本口径。**不做。**
|
|
71
|
+
|
|
72
|
+
### 4.2 现在的做法:让「办公室聊天」本身成为 dsh 会话
|
|
73
|
+
|
|
74
|
+
`presets/argent-office.patch.yml` 声明 **`argent-office`(六禾园办公室助理)**:
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
persona(话题边界) + compaction(长会话自动压缩) + office-guard(工具边界)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
从 ERP 视图的「聊一聊」点「和办公室聊一聊(dsh 会话)」⇒
|
|
81
|
+
|
|
82
|
+
- **建在你当前 workspace**:`ctx.uiWorkspace.connectWorkspace(workspaceId, { agentPreset: 'argent-office' })`
|
|
83
|
+
(失败退回 `sessions.create({ agentPreset, workspaceId })`);
|
|
84
|
+
⚠️ 不传 workspaceId 会掉进"请选择 workspace",用户选完后 UI 会另建 blank 会话、preset 被重置成默认(2026-11-07 实测)。
|
|
85
|
+
- **模型钉死**:建好后 `ctx.remote.session.selectModel({ sessionId, provider: 'whyshu', model: 'deepseek-flash' })`
|
|
86
|
+
⇒ 走问述代理/积分,而不是宿主默认的 deepseek-account;失败只提示、不阻塞(可在模型选择里手动选)。
|
|
87
|
+
- 打开后就是原生 Chat(轨迹/统计/中断/队列全在)。
|
|
88
|
+
|
|
89
|
+
ERP 网页里那个「办公室聊一聊」**保持原样**(服务端 SSE + 服务端计费),两条链路并存、互不冒充。
|
|
90
|
+
|
|
91
|
+
### 4.3 边界是**三层**,不只靠提示词
|
|
92
|
+
|
|
93
|
+
| 层 | 做法 | 说明 |
|
|
94
|
+
|---|---|---|
|
|
95
|
+
| ① 能力边界 | preset **不挂** `tool-bash` / `tool-pwsh` / `tool-fs` / `tool-fs-search` / `tool-web` / `tool-skill` / `tool-subagent` / `tool-workflow` 行 | 这个会话没有本机、终端、文件、联网、委派能力(web 组合已把宿主级这些工具行 disable,只有 preset 挂才有) |
|
|
96
|
+
| ② 工具边界 | `office-guard` 用 `ctx.tools.restrict({ allow })` 把作用域内可见的**全局**工具收敛成只放行 `mcp__argent__erp_*` | Agent Team 等其余全局工具(它们由 profile 级 bundle 注册,对所有会话可见)对办公室会话**不可见**;按前缀匹配、运行时重算,不写死带后缀的工具名 |
|
|
97
|
+
| ③ 话题边界 | persona 写死:只聊六禾园办公室(在办/待办/货件节点/发票/执行机/成员/日报/异常),其它话题统一拒绝并引导回来;事实必须先用 ERP 工具查证,不许编;只读,不做写操作 | 这是"模型意愿"层,和前两层叠加 |
|
|
98
|
+
|
|
99
|
+
`office-guard` 的三条红线:永不抛出(否则整个 preset 不可用)、不写死工具名、无 `tools/change` 循环
|
|
100
|
+
(allow 集合从全局视图算,集合不变就不再重注册)。
|
|
101
|
+
|
|
102
|
+
### 4.4 已知取舍
|
|
103
|
+
|
|
104
|
+
- **计费口径**:办公室会话在**创建时钉死** `whyshu / deepseek-flash`(走问述积分);若用户事后手动切模型,以用户选择为准(本插件不抢占)。
|
|
105
|
+
- **ERP「AI 团队」不接管**:那是**问述内部**用的通道,`create_session` 缺省仍走宿主默认 preset(2026-11-07 用户确认后已回退);
|
|
106
|
+
只有 ERP **显式**选到 `argent-office` 时,机器侧才把该会话模型钉成同一套
|
|
107
|
+
(`plugins/argent/src/office-runtime.js`,env 可覆盖:`ARGENT_OFFICE_PRESET` / `ARGENT_OFFICE_MODEL_PROVIDER` / `ARGENT_OFFICE_MODEL`;
|
|
108
|
+
⚠️ 该文件属 `@whyshu/argent`,改动要等它下次发版 + 重启才在客户机生效)。
|
|
109
|
+
- **ERP 侧历史不互通**:ERP 的 `OfficeChatSession` 与 dsh Session 是两套存储;本视图的"历史"只读 ERP 那一侧。
|
|
110
|
+
- **ERP 的 chat 续聊本来就没有服务端记忆**(前端只发 `{message, sessionId}`,服务端 messages 仅 = 现场快照 + 当前消息,
|
|
111
|
+
`argentV1.js:1083-1084`)——换成 dsh 真多轮反而是**能力升级**,但不要再指望两边记录对得上。
|
|
112
|
+
- **反方向通道别混用**:ERP→执行机的 `office/sessions/*` 命令队列 + 「AI 团队」面板
|
|
113
|
+
(`plugins/argent/src/office-runtime.js` 机器对话执行器,`chatEnabled` 默认关)是"ERP 当 UI、dsh 当执行",
|
|
114
|
+
与本方案方向相反。
|
|
115
|
+
|
|
116
|
+
## 5. 端点(全部 GET,只读)
|
|
117
|
+
|
|
118
|
+
| 路径 | 作用 |
|
|
119
|
+
|---|---|
|
|
120
|
+
| `/api/argent-erp/health` | 存活 + 版本 + `erpTools`(ERP 工具数;0=缺 @whyshu/argent)+ `officePreset` + `clientPingAt`(bundle 加载)/ `viewPingAt`(视图渲染)|
|
|
121
|
+
| `/api/argent-erp/whoami` | 账号 + 租户列表 + 默认租户 |
|
|
122
|
+
| `/api/argent-erp/overview?tenant=` | 办公室现场(KPI/在岗/执行机/待办 20/动态 10,脱敏) |
|
|
123
|
+
| `/api/argent-erp/timeline?tenant=&days=` | 时间线(`/sku-flows`,按天分组) |
|
|
124
|
+
| `/api/argent-erp/flow?tenant=&id=` | 流程详情(8+ 节点) |
|
|
125
|
+
| `/api/argent-erp/shipment?tenant=&recordId=` | 货件详情 |
|
|
126
|
+
| `/api/argent-erp/shipments?tenant=&q=&limit=` | 货件列表 |
|
|
127
|
+
| `/api/argent-erp/chat/sessions?tenant=` | 「办公室聊一聊」历史列表(只读) |
|
|
128
|
+
| `/api/argent-erp/chat/session?tenant=&id=` | 单个历史会话(只读) |
|
|
129
|
+
|
|
130
|
+
## 6. 鉴权与隐私
|
|
131
|
+
|
|
132
|
+
- token 解析唯一入口:`src/vendor/account-token.mjs`(env → `~/.dsh/.credentials.yaml` 的 `refs.WHYSHU_API_KEY`);
|
|
133
|
+
- token **只在宿主进程内存里**用于请求 whyshu.com,⛔ 不进浏览器、不落日志;
|
|
134
|
+
- 结果经 `src/vendor/redact.mjs`:手机号打码、`token/downloadUrl/tenantId` 丢弃、长文本截断。
|
|
135
|
+
|
|
136
|
+
## 7. 安装 / 验证 / 回滚
|
|
137
|
+
|
|
138
|
+
### 7.0 用户安装(发布后)
|
|
139
|
+
|
|
140
|
+
```text
|
|
141
|
+
dsh 设置 → 插件(Plugins)→ 安装 bundle → @whyshu/argent-erp
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
- 装完**重启 dsh**(bundle patch 的宿主行与 preset 行在启动时装配);
|
|
145
|
+
- 之后新建会话的 **preset 选择器**里会出现「六禾园办公室助理」,对话顶部出现「ERP」tab;
|
|
146
|
+
- ⚠️ **同机需要 `@whyshu/argent`**(≥0.2.0):它提供 `mcp__argent__erp_*` 工具与 `whyshu` provider。
|
|
147
|
+
缺它时插件仍能装、视图仍能看(端点会报 no_token),但办公室角色会被 `office-guard` **安全降级为无工具**;
|
|
148
|
+
宿主 `/api/argent-erp/health` 的 `erpTools` 会返回 `0`(= 没有 ERP 工具),`-1` = 读不到 tools 服务。
|
|
149
|
+
- 发布:`bash scripts/npm-publish-argent.sh --only argent-erp`(默认 dry-run;`--apply` 才真发)。
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
# 1) 装进当前 profile(DSH 原生;勿手写 profile 的 package.json / cordis.patch.yml)
|
|
153
|
+
# 会话内用 plugin_manager install_bundle,target = 本包绝对路径
|
|
154
|
+
# 重装(已装过新版):remove_bundle → install_bundle
|
|
155
|
+
|
|
156
|
+
# 2) 宿主端点
|
|
157
|
+
curl -s http://127.0.0.1:3080/api/argent-erp/health # {"ok":true,"version":"0.2.0",...}
|
|
158
|
+
|
|
159
|
+
# 3) preset 行是否落了(应含 include:preset-argent-office)
|
|
160
|
+
# cordis_inspect_query host/Config/listConfigs name='@deepseek-ai/dsh-agent-preset'
|
|
161
|
+
|
|
162
|
+
# 4) 客户端 tab 是否注册
|
|
163
|
+
# cordis_inspect_query client/Slots/listSubTree root='conversation.view'
|
|
164
|
+
# ⇒ occupants 含 { registrant: "argent-erp-client", id: "erp", order: 5, active: true }
|
|
165
|
+
|
|
166
|
+
# 5) 单测(15 项,含 preset 边界断言)
|
|
167
|
+
node plugins/argent-erp/test/client-bundle.test.mjs
|
|
168
|
+
node plugins/argent/test/office-preset-default.test.mjs # 机器执行器 preset/模型口径一致(8 项)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
- 宿主侧改动**需要用户手动重启 dsh**(⛔ agent 不重启);客户端 bundle 改动只需浏览器硬刷新。
|
|
172
|
+
- 回滚:`plugin_manager remove_bundle @whyshu/argent-erp` 后重启(视图与办公室 preset 一起下线)。
|
|
173
|
+
|
|
174
|
+
## 8. 已知限制
|
|
175
|
+
|
|
176
|
+
- 只读:写操作(派单/开票执行/聊天写动作)仍走 ERP web;
|
|
177
|
+
- 工具边界是"收敛全局工具",**不含**进 ERP 写路径(ERP 还没 `POST /office/actions/prepare`);
|
|
178
|
+
- 3D 办公室场景(`office-scene-3d.js` + vendored three.js)**不搬**:面板尺寸/性能都不划算,只搬数据卡片;
|
|
179
|
+
- 与旧包 `@whyshu/argent-erp-ui`(右侧栏面板,v0.9.0)**不要同时装**:两者都注册 `/api/argent-erp/*`。
|
|
180
|
+
旧包保留作回退。
|