@cydm/pie 1.0.1 → 1.0.2

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/dist/builtin/extensions/ask-user/index.js +2924 -0
  2. package/dist/builtin/extensions/changelog/index.js +200 -0
  3. package/dist/builtin/extensions/deploy/index.js +11 -0
  4. package/dist/builtin/extensions/document-attachments/index.js +144 -0
  5. package/dist/builtin/extensions/files/index.js +10 -0
  6. package/dist/builtin/extensions/init/index.js +144 -0
  7. package/dist/builtin/extensions/kimi-attachments/index.js +46 -0
  8. package/dist/builtin/extensions/plan-mode/index.js +209 -0
  9. package/dist/builtin/extensions/questionnaire/index.js +2753 -0
  10. package/dist/builtin/extensions/subagent/index.js +11031 -0
  11. package/dist/builtin/extensions/todo/index.js +162 -0
  12. package/dist/builtin/skills/browser-tools/CHANGELOG.md +47 -0
  13. package/dist/builtin/skills/browser-tools/browser-cookies.js +35 -0
  14. package/dist/builtin/skills/browser-tools/browser-screenshot.js +34 -0
  15. package/dist/builtin/skills/browser-tools/browser-start.js +86 -0
  16. package/dist/builtin/skills/skill-creator/LICENSE.txt +202 -0
  17. package/dist/builtin/skills/skill-creator/SKILL.md +485 -0
  18. package/dist/builtin/skills/skill-creator/agents/analyzer.md +274 -0
  19. package/dist/builtin/skills/skill-creator/agents/comparator.md +202 -0
  20. package/dist/builtin/skills/skill-creator/agents/grader.md +223 -0
  21. package/dist/builtin/skills/skill-creator/assets/eval_review.html +146 -0
  22. package/dist/builtin/skills/skill-creator/eval-viewer/generate_review.py +471 -0
  23. package/dist/builtin/skills/skill-creator/eval-viewer/viewer.html +1325 -0
  24. package/dist/builtin/skills/skill-creator/references/schemas.md +430 -0
  25. package/dist/builtin/skills/skill-creator/scripts/__init__.py +0 -0
  26. package/dist/builtin/skills/skill-creator/scripts/aggregate_benchmark.py +401 -0
  27. package/dist/builtin/skills/skill-creator/scripts/generate_report.py +326 -0
  28. package/dist/builtin/skills/skill-creator/scripts/improve_description.py +247 -0
  29. package/dist/builtin/skills/skill-creator/scripts/package_skill.py +136 -0
  30. package/dist/builtin/skills/skill-creator/scripts/quick_validate.py +103 -0
  31. package/dist/builtin/skills/skill-creator/scripts/run_eval.py +310 -0
  32. package/dist/builtin/skills/skill-creator/scripts/run_loop.py +328 -0
  33. package/dist/builtin/skills/skill-creator/scripts/utils.py +47 -0
  34. package/dist/cli.js +78983 -0
  35. package/dist/theme/dark.json +85 -0
  36. package/dist/theme/light.json +84 -0
  37. package/package.json +1 -1
