rol-websocket-channel 1.8.8 → 1.8.9
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.
|
@@ -8,6 +8,8 @@ import { JsonRpcException, JSON_RPC_ERRORS } from '../jsonrpc.js';
|
|
|
8
8
|
const execFileAsync = promisify(execFile);
|
|
9
9
|
const REGISTRY_PACKAGE = '@rorolee-expert/registry';
|
|
10
10
|
const OPTIONAL_SKILL_FILES = ['manifest.json', 'prompt.md'];
|
|
11
|
+
const OPTIONAL_SKILL_DIRS = ['scripts'];
|
|
12
|
+
const RESOURCE_SYNC_VERSION = 1;
|
|
11
13
|
export const syncExperts = async (params, context) => {
|
|
12
14
|
const objectParams = isObject(params) ? params : {};
|
|
13
15
|
const filterId = pickString(objectParams.id) ?? pickString(objectParams.expertId);
|
|
@@ -35,6 +37,8 @@ export const syncExperts = async (params, context) => {
|
|
|
35
37
|
if (!force &&
|
|
36
38
|
previous?.version === expert.version &&
|
|
37
39
|
previous.packageName === expert.packageName &&
|
|
40
|
+
previous.resourceSyncVersion === RESOURCE_SYNC_VERSION &&
|
|
41
|
+
await copiedDirsStillExist(targetDir, previous.copiedDirs) &&
|
|
38
42
|
await pathExists(skillPath)) {
|
|
39
43
|
results.push({
|
|
40
44
|
id: expert.id,
|
|
@@ -60,17 +64,31 @@ export const syncExperts = async (params, context) => {
|
|
|
60
64
|
await ensureDir(targetDir);
|
|
61
65
|
await fs.copyFile(sourceSkillPath, skillPath);
|
|
62
66
|
const copiedFiles = ['SKILL.md'];
|
|
67
|
+
const copiedDirs = [];
|
|
63
68
|
for (const fileName of OPTIONAL_SKILL_FILES) {
|
|
64
69
|
const copied = await copyIfExists(path.join(packageDir, fileName), path.join(targetDir, fileName));
|
|
65
70
|
if (copied) {
|
|
66
71
|
copiedFiles.push(fileName);
|
|
67
72
|
}
|
|
68
73
|
}
|
|
74
|
+
for (const dirName of OPTIONAL_SKILL_DIRS) {
|
|
75
|
+
const sourceDir = path.join(packageDir, dirName);
|
|
76
|
+
if (!(await pathExists(sourceDir))) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
const targetResourceDir = path.join(targetDir, dirName);
|
|
80
|
+
await fs.rm(targetResourceDir, { recursive: true, force: true });
|
|
81
|
+
await fs.cp(sourceDir, targetResourceDir, { recursive: true });
|
|
82
|
+
copiedFiles.push(`${dirName}/`);
|
|
83
|
+
copiedDirs.push(dirName);
|
|
84
|
+
}
|
|
69
85
|
installedState[expert.id] = {
|
|
70
86
|
packageName: expert.packageName,
|
|
71
87
|
version: expert.version,
|
|
72
88
|
skillPath,
|
|
73
|
-
installedAt: new Date().toISOString()
|
|
89
|
+
installedAt: new Date().toISOString(),
|
|
90
|
+
resourceSyncVersion: RESOURCE_SYNC_VERSION,
|
|
91
|
+
copiedDirs
|
|
74
92
|
};
|
|
75
93
|
results.push({
|
|
76
94
|
id: expert.id,
|
|
@@ -175,6 +193,12 @@ async function readInstalledState(installedStatePath) {
|
|
|
175
193
|
const version = pickString(value.version);
|
|
176
194
|
const skillPath = pickString(value.skillPath);
|
|
177
195
|
const installedAt = pickString(value.installedAt);
|
|
196
|
+
const resourceSyncVersion = typeof value.resourceSyncVersion === 'number'
|
|
197
|
+
? value.resourceSyncVersion
|
|
198
|
+
: undefined;
|
|
199
|
+
const copiedDirs = Array.isArray(value.copiedDirs)
|
|
200
|
+
? value.copiedDirs.filter((item) => typeof item === 'string')
|
|
201
|
+
: undefined;
|
|
178
202
|
if (!packageName || !version || !skillPath || !installedAt) {
|
|
179
203
|
continue;
|
|
180
204
|
}
|
|
@@ -182,11 +206,24 @@ async function readInstalledState(installedStatePath) {
|
|
|
182
206
|
packageName,
|
|
183
207
|
version,
|
|
184
208
|
skillPath,
|
|
185
|
-
installedAt
|
|
209
|
+
installedAt,
|
|
210
|
+
resourceSyncVersion,
|
|
211
|
+
copiedDirs
|
|
186
212
|
};
|
|
187
213
|
}
|
|
188
214
|
return installed;
|
|
189
215
|
}
|
|
216
|
+
async function copiedDirsStillExist(targetDir, copiedDirs) {
|
|
217
|
+
if (!copiedDirs?.length) {
|
|
218
|
+
return true;
|
|
219
|
+
}
|
|
220
|
+
for (const dirName of copiedDirs) {
|
|
221
|
+
if (!(await pathExists(path.join(targetDir, dirName)))) {
|
|
222
|
+
return false;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return true;
|
|
226
|
+
}
|
|
190
227
|
async function resolveOpenClawDir(context) {
|
|
191
228
|
const candidates = uniqueStrings([
|
|
192
229
|
context.openclawRoot,
|
package/package.json
CHANGED
|
@@ -11,6 +11,8 @@ import type { JsonValue, MethodContext, MethodHandler } from '../types.js';
|
|
|
11
11
|
const execFileAsync = promisify(execFile);
|
|
12
12
|
const REGISTRY_PACKAGE = '@rorolee-expert/registry';
|
|
13
13
|
const OPTIONAL_SKILL_FILES = ['manifest.json', 'prompt.md'] as const;
|
|
14
|
+
const OPTIONAL_SKILL_DIRS = ['scripts'] as const;
|
|
15
|
+
const RESOURCE_SYNC_VERSION = 1;
|
|
14
16
|
|
|
15
17
|
interface ExpertRegistry {
|
|
16
18
|
experts?: unknown;
|
|
@@ -27,6 +29,8 @@ interface InstalledExpert {
|
|
|
27
29
|
version: string;
|
|
28
30
|
skillPath: string;
|
|
29
31
|
installedAt: string;
|
|
32
|
+
resourceSyncVersion?: number;
|
|
33
|
+
copiedDirs?: string[];
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
interface SyncExpertsParams {
|
|
@@ -78,6 +82,8 @@ export const syncExperts: MethodHandler = async (params, context): Promise<JsonV
|
|
|
78
82
|
!force &&
|
|
79
83
|
previous?.version === expert.version &&
|
|
80
84
|
previous.packageName === expert.packageName &&
|
|
85
|
+
previous.resourceSyncVersion === RESOURCE_SYNC_VERSION &&
|
|
86
|
+
await copiedDirsStillExist(targetDir, previous.copiedDirs) &&
|
|
81
87
|
await pathExists(skillPath)
|
|
82
88
|
) {
|
|
83
89
|
results.push({
|
|
@@ -116,6 +122,7 @@ export const syncExperts: MethodHandler = async (params, context): Promise<JsonV
|
|
|
116
122
|
await fs.copyFile(sourceSkillPath, skillPath);
|
|
117
123
|
|
|
118
124
|
const copiedFiles = ['SKILL.md'];
|
|
125
|
+
const copiedDirs: string[] = [];
|
|
119
126
|
for (const fileName of OPTIONAL_SKILL_FILES) {
|
|
120
127
|
const copied = await copyIfExists(
|
|
121
128
|
path.join(packageDir, fileName),
|
|
@@ -126,11 +133,26 @@ export const syncExperts: MethodHandler = async (params, context): Promise<JsonV
|
|
|
126
133
|
}
|
|
127
134
|
}
|
|
128
135
|
|
|
136
|
+
for (const dirName of OPTIONAL_SKILL_DIRS) {
|
|
137
|
+
const sourceDir = path.join(packageDir, dirName);
|
|
138
|
+
if (!(await pathExists(sourceDir))) {
|
|
139
|
+
continue;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const targetResourceDir = path.join(targetDir, dirName);
|
|
143
|
+
await fs.rm(targetResourceDir, { recursive: true, force: true });
|
|
144
|
+
await fs.cp(sourceDir, targetResourceDir, { recursive: true });
|
|
145
|
+
copiedFiles.push(`${dirName}/`);
|
|
146
|
+
copiedDirs.push(dirName);
|
|
147
|
+
}
|
|
148
|
+
|
|
129
149
|
installedState[expert.id] = {
|
|
130
150
|
packageName: expert.packageName,
|
|
131
151
|
version: expert.version,
|
|
132
152
|
skillPath,
|
|
133
|
-
installedAt: new Date().toISOString()
|
|
153
|
+
installedAt: new Date().toISOString(),
|
|
154
|
+
resourceSyncVersion: RESOURCE_SYNC_VERSION,
|
|
155
|
+
copiedDirs
|
|
134
156
|
};
|
|
135
157
|
|
|
136
158
|
results.push({
|
|
@@ -274,6 +296,12 @@ async function readInstalledState(installedStatePath: string): Promise<Installed
|
|
|
274
296
|
const version = pickString(value.version);
|
|
275
297
|
const skillPath = pickString(value.skillPath);
|
|
276
298
|
const installedAt = pickString(value.installedAt);
|
|
299
|
+
const resourceSyncVersion = typeof value.resourceSyncVersion === 'number'
|
|
300
|
+
? value.resourceSyncVersion
|
|
301
|
+
: undefined;
|
|
302
|
+
const copiedDirs = Array.isArray(value.copiedDirs)
|
|
303
|
+
? value.copiedDirs.filter((item): item is string => typeof item === 'string')
|
|
304
|
+
: undefined;
|
|
277
305
|
if (!packageName || !version || !skillPath || !installedAt) {
|
|
278
306
|
continue;
|
|
279
307
|
}
|
|
@@ -282,13 +310,29 @@ async function readInstalledState(installedStatePath: string): Promise<Installed
|
|
|
282
310
|
packageName,
|
|
283
311
|
version,
|
|
284
312
|
skillPath,
|
|
285
|
-
installedAt
|
|
313
|
+
installedAt,
|
|
314
|
+
resourceSyncVersion,
|
|
315
|
+
copiedDirs
|
|
286
316
|
};
|
|
287
317
|
}
|
|
288
318
|
|
|
289
319
|
return installed;
|
|
290
320
|
}
|
|
291
321
|
|
|
322
|
+
async function copiedDirsStillExist(targetDir: string, copiedDirs: string[] | undefined): Promise<boolean> {
|
|
323
|
+
if (!copiedDirs?.length) {
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
for (const dirName of copiedDirs) {
|
|
328
|
+
if (!(await pathExists(path.join(targetDir, dirName)))) {
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
return true;
|
|
334
|
+
}
|
|
335
|
+
|
|
292
336
|
async function resolveOpenClawDir(context: MethodContext): Promise<string> {
|
|
293
337
|
const candidates = uniqueStrings([
|
|
294
338
|
context.openclawRoot,
|