@dcrays/dcgchat 0.1.9 → 0.1.10
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/package.json +1 -1
- package/src/skill.ts +68 -29
package/package.json
CHANGED
package/src/skill.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import axios from 'axios';
|
|
3
3
|
/** @ts-ignore */
|
|
4
4
|
import unzipper from 'unzipper';
|
|
5
|
+
import { pipeline } from "stream/promises";
|
|
5
6
|
import fs from 'fs';
|
|
6
7
|
import path from 'path';
|
|
7
8
|
import { logDcgchat } from './log.js';
|
|
@@ -53,36 +54,74 @@ export async function installSkill(params: ISkillParams, msgContent: Record<stri
|
|
|
53
54
|
fs.mkdirSync(skillDir, { recursive: true });
|
|
54
55
|
// 解压文件到目标目录,跳过顶层文件夹
|
|
55
56
|
await new Promise((resolve, reject) => {
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
57
|
+
const tasks: Promise<void>[] = [];
|
|
58
|
+
let rootDir: string | null = null;
|
|
59
|
+
let hasError = false;
|
|
60
|
+
|
|
61
|
+
response.data
|
|
62
|
+
.pipe(unzipper.Parse())
|
|
63
|
+
.on("entry", (entry: any) => {
|
|
64
|
+
if (hasError) {
|
|
65
|
+
entry.autodrain();
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
try {
|
|
70
|
+
const entryPath = entry.path;
|
|
71
|
+
const pathParts = entryPath.split("/");
|
|
72
|
+
|
|
73
|
+
// 检测根目录
|
|
74
|
+
if (!rootDir && pathParts.length > 1) {
|
|
75
|
+
rootDir = pathParts[0];
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
let newPath = entryPath;
|
|
79
|
+
|
|
80
|
+
// 移除顶层文件夹
|
|
81
|
+
if (rootDir && entryPath.startsWith(rootDir + "/")) {
|
|
82
|
+
newPath = entryPath.slice(rootDir.length + 1);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (!newPath) {
|
|
86
|
+
entry.autodrain();
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const targetPath = path.join(skillDir, newPath);
|
|
91
|
+
|
|
92
|
+
if (entry.type === "Directory") {
|
|
93
|
+
fs.mkdirSync(targetPath, { recursive: true });
|
|
94
|
+
entry.autodrain();
|
|
95
|
+
} else {
|
|
96
|
+
const parentDir = path.dirname(targetPath);
|
|
97
|
+
fs.mkdirSync(parentDir, { recursive: true });
|
|
98
|
+
const writeStream = fs.createWriteStream(targetPath);
|
|
99
|
+
const task = pipeline(entry, writeStream).catch((err) => {
|
|
100
|
+
hasError = true;
|
|
101
|
+
throw new Error(`解压文件失败 ${entryPath}: ${err.message}`);
|
|
102
|
+
});
|
|
103
|
+
tasks.push(task);
|
|
104
|
+
}
|
|
105
|
+
} catch (err) {
|
|
106
|
+
hasError = true;
|
|
107
|
+
entry.autodrain();
|
|
108
|
+
reject(new Error(`处理entry失败: ${err}`));
|
|
109
|
+
}
|
|
110
|
+
})
|
|
111
|
+
.on("close", async () => {
|
|
112
|
+
try {
|
|
113
|
+
await Promise.all(tasks);
|
|
114
|
+
resolve(null);
|
|
115
|
+
} catch (err) {
|
|
116
|
+
reject(err);
|
|
117
|
+
}
|
|
118
|
+
})
|
|
119
|
+
.on("error", (err) => {
|
|
120
|
+
hasError = true;
|
|
121
|
+
reject(new Error(`解压流错误: ${err.message}`));
|
|
84
122
|
});
|
|
85
|
-
|
|
123
|
+
});
|
|
124
|
+
sendEvent({ ...msgContent, status: 'ok' })
|
|
86
125
|
} catch (error) {
|
|
87
126
|
// 如果安装失败,清理目录
|
|
88
127
|
if (fs.existsSync(skillDir)) {
|