@@ -0,0 +1,200 @@
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
+ };
@@ -0,0 +1,11 @@
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
+ };
@@ -0,0 +1,144 @@
1
+ import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
+
3
+ // builtin/extensions/document-attachments/index.ts
4
+ import * as fs from "node:fs";
5
+ import * as path from "node:path";
6
+ import { spawnSync } from "node:child_process";
7
+ var MAX_TEXT_CHARS = 24e3;
8
+ var PYTHON_CANDIDATES = [
9
+ process.env.PYTHON,
10
+ "/opt/anaconda3/bin/python3",
11
+ "python3"
12
+ ].filter((value) => Boolean(value));
13
+ function isTextCapable(model) {
14
+ return (model.input ?? []).includes("text");
15
+ }
16
+ function isSupportedDocument(attachment) {
17
+ return attachment.mimeType === "application/pdf" || attachment.mimeType === "text/html" || attachment.mimeType === "text/plain" || attachment.mimeType === "text/markdown" || attachment.mimeType === "application/json" || attachment.name.endsWith(".html") || attachment.name.endsWith(".htm") || attachment.name.endsWith(".md") || attachment.name.endsWith(".txt") || attachment.name.endsWith(".json") || attachment.name.endsWith(".pdf");
18
+ }
19
+ function truncateText(text) {
20
+ const normalized = text.replace(/\r\n/g, "\n").replace(/\n{3,}/g, "\n\n").trim();
21
+ if (normalized.length <= MAX_TEXT_CHARS) return normalized;
22
+ return `${normalized.slice(0, MAX_TEXT_CHARS)}
23
+
24
+ [Truncated after ${MAX_TEXT_CHARS} characters]`;
25
+ }
26
+ function runPythonScript(script, fallbackMessage) {
27
+ const failures = [];
28
+ for (const pythonBin of PYTHON_CANDIDATES) {
29
+ const result = spawnSync(pythonBin, ["-c", script], { encoding: "utf8" });
30
+ if (result.status === 0) {
31
+ return result.stdout;
32
+ }
33
+ const detail = (result.stderr || result.stdout || `exit ${result.status}`).trim();
34
+ failures.push(`${pythonBin}: ${detail}`);
35
+ }
36
+ throw new Error(`${fallbackMessage}
37
+ ${failures.join("\n")}`);
38
+ }
39
+ function extractHtmlText(filePath) {
40
+ const script = `
41
+ from pathlib import Path
42
+ from html.parser import HTMLParser
43
+
44
+ class Extractor(HTMLParser):
45
+ def __init__(self):
46
+ super().__init__()
47
+ self.parts = []
48
+ self.skip_depth = 0
49
+ def handle_starttag(self, tag, attrs):
50
+ if tag in ("script", "style"):
51
+ self.skip_depth += 1
52
+ def handle_endtag(self, tag):
53
+ if tag in ("script", "style") and self.skip_depth > 0:
54
+ self.skip_depth -= 1
55
+ def handle_data(self, data):
56
+ if self.skip_depth:
57
+ return
58
+ data = data.strip()
59
+ if data:
60
+ self.parts.append(data)
61
+
62
+ p = Path(${JSON.stringify(filePath)})
63
+ parser = Extractor()
64
+ parser.feed(p.read_text("utf-8"))
65
+ print("\\n".join(parser.parts))
66
+ `;
67
+ return runPythonScript(script, "Failed to extract HTML text");
68
+ }
69
+ function extractPdfText(filePath) {
70
+ const script = `
71
+ reader = None
72
+ errors = []
73
+
74
+ for module_name in ("pypdf", "PyPDF2"):
75
+ try:
76
+ module = __import__(module_name, fromlist=["PdfReader"])
77
+ reader = module.PdfReader(${JSON.stringify(filePath)})
78
+ break
79
+ except Exception as exc:
80
+ errors.append(f"{module_name}: {exc}")
81
+
82
+ if reader is None:
83
+ raise RuntimeError(" | ".join(errors) or "No supported PDF reader module found")
84
+
85
+ parts = []
86
+ for page in reader.pages:
87
+ try:
88
+ text = page.extract_text() or ""
89
+ except Exception:
90
+ text = ""
91
+ if text.strip():
92
+ parts.append(text)
93
+ print("\\n\\n".join(parts))
94
+ `;
95
+ return runPythonScript(script, "Failed to extract PDF text");
96
+ }
97
+ function extractPlainText(filePath) {
98
+ return fs.readFileSync(filePath, "utf8");
99
+ }
100
+ function extractDocumentText(attachment) {
101
+ const filePath = attachment.path;
102
+ if (!filePath || !fs.existsSync(filePath)) {
103
+ throw new Error(`Local attachment path is unavailable for ${attachment.name}`);
104
+ }
105
+ const ext = path.extname(filePath).toLowerCase();
106
+ if (attachment.mimeType === "application/pdf" || ext === ".pdf") {
107
+ return extractPdfText(filePath);
108
+ }
109
+ if (attachment.mimeType === "text/html" || ext === ".html" || ext === ".htm") {
110
+ return extractHtmlText(filePath);
111
+ }
112
+ return extractPlainText(filePath);
113
+ }
114
+ function documentAttachmentsExtension(ctx) {
115
+ ctx.log("Document attachment extension loaded");
116
+ ctx.registerAttachmentHandler({
117
+ name: "local-document-preprocess",
118
+ priority: 20,
119
+ matches(model, attachment) {
120
+ return isTextCapable(model) && isSupportedDocument(attachment) && Boolean(attachment.path);
121
+ },
122
+ async prepare(_model, attachment, prepareCtx) {
123
+ const extracted = extractDocumentText(attachment);
124
+ const text = truncateText(extracted);
125
+ prepareCtx.log(`Document handler extracted ${text.length} chars from ${attachment.name}`);
126
+ const prefix = [
127
+ `[Document: ${attachment.name}]`,
128
+ `MIME: ${attachment.mimeType}`,
129
+ ""
130
+ ].join("\n");
131
+ return {
132
+ items: [
133
+ {
134
+ type: "text",
135
+ text: `${prefix}${text}`
136
+ }
137
+ ]
138
+ };
139
+ }
140
+ });
141
+ }
142
+ export {
143
+ documentAttachmentsExtension as default
144
+ };
@@ -0,0 +1,10 @@
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
+ };
@@ -0,0 +1,144 @@
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
+ };
@@ -0,0 +1,46 @@
1
+ import { createRequire as __createRequire } from "node:module"; const require = __createRequire(import.meta.url);
2
+
3
+ // builtin/extensions/kimi-attachments/index.ts
4
+ function isKimiProvider(provider) {
5
+ return provider === "kimi-cn" || provider === "kimi-api" || provider === "kimi";
6
+ }
7
+ function getModality(mimeType) {
8
+ if (mimeType.startsWith("image/")) return "image";
9
+ if (mimeType.startsWith("video/")) return "video";
10
+ return "file";
11
+ }
12
+ function kimiAttachmentsExtension(ctx) {
13
+ ctx.log("Kimi attachment extension loaded");
14
+ ctx.registerAttachmentHandler({
15
+ name: "kimi-native-attachments",
16
+ priority: 100,
17
+ matches(model, attachment) {
18
+ return isKimiProvider(model.provider) && Boolean(attachment.fileId) && getModality(attachment.mimeType) !== "file";
19
+ },
20
+ async prepare(_model, attachment, prepareCtx) {
21
+ const fileId = attachment.fileId;
22
+ if (!fileId) {
23
+ return {
24
+ items: [{ type: "text", text: `[${attachment.id}]` }],
25
+ warnings: ["\u9644\u4EF6\u7F3A\u5C11 fileId\uFF0C\u65E0\u6CD5\u8D70 Kimi \u539F\u751F\u5F15\u7528"]
26
+ };
27
+ }
28
+ const modality = getModality(attachment.mimeType);
29
+ const url = `ms://${fileId}`;
30
+ prepareCtx.log(`Kimi handler prepared ${modality} reference for ${attachment.id}`);
31
+ return {
32
+ items: [
33
+ {
34
+ type: "file-ref",
35
+ mimeType: attachment.mimeType,
36
+ url,
37
+ modality
38
+ }
39
+ ]
40
+ };
41
+ }
42
+ });
43
+ }
44
+ export {
45
+ kimiAttachmentsExtension as default
46
+ };