@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.
Files changed (37) hide show
  1. package/README.md +117 -88
  2. package/package.json +4 -3
  3. package/dist/builtin/extensions/ask-user/index.js +0 -2924
  4. package/dist/builtin/extensions/changelog/index.js +0 -200
  5. package/dist/builtin/extensions/compact/index.js +0 -52
  6. package/dist/builtin/extensions/deploy/index.js +0 -11
  7. package/dist/builtin/extensions/files/index.js +0 -10
  8. package/dist/builtin/extensions/init/index.js +0 -144
  9. package/dist/builtin/extensions/plan-mode/index.js +0 -209
  10. package/dist/builtin/extensions/questionnaire/index.js +0 -2753
  11. package/dist/builtin/extensions/subagent/index.js +0 -7350
  12. package/dist/builtin/extensions/todo/index.js +0 -162
  13. package/dist/builtin/skills/browser-tools/CHANGELOG.md +0 -47
  14. package/dist/builtin/skills/browser-tools/browser-cookies.js +0 -35
  15. package/dist/builtin/skills/browser-tools/browser-screenshot.js +0 -34
  16. package/dist/builtin/skills/browser-tools/browser-start.js +0 -86
  17. package/dist/builtin/skills/skill-creator/LICENSE.txt +0 -202
  18. package/dist/builtin/skills/skill-creator/SKILL.md +0 -485
  19. package/dist/builtin/skills/skill-creator/agents/analyzer.md +0 -274
  20. package/dist/builtin/skills/skill-creator/agents/comparator.md +0 -202
  21. package/dist/builtin/skills/skill-creator/agents/grader.md +0 -223
  22. package/dist/builtin/skills/skill-creator/assets/eval_review.html +0 -146
  23. package/dist/builtin/skills/skill-creator/eval-viewer/generate_review.py +0 -471
  24. package/dist/builtin/skills/skill-creator/eval-viewer/viewer.html +0 -1325
  25. package/dist/builtin/skills/skill-creator/references/schemas.md +0 -430
  26. package/dist/builtin/skills/skill-creator/scripts/__init__.py +0 -0
  27. package/dist/builtin/skills/skill-creator/scripts/aggregate_benchmark.py +0 -401
  28. package/dist/builtin/skills/skill-creator/scripts/generate_report.py +0 -326
  29. package/dist/builtin/skills/skill-creator/scripts/improve_description.py +0 -247
  30. package/dist/builtin/skills/skill-creator/scripts/package_skill.py +0 -136
  31. package/dist/builtin/skills/skill-creator/scripts/quick_validate.py +0 -103
  32. package/dist/builtin/skills/skill-creator/scripts/run_eval.py +0 -310
  33. package/dist/builtin/skills/skill-creator/scripts/run_loop.py +0 -328
  34. package/dist/builtin/skills/skill-creator/scripts/utils.py +0 -47
  35. package/dist/cli.js +0 -74440
  36. package/dist/theme/dark.json +0 -85
  37. 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
- };