@dsh-workbench/core 0.1.11 → 0.1.12

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.
@@ -1474,7 +1474,7 @@ var panelsUnit = {
1474
1474
  };
1475
1475
  //#endregion
1476
1476
  //#region src/modules/panels/model/approval.ts
1477
- var READ$1 = { kind: "read" };
1477
+ var READ = { kind: "read" };
1478
1478
  var READ_ONLY_ACTIONS = /* @__PURE__ */ new Set(["list", ""]);
1479
1479
  function actionOf$1(call) {
1480
1480
  const raw = call.arguments;
@@ -1502,7 +1502,7 @@ var panelsApproval = (call) => {
1502
1502
  const readAction = action !== void 0 && action !== "" && READ_ONLY_ACTIONS.has(action);
1503
1503
  const what = whatOf(id);
1504
1504
  if (call.name === "workbench_modules") {
1505
- if (readAction) return READ$1;
1505
+ if (readAction) return READ;
1506
1506
  if (action === "update-dependency") return askOf(`workbench_modules update-dependency ${id ?? ""} upgrades a shared dependency on this machine`, {
1507
1507
  en: "it upgrades that shared dependency on this machine. Allow?",
1508
1508
  zh: `会升级共用依赖 ${what}。允许吗?`
@@ -1521,7 +1521,7 @@ var panelsApproval = (call) => {
1521
1521
  });
1522
1522
  }
1523
1523
  if (call.name !== "workbench_panels") return void 0;
1524
- if (readAction) return READ$1;
1524
+ if (readAction) return READ;
1525
1525
  if (action === "hide") return askOf("workbench_panels hide removes a module from the panel", {
1526
1526
  en: "it takes that module off this panel (its agent tools go offline here too). Allow?",
1527
1527
  zh: `${what}会从这个项目的面板上收起来(这个项目里它的 agent 工具也一起下线)。允许吗?`
@@ -3999,54 +3999,6 @@ function createUnitRegistry() {
3999
3999
  };
4000
4000
  }
4001
4001
  //#endregion
4002
- //#region src/shared/api/host/approval-legacy.ts
4003
- var READ = { kind: "read" };
4004
- function confirmed(call) {
4005
- const raw = call.arguments;
4006
- if (typeof raw !== "object" || raw === null) return void 0;
4007
- const value = raw.confirm;
4008
- return typeof value === "boolean" ? value : void 0;
4009
- }
4010
- var legacyApproval = (call) => {
4011
- const name = call.name ?? "";
4012
- if (name === "workbench_cmdb_release") {
4013
- if (confirmed(call) !== true) return READ;
4014
- return {
4015
- kind: "ask",
4016
- reason: "confirm=true releases a version to a real environment",
4017
- question: {
4018
- en: "it deploys on the platform for real (non-production). Allow?",
4019
- zh: "会在平台上真的部署一次(非生产环境)。允许吗?"
4020
- },
4021
- fallback: {
4022
- en: "The agent wants to deploy a version for real (confirm: true) — it deploys on the platform (non-production). Allow?",
4023
- zh: "agent 想在非生产环境上**真的部署一个版本**(confirm: true)—— 会在平台上部署。允许吗?"
4024
- }
4025
- };
4026
- }
4027
- if (name !== "workbench_coding_issue_comment" && name !== "workbench_coding_issue_transfer") return void 0;
4028
- if (confirmed(call) !== true) return READ;
4029
- const comment = name === "workbench_coding_issue_comment";
4030
- return {
4031
- kind: "ask",
4032
- reason: comment ? "confirm=true posts a comment on the platform" : "confirm=true moves an issue to another status on the platform",
4033
- question: comment ? {
4034
- en: "it posts that comment on the platform for real. Allow?",
4035
- zh: "会在平台上真的发表这条评论。允许吗?"
4036
- } : {
4037
- en: "it changes that issue status on the platform for real. Allow?",
4038
- zh: "会在平台上真的改这条缺陷的状态。允许吗?"
4039
- },
4040
- fallback: comment ? {
4041
- en: "The agent wants to post a comment on the platform for real (confirm: true) — it writes on the platform. Allow?",
4042
- zh: "agent 想**真的给一条缺陷加评论**(confirm: true)—— 会写平台数据。允许吗?"
4043
- } : {
4044
- en: "The agent wants to move an issue to another status for real (confirm: true) — it writes on the platform. Allow?",
4045
- zh: "agent 想**真的把一条缺陷流转到别的状态**(confirm: true)—— 会写平台数据。允许吗?"
4046
- }
4047
- };
4048
- };
4049
- //#endregion
4050
4002
  //#region src/shared/api/host/tool-scope.ts
4051
4003
  function agentOf(value) {
4052
4004
  return typeof value === "object" && value !== null ? value : void 0;
@@ -4389,13 +4341,15 @@ function apply(ctx) {
4389
4341
  const owner = tool === void 0 ? void 0 : mounted.get(tool.unit)?.result;
4390
4342
  const detailOf = owner === void 0 ? void 0 : (call) => owner.approvalDetail?.(call);
4391
4343
  const workspace = sessionWorkspace(exec) ?? void 0;
4392
- return await approvalFor({
4344
+ const call = {
4393
4345
  ...name === void 0 ? {} : { name },
4394
4346
  arguments: exec.arguments,
4395
4347
  ...workspace === void 0 ? {} : { workspace }
4396
- }, {
4348
+ };
4349
+ const policy = owner?.needsApproval;
4350
+ return await approvalFor(call, {
4397
4351
  detailOf,
4398
- policy: owner?.needsApproval ?? legacyApproval,
4352
+ policy,
4399
4353
  writes: tool?.writes ?? false
4400
4354
  }) ?? decision;
4401
4355
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dsh-workbench/core",
3
- "version": "0.1.11",
3
+ "version": "0.1.12",
4
4
  "description": "个人工作台:Agent 工作台外壳(左栏 + 常驻对话 + 自研右侧数据面板)。",
5
5
  "type": "module",
6
6
  "icon": "./icon.svg",
@@ -86,7 +86,7 @@
86
86
  "access": "public"
87
87
  },
88
88
  "dependencies": {
89
- "@dsh-workbench/shared": "0.1.11"
89
+ "@dsh-workbench/shared": "0.1.12"
90
90
  },
91
91
  "scripts": {
92
92
  "build": "node scripts/build.mjs && node scripts/build-types.mjs",
@@ -0,0 +1,54 @@
1
+ # 数据从哪来:干净机器上先用 opencli 探,再把它固化成一条读
2
+
3
+ 用户往往只说"我要看发布情况""我想看缺陷看板" —— 他不知道那套系统叫什么、接口在哪、要什么参数。
4
+ 干净机器上你也没有现成的 skill 可抄。所以这一步是**探查**,不是查手册。
5
+
6
+ ## 先判:这是 DIY 域还是工程域
7
+
8
+ | 情况 | 判 |
9
+ |---|---|
10
+ | 他已经在浏览器里登录过那套系统 | **DIY 域** —— 用 opencli 复用他的登录去探 |
11
+ | 要**新凭据**(新账号 / 密钥 / token) | **工程域** —— 停下来,说清要谁去配什么 |
12
+ | 要起新服务 / 新进程 / 加新依赖 | **工程域** |
13
+ | 数据在本地文件 / 一条已有命令 / 一个不要凭据的 GET 上 | **DIY 域** —— 直接造 |
14
+
15
+ 判的是「**要不要新凭据**」,不是「要不要接新平台」。复用已有登录的探查,正是把一大类需求留在 DIY 域的原因。
16
+
17
+ ## 四步
18
+
19
+ 1. **问出他在看什么(用他的词)** —— "你平时是在哪个网页 / 哪个软件里看这个的?" 记下他说的入口。
20
+ **不要**问"你们用 argocd 还是 jenkins" —— 他多半不知道,也答不上来。
21
+ 2. **探** —— 用 `opencli`。**它随工作台预装**:隔离运行时在 `$DSH_HOME/workbench/opencli/`,
22
+ 启动体检自己装,**不碰**用户本机的 `~/.opencli`(工作台已经把它挂成命令,`bin/opencli-isolated` 是那层壳)。
23
+ 目标是找到**承载数据的那一处**:列表页本身,或它背后的那一个 XHR。记下:命令 / URL、需要的参数、凭据从哪来。
24
+ - 数据通常来自 **opencli 的某个插件**(`opencli <plugin> …`)—— 先看这台机器上哪些插件能用,
25
+ **别自己拼接口**。
26
+ - 隔离运行时没装好时它会自己说"opencli 的隔离运行时还没装好" —— 把体检那屏的原话转给用户,
27
+ 别硬编 URL 猜(那正是"看起来能用、其实读不到"的来源)。
28
+ 3. **试一条最小读** —— 先证明"能拿到",再写模块:
29
+ - 拿得到结构化输出 → 记下字段形状
30
+ - 要登录但已过期 → 记下"未登录"长什么样
31
+ - 超时 / 被墙 → 记下这两种失败的形状
32
+ 这一步的产出是**一条可重复的命令或请求**,不是"我探过了"。
33
+ 4. **固化进模块** —— 把它写进模块的**宿主半侧**(一条命令,或只读路由里的一个 HTTP GET)。
34
+ 之后卡片只依赖**这一条**;渲染怎么改都不动它。
35
+
36
+ `opencli` 是**侦察兵,不是日常通道**:探明之后,日常读必须是一条固定的、便宜的、能解释的调用。
37
+
38
+ ## 固化时一并写掉三态
39
+
40
+ 拿不到数据是常态(第一次读、登录过期、站点改版、接口超时)。卡片**必须**画得出来:
41
+
42
+ | 情况 | 卡片说什么 |
43
+ |---|---|
44
+ | 没登录 / 凭据过期 | "去 XX 登录一下"(可点,指到他平时那个入口) |
45
+ | 超时 / 网络不通 | "这次没读到,稍后重试" + 重试 |
46
+ | 站点改版、字段没了 | "读到的形状和预期不一样"(别显示空白,也别显示 0) |
47
+
48
+ 空数据下抛异常的卡片 = 用户眼里的"卡片一直不出来"。这条 `check:cards` 会拦(见 [REVIEW.md](REVIEW.md))。
49
+
50
+ ## 你自己的门禁会查
51
+
52
+ - 数据源写在**宿主半侧**,卡片只消费它的返回;
53
+ - 只读路由出错时回 `{ ok: false, error: { code, message, hint? } }`(HTTP 仍是 200,外壳原样转发);
54
+ - `?wbMock=1` 下三档夹具都要能出(正常 / 空 / 出错)—— 这是你自己验收"三态"的快捷方式。
@@ -13,12 +13,13 @@
13
13
  | 卡片要能自己配(钉一个环境、选一个仓库) | **DIY 域** | 配置清单([PANEL.md](PANEL.md) §5) |
14
14
  | 要 agent 替他做一两件**只读**的事 | **DIY 域** | 能力清单([TOOLS.md](TOOLS.md)) |
15
15
  | 要 agent 动真东西(提交、发布、改配置) | **DIY 域**,但必须写明点头那一步 | 预览 + 确认两拍([TOOLS.md](TOOLS.md) §5–§7) |
16
- | 要接一个新平台的账号 / 凭据 / 新命令 | **工程域** | 停,说清为什么,回工作台仓库走工程流程 |
16
+ | 他已经在浏览器里登录过那套系统,只是**没人告诉他数据在哪** | **DIY 域** | 用 opencli 复用他的登录去探([DATASOURCE.md](DATASOURCE.md)) |
17
+ | 要**新凭据**(新账号 / 密钥 / token) | **工程域** | 停,说清要谁去配什么,回工作台仓库走工程流程 |
17
18
  | 一条流:多步、要等很久、中途要人、失败要能接着来 | **工程域** | 同上 |
18
19
  | 要新建服务 / 新进程 / 新依赖 | **工程域** | 同上 |
19
20
  | 要改工作台外壳,或改一份**已经发布**的模块 | **工程域** | 同上 |
20
21
 
21
- 判域产出的是**他能听懂的一句话**("这件事要接一个新平台的账号,得按工程流程走"),
22
+ 判域产出的是**他能听懂的一句话**("这件事得先有人给你配一个 XX 的账号,我按工程流程走"),
22
23
  以及"接下来会发生什么、还要多久"。不是"你这个需求超纲了"。
23
24
 
24
25
  ## 1 两条分工(贯穿全程)
@@ -7,18 +7,20 @@ description: 在工作台里凭需求造一个模块(面板上的一块内容
7
7
 
8
8
  交付物是**面板上能点开的一块内容**,不是一份要他读的技术方案。
9
9
 
10
- ## 六步
10
+ ## 七步
11
11
 
12
12
  1. **判域** —— 先读 [DESIGN.md](DESIGN.md) §0。不是所有需求都该在这里做;判完给他**一句人话 + 下一步**。
13
13
  2. **问三张表** —— 见 [STEPS.md](STEPS.md)。只问他看得见、能决定的事;**实现一律不问**。
14
14
  这一步的产出是 ASCII 画面 + 三张表,不是文字。
15
- 3. **从模板改** —— [BUILD.md](BUILD.md) §1–§2:在工坊里 `dsh-wb-module init` 一个骨架,
15
+ 3. **先定数据从哪来** —— [DATASOURCE.md](DATASOURCE.md):干净机器上没有现成 skill 可抄,
16
+ 用 `opencli` 复用他的登录去探,探明后**固化成一条读**。顺手把三态写掉。
17
+ 4. **从模板改** —— [BUILD.md](BUILD.md) §1–§2:在工坊里 `dsh-wb-module init` 一个骨架,
16
18
  只改数据源与渲染。**不从零写。**
17
- 4. **自己过门禁** —— `dsh-wb-module build` + `check`;红了自己修([REVIEW.md](REVIEW.md) 有对照),
19
+ 5. **自己过门禁** —— `dsh-wb-module build` + `check`;红了自己修([REVIEW.md](REVIEW.md) 有对照),
18
20
  不抛给他、也不贴报错给他看。
19
- 5. **让他看一眼** —— 先对着 ASCII 图确认,再**装上看看**(装是宿主侧那一跳,它会顺手在面板里打开它)。
21
+ 6. **让他看一眼** —— 先对着 ASCII 图确认,再**装上看看**(装是宿主侧那一跳,它会顺手在面板里打开它)。
20
22
  **这一跳一辈子只走一次**:之后只重建、不重装。
21
- 6. **验收** —— 逐条对着三张表走:「打开哪 → 看什么 → 点什么 → 应该看到什么」。
23
+ 7. **验收** —— 逐条对着三张表走:「打开哪 → 看什么 → 点什么 → 应该看到什么」。
22
24
  他说哪不对就回对话改,改完让他看**同一处**;不给他看 diff、日志、代码。
23
25
 
24
26
  ## 每个问题都带推荐答案
@@ -33,6 +35,7 @@ description: 在工作台里凭需求造一个模块(面板上的一块内容
33
35
  | 判这个需求该不该在这里做 | [DESIGN.md](DESIGN.md) §0 |
34
36
  | 两条分工、三张表、怎么用 ASCII 跟他说话 | [DESIGN.md](DESIGN.md) |
35
37
  | 步骤 1 / 2 / 3 各自问什么、什么时候算做完 | [STEPS.md](STEPS.md) |
38
+ | **数据从哪来**(干净机器上怎么找到那一条读) | [DATASOURCE.md](DATASOURCE.md) |
36
39
  | 面板上该有什么、状态矩阵怎么写、界面习惯 | [PANEL.md](PANEL.md) |
37
40
  | 能力怎么划、传什么拿回什么、哪几件要点头 | [TOOLS.md](TOOLS.md) |
38
41
  | agent 动完面板哪一格变、他正在干的时候看哪儿 | [LINKAGE.md](LINKAGE.md) |
@@ -1,2 +0,0 @@
1
- import type { ApprovalPolicy } from '@dsh-workbench/shared/host';
2
- export declare const legacyApproval: ApprovalPolicy;