@cydm/pie 0.1.1 → 1.0.1
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 +117 -88
- package/package.json +4 -3
- package/dist/builtin/extensions/ask-user/index.js +0 -2924
- package/dist/builtin/extensions/changelog/index.js +0 -200
- package/dist/builtin/extensions/compact/index.js +0 -52
- package/dist/builtin/extensions/deploy/index.js +0 -11
- package/dist/builtin/extensions/files/index.js +0 -10
- package/dist/builtin/extensions/init/index.js +0 -144
- package/dist/builtin/extensions/plan-mode/index.js +0 -209
- package/dist/builtin/extensions/questionnaire/index.js +0 -2753
- package/dist/builtin/extensions/subagent/index.js +0 -7350
- package/dist/builtin/extensions/todo/index.js +0 -162
- package/dist/builtin/skills/browser-tools/CHANGELOG.md +0 -47
- package/dist/builtin/skills/browser-tools/browser-cookies.js +0 -35
- package/dist/builtin/skills/browser-tools/browser-screenshot.js +0 -34
- package/dist/builtin/skills/browser-tools/browser-start.js +0 -86
- package/dist/builtin/skills/skill-creator/LICENSE.txt +0 -202
- package/dist/builtin/skills/skill-creator/SKILL.md +0 -485
- package/dist/builtin/skills/skill-creator/agents/analyzer.md +0 -274
- package/dist/builtin/skills/skill-creator/agents/comparator.md +0 -202
- package/dist/builtin/skills/skill-creator/agents/grader.md +0 -223
- package/dist/builtin/skills/skill-creator/assets/eval_review.html +0 -146
- package/dist/builtin/skills/skill-creator/eval-viewer/generate_review.py +0 -471
- package/dist/builtin/skills/skill-creator/eval-viewer/viewer.html +0 -1325
- package/dist/builtin/skills/skill-creator/references/schemas.md +0 -430
- package/dist/builtin/skills/skill-creator/scripts/__init__.py +0 -0
- package/dist/builtin/skills/skill-creator/scripts/aggregate_benchmark.py +0 -401
- package/dist/builtin/skills/skill-creator/scripts/generate_report.py +0 -326
- package/dist/builtin/skills/skill-creator/scripts/improve_description.py +0 -247
- package/dist/builtin/skills/skill-creator/scripts/package_skill.py +0 -136
- package/dist/builtin/skills/skill-creator/scripts/quick_validate.py +0 -103
- package/dist/builtin/skills/skill-creator/scripts/run_eval.py +0 -310
- package/dist/builtin/skills/skill-creator/scripts/run_loop.py +0 -328
- package/dist/builtin/skills/skill-creator/scripts/utils.py +0 -47
- package/dist/cli.js +0 -74440
- package/dist/theme/dark.json +0 -85
- package/dist/theme/light.json +0 -84
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
|
-
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
3
|
-
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
4
|
-
}) : x)(function(x) {
|
|
5
|
-
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
6
|
-
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
// builtin/extensions/changelog/index.ts
|
|
10
|
-
function getRecentCommits(cwd, count = 10) {
|
|
11
|
-
try {
|
|
12
|
-
const { spawnSync } = __require("child_process");
|
|
13
|
-
const result = spawnSync(
|
|
14
|
-
"git",
|
|
15
|
-
["log", `--max-count=${count}`, "--pretty=format:%h %s", "--no-merges"],
|
|
16
|
-
{ cwd, encoding: "utf8" }
|
|
17
|
-
);
|
|
18
|
-
return result.status === 0 ? result.stdout : "";
|
|
19
|
-
} catch {
|
|
20
|
-
return "";
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
function getChangedFiles(cwd) {
|
|
24
|
-
try {
|
|
25
|
-
const { spawnSync } = __require("child_process");
|
|
26
|
-
const result = spawnSync(
|
|
27
|
-
"git",
|
|
28
|
-
["diff", "HEAD~5", "--name-only", "--stat"],
|
|
29
|
-
{ cwd, encoding: "utf8" }
|
|
30
|
-
);
|
|
31
|
-
return result.status === 0 ? result.stdout : "";
|
|
32
|
-
} catch {
|
|
33
|
-
return "";
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
async function readChangelog(cwd) {
|
|
37
|
-
try {
|
|
38
|
-
const fs = await import("fs");
|
|
39
|
-
const path = await import("path");
|
|
40
|
-
const changelogPath = path.join(cwd, "CHANGELOG.md");
|
|
41
|
-
if (fs.existsSync(changelogPath)) {
|
|
42
|
-
return fs.readFileSync(changelogPath, "utf-8");
|
|
43
|
-
}
|
|
44
|
-
} catch {
|
|
45
|
-
}
|
|
46
|
-
return null;
|
|
47
|
-
}
|
|
48
|
-
function changelogExtension(ctx) {
|
|
49
|
-
ctx.log("Changelog extension loaded");
|
|
50
|
-
ctx.ui.notify("\u{1F4DD} Changelog extension loaded", "info");
|
|
51
|
-
ctx.registerCommand({
|
|
52
|
-
path: ["tools", "changelog"],
|
|
53
|
-
description: "Smart changelog management with gap detection",
|
|
54
|
-
handler: async (ctx2, args) => {
|
|
55
|
-
const fs = await import("fs");
|
|
56
|
-
const path = await import("path");
|
|
57
|
-
const changelogPath = path.join(ctx2.cwd, "CHANGELOG.md");
|
|
58
|
-
if (args?.includes("--show")) {
|
|
59
|
-
if (!fs.existsSync(changelogPath)) {
|
|
60
|
-
return "No CHANGELOG.md found.";
|
|
61
|
-
}
|
|
62
|
-
const content = fs.readFileSync(changelogPath, "utf-8");
|
|
63
|
-
return "Current CHANGELOG:\n\n" + content.slice(0, 2e3) + (content.length > 2e3 ? "\n\n..." : "");
|
|
64
|
-
}
|
|
65
|
-
if (args?.trim() === "check") {
|
|
66
|
-
const commits2 = getRecentCommits(ctx2.cwd, 15);
|
|
67
|
-
const changelog2 = await readChangelog(ctx2.cwd);
|
|
68
|
-
const changedFiles2 = getChangedFiles(ctx2.cwd);
|
|
69
|
-
if (!commits2) {
|
|
70
|
-
return "No git history found. Cannot check for missing entries.";
|
|
71
|
-
}
|
|
72
|
-
return `\u{1F50D} CHANGELOG \u9057\u6F0F\u68C0\u67E5
|
|
73
|
-
|
|
74
|
-
\u8BF7\u5206\u6790\u4EE5\u4E0B\u4FE1\u606F\uFF0C\u68C0\u67E5 CHANGELOG \u662F\u5426\u6709\u9057\u6F0F\uFF1A
|
|
75
|
-
|
|
76
|
-
## \u6700\u8FD1 Git \u63D0\u4EA4
|
|
77
|
-
${commits2 || "(\u65E0\u6CD5\u83B7\u53D6)"}
|
|
78
|
-
|
|
79
|
-
## \u53D8\u66F4\u6587\u4EF6
|
|
80
|
-
${changedFiles2 || "(\u65E0\u6CD5\u83B7\u53D6)"}
|
|
81
|
-
|
|
82
|
-
## \u5F53\u524D CHANGELOG
|
|
83
|
-
${changelog2 ? changelog2.slice(0, 1500) + "\n..." : "(\u6587\u4EF6\u4E0D\u5B58\u5728)"}
|
|
84
|
-
|
|
85
|
-
\u8BF7\u5BF9\u6BD4\u5206\u6790\uFF1A
|
|
86
|
-
1. \u54EA\u4E9B\u91CD\u8981\u7684\u53D8\u66F4\u5DF2\u7ECF\u63D0\u4EA4\u5230 git \u4F46\u6CA1\u6709\u8BB0\u5F55\u5728 CHANGELOG\uFF1F
|
|
87
|
-
2. \u5F53\u524D [Unreleased] \u90E8\u5206\u662F\u5426\u5B8C\u6574\u53CD\u6620\u4E86\u6700\u8FD1\u7684\u5DE5\u4F5C\uFF1F
|
|
88
|
-
3. \u5217\u51FA\u9057\u6F0F\u7684\u6761\u76EE\u5EFA\u8BAE\uFF08\u6309 Added/Changed/Fixed \u5206\u7C7B\uFF09
|
|
89
|
-
|
|
90
|
-
\u53EA\u8FD4\u56DE\u5206\u6790\u62A5\u544A\uFF0C\u4E0D\u8981\u4FEE\u6539\u6587\u4EF6\u3002`;
|
|
91
|
-
}
|
|
92
|
-
if (args?.startsWith("add ")) {
|
|
93
|
-
const description = args.slice(4).trim();
|
|
94
|
-
const existingChangelog = await readChangelog(ctx2.cwd);
|
|
95
|
-
ctx2.ui.notify(`\u{1F4DD} \u6B63\u5728\u751F\u6210 changelog \u6761\u76EE...`, "info");
|
|
96
|
-
return `\u8BF7\u5C06\u4EE5\u4E0B\u63CF\u8FF0\u8F6C\u6362\u4E3A\u4E13\u4E1A\u7684 CHANGELOG \u6761\u76EE\uFF1A
|
|
97
|
-
|
|
98
|
-
\u63CF\u8FF0\uFF1A"${description}"
|
|
99
|
-
|
|
100
|
-
${existingChangelog ? `
|
|
101
|
-
\u53C2\u8003\u73B0\u6709\u683C\u5F0F\uFF1A
|
|
102
|
-
\`\`\`
|
|
103
|
-
${existingChangelog.slice(0, 800)}
|
|
104
|
-
...
|
|
105
|
-
\`\`\`` : ""}
|
|
106
|
-
|
|
107
|
-
\u8981\u6C42\uFF1A
|
|
108
|
-
1. \u9009\u62E9\u5408\u9002\u7684\u5206\u7C7B\uFF1A**Added** / **Changed** / **Fixed** / **Removed** / **Deprecated** / **Security**
|
|
109
|
-
2. \u4F7F\u7528\u73B0\u5728\u65F6\u6001\uFF0C\u7B80\u6D01\u4F46\u5305\u542B\u5173\u952E\u6280\u672F\u7EC6\u8282
|
|
110
|
-
3. \u5982\u6709\u76F8\u5173\u6587\u4EF6\u8DEF\u5F84\uFF0C\u8BF7\u5305\u542B
|
|
111
|
-
|
|
112
|
-
\u683C\u5F0F\u793A\u4F8B\uFF1A
|
|
113
|
-
- **Added**: \u65B0\u589E\u7528\u6237\u8BA4\u8BC1\u6A21\u5757\uFF0C\u652F\u6301 JWT token \u9A8C\u8BC1\uFF08src/auth/\uFF09
|
|
114
|
-
- **Fixed**: \u4FEE\u590D\u5185\u5B58\u6CC4\u6F0F\u95EE\u9898\uFF0C\u4F18\u5316\u4E86\u5927\u6587\u4EF6\u5904\u7406\u6027\u80FD
|
|
115
|
-
|
|
116
|
-
\u4F7F\u7528 write \u5DE5\u5177\u66F4\u65B0 CHANGELOG.md\uFF1A
|
|
117
|
-
- \u5982\u679C\u4E0D\u5B58\u5728\uFF0C\u521B\u5EFA\u6807\u51C6\u683C\u5F0F\uFF08\u5305\u542B ## [Unreleased] \u90E8\u5206\uFF09
|
|
118
|
-
- \u5C06\u65B0\u6761\u76EE\u6DFB\u52A0\u5230 [Unreleased] \u90E8\u5206\u7684\u5408\u9002\u4F4D\u7F6E
|
|
119
|
-
- \u4FDD\u6301\u73B0\u6709\u6761\u76EE\u4E0D\u53D8`;
|
|
120
|
-
}
|
|
121
|
-
if (args?.startsWith("release")) {
|
|
122
|
-
const versionHint = args.slice(7).trim();
|
|
123
|
-
const existingChangelog = await readChangelog(ctx2.cwd);
|
|
124
|
-
if (!existingChangelog) {
|
|
125
|
-
return "No CHANGELOG.md found. Create one first with /changelog";
|
|
126
|
-
}
|
|
127
|
-
ctx2.ui.notify(`\u{1F4DD} Preparing release ${versionHint || "..."}`, "info");
|
|
128
|
-
return `\u8BF7\u5C06 [Unreleased] \u90E8\u5206\u7684\u5185\u5BB9\u6574\u7406\u4E3A\u4E00\u4E2A\u65B0\u7248\u672C\u53D1\u5E03\u3002
|
|
129
|
-
|
|
130
|
-
\u5F53\u524D CHANGELOG\uFF1A
|
|
131
|
-
\`\`\`
|
|
132
|
-
${existingChangelog.slice(0, 1500)}
|
|
133
|
-
...
|
|
134
|
-
\`\`\`
|
|
135
|
-
|
|
136
|
-
\u7248\u672C\u63D0\u793A\uFF1A${versionHint || "\u6839\u636E\u53D8\u66F4\u5185\u5BB9\u81EA\u52A8\u5224\u65AD\uFF08patch/minor/major\uFF09"}
|
|
137
|
-
|
|
138
|
-
Semantic Versioning \u89C4\u5219\uFF1A
|
|
139
|
-
- **patch** (0.0.x): Bug fixes only
|
|
140
|
-
- **minor** (0.x.0): New features, backward compatible
|
|
141
|
-
- **major** (x.0.0): Breaking changes
|
|
142
|
-
|
|
143
|
-
\u4EFB\u52A1\uFF1A
|
|
144
|
-
1. \u5206\u6790 [Unreleased] \u4E2D\u7684\u53D8\u66F4\u7C7B\u578B
|
|
145
|
-
2. \u786E\u5B9A\u5408\u9002\u7684\u7248\u672C\u53F7\uFF08\u5982\u679C\u7528\u6237\u672A\u6307\u5B9A\uFF09
|
|
146
|
-
3. \u521B\u5EFA\u65B0\u7684\u7248\u672C\u8282\uFF08\u5982 ## [1.2.0] - 2024-03-06\uFF09
|
|
147
|
-
4. \u5C06 [Unreleased] \u7684\u5185\u5BB9\u79FB\u52A8\u5230\u65B0\u7248\u672C\u8282
|
|
148
|
-
5. \u6E05\u7A7A [Unreleased] \u90E8\u5206\uFF0C\u53EA\u4FDD\u7559\u7A7A\u5217\u8868
|
|
149
|
-
6. \u5728\u6587\u4EF6\u5E95\u90E8\u66F4\u65B0\u7248\u672C\u5BF9\u6BD4\u94FE\u63A5\uFF08\u5982\u679C\u9700\u8981\uFF09
|
|
150
|
-
|
|
151
|
-
\u4F7F\u7528 write \u5DE5\u5177\u66F4\u65B0 CHANGELOG.md`;
|
|
152
|
-
}
|
|
153
|
-
const commits = getRecentCommits(ctx2.cwd, 15);
|
|
154
|
-
const changelog = await readChangelog(ctx2.cwd);
|
|
155
|
-
const changedFiles = getChangedFiles(ctx2.cwd);
|
|
156
|
-
if (!commits && !changelog) {
|
|
157
|
-
return "No git history or CHANGELOG.md found. Initialize with: /changelog add <description>";
|
|
158
|
-
}
|
|
159
|
-
ctx2.ui.notify("\u{1F50D} \u5206\u6790\u53D8\u66F4\u5E76\u68C0\u67E5\u9057\u6F0F...", "info");
|
|
160
|
-
return `\u{1F4DD} \u667A\u80FD Changelog \u66F4\u65B0
|
|
161
|
-
|
|
162
|
-
\u8BF7\u5206\u6790\u4EE5\u4E0B\u4FE1\u606F\uFF0C\u68C0\u67E5\u5E76\u8865\u5145\u9057\u6F0F\u7684 CHANGELOG \u6761\u76EE\uFF1A
|
|
163
|
-
|
|
164
|
-
## \u6700\u8FD1 Git \u63D0\u4EA4\u8BB0\u5F55
|
|
165
|
-
${commits || "(\u65E0\u6CD5\u83B7\u53D6 git \u5386\u53F2)"}
|
|
166
|
-
|
|
167
|
-
## \u6700\u8FD1\u53D8\u66F4\u7684\u6587\u4EF6
|
|
168
|
-
${changedFiles || "(\u65E0\u6CD5\u83B7\u53D6)"}
|
|
169
|
-
|
|
170
|
-
## \u5F53\u524D CHANGELOG.md
|
|
171
|
-
${changelog ? "\n```\n" + changelog.slice(0, 2e3) + "\n...\n```" : "(\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u9700\u8981\u521B\u5EFA)"}
|
|
172
|
-
|
|
173
|
-
## \u4EFB\u52A1
|
|
174
|
-
|
|
175
|
-
1. **\u5BF9\u6BD4\u5206\u6790**\uFF1A
|
|
176
|
-
- \u67E5\u770B git \u63D0\u4EA4\u4E2D\u6709\u54EA\u4E9B\u91CD\u8981\u53D8\u66F4
|
|
177
|
-
- \u5BF9\u6BD4 CHANGELOG \u7684 [Unreleased] \u90E8\u5206
|
|
178
|
-
- \u8BC6\u522B\u9057\u6F0F\u7684\u6761\u76EE
|
|
179
|
-
|
|
180
|
-
2. **\u8865\u5145\u9057\u6F0F**\uFF08\u5982\u679C\u6709\uFF09\uFF1A
|
|
181
|
-
- \u4E3A\u6BCF\u4E2A\u9057\u6F0F\u7684\u53D8\u66F4\u521B\u5EFA\u4E13\u4E1A\u6761\u76EE
|
|
182
|
-
- \u5206\u7C7B\uFF1A**Added** / **Changed** / **Fixed** / **Removed**
|
|
183
|
-
- \u5305\u542B\u6280\u672F\u7EC6\u8282\u548C\u6587\u4EF6\u8DEF\u5F84
|
|
184
|
-
|
|
185
|
-
3. **\u66F4\u65B0\u6587\u4EF6**\uFF1A
|
|
186
|
-
- \u4F7F\u7528 write \u5DE5\u5177\u66F4\u65B0 CHANGELOG.md
|
|
187
|
-
- \u5982\u679C\u4E0D\u5B58\u5728\uFF0C\u521B\u5EFA\u6807\u51C6\u683C\u5F0F
|
|
188
|
-
- \u53EA\u6DFB\u52A0\u9057\u6F0F\u7684\u6761\u76EE\uFF0C\u4FDD\u6301\u73B0\u6709\u5185\u5BB9
|
|
189
|
-
|
|
190
|
-
4. **\u62A5\u544A\u7ED3\u679C**\uFF1A
|
|
191
|
-
- \u6DFB\u52A0\u4E86\u54EA\u4E9B\u6761\u76EE
|
|
192
|
-
- \u662F\u5426\u6709\u4E0D\u786E\u5B9A\u662F\u5426\u9700\u8981\u8BB0\u5F55\u7684\u5185\u5BB9`;
|
|
193
|
-
}
|
|
194
|
-
});
|
|
195
|
-
ctx.log("Changelog extension ready");
|
|
196
|
-
ctx.ui.notify(" Changelog extension loaded", "info");
|
|
197
|
-
}
|
|
198
|
-
export {
|
|
199
|
-
changelogExtension as default
|
|
200
|
-
};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
|
-
|
|
3
|
-
// builtin/extensions/compact/index.ts
|
|
4
|
-
function compactExtension(ctx) {
|
|
5
|
-
ctx.log("Compact extension loaded");
|
|
6
|
-
ctx.ui.notify("\u{1F5DC}\uFE0F Compact extension loaded", "info");
|
|
7
|
-
ctx.registerCommand({
|
|
8
|
-
path: ["tools", "compact"],
|
|
9
|
-
description: "Auto-summarize and compact conversation history",
|
|
10
|
-
handler: async (ctx2, args) => {
|
|
11
|
-
const focus = args?.trim();
|
|
12
|
-
let prompt = `Please summarize our conversation into a compact form.
|
|
13
|
-
|
|
14
|
-
Your task:
|
|
15
|
-
1. Analyze the conversation history:
|
|
16
|
-
- What was the original goal or question?
|
|
17
|
-
- What decisions were made?
|
|
18
|
-
- What code changes or file operations were performed?
|
|
19
|
-
- What is the current state?
|
|
20
|
-
- Are there any pending tasks or next steps?
|
|
21
|
-
|
|
22
|
-
2. Create a concise summary that captures:
|
|
23
|
-
- The essence of what was discussed
|
|
24
|
-
- Key technical decisions and their rationale
|
|
25
|
-
- Files that were modified or created
|
|
26
|
-
- Important code patterns or approaches established
|
|
27
|
-
- Any unresolved questions or TODOs
|
|
28
|
-
|
|
29
|
-
3. Format the summary to be:
|
|
30
|
-
- Under 500 words
|
|
31
|
-
- Well-structured with clear sections
|
|
32
|
-
- Technical and specific (include file paths, function names, etc.)
|
|
33
|
-
- Useful as context for continuing this work later
|
|
34
|
-
|
|
35
|
-
The summary should be detailed enough that another AI assistant could pick up where we left off.`;
|
|
36
|
-
if (focus) {
|
|
37
|
-
prompt += `
|
|
38
|
-
|
|
39
|
-
Special focus: ${focus}
|
|
40
|
-
Please pay particular attention to aspects related to "${focus}" in your summary.`;
|
|
41
|
-
}
|
|
42
|
-
prompt += `
|
|
43
|
-
|
|
44
|
-
After providing the summary, I will use it to update the conversation context. The original detailed messages can then be archived.`;
|
|
45
|
-
return prompt;
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
ctx.log("Compact extension ready");
|
|
49
|
-
}
|
|
50
|
-
export {
|
|
51
|
-
compactExtension as default
|
|
52
|
-
};
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
|
-
|
|
3
|
-
// builtin/extensions/deploy/index.ts
|
|
4
|
-
function deployExtension(ctx) {
|
|
5
|
-
ctx.log("Deploy extension loaded");
|
|
6
|
-
ctx.ui.notify("\u{1F680} Deploy extension loaded", "info");
|
|
7
|
-
ctx.log("Deploy extension ready");
|
|
8
|
-
}
|
|
9
|
-
export {
|
|
10
|
-
deployExtension as default
|
|
11
|
-
};
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
|
-
|
|
3
|
-
// builtin/extensions/files/index.ts
|
|
4
|
-
function filesExtension(ctx) {
|
|
5
|
-
ctx.log("Files extension loaded");
|
|
6
|
-
ctx.ui.notify("\u{1F4C1} Files extension loaded", "info");
|
|
7
|
-
}
|
|
8
|
-
export {
|
|
9
|
-
filesExtension as default
|
|
10
|
-
};
|
|
@@ -1,144 +0,0 @@
|
|
|
1
|
-
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
|
-
|
|
3
|
-
// builtin/extensions/init/index.ts
|
|
4
|
-
async function loadExistingKnowledge(cwd) {
|
|
5
|
-
try {
|
|
6
|
-
const fs = await import("fs");
|
|
7
|
-
const path = await import("path");
|
|
8
|
-
const agentsPath = path.join(cwd, ".pie", "agents.md");
|
|
9
|
-
if (fs.existsSync(agentsPath)) {
|
|
10
|
-
return fs.readFileSync(agentsPath, "utf-8");
|
|
11
|
-
}
|
|
12
|
-
} catch {
|
|
13
|
-
}
|
|
14
|
-
return null;
|
|
15
|
-
}
|
|
16
|
-
async function ensurePieDir(cwd) {
|
|
17
|
-
const fs = await import("fs");
|
|
18
|
-
const path = await import("path");
|
|
19
|
-
const pieDir = path.join(cwd, ".pie");
|
|
20
|
-
if (!fs.existsSync(pieDir)) {
|
|
21
|
-
fs.mkdirSync(pieDir, { recursive: true });
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
function buildResearchPrompt(params) {
|
|
25
|
-
const { isUpdate, existingContent, userIntent, cwd } = params;
|
|
26
|
-
if (isUpdate && existingContent) {
|
|
27
|
-
const truncatedContent = existingContent.length > 4e3 ? existingContent.slice(0, 4e3) + "\n... (truncated)" : existingContent;
|
|
28
|
-
return `\u{1F4DD} \u66F4\u65B0\u9879\u76EE\u77E5\u8BC6\u6587\u6863
|
|
29
|
-
|
|
30
|
-
\u5F53\u524D .pie/agents.md \u5185\u5BB9\uFF1A
|
|
31
|
-
\`\`\`
|
|
32
|
-
${truncatedContent}
|
|
33
|
-
\`\`\`
|
|
34
|
-
|
|
35
|
-
${userIntent ? `\u{1F4CC} \u7528\u6237\u66F4\u65B0\u610F\u56FE\uFF1A${userIntent}
|
|
36
|
-
|
|
37
|
-
` : ""}\u8BF7\u91CD\u65B0\u7814\u7A76\u9879\u76EE\u5E76\u66F4\u65B0\u77E5\u8BC6\u6587\u6863\uFF1A
|
|
38
|
-
|
|
39
|
-
1. \u63A2\u7D22\u5F53\u524D\u4EE3\u7801\u7ED3\u6784\uFF0C\u5BF9\u6BD4\u73B0\u6709\u6587\u6863
|
|
40
|
-
2. \u8BC6\u522B\u65B0\u589E/\u53D8\u66F4/\u79FB\u9664\u7684\u6A21\u5757\u548C\u6587\u4EF6
|
|
41
|
-
3. ${userIntent ? `\u91CD\u70B9\u5173\u6CE8\uFF1A${userIntent}` : "\u8865\u5145\u7F3A\u5931\u7684\u7EC6\u8282\u548C\u67B6\u6784\u8BF4\u660E\uFF0C\u66F4\u65B0\u8FC7\u65F6\u7684\u4FE1\u606F"}
|
|
42
|
-
4. \u4FDD\u6301\u6587\u6863\u7ED3\u6784\u6E05\u6670\uFF0C\u7EF4\u62A4\u7AE0\u8282\u5B8C\u6574\u6027
|
|
43
|
-
5. \u66F4\u65B0\u540E\u786E\u4FDD agents.md \u4ECD\u7136\u6709\u7528\u4E14\u51C6\u786E
|
|
44
|
-
|
|
45
|
-
\u8BF7\u4F7F\u7528 write \u5DE5\u5177\u66F4\u65B0 \`.pie/agents.md\` \u6587\u4EF6\u3002
|
|
46
|
-
|
|
47
|
-
\u5DE5\u4F5C\u76EE\u5F55\uFF1A${cwd}`;
|
|
48
|
-
}
|
|
49
|
-
return `\u{1F50D} \u521D\u59CB\u5316\u9879\u76EE\u7814\u7A76
|
|
50
|
-
|
|
51
|
-
${userIntent ? `\u{1F4CC} \u7528\u6237\u7814\u7A76\u610F\u56FE\uFF1A${userIntent}
|
|
52
|
-
|
|
53
|
-
` : ""}\u8BF7\u5E2E\u6211\u5168\u9762\u7814\u7A76\u5F53\u524D\u9879\u76EE\u5E76\u521B\u5EFA \`.pie/agents.md\` \u77E5\u8BC6\u6587\u6863\u3002
|
|
54
|
-
|
|
55
|
-
\u7814\u7A76\u4EFB\u52A1\uFF1A
|
|
56
|
-
1. \u8BC6\u522B\u9879\u76EE\u7C7B\u578B\u548C\u6280\u672F\u6808\uFF08\u67E5\u770B package.json, Cargo.toml, go.mod, requirements.txt, pyproject.toml \u7B49\uFF09
|
|
57
|
-
2. \u63A2\u7D22\u6E90\u4EE3\u7801\u76EE\u5F55\u7ED3\u6784\uFF08src/, lib/, app/ \u7B49\u5E38\u89C1\u76EE\u5F55\uFF09
|
|
58
|
-
3. \u8BFB\u53D6\u5173\u952E\u914D\u7F6E\u6587\u4EF6\u7406\u89E3\u9879\u76EE\u8BBE\u7F6E
|
|
59
|
-
4. \u8BC6\u522B\u4E3B\u8981\u6A21\u5757\u3001\u5165\u53E3\u70B9\u3001\u6838\u5FC3\u7C7B/\u51FD\u6570
|
|
60
|
-
5. \u5206\u6790\u67B6\u6784\u6A21\u5F0F\u548C\u8BBE\u8BA1\u51B3\u7B56
|
|
61
|
-
6. \u63A8\u65AD\u5F00\u53D1\u89C4\u8303\uFF08\u4EE3\u7801\u98CE\u683C\u3001\u6D4B\u8BD5\u3001\u6784\u5EFA\u6D41\u7A0B\uFF09
|
|
62
|
-
|
|
63
|
-
\u8BF7\u751F\u6210\u5305\u542B\u4EE5\u4E0B\u7AE0\u8282\u7684 agents.md\uFF1A
|
|
64
|
-
|
|
65
|
-
\`\`\`
|
|
66
|
-
# Project: <\u9879\u76EE\u540D\u79F0>
|
|
67
|
-
|
|
68
|
-
## \u6982\u89C8
|
|
69
|
-
- \u7C7B\u578B\uFF1A<\u9879\u76EE\u7C7B\u578B>
|
|
70
|
-
- \u6280\u672F\u6808\uFF1A<\u4E3B\u8981\u6280\u672F>
|
|
71
|
-
- \u4E00\u53E5\u8BDD\u63CF\u8FF0\uFF1A<\u9879\u76EE\u7528\u9014>
|
|
72
|
-
|
|
73
|
-
## \u67B6\u6784\u5206\u6790
|
|
74
|
-
- \u6A21\u5757\u5212\u5206
|
|
75
|
-
- \u5173\u952E\u7EC4\u4EF6\u8BF4\u660E
|
|
76
|
-
- \u4F9D\u8D56\u5173\u7CFB
|
|
77
|
-
|
|
78
|
-
## \u6838\u5FC3\u6587\u4EF6
|
|
79
|
-
| \u7528\u9014 | \u8DEF\u5F84 | \u8BF4\u660E |
|
|
80
|
-
|------|------|------|
|
|
81
|
-
|
|
82
|
-
## \u5F00\u53D1\u89C4\u8303
|
|
83
|
-
- \u4EE3\u7801\u98CE\u683C
|
|
84
|
-
- \u6D4B\u8BD5\u6A21\u5F0F
|
|
85
|
-
- \u6784\u5EFA/\u8FD0\u884C\u65B9\u5F0F
|
|
86
|
-
|
|
87
|
-
## \u63A2\u7D22\u6E05\u5355\uFF08\u5F85\u6DF1\u5165\u7814\u7A76\uFF09
|
|
88
|
-
- [ ]
|
|
89
|
-
\`\`\`
|
|
90
|
-
|
|
91
|
-
\u8BF7\u4F7F\u7528 write \u5DE5\u5177\u521B\u5EFA \`.pie/agents.md\` \u6587\u4EF6\u3002
|
|
92
|
-
|
|
93
|
-
\u5DE5\u4F5C\u76EE\u5F55\uFF1A${cwd}`;
|
|
94
|
-
}
|
|
95
|
-
async function initExtension(ctx) {
|
|
96
|
-
ctx.log("Init extension loaded");
|
|
97
|
-
let cachedKnowledge = null;
|
|
98
|
-
try {
|
|
99
|
-
cachedKnowledge = await loadExistingKnowledge(ctx.cwd);
|
|
100
|
-
if (cachedKnowledge) {
|
|
101
|
-
const firstLine = cachedKnowledge.split("\n")[0] || "";
|
|
102
|
-
const projectName = firstLine.replace(/^#\s*/, "").trim() || "\u9879\u76EE";
|
|
103
|
-
ctx.ui.notify(`\u{1F4DA} \u5DF2\u52A0\u8F7D ${projectName} \u77E5\u8BC6\u6587\u6863`, "info");
|
|
104
|
-
ctx.log(`Pre-loaded agents.md (${cachedKnowledge.length} chars)`);
|
|
105
|
-
} else {
|
|
106
|
-
ctx.ui.notify("\u{1F4DA} Init extension loaded (no existing knowledge)", "info");
|
|
107
|
-
ctx.log("No existing agents.md found");
|
|
108
|
-
}
|
|
109
|
-
} catch (err) {
|
|
110
|
-
ctx.ui.notify("\u{1F4DA} Init extension loaded", "info");
|
|
111
|
-
ctx.log(`Failed to pre-load agents.md: ${err}`);
|
|
112
|
-
}
|
|
113
|
-
ctx.registerCommand({
|
|
114
|
-
path: ["tools", "init"],
|
|
115
|
-
description: "\u7814\u7A76\u9879\u76EE\u5E76\u751F\u6210/\u66F4\u65B0 agents.md \u77E5\u8BC6\u6587\u6863",
|
|
116
|
-
handler: async (ctx2, args) => {
|
|
117
|
-
await ensurePieDir(ctx2.cwd);
|
|
118
|
-
const existingContent = await loadExistingKnowledge(ctx2.cwd);
|
|
119
|
-
const isUpdate = !!existingContent;
|
|
120
|
-
const userIntent = args?.trim();
|
|
121
|
-
cachedKnowledge = existingContent;
|
|
122
|
-
if (isUpdate) {
|
|
123
|
-
if (userIntent) {
|
|
124
|
-
ctx2.ui.notify(`\u{1F4DD} \u6B63\u5728\u66F4\u65B0\u9879\u76EE\u77E5\u8BC6\uFF08${userIntent}\uFF09...`, "info");
|
|
125
|
-
} else {
|
|
126
|
-
ctx2.ui.notify("\u{1F4DD} \u6B63\u5728\u66F4\u65B0\u9879\u76EE\u77E5\u8BC6...", "info");
|
|
127
|
-
}
|
|
128
|
-
} else {
|
|
129
|
-
ctx2.ui.notify("\u{1F50D} \u6B63\u5728\u521D\u59CB\u5316\u9879\u76EE\u7814\u7A76...", "info");
|
|
130
|
-
}
|
|
131
|
-
const researchPrompt = buildResearchPrompt({
|
|
132
|
-
isUpdate,
|
|
133
|
-
existingContent,
|
|
134
|
-
userIntent,
|
|
135
|
-
cwd: ctx2.cwd
|
|
136
|
-
});
|
|
137
|
-
return researchPrompt;
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
ctx.log("Init extension ready");
|
|
141
|
-
}
|
|
142
|
-
export {
|
|
143
|
-
initExtension as default
|
|
144
|
-
};
|
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
|
|
2
|
-
|
|
3
|
-
// builtin/extensions/plan-mode/index.ts
|
|
4
|
-
function extractTodoItems(text) {
|
|
5
|
-
const items = [];
|
|
6
|
-
const planMatch = text.match(/Plan:\s*\n?([\s\S]*?)(?=\n\n|\n[A-Z]|$)/i);
|
|
7
|
-
if (!planMatch) return items;
|
|
8
|
-
const planSection = planMatch[1];
|
|
9
|
-
const lines = planSection.split("\n");
|
|
10
|
-
for (const line of lines) {
|
|
11
|
-
const trimmed = line.trim();
|
|
12
|
-
const match = trimmed.match(/^(?:\d+[.):\s]+|[\-*]\s+)(.+)$/);
|
|
13
|
-
if (match) {
|
|
14
|
-
items.push({
|
|
15
|
-
step: items.length + 1,
|
|
16
|
-
text: match[1].trim(),
|
|
17
|
-
completed: false
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
return items;
|
|
22
|
-
}
|
|
23
|
-
function isSafeCommand(command) {
|
|
24
|
-
const trimmed = command.trim();
|
|
25
|
-
const safePrefixes = [
|
|
26
|
-
"cat ",
|
|
27
|
-
"ls ",
|
|
28
|
-
"find ",
|
|
29
|
-
"grep ",
|
|
30
|
-
"head ",
|
|
31
|
-
"tail ",
|
|
32
|
-
"echo ",
|
|
33
|
-
"pwd",
|
|
34
|
-
"cd ",
|
|
35
|
-
"which ",
|
|
36
|
-
"git status",
|
|
37
|
-
"git log",
|
|
38
|
-
"git diff",
|
|
39
|
-
"git show",
|
|
40
|
-
"git branch -a",
|
|
41
|
-
"git remote -v",
|
|
42
|
-
"git config --list",
|
|
43
|
-
"npm list",
|
|
44
|
-
"npm view"
|
|
45
|
-
];
|
|
46
|
-
const dangerousPatterns = [
|
|
47
|
-
/\brm\s+-[rf]*/i,
|
|
48
|
-
/>[\s]*\/dev\//,
|
|
49
|
-
/\|.*\brm\b/,
|
|
50
|
-
/git\s+push/i,
|
|
51
|
-
/git\s+reset/i,
|
|
52
|
-
/git\s+checkout\s+-/,
|
|
53
|
-
/git\s+revert/i,
|
|
54
|
-
/npm\s+publish/i,
|
|
55
|
-
/npm\s+uninstall/i,
|
|
56
|
-
/npm\s+rm/i
|
|
57
|
-
];
|
|
58
|
-
for (const pattern of dangerousPatterns) {
|
|
59
|
-
if (pattern.test(trimmed)) {
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
for (const prefix of safePrefixes) {
|
|
64
|
-
if (trimmed.startsWith(prefix)) {
|
|
65
|
-
return true;
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
if (/^[a-z]+$/.test(trimmed)) {
|
|
69
|
-
return ["pwd", "ls", "clear", "whoami"].includes(trimmed);
|
|
70
|
-
}
|
|
71
|
-
return false;
|
|
72
|
-
}
|
|
73
|
-
function markCompletedSteps(text, todoItems2) {
|
|
74
|
-
let markedCount = 0;
|
|
75
|
-
const doneMatches = text.matchAll(/\[DONE:\s*(\d+)\]/gi);
|
|
76
|
-
for (const match of doneMatches) {
|
|
77
|
-
const stepNum = parseInt(match[1], 10);
|
|
78
|
-
const item = todoItems2.find((t) => t.step === stepNum);
|
|
79
|
-
if (item && !item.completed) {
|
|
80
|
-
item.completed = true;
|
|
81
|
-
markedCount++;
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
return markedCount;
|
|
85
|
-
}
|
|
86
|
-
var PLAN_MODE_TOOLS = ["read", "bash", "grep", "find", "ls", "questionnaire"];
|
|
87
|
-
var NORMAL_MODE_TOOLS = ["read", "bash", "edit", "write", "grep", "find", "ls", "questionnaire"];
|
|
88
|
-
var planModeEnabled = false;
|
|
89
|
-
var executionMode = false;
|
|
90
|
-
var todoItems = [];
|
|
91
|
-
function planModeExtension(ctx) {
|
|
92
|
-
ctx.log("Plan mode extension loaded");
|
|
93
|
-
function updateStatus() {
|
|
94
|
-
if (executionMode && todoItems.length > 0) {
|
|
95
|
-
const completed = todoItems.filter((t) => t.completed).length;
|
|
96
|
-
ctx.ui.notify(`\u{1F4CB} Plan: ${completed}/${todoItems.length} completed`, "info");
|
|
97
|
-
} else if (planModeEnabled) {
|
|
98
|
-
ctx.ui.notify("\u23F8\uFE0F Plan mode active (read-only)", "info");
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
function togglePlanMode() {
|
|
102
|
-
planModeEnabled = !planModeEnabled;
|
|
103
|
-
executionMode = false;
|
|
104
|
-
todoItems = [];
|
|
105
|
-
ctx.setPlanMode(planModeEnabled);
|
|
106
|
-
if (planModeEnabled) {
|
|
107
|
-
ctx.setActiveTools(PLAN_MODE_TOOLS);
|
|
108
|
-
ctx.ui.notify(`Plan mode enabled. Available tools: ${PLAN_MODE_TOOLS.join(", ")}`);
|
|
109
|
-
} else {
|
|
110
|
-
ctx.setActiveTools(NORMAL_MODE_TOOLS);
|
|
111
|
-
ctx.ui.notify("Plan mode disabled. Full access restored.");
|
|
112
|
-
}
|
|
113
|
-
updateStatus();
|
|
114
|
-
}
|
|
115
|
-
ctx.registerCommand({
|
|
116
|
-
path: ["tools", "plan"],
|
|
117
|
-
description: "Toggle plan mode (read-only exploration)",
|
|
118
|
-
handler: async (_ctx) => {
|
|
119
|
-
togglePlanMode();
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
ctx.registerShortcut("ctrl+alt+p", {
|
|
123
|
-
description: "Toggle plan mode",
|
|
124
|
-
handler: async () => {
|
|
125
|
-
togglePlanMode();
|
|
126
|
-
}
|
|
127
|
-
});
|
|
128
|
-
ctx.on("tool:call", async (event) => {
|
|
129
|
-
if (!planModeEnabled || event.toolName !== "bash") return;
|
|
130
|
-
const command = event.args?.command;
|
|
131
|
-
if (command && !isSafeCommand(command)) {
|
|
132
|
-
ctx.ui.notify(
|
|
133
|
-
`Plan mode: Command blocked (not allowlisted). Use /plan to disable plan mode first.
|
|
134
|
-
Command: ${command}`,
|
|
135
|
-
"error"
|
|
136
|
-
);
|
|
137
|
-
return { block: true, reason: `Plan mode: command "${command}" is not in the allowlist. Disable plan mode with /plan to run this command.` };
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
ctx.on("agent:start", async () => {
|
|
141
|
-
if (planModeEnabled) {
|
|
142
|
-
ctx.log("[plan-mode] Injecting plan mode context");
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
ctx.on("turn:end", async (event) => {
|
|
146
|
-
if (!executionMode || todoItems.length === 0) return;
|
|
147
|
-
const message = event.message;
|
|
148
|
-
if (message?.role === "assistant" && Array.isArray(message.content)) {
|
|
149
|
-
const text = message.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
150
|
-
if (markCompletedSteps(text, todoItems) > 0) {
|
|
151
|
-
updateStatus();
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
ctx.on("agent:end", async (event) => {
|
|
156
|
-
if (executionMode && todoItems.length > 0) {
|
|
157
|
-
if (todoItems.every((t) => t.completed)) {
|
|
158
|
-
const completedList = todoItems.map((t) => `\u2713 ${t.text}`).join("\n");
|
|
159
|
-
ctx.ui.notify(`**Plan Complete!** \u2713
|
|
160
|
-
|
|
161
|
-
${completedList}`, "info");
|
|
162
|
-
executionMode = false;
|
|
163
|
-
todoItems = [];
|
|
164
|
-
ctx.setActiveTools(NORMAL_MODE_TOOLS);
|
|
165
|
-
}
|
|
166
|
-
return;
|
|
167
|
-
}
|
|
168
|
-
if (!planModeEnabled || !ctx.hasUI) return;
|
|
169
|
-
const messages = event.messages || [];
|
|
170
|
-
const lastAssistant = [...messages].reverse().find(
|
|
171
|
-
(m) => m.role === "assistant" && Array.isArray(m.content)
|
|
172
|
-
);
|
|
173
|
-
if (lastAssistant) {
|
|
174
|
-
const text = lastAssistant.content.filter((c) => c.type === "text").map((c) => c.text).join("\n");
|
|
175
|
-
const extracted = extractTodoItems(text);
|
|
176
|
-
if (extracted.length > 0) {
|
|
177
|
-
todoItems = extracted;
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
if (todoItems.length > 0) {
|
|
181
|
-
const todoListText = todoItems.map((t) => `${t.step}. \u2610 ${t.text}`).join("\n");
|
|
182
|
-
ctx.ui.notify(`**Plan Steps (${todoItems.length}):**
|
|
183
|
-
${todoListText}`, "info");
|
|
184
|
-
const choice = await ctx.ui.select("Plan mode - what next?", [
|
|
185
|
-
todoItems.length > 0 ? "Execute the plan (track progress)" : "Execute the plan",
|
|
186
|
-
"Stay in plan mode",
|
|
187
|
-
"Refine the plan"
|
|
188
|
-
]);
|
|
189
|
-
if (choice?.startsWith("Execute")) {
|
|
190
|
-
planModeEnabled = false;
|
|
191
|
-
executionMode = todoItems.length > 0;
|
|
192
|
-
ctx.setPlanMode(false);
|
|
193
|
-
ctx.setActiveTools(NORMAL_MODE_TOOLS);
|
|
194
|
-
updateStatus();
|
|
195
|
-
const execMessage = todoItems.length > 0 ? `Execute the plan. Start with: ${todoItems[0].text}. Mark completed steps with [DONE:n] in your response.` : "Execute the plan you just created.";
|
|
196
|
-
ctx.sendUserMessage(execMessage);
|
|
197
|
-
} else if (choice === "Refine the plan") {
|
|
198
|
-
const refinement = await ctx.ui.editor("Refine the plan:", "");
|
|
199
|
-
if (refinement?.trim()) {
|
|
200
|
-
ctx.sendUserMessage(refinement.trim());
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
});
|
|
205
|
-
ctx.ui.notify("\u23F8\uFE0F Plan mode extension loaded", "info");
|
|
206
|
-
}
|
|
207
|
-
export {
|
|
208
|
-
planModeExtension as default
|
|
209
|
-
};
|