@ranger1/dx 0.1.30 → 0.1.32
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.
|
@@ -33,3 +33,14 @@ tools:
|
|
|
33
33
|
```bash
|
|
34
34
|
python3 ~/.opencode/agents/pr_context.py --pr <PR_NUMBER> --round <ROUND>
|
|
35
35
|
```
|
|
36
|
+
|
|
37
|
+
## 脚本输出处理(强制)
|
|
38
|
+
|
|
39
|
+
- 脚本 stdout 只会输出**单一一行 JSON**(可 `JSON.parse()`)。
|
|
40
|
+
- **成功时**:你的最终输出必须是**脚本 stdout 的那一行 JSON 原样内容**。
|
|
41
|
+
- 禁止:解释/分析/补充文字
|
|
42
|
+
- 禁止:代码块(```)
|
|
43
|
+
- 禁止:前后空行
|
|
44
|
+
- **失败/异常时**:
|
|
45
|
+
- 若脚本 stdout 已输出合法 JSON(包含 `error` 或其他字段)→ 仍然**原样返回该 JSON**。
|
|
46
|
+
- 若脚本未输出合法 JSON / 退出异常 → 仅输出一行 JSON:`{"error":"PR_CONTEXT_AGENT_FAILED"}`(必要时可加 `detail` 字段)。
|
|
@@ -26,6 +26,18 @@ tools:
|
|
|
26
26
|
python3 ~/.opencode/agents/pr_precheck.py <PR_NUMBER>
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
## 脚本输出处理(强制)
|
|
30
|
+
|
|
31
|
+
- 脚本 stdout 只会输出**单一一行 JSON**(可 `JSON.parse()`)。
|
|
32
|
+
- **成功时**:你的最终输出必须是**脚本 stdout 的那一行 JSON 原样内容**。
|
|
33
|
+
- 典型返回:`{"ok":true}` 或 `{"ok":false,"fixFile":"..."}`
|
|
34
|
+
- 禁止:解释/分析/补充文字
|
|
35
|
+
- 禁止:代码块(```)
|
|
36
|
+
- 禁止:前后空行
|
|
37
|
+
- **失败/异常时**:
|
|
38
|
+
- 若脚本 stdout 已输出合法 JSON(包含 `error` 或其他字段)→ 仍然**原样返回该 JSON**。
|
|
39
|
+
- 若脚本未输出合法 JSON / 退出异常 → 仅输出一行 JSON:`{"error":"PR_PRECHECK_AGENT_FAILED"}`(必要时可加 `detail` 字段)。
|
|
40
|
+
|
|
29
41
|
## 仅当出现 merge 冲突时怎么处理
|
|
30
42
|
|
|
31
43
|
当脚本输出 `{"error":"PR_MERGE_CONFLICTS_UNRESOLVED"}` 时:
|
|
@@ -46,11 +46,16 @@ reviewFile: review-GMN-pr123-r1-abcdef123456.md
|
|
|
46
46
|
|
|
47
47
|
所有确定性工作(解析/聚合/发评论/生成 fixFile/输出 JSON)都由 `~/.opencode/agents/pr_review_aggregate.py` 完成。
|
|
48
48
|
|
|
49
|
-
|
|
49
|
+
你只做两件事:
|
|
50
50
|
|
|
51
|
-
|
|
51
|
+
1) 在模式 A 里用大模型判断哪些 finding 是重复的,并把重复分组作为参数传给脚本(不落盘)。
|
|
52
|
+
2) 调用脚本后,把脚本 stdout 的 JSON **原样返回**给调用者(不做解释/分析)。
|
|
52
53
|
|
|
53
|
-
|
|
54
|
+
## 重复分组(仅作为脚本入参)
|
|
55
|
+
|
|
56
|
+
你需要基于 3 份 `reviewFile` 内容判断重复 finding 分组,生成**一行 JSON**(不要代码块、不要解释文字、不要换行)。
|
|
57
|
+
|
|
58
|
+
注意:这行 JSON **不是你的最终输出**,它只用于生成 `--duplicate-groups-b64` 传给脚本。
|
|
54
59
|
|
|
55
60
|
```json
|
|
56
61
|
{"duplicateGroups":[["CDX-001","CLD-003"],["GMN-002","CLD-005","CDX-004"]]}
|
|
@@ -81,3 +86,15 @@ python3 ~/.opencode/agents/pr_review_aggregate.py \
|
|
|
81
86
|
--run-id <RUN_ID> \
|
|
82
87
|
--fix-report-file <FIX_REPORT_FILE>
|
|
83
88
|
```
|
|
89
|
+
|
|
90
|
+
## 脚本输出处理(强制)
|
|
91
|
+
|
|
92
|
+
- 脚本 stdout 只会输出**单一一行 JSON**(可 `JSON.parse()`)。
|
|
93
|
+
- **成功时**:你的最终输出必须是**脚本 stdout 的那一行 JSON 原样内容**。
|
|
94
|
+
- 典型返回:`{"stop":true}` 或 `{"stop":false,"fixFile":"..."}` 或 `{"ok":true}`
|
|
95
|
+
- 禁止:解释/分析/补充文字
|
|
96
|
+
- 禁止:代码块(```)
|
|
97
|
+
- 禁止:前后空行
|
|
98
|
+
- **失败/异常时**:
|
|
99
|
+
- 若脚本 stdout 已输出合法 JSON(包含 `error` 或其他字段)→ 仍然**原样返回该 JSON**。
|
|
100
|
+
- 若脚本未输出合法 JSON / 退出异常 → 仅输出一行 JSON:`{"error":"PR_REVIEW_AGGREGATE_AGENT_FAILED"}`(必要时可加 `detail` 字段)。
|
package/lib/opencode-initial.js
CHANGED
|
@@ -4,7 +4,7 @@ import os from 'node:os'
|
|
|
4
4
|
|
|
5
5
|
import { logger } from './logger.js'
|
|
6
6
|
|
|
7
|
-
async function
|
|
7
|
+
async function collectTemplateFiles(dir) {
|
|
8
8
|
const out = []
|
|
9
9
|
|
|
10
10
|
async function walk(current) {
|
|
@@ -18,11 +18,19 @@ async function collectMarkdownFiles(dir) {
|
|
|
18
18
|
for (const entry of entries) {
|
|
19
19
|
const full = join(current, entry.name)
|
|
20
20
|
if (entry.isDirectory()) {
|
|
21
|
+
// 跳过 __pycache__ 和其他缓存目录
|
|
22
|
+
if (entry.name === '__pycache__' || entry.name === '.pytest_cache') {
|
|
23
|
+
continue
|
|
24
|
+
}
|
|
21
25
|
await walk(full)
|
|
22
26
|
continue
|
|
23
27
|
}
|
|
24
28
|
if (!entry.isFile()) continue
|
|
25
|
-
|
|
29
|
+
const lowerName = entry.name.toLowerCase()
|
|
30
|
+
// 拷贝 .md 和 .py 文件
|
|
31
|
+
if (!lowerName.endsWith('.md') && !lowerName.endsWith('.py')) continue
|
|
32
|
+
// 跳过 Python 编译文件
|
|
33
|
+
if (lowerName.endsWith('.pyc') || lowerName.endsWith('.pyo') || lowerName.endsWith('.pyd')) continue
|
|
26
34
|
out.push(full)
|
|
27
35
|
}
|
|
28
36
|
}
|
|
@@ -47,15 +55,30 @@ async function assertDirExists(path, label) {
|
|
|
47
55
|
}
|
|
48
56
|
}
|
|
49
57
|
|
|
50
|
-
async function
|
|
51
|
-
const files = await
|
|
58
|
+
async function copyTemplateTree({ srcDir, dstDir }) {
|
|
59
|
+
const files = await collectTemplateFiles(srcDir)
|
|
60
|
+
let mdCount = 0
|
|
61
|
+
let pyCount = 0
|
|
62
|
+
|
|
52
63
|
for (const file of files) {
|
|
53
64
|
const rel = relative(srcDir, file)
|
|
54
65
|
const target = join(dstDir, rel)
|
|
55
66
|
await ensureDir(dirname(target))
|
|
56
67
|
await fs.copyFile(file, target)
|
|
68
|
+
|
|
69
|
+
if (file.endsWith('.md')) {
|
|
70
|
+
mdCount++
|
|
71
|
+
} else if (file.endsWith('.py')) {
|
|
72
|
+
pyCount++
|
|
73
|
+
try {
|
|
74
|
+
await fs.chmod(target, 0o755)
|
|
75
|
+
} catch {
|
|
76
|
+
// 忽略权限设置失败
|
|
77
|
+
}
|
|
78
|
+
}
|
|
57
79
|
}
|
|
58
|
-
|
|
80
|
+
|
|
81
|
+
return { total: files.length, md: mdCount, py: pyCount }
|
|
59
82
|
}
|
|
60
83
|
|
|
61
84
|
function resolveTemplateRoot(packageRoot) {
|
|
@@ -98,10 +121,10 @@ export async function runOpenCodeInitial(options = {}) {
|
|
|
98
121
|
await ensureDir(dstAgents)
|
|
99
122
|
await ensureDir(dstCommands)
|
|
100
123
|
|
|
101
|
-
const
|
|
102
|
-
const
|
|
124
|
+
const agentsStats = await copyTemplateTree({ srcDir: srcAgents, dstDir: dstAgents })
|
|
125
|
+
const commandsStats = await copyTemplateTree({ srcDir: srcCommands, dstDir: dstCommands })
|
|
103
126
|
|
|
104
127
|
logger.success(`已初始化 OpenCode 模板到: ${dstRoot}`)
|
|
105
|
-
logger.info(`agents: ${
|
|
106
|
-
logger.info(`commands: ${
|
|
128
|
+
logger.info(`agents: ${agentsStats.md} 个 .md 文件${agentsStats.py > 0 ? ` + ${agentsStats.py} 个 .py 文件` : ''}`)
|
|
129
|
+
logger.info(`commands: ${commandsStats.md} 个 .md 文件${commandsStats.py > 0 ? ` + ${commandsStats.py} 个 .py 文件` : ''}`)
|
|
107
130
|
}
|