sapbuddy-dsh 0.0.3 → 0.0.4
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 +4 -0
- package/cordis.patch.yml +1 -1
- package/defaults/AGENTS.md +2 -2
- package/defaults/prompts/SYSTEM.md +1 -1
- package/dist/sap-tools/gate.js +10 -1
- package/dist/sap-tools/register.d.ts +3 -0
- package/dist/sap-tools/register.js +3 -3
- package/dist/sap-tools/tools/writeTools.js +2 -3
- package/dist/tools.js +1 -14
- package/package.json +4 -1
- package/skills/dev-write/SKILL.md +4 -6
package/README.md
CHANGED
|
@@ -152,3 +152,7 @@ pnpm --filter sapbuddy-dsh test # 172 用例
|
|
|
152
152
|
## 许可证
|
|
153
153
|
|
|
154
154
|
MIT。工具实现同步自上游 [gxx950224/sapbuddy](https://github.com/gxx950224/sapbuddy)。
|
|
155
|
+
|
|
156
|
+
## 0.0.4
|
|
157
|
+
|
|
158
|
+
本版本基于已构建产物修改发布。取消 ABAP 源码硬编码中文的写入阻断;修复 Web 原生审批获批后未开启默认 15 分钟授权窗口的问题,写入与激活共用窗口。中文文案改为维护建议,其他连接与对象保护保持生效。
|
package/cordis.patch.yml
CHANGED
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
6b. 新建/修改流程:创建只调一次精确搜索 → 收集齐开发包/对象名/描述/传输请求 → 完整计划展示 → 确认后写;修改先读当前源码 + 查未释放请求(有则沿用)→ 计划 → 确认后写;请求描述 sapbuddy_<摘要>_<YYYYMMDD>。
|
|
72
72
|
6c. 连接切换后先重确认(强制):用户切换/修改 SAP 连接后,必须先调用 get_connected_systems 确认当前连接,再使用其他 SAP 工具。
|
|
73
73
|
7. 写操作谨慎:写工具需要服务器 security.readOnly=false;生产系统只读。
|
|
74
|
-
8. 按技能加载(强制):写代码/写 SAP 对象先遵循 dev-write
|
|
74
|
+
8. 按技能加载(强制):写代码/写 SAP 对象先遵循 dev-write 技能(裸内置类型、匈牙利前缀、Clean ABAP);批量翻译先遵循 translate-workflow 技能(先 list 后 set、禁止猜 key 写入)。
|
|
75
75
|
防死循环与止损:
|
|
76
76
|
1. 用户纠错后先整体复盘(读对象现状、列异常清单再动手)。
|
|
77
77
|
2. 覆盖型写操作前先读当前内容备份;发现"修一处坏一处"立即停手。
|
package/defaults/AGENTS.md
CHANGED
|
@@ -59,7 +59,7 @@ scripts/install.mjs # 安装器(校验 dsh.bundle.patch + dsh pl
|
|
|
59
59
|
│
|
|
60
60
|
└─ ④ index.ts execute 路径(每个写工具,纵深防御)
|
|
61
61
|
├─ isConnectionDirty → 连接变更强制重确认
|
|
62
|
-
├─
|
|
62
|
+
├─ scanCodeIssues → 自建结构字段裸内置类型仅提示
|
|
63
63
|
└─ assertDevClient → 非开发客户端(T000.CCCATEGORY 非 C)拒绝写
|
|
64
64
|
```
|
|
65
65
|
|
|
@@ -91,7 +91,7 @@ node scripts/install.mjs --profile desktop --dry-run # 预览命令
|
|
|
91
91
|
| 写操作拦截(确认/知识库只读/配置保护) | `gate.ts` installWriteGate(guard + pre-execute + inbox) | 硬强制 |
|
|
92
92
|
| abap_wiki 知识库写工具拦截(`mcp__abap_wiki__*`,一律硬拦、不可放行) | `gate.ts` wikiWriteViolation | 硬强制 |
|
|
93
93
|
| 敏感配置禁止 AI 读写(connections/auth/settings/models;bash 命令含敏感路径/文件名也拦;preset 目录 output/skills/sessions/prompts/uploads 子树除外) | `gate.ts` configPathViolation | 硬强制 |
|
|
94
|
-
|
|
|
94
|
+
| 代码规则扫描(自建表结构字段裸内置类型仅提示;程序内局部变量放行) | `code-policy.ts` scanCodeIssues + `index.ts` execute | 裸类型非阻断;中文按规范建议处理 |
|
|
95
95
|
| 开发客户端守卫(T000 类别) | `adtManager.ts` assertDevClient + `index.ts` execute | 硬强制 |
|
|
96
96
|
| 创建:包名/描述必填、$TMP 提示、requestText 建请求 | `tools/writeTools.ts` create_object_programmatically | 硬强制 |
|
|
97
97
|
| 修改:自动沿用/创建请求、请求描述格式 | `tools/writeTools.ts` replace_string_in_abap_object | 硬强制 |
|
|
@@ -32,7 +32,7 @@ SapBuddy — SAP ABAP AI 全能助手,面向**开发顾问与业务顾问**。
|
|
|
32
32
|
- **工具硬化**:`create_object_programmatically` 缺包名/描述会被拦截;传 $TMP 需用户单独确认(不进传输请求);`replace_string` 无未释放请求时自动建请求——这些无需 LLM 自觉,工具强制执行。
|
|
33
33
|
6c. **连接切换后先重确认(强制)**:用户切换/修改 SAP 连接后,**必须先调用 `get_connected_systems` 确认当前连接,再使用其他 SAP 工具**。工具层强制拦截:未确认前其他 SAP 工具一律失败(返回"连接配置已变更,先调用 get_connected_systems")。看到该拦截错误时,立即调用 `get_connected_systems`,再重试被拦的操作。
|
|
34
34
|
7. **写操作谨慎**:写工具(创建/编辑/激活)需要服务器 `security.readOnly=false`;生产系统只读。
|
|
35
|
-
8. **按技能加载(强制)**:写代码/写 SAP 对象(函数模块/表结构/函数组 include/文本元素等)先遵循 `dev-write`
|
|
35
|
+
8. **按技能加载(强制)**:写代码/写 SAP 对象(函数模块/表结构/函数组 include/文本元素等)先遵循 `dev-write` 技能(编码规范、写入规范);批量翻译(Excel 清单→SAP)先遵循 `translate-workflow` 技能(先 list 后 set、匹配不上报告、**禁止猜 key 写入**)。技能按话题自动加载,做对应任务时**必须遵守**。
|
|
36
36
|
|
|
37
37
|
## 防死循环与止损(软约束,靠自觉;能代码强制的已由工具层兜底)
|
|
38
38
|
|
package/dist/sap-tools/gate.js
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* 权威校验(开发客户端守卫 assertDevClient、硬编码中文/裸类型扫描、审计)保留在
|
|
12
12
|
* 工具 execute 路径(index.ts),与 pi 版 registerSapTools 包装一致。
|
|
13
13
|
*/
|
|
14
|
-
import { isWriteTool, isWriteApproved, handleUserMessage, isReadOnly, namespaceViolation } from "./register.js";
|
|
14
|
+
import { isWriteTool, isWriteApproved, handleUserMessage, isReadOnly, namespaceViolation, approvalWindowMs, setWriteApprovalWindow } from "./register.js";
|
|
15
15
|
import { isConnectionDirty } from "./adtManager.js";
|
|
16
16
|
import { sapbuddyHome, sapbuddyPath } from "./sapbuddy-home.js";
|
|
17
17
|
/** 敏感配置文件清单(禁止 AI 读写;位置无关)。MCP 配置由 DSH 内置 dsh-mcp-client 管理(profile patch),不在本目录保护范围内。 */
|
|
@@ -142,6 +142,8 @@ const defaultDeps = {
|
|
|
142
142
|
isReadOnly,
|
|
143
143
|
isConnectionDirty,
|
|
144
144
|
isWriteApproved,
|
|
145
|
+
approvalWindowMs,
|
|
146
|
+
setWriteApprovalWindow,
|
|
145
147
|
handleUserMessage,
|
|
146
148
|
};
|
|
147
149
|
/**
|
|
@@ -191,6 +193,13 @@ export function installWriteGate(ctx, deps = {}) {
|
|
|
191
193
|
return { kind: "ask", reason: decision.reason };
|
|
192
194
|
return next();
|
|
193
195
|
}));
|
|
196
|
+
// approval/asked、approval/decided 是日志记录;运行时审批通过 waterfall 返回结果。
|
|
197
|
+
disposers.push(ctx.on("approval/request", async (request, next) => {
|
|
198
|
+
const outcome = await next();
|
|
199
|
+
if (isWriteTool(request.toolName) && outcome === "allowed-once")
|
|
200
|
+
d.setWriteApprovalWindow(d.approvalWindowMs());
|
|
201
|
+
return outcome;
|
|
202
|
+
}));
|
|
194
203
|
// 3) 用户消息 → 确认词/拒绝词 → 授权窗口(headless/CLI 回退)
|
|
195
204
|
disposers.push(ctx.on("agent/inbox/claimed", (payload) => {
|
|
196
205
|
d.handleUserMessage(extractUserText(payload?.message));
|
|
@@ -7,8 +7,8 @@
|
|
|
7
7
|
*
|
|
8
8
|
* 代码级强制规则(不依赖 LLM 遵守,写工具内容写入前硬校验):
|
|
9
9
|
* 1. 开发客户端守卫:非开发类客户端拒绝一切写操作(assertDevClient,见 index.ts execute 路径)
|
|
10
|
-
* 2.
|
|
11
|
-
* 3.
|
|
10
|
+
* 2. 源码规则提示:自建结构/表字段的裸内置类型仅提示,不阻断写入
|
|
11
|
+
* 3. 中文文案由消息类/文本元素作为维护建议,不在工具层硬拦截
|
|
12
12
|
*/
|
|
13
13
|
import { readFileSync } from "node:fs";
|
|
14
14
|
import { sapbuddyPath } from "./sapbuddy-home.js";
|
|
@@ -96,7 +96,7 @@ export function extractObjectNames(input) {
|
|
|
96
96
|
const CONFIRM_RE = /^(?:确认|同意|允许|批准|就这么办|执行|继续执行|go ahead)(?=$|[\s,,。.!!::;;])/i;
|
|
97
97
|
const REJECT_RE = /拒绝|不要|取消|算了|不干|停止|换个方案|重新来|推翻|改回|不用了|撤回|不执行|不能执行|先别|暂不|先不做|别急|别继续/i;
|
|
98
98
|
/** 授权窗口毫秒数:读配置目录 settings.json 的 approvalWindowMinutes(默认 15 分钟) */
|
|
99
|
-
function approvalWindowMs() {
|
|
99
|
+
export function approvalWindowMs() {
|
|
100
100
|
try {
|
|
101
101
|
const cfg = JSON.parse(readFileSync(sapbuddyPath("settings.json"), "utf8").toString());
|
|
102
102
|
const m = Number(cfg.approvalWindowMinutes);
|
|
@@ -732,9 +732,8 @@ export const replaceStringTool = {
|
|
|
732
732
|
// ② 用户指定 requestNumber → 用用户指定的,并作为本需求共享请求;
|
|
733
733
|
// ③ 否则复用本需求共享请求(同需求多对象放同一请求);
|
|
734
734
|
// ④ 都没有才自动新建一个,并记为共享请求。
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
throw new Error(`代码级规则拦截(最终待写入源码):\n${violations.join("\n")}`);
|
|
735
|
+
// 仅保留类型提示;中文不阻断源码写入。
|
|
736
|
+
const { warnings } = scanCodeIssues(updated);
|
|
738
737
|
const lockInfo = lock;
|
|
739
738
|
const isLocal = lockInfo.IS_LOCAL === "X";
|
|
740
739
|
let transport = isLocal ? undefined : (lockInfo.CORRNR || undefined);
|
package/dist/tools.js
CHANGED
|
@@ -23,7 +23,7 @@ import { zodToParameterSpec } from "./sap-tools/zod-to-spec.js";
|
|
|
23
23
|
import { installWriteGate } from "./sap-tools/gate.js";
|
|
24
24
|
import { installPromptFiles } from "./sap-tools/prompt-files.js";
|
|
25
25
|
import { ensureSapbuddyHome } from "./sap-tools/sapbuddy-home.js";
|
|
26
|
-
import {
|
|
26
|
+
import { extractObjectNames } from "./sap-tools/register.js";
|
|
27
27
|
import { isConnectionDirty, assertDevClient, withConnMutex } from "./sap-tools/adtManager.js";
|
|
28
28
|
import { resolveConnectionId } from "./sap-tools/tools/shared.js";
|
|
29
29
|
import { appendAudit } from "./sap-tools/auditLog.js";
|
|
@@ -56,19 +56,6 @@ function registerOne(registry, t) {
|
|
|
56
56
|
if (t.name !== "get_connected_systems" && isConnectionDirty()) {
|
|
57
57
|
return "⛔ SAP 连接配置已变更,必须先调用 get_connected_systems 确认当前连接,然后再重试本操作。";
|
|
58
58
|
}
|
|
59
|
-
// 内容级强制规则:写入代码前硬校验(硬编码中文阻断;裸内置类型仅提示)——纯本地检查,不触连接
|
|
60
|
-
if (t.name === "replace_string_in_abap_object") {
|
|
61
|
-
const code = p.fullSource ?? p.newString;
|
|
62
|
-
if (typeof code === "string") {
|
|
63
|
-
const { violations, warnings } = scanCodeIssues(code);
|
|
64
|
-
if (violations.length > 0) {
|
|
65
|
-
return `⛔ 代码级规则拦截(不依赖 AI 自觉,写前硬校验):\n${violations.join("\n")}\n\n请修正后重试:硬编码中文 → 消息类/文本元素。`;
|
|
66
|
-
}
|
|
67
|
-
if (warnings.length > 0) {
|
|
68
|
-
console.warn(`[sapbuddy-dsh] 代码提示(不阻断):\n${warnings.join("\n")}`);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
59
|
// 写工具在连接互斥锁内执行(lock→改→存→激活 原子);读工具直接执行
|
|
73
60
|
const connId = await resolveConnectionId(p.connectionId);
|
|
74
61
|
const text = t.write
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sapbuddy-dsh",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.4",
|
|
4
4
|
"description": "SapBuddy —— SAP ABAP AI 全能助手(DeepSeek Harness 插件):41 个 SAP 工具 + 8 个 ABAP 技能 + SapBuddy preset + 连接设置页。一个包名装完。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -81,5 +81,8 @@
|
|
|
81
81
|
"test": "node scripts/clean.mjs && tsc && node --test",
|
|
82
82
|
"check": "tsc --noEmit",
|
|
83
83
|
"prepack": "node scripts/clean.mjs && tsc && node scripts/build-client.mjs"
|
|
84
|
+
},
|
|
85
|
+
"publishConfig": {
|
|
86
|
+
"access": "public"
|
|
84
87
|
}
|
|
85
88
|
}
|
|
@@ -15,13 +15,11 @@ disable: false
|
|
|
15
15
|
> 本技能为项目**编码与写入规范**的唯一权威(从 SYSTEM.md 迁出)。写代码/写 SAP 对象前必须先遵循本技能。
|
|
16
16
|
> 相关:代码**风格/质量审查**见 `clean-abap` 技能;批量**翻译**见 `translate-workflow` 技能。
|
|
17
17
|
|
|
18
|
-
##
|
|
18
|
+
## 中文文案规范(建议)
|
|
19
19
|
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
- 找不到合适消息类/文本元素时,创建 Z 消息类(`create_object_programmatically` MSAG/N)或维护文本元素。
|
|
24
|
-
- 技术性注释可用中文(注释非运行时文案),但用户可见文案必须走消息类/文本元素(此"禁硬编码中文"指**代码里**的文案,非文本元素的中文翻译)。
|
|
20
|
+
- 代码内可以按业务需要使用中文文案;面向用户的提示/错误优先使用**消息类**(`MESSAGE e001(zmsg) WITH ...`)或文本元素(`TEXT-001`、Selection Text),便于维护和翻译。
|
|
21
|
+
- 选择屏幕标签/块标题/ALV 列文本优先使用**文本元素**;新增/修改文本元素用 `manage_text_elements`,翻译成其它语言用 `translate_text_pool`。
|
|
22
|
+
- 技术性注释可以使用中文;中文硬编码不再作为工具写入阻断条件。
|
|
25
23
|
|
|
26
24
|
## 编码规范(默认:SAP 官方 Clean ABAP)
|
|
27
25
|
|