oh-pi 0.1.65 → 0.1.66
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/dist/utils/detect.js +15 -10
- package/dist/utils/install.js +40 -17
- package/package.json +1 -1
package/dist/utils/detect.js
CHANGED
|
@@ -81,17 +81,22 @@ function detectProviders(agentDir) {
|
|
|
81
81
|
*/
|
|
82
82
|
export async function detectEnv() {
|
|
83
83
|
const agentDir = join(homedir(), ".pi", "agent");
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
84
|
+
// 并行检测 pi 版本和扫描配置
|
|
85
|
+
const [versionResult, existingFiles] = await Promise.all([
|
|
86
|
+
new Promise((resolve) => {
|
|
87
|
+
try {
|
|
88
|
+
const v = execSync("pi --version", { encoding: "utf8", timeout: 3000 }).trim();
|
|
89
|
+
resolve({ installed: true, version: v });
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
resolve({ installed: false, version: null });
|
|
93
|
+
}
|
|
94
|
+
}),
|
|
95
|
+
Promise.resolve(scanDir(agentDir)),
|
|
96
|
+
]);
|
|
92
97
|
return {
|
|
93
|
-
piInstalled,
|
|
94
|
-
piVersion,
|
|
98
|
+
piInstalled: versionResult.installed,
|
|
99
|
+
piVersion: versionResult.version,
|
|
95
100
|
hasExistingConfig: existsSync(join(agentDir, "settings.json")),
|
|
96
101
|
agentDir,
|
|
97
102
|
terminal: process.env.TERM_PROGRAM ?? process.env.TERM ?? "unknown",
|
package/dist/utils/install.js
CHANGED
|
@@ -12,13 +12,40 @@ function ensureDir(dir) {
|
|
|
12
12
|
mkdirSync(dir, { recursive: true });
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
* @param
|
|
15
|
+
* 增量同步目录:只复制有变化的文件,删除源中不存在的文件
|
|
16
|
+
* @param src - 源目录路径
|
|
17
|
+
* @param dest - 目标目录路径
|
|
17
18
|
*/
|
|
18
|
-
function
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
19
|
+
function syncDir(src, dest) {
|
|
20
|
+
ensureDir(dest);
|
|
21
|
+
const srcEntries = new Set();
|
|
22
|
+
for (const entry of readdirSync(src, { withFileTypes: true })) {
|
|
23
|
+
srcEntries.add(entry.name);
|
|
24
|
+
const srcPath = join(src, entry.name);
|
|
25
|
+
const destPath = join(dest, entry.name);
|
|
26
|
+
if (entry.isDirectory()) {
|
|
27
|
+
syncDir(srcPath, destPath);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// 只在文件大小不同时复制
|
|
31
|
+
try {
|
|
32
|
+
if (existsSync(destPath) && statSync(destPath).size === statSync(srcPath).size)
|
|
33
|
+
continue;
|
|
34
|
+
}
|
|
35
|
+
catch { /* copy anyway */ }
|
|
36
|
+
copyFileSync(srcPath, destPath);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// 删除目标中源不存在的文件
|
|
40
|
+
try {
|
|
41
|
+
for (const entry of readdirSync(dest, { withFileTypes: true })) {
|
|
42
|
+
if (!srcEntries.has(entry.name)) {
|
|
43
|
+
const p = join(dest, entry.name);
|
|
44
|
+
rmSync(p, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch { /* skip */ }
|
|
22
49
|
}
|
|
23
50
|
/**
|
|
24
51
|
* 递归复制目录及其所有内容到目标路径
|
|
@@ -149,12 +176,12 @@ export function applyConfig(config) {
|
|
|
149
176
|
catch { /* template not found, skip */ }
|
|
150
177
|
// 6. Copy extensions (single file .ts or directory with index.ts)
|
|
151
178
|
const extDir = join(agentDir, "extensions");
|
|
152
|
-
|
|
179
|
+
ensureDir(extDir);
|
|
153
180
|
for (const ext of config.extensions) {
|
|
154
181
|
const dirSrc = resources.extension(ext);
|
|
155
182
|
const fileSrc = resources.extensionFile(ext);
|
|
156
183
|
if (existsSync(dirSrc) && statSync(dirSrc).isDirectory()) {
|
|
157
|
-
|
|
184
|
+
syncDir(dirSrc, join(extDir, ext));
|
|
158
185
|
}
|
|
159
186
|
else {
|
|
160
187
|
try {
|
|
@@ -165,7 +192,7 @@ export function applyConfig(config) {
|
|
|
165
192
|
}
|
|
166
193
|
// 7. Copy prompts
|
|
167
194
|
const promptDir = join(agentDir, "prompts");
|
|
168
|
-
|
|
195
|
+
ensureDir(promptDir);
|
|
169
196
|
for (const p of config.prompts) {
|
|
170
197
|
const src = resources.prompt(p);
|
|
171
198
|
try {
|
|
@@ -175,19 +202,15 @@ export function applyConfig(config) {
|
|
|
175
202
|
}
|
|
176
203
|
// 8. Copy skills (auto-discover all from pi-package/skills/)
|
|
177
204
|
const skillDir = join(agentDir, "skills");
|
|
178
|
-
cleanDir(skillDir);
|
|
179
205
|
const skillsSrcDir = resources.skillsDir();
|
|
180
206
|
try {
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
copyDir(join(skillsSrcDir, entry.name), join(skillDir, entry.name));
|
|
184
|
-
}
|
|
185
|
-
}
|
|
207
|
+
if (existsSync(skillsSrcDir))
|
|
208
|
+
syncDir(skillsSrcDir, skillDir);
|
|
186
209
|
}
|
|
187
210
|
catch { /* skills dir not found, skip */ }
|
|
188
211
|
// 9. Copy themes (only custom ones)
|
|
189
212
|
const themeDir = join(agentDir, "themes");
|
|
190
|
-
|
|
213
|
+
ensureDir(themeDir);
|
|
191
214
|
const themeSrc = resources.theme(config.theme);
|
|
192
215
|
try {
|
|
193
216
|
copyFileSync(themeSrc, join(themeDir, `${config.theme}.json`));
|
|
@@ -199,7 +222,7 @@ export function applyConfig(config) {
|
|
|
199
222
|
*/
|
|
200
223
|
export function installPi() {
|
|
201
224
|
try {
|
|
202
|
-
execSync("npm install -g @mariozechner/pi-coding-agent", { stdio: "
|
|
225
|
+
execSync("npm install -g @mariozechner/pi-coding-agent", { stdio: "pipe", timeout: 120000 });
|
|
203
226
|
}
|
|
204
227
|
catch {
|
|
205
228
|
throw new Error("Failed to install pi-coding-agent");
|