@powerformer/refly-cli 0.1.16 → 0.1.18
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/bin/refly.js +2394 -879
- package/dist/bin/refly.js.map +1 -1
- package/dist/index.d.ts +33 -3
- package/dist/index.js +624 -150
- package/dist/index.js.map +1 -1
- package/package.json +2 -1
- package/skill/SKILL.md +21 -19
- package/skill/references/skill.md +29 -64
- package/skill/registry.json +0 -15
package/dist/index.js
CHANGED
|
@@ -6,6 +6,9 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
|
6
6
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
7
7
|
var __getProtoOf = Object.getPrototypeOf;
|
|
8
8
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
9
|
+
var __esm = (fn, res) => function __init() {
|
|
10
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
11
|
+
};
|
|
9
12
|
var __export = (target, all) => {
|
|
10
13
|
for (var name in all)
|
|
11
14
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -28,6 +31,516 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
28
31
|
));
|
|
29
32
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
30
33
|
|
|
34
|
+
// ../../node_modules/.pnpm/tsup@8.5.1_@swc+core@1.12.14_@swc+helpers@0.5.17__jiti@2.6.1_postcss@8.5.6_tsx@4.20.6_typescript@5.8.3_yaml@2.8.0/node_modules/tsup/assets/cjs_shims.js
|
|
35
|
+
var init_cjs_shims = __esm({
|
|
36
|
+
"../../node_modules/.pnpm/tsup@8.5.1_@swc+core@1.12.14_@swc+helpers@0.5.17__jiti@2.6.1_postcss@8.5.6_tsx@4.20.6_typescript@5.8.3_yaml@2.8.0/node_modules/tsup/assets/cjs_shims.js"() {
|
|
37
|
+
"use strict";
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
// src/config/paths.ts
|
|
42
|
+
function getReflyDir() {
|
|
43
|
+
const dir = path.join(os.homedir(), ".refly");
|
|
44
|
+
ensureDir(dir);
|
|
45
|
+
return dir;
|
|
46
|
+
}
|
|
47
|
+
function getClaudeCommandsDir() {
|
|
48
|
+
return path.join(os.homedir(), ".claude", "commands");
|
|
49
|
+
}
|
|
50
|
+
function ensureDir(dir) {
|
|
51
|
+
if (!fs.existsSync(dir)) {
|
|
52
|
+
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function getConfigPath() {
|
|
56
|
+
return path.join(getReflyDir(), "config.json");
|
|
57
|
+
}
|
|
58
|
+
function getReflySkillsDir() {
|
|
59
|
+
return path.join(getReflyDir(), "skills");
|
|
60
|
+
}
|
|
61
|
+
function getReflyBaseSkillDir() {
|
|
62
|
+
return path.join(getReflySkillsDir(), "base");
|
|
63
|
+
}
|
|
64
|
+
function getReflyDomainSkillDir(skillName) {
|
|
65
|
+
return path.join(getReflySkillsDir(), skillName);
|
|
66
|
+
}
|
|
67
|
+
function getClaudeSkillsDir() {
|
|
68
|
+
return path.join(os.homedir(), ".claude", "skills");
|
|
69
|
+
}
|
|
70
|
+
function getClaudeSkillSymlinkPath(skillName) {
|
|
71
|
+
return path.join(getClaudeSkillsDir(), skillName);
|
|
72
|
+
}
|
|
73
|
+
function ensureReflySkillsDir() {
|
|
74
|
+
const dir = getReflySkillsDir();
|
|
75
|
+
if (!fs.existsSync(dir)) {
|
|
76
|
+
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
function ensureClaudeSkillsDir() {
|
|
80
|
+
const dir = getClaudeSkillsDir();
|
|
81
|
+
if (!fs.existsSync(dir)) {
|
|
82
|
+
fs.mkdirSync(dir, { recursive: true, mode: 493 });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
var os, path, fs;
|
|
86
|
+
var init_paths = __esm({
|
|
87
|
+
"src/config/paths.ts"() {
|
|
88
|
+
"use strict";
|
|
89
|
+
init_cjs_shims();
|
|
90
|
+
os = __toESM(require("os"));
|
|
91
|
+
path = __toESM(require("path"));
|
|
92
|
+
fs = __toESM(require("fs"));
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
// src/utils/logger.ts
|
|
97
|
+
function redact(message) {
|
|
98
|
+
let result = message;
|
|
99
|
+
for (const pattern of SENSITIVE_PATTERNS) {
|
|
100
|
+
result = result.replace(pattern, "[REDACTED]");
|
|
101
|
+
}
|
|
102
|
+
return result;
|
|
103
|
+
}
|
|
104
|
+
var fs3, path3, LOG_FILE, MAX_LOG_SIZE, LOG_LEVELS, SENSITIVE_PATTERNS, Logger, logger;
|
|
105
|
+
var init_logger = __esm({
|
|
106
|
+
"src/utils/logger.ts"() {
|
|
107
|
+
"use strict";
|
|
108
|
+
init_cjs_shims();
|
|
109
|
+
fs3 = __toESM(require("fs"));
|
|
110
|
+
path3 = __toESM(require("path"));
|
|
111
|
+
init_paths();
|
|
112
|
+
LOG_FILE = "cli.log";
|
|
113
|
+
MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
114
|
+
LOG_LEVELS = {
|
|
115
|
+
debug: 0,
|
|
116
|
+
info: 1,
|
|
117
|
+
warn: 2,
|
|
118
|
+
error: 3
|
|
119
|
+
};
|
|
120
|
+
SENSITIVE_PATTERNS = [
|
|
121
|
+
/Bearer\s+[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+/gi,
|
|
122
|
+
/[A-Za-z0-9]{32,}/g,
|
|
123
|
+
// API keys
|
|
124
|
+
/"(access_?token|refresh_?token|api_?key|secret|password)":\s*"[^"]+"/gi
|
|
125
|
+
];
|
|
126
|
+
Logger = class {
|
|
127
|
+
level = "info";
|
|
128
|
+
logToFile = false;
|
|
129
|
+
setLevel(level) {
|
|
130
|
+
this.level = level;
|
|
131
|
+
}
|
|
132
|
+
enableFileLogging() {
|
|
133
|
+
this.logToFile = true;
|
|
134
|
+
}
|
|
135
|
+
shouldLog(level) {
|
|
136
|
+
return LOG_LEVELS[level] >= LOG_LEVELS[this.level];
|
|
137
|
+
}
|
|
138
|
+
formatMessage(level, message) {
|
|
139
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
140
|
+
const safeMessage = redact(message);
|
|
141
|
+
return `[${timestamp}] [${level.toUpperCase()}] ${safeMessage}`;
|
|
142
|
+
}
|
|
143
|
+
writeToFile(formatted) {
|
|
144
|
+
if (!this.logToFile) return;
|
|
145
|
+
try {
|
|
146
|
+
const logPath = path3.join(getReflyDir(), LOG_FILE);
|
|
147
|
+
try {
|
|
148
|
+
const stats = fs3.statSync(logPath);
|
|
149
|
+
if (stats.size > MAX_LOG_SIZE) {
|
|
150
|
+
fs3.renameSync(logPath, `${logPath}.old`);
|
|
151
|
+
}
|
|
152
|
+
} catch {
|
|
153
|
+
}
|
|
154
|
+
fs3.appendFileSync(logPath, `${formatted}
|
|
155
|
+
`);
|
|
156
|
+
} catch {
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
debug(message, ...args) {
|
|
160
|
+
if (!this.shouldLog("debug")) return;
|
|
161
|
+
const formatted = this.formatMessage("debug", this.interpolate(message, args));
|
|
162
|
+
this.writeToFile(formatted);
|
|
163
|
+
}
|
|
164
|
+
info(message, ...args) {
|
|
165
|
+
if (!this.shouldLog("info")) return;
|
|
166
|
+
const formatted = this.formatMessage("info", this.interpolate(message, args));
|
|
167
|
+
this.writeToFile(formatted);
|
|
168
|
+
}
|
|
169
|
+
warn(message, ...args) {
|
|
170
|
+
if (!this.shouldLog("warn")) return;
|
|
171
|
+
const formatted = this.formatMessage("warn", this.interpolate(message, args));
|
|
172
|
+
this.writeToFile(formatted);
|
|
173
|
+
}
|
|
174
|
+
error(message, ...args) {
|
|
175
|
+
if (!this.shouldLog("error")) return;
|
|
176
|
+
const formatted = this.formatMessage("error", this.interpolate(message, args));
|
|
177
|
+
this.writeToFile(formatted);
|
|
178
|
+
}
|
|
179
|
+
interpolate(message, args) {
|
|
180
|
+
if (args.length === 0) return message;
|
|
181
|
+
return `${message} ${args.map((a) => JSON.stringify(a)).join(" ")}`;
|
|
182
|
+
}
|
|
183
|
+
};
|
|
184
|
+
logger = new Logger();
|
|
185
|
+
}
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
// src/skill/symlink.ts
|
|
189
|
+
var symlink_exports = {};
|
|
190
|
+
__export(symlink_exports, {
|
|
191
|
+
createReflySkillWithSymlink: () => createReflySkillWithSymlink,
|
|
192
|
+
createSkillSymlink: () => createSkillSymlink,
|
|
193
|
+
deleteDomainSkillWithSymlink: () => deleteDomainSkillWithSymlink,
|
|
194
|
+
generateReflySkillMd: () => generateReflySkillMd,
|
|
195
|
+
initializeBaseSkillSymlink: () => initializeBaseSkillSymlink,
|
|
196
|
+
isSkillSymlinkValid: () => isSkillSymlinkValid,
|
|
197
|
+
listSkillSymlinks: () => listSkillSymlinks,
|
|
198
|
+
parseReflySkillMd: () => parseReflySkillMd,
|
|
199
|
+
removeSkillSymlink: () => removeSkillSymlink
|
|
200
|
+
});
|
|
201
|
+
function createSkillSymlink(skillName) {
|
|
202
|
+
const reflyPath = skillName === "refly" ? getReflyBaseSkillDir() : getReflyDomainSkillDir(skillName);
|
|
203
|
+
const claudePath = getClaudeSkillSymlinkPath(skillName);
|
|
204
|
+
try {
|
|
205
|
+
ensureReflySkillsDir();
|
|
206
|
+
ensureClaudeSkillsDir();
|
|
207
|
+
if (!fs5.existsSync(reflyPath)) {
|
|
208
|
+
return {
|
|
209
|
+
success: false,
|
|
210
|
+
skillName,
|
|
211
|
+
reflyPath,
|
|
212
|
+
claudePath,
|
|
213
|
+
error: `Source skill directory does not exist: ${reflyPath}`
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
if (fs5.existsSync(claudePath) || fs5.lstatSync(claudePath).isSymbolicLink()) {
|
|
217
|
+
const stat = fs5.lstatSync(claudePath);
|
|
218
|
+
if (stat.isSymbolicLink()) {
|
|
219
|
+
fs5.unlinkSync(claudePath);
|
|
220
|
+
logger.debug(`Removed existing symlink: ${claudePath}`);
|
|
221
|
+
} else if (stat.isDirectory()) {
|
|
222
|
+
logger.warn(`Cannot create symlink: ${claudePath} is a directory, not a symlink`);
|
|
223
|
+
return {
|
|
224
|
+
success: false,
|
|
225
|
+
skillName,
|
|
226
|
+
reflyPath,
|
|
227
|
+
claudePath,
|
|
228
|
+
error: `Target path is a directory, not a symlink: ${claudePath}`
|
|
229
|
+
};
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
fs5.symlinkSync(reflyPath, claudePath, "dir");
|
|
233
|
+
logger.info(`Created symlink: ${claudePath} -> ${reflyPath}`);
|
|
234
|
+
return {
|
|
235
|
+
success: true,
|
|
236
|
+
skillName,
|
|
237
|
+
reflyPath,
|
|
238
|
+
claudePath
|
|
239
|
+
};
|
|
240
|
+
} catch (err) {
|
|
241
|
+
if (err.code === "ENOENT") {
|
|
242
|
+
try {
|
|
243
|
+
fs5.symlinkSync(reflyPath, claudePath, "dir");
|
|
244
|
+
logger.info(`Created symlink: ${claudePath} -> ${reflyPath}`);
|
|
245
|
+
return {
|
|
246
|
+
success: true,
|
|
247
|
+
skillName,
|
|
248
|
+
reflyPath,
|
|
249
|
+
claudePath
|
|
250
|
+
};
|
|
251
|
+
} catch (innerErr) {
|
|
252
|
+
return {
|
|
253
|
+
success: false,
|
|
254
|
+
skillName,
|
|
255
|
+
reflyPath,
|
|
256
|
+
claudePath,
|
|
257
|
+
error: innerErr.message
|
|
258
|
+
};
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
return {
|
|
262
|
+
success: false,
|
|
263
|
+
skillName,
|
|
264
|
+
reflyPath,
|
|
265
|
+
claudePath,
|
|
266
|
+
error: err.message
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
function removeSkillSymlink(skillName) {
|
|
271
|
+
const claudePath = getClaudeSkillSymlinkPath(skillName);
|
|
272
|
+
try {
|
|
273
|
+
if (!fs5.existsSync(claudePath)) {
|
|
274
|
+
logger.debug(`Symlink not found: ${claudePath}`);
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
const stat = fs5.lstatSync(claudePath);
|
|
278
|
+
if (!stat.isSymbolicLink()) {
|
|
279
|
+
logger.warn(`Not a symlink: ${claudePath}`);
|
|
280
|
+
return false;
|
|
281
|
+
}
|
|
282
|
+
fs5.unlinkSync(claudePath);
|
|
283
|
+
logger.info(`Removed symlink: ${claudePath}`);
|
|
284
|
+
return true;
|
|
285
|
+
} catch (err) {
|
|
286
|
+
logger.error(`Failed to remove symlink ${claudePath}:`, err);
|
|
287
|
+
return false;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function isSkillSymlinkValid(skillName) {
|
|
291
|
+
const claudePath = getClaudeSkillSymlinkPath(skillName);
|
|
292
|
+
const expectedTarget = skillName === "refly" ? getReflyBaseSkillDir() : getReflyDomainSkillDir(skillName);
|
|
293
|
+
try {
|
|
294
|
+
if (!fs5.existsSync(claudePath)) {
|
|
295
|
+
return { exists: false, isSymlink: false, isValid: false };
|
|
296
|
+
}
|
|
297
|
+
const stat = fs5.lstatSync(claudePath);
|
|
298
|
+
if (!stat.isSymbolicLink()) {
|
|
299
|
+
return { exists: true, isSymlink: false, isValid: false };
|
|
300
|
+
}
|
|
301
|
+
const target = fs5.readlinkSync(claudePath);
|
|
302
|
+
const resolvedTarget = path5.resolve(path5.dirname(claudePath), target);
|
|
303
|
+
const isValid2 = resolvedTarget === expectedTarget && fs5.existsSync(resolvedTarget);
|
|
304
|
+
return {
|
|
305
|
+
exists: true,
|
|
306
|
+
isSymlink: true,
|
|
307
|
+
isValid: isValid2,
|
|
308
|
+
target: resolvedTarget
|
|
309
|
+
};
|
|
310
|
+
} catch {
|
|
311
|
+
return { exists: false, isSymlink: false, isValid: false };
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
function initializeBaseSkillSymlink() {
|
|
315
|
+
const baseDir = getReflyBaseSkillDir();
|
|
316
|
+
ensureDir(baseDir);
|
|
317
|
+
ensureDir(path5.join(baseDir, "rules"));
|
|
318
|
+
return createSkillSymlink("refly");
|
|
319
|
+
}
|
|
320
|
+
function createReflySkillWithSymlink(skillName, skillMdContent, options) {
|
|
321
|
+
const skillDir = getReflyDomainSkillDir(skillName);
|
|
322
|
+
try {
|
|
323
|
+
ensureReflySkillsDir();
|
|
324
|
+
if (fs5.existsSync(skillDir)) {
|
|
325
|
+
if (options?.force) {
|
|
326
|
+
const skillMdPath2 = path5.join(skillDir, "SKILL.md");
|
|
327
|
+
fs5.writeFileSync(skillMdPath2, skillMdContent, { encoding: "utf-8", mode: 420 });
|
|
328
|
+
logger.debug(`Updated SKILL.md (force): ${skillMdPath2}`);
|
|
329
|
+
return createSkillSymlink(skillName);
|
|
330
|
+
}
|
|
331
|
+
return {
|
|
332
|
+
success: false,
|
|
333
|
+
skillName,
|
|
334
|
+
reflyPath: skillDir,
|
|
335
|
+
claudePath: getClaudeSkillSymlinkPath(skillName),
|
|
336
|
+
error: `Skill directory already exists: ${skillDir}`
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
fs5.mkdirSync(skillDir, { recursive: true, mode: 493 });
|
|
340
|
+
const skillMdPath = path5.join(skillDir, "SKILL.md");
|
|
341
|
+
fs5.writeFileSync(skillMdPath, skillMdContent, { encoding: "utf-8", mode: 420 });
|
|
342
|
+
logger.debug(`Created SKILL.md: ${skillMdPath}`);
|
|
343
|
+
return createSkillSymlink(skillName);
|
|
344
|
+
} catch (err) {
|
|
345
|
+
return {
|
|
346
|
+
success: false,
|
|
347
|
+
skillName,
|
|
348
|
+
reflyPath: skillDir,
|
|
349
|
+
claudePath: getClaudeSkillSymlinkPath(skillName),
|
|
350
|
+
error: err.message
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
function deleteDomainSkillWithSymlink(skillName) {
|
|
355
|
+
const symlinkRemoved = removeSkillSymlink(skillName);
|
|
356
|
+
const skillDir = getReflyDomainSkillDir(skillName);
|
|
357
|
+
let directoryRemoved = false;
|
|
358
|
+
try {
|
|
359
|
+
if (fs5.existsSync(skillDir)) {
|
|
360
|
+
fs5.rmSync(skillDir, { recursive: true, force: true });
|
|
361
|
+
directoryRemoved = true;
|
|
362
|
+
logger.info(`Removed skill directory: ${skillDir}`);
|
|
363
|
+
}
|
|
364
|
+
} catch (err) {
|
|
365
|
+
logger.error(`Failed to remove skill directory ${skillDir}:`, err);
|
|
366
|
+
}
|
|
367
|
+
return { symlinkRemoved, directoryRemoved };
|
|
368
|
+
}
|
|
369
|
+
function listSkillSymlinks() {
|
|
370
|
+
const claudeSkillsDir = getClaudeSkillsDir();
|
|
371
|
+
const results = [];
|
|
372
|
+
if (!fs5.existsSync(claudeSkillsDir)) {
|
|
373
|
+
return results;
|
|
374
|
+
}
|
|
375
|
+
try {
|
|
376
|
+
const entries = fs5.readdirSync(claudeSkillsDir, { withFileTypes: true });
|
|
377
|
+
for (const entry of entries) {
|
|
378
|
+
const fullPath = path5.join(claudeSkillsDir, entry.name);
|
|
379
|
+
try {
|
|
380
|
+
const stat = fs5.lstatSync(fullPath);
|
|
381
|
+
if (stat.isSymbolicLink()) {
|
|
382
|
+
const target = fs5.readlinkSync(fullPath);
|
|
383
|
+
const resolvedTarget = path5.resolve(path5.dirname(fullPath), target);
|
|
384
|
+
const isValid2 = fs5.existsSync(resolvedTarget);
|
|
385
|
+
results.push({
|
|
386
|
+
name: entry.name,
|
|
387
|
+
claudePath: fullPath,
|
|
388
|
+
target: resolvedTarget,
|
|
389
|
+
isValid: isValid2
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
} catch {
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
} catch {
|
|
396
|
+
}
|
|
397
|
+
return results;
|
|
398
|
+
}
|
|
399
|
+
function generateReflySkillMd(options) {
|
|
400
|
+
const {
|
|
401
|
+
name,
|
|
402
|
+
displayName,
|
|
403
|
+
description,
|
|
404
|
+
skillId,
|
|
405
|
+
workflowId,
|
|
406
|
+
installationId,
|
|
407
|
+
triggers = [],
|
|
408
|
+
tags = [],
|
|
409
|
+
version = "1.0.0",
|
|
410
|
+
inputSchema,
|
|
411
|
+
outputSchema
|
|
412
|
+
} = options;
|
|
413
|
+
const frontmatterLines = ["---", `name: ${name}`];
|
|
414
|
+
frontmatterLines.push(`description: ${description}`);
|
|
415
|
+
if (tags.length > 0) {
|
|
416
|
+
frontmatterLines.push("tags:");
|
|
417
|
+
frontmatterLines.push(...tags.map((t) => ` - ${t}`));
|
|
418
|
+
}
|
|
419
|
+
frontmatterLines.push(`version: ${version}`);
|
|
420
|
+
frontmatterLines.push(`skillId: ${skillId}`);
|
|
421
|
+
frontmatterLines.push(`workflowId: ${workflowId}`);
|
|
422
|
+
if (installationId) {
|
|
423
|
+
frontmatterLines.push(`installationId: ${installationId}`);
|
|
424
|
+
}
|
|
425
|
+
if (triggers.length > 0) {
|
|
426
|
+
frontmatterLines.push("triggers:");
|
|
427
|
+
frontmatterLines.push(...triggers.map((t) => ` - ${t}`));
|
|
428
|
+
}
|
|
429
|
+
frontmatterLines.push("---");
|
|
430
|
+
const title = displayName || name.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
431
|
+
const inputExample = inputSchema ? JSON.stringify(inputSchema, null, 2) : `{
|
|
432
|
+
"query": "your input here"
|
|
433
|
+
}`;
|
|
434
|
+
const runCommand = installationId ? `refly skill run ${installationId} --input '${inputSchema ? JSON.stringify(inputSchema) : "{}"}'` : `refly workflow run ${workflowId} --input '${inputSchema ? JSON.stringify(inputSchema) : "{}"}'`;
|
|
435
|
+
const outputSection = outputSchema ? `The skill returns:
|
|
436
|
+
|
|
437
|
+
\`\`\`json
|
|
438
|
+
${JSON.stringify(outputSchema, null, 2)}
|
|
439
|
+
\`\`\`` : "The skill returns the workflow execution result.";
|
|
440
|
+
const content = `
|
|
441
|
+
|
|
442
|
+
# ${title}
|
|
443
|
+
|
|
444
|
+
${description}
|
|
445
|
+
|
|
446
|
+
## Usage
|
|
447
|
+
|
|
448
|
+
This skill is executed via Refly CLI:
|
|
449
|
+
|
|
450
|
+
\`\`\`bash
|
|
451
|
+
${runCommand}
|
|
452
|
+
\`\`\`
|
|
453
|
+
|
|
454
|
+
## Input
|
|
455
|
+
|
|
456
|
+
Provide input as JSON:
|
|
457
|
+
|
|
458
|
+
\`\`\`json
|
|
459
|
+
${inputExample}
|
|
460
|
+
\`\`\`
|
|
461
|
+
|
|
462
|
+
## Output
|
|
463
|
+
|
|
464
|
+
${outputSection}
|
|
465
|
+
|
|
466
|
+
## Rules
|
|
467
|
+
|
|
468
|
+
For workflow operations, refer to the base skill rules:
|
|
469
|
+
- Workflow: \`~/.claude/skills/refly/rules/workflow.md\`
|
|
470
|
+
- Node: \`~/.claude/skills/refly/rules/node.md\`
|
|
471
|
+
- File: \`~/.claude/skills/refly/rules/file.md\`
|
|
472
|
+
`;
|
|
473
|
+
return frontmatterLines.join("\n") + content;
|
|
474
|
+
}
|
|
475
|
+
function parseReflySkillMd(content) {
|
|
476
|
+
const frontmatterRegex = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/;
|
|
477
|
+
const match = content.match(frontmatterRegex);
|
|
478
|
+
if (!match) {
|
|
479
|
+
throw new Error("Invalid SKILL.md format: missing frontmatter");
|
|
480
|
+
}
|
|
481
|
+
const [, frontmatterStr, body] = match;
|
|
482
|
+
const meta = {};
|
|
483
|
+
const lines = frontmatterStr.split("\n");
|
|
484
|
+
let currentKey = null;
|
|
485
|
+
let currentArray = [];
|
|
486
|
+
for (const line of lines) {
|
|
487
|
+
const trimmed = line.trim();
|
|
488
|
+
if (trimmed.startsWith("- ")) {
|
|
489
|
+
if (currentKey) {
|
|
490
|
+
currentArray.push(trimmed.slice(2).trim());
|
|
491
|
+
}
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
if (currentKey && currentArray.length > 0) {
|
|
495
|
+
meta[currentKey] = currentArray;
|
|
496
|
+
currentArray = [];
|
|
497
|
+
currentKey = null;
|
|
498
|
+
}
|
|
499
|
+
const colonIndex = trimmed.indexOf(":");
|
|
500
|
+
if (colonIndex > 0) {
|
|
501
|
+
const key = trimmed.slice(0, colonIndex).trim();
|
|
502
|
+
const value = trimmed.slice(colonIndex + 1).trim();
|
|
503
|
+
if (value === "") {
|
|
504
|
+
currentKey = key;
|
|
505
|
+
currentArray = [];
|
|
506
|
+
} else {
|
|
507
|
+
meta[key] = value;
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
if (currentKey && currentArray.length > 0) {
|
|
512
|
+
meta[currentKey] = currentArray;
|
|
513
|
+
}
|
|
514
|
+
if (!meta.name) {
|
|
515
|
+
throw new Error('Invalid SKILL.md: missing required field "name"');
|
|
516
|
+
}
|
|
517
|
+
if (!meta.description) {
|
|
518
|
+
throw new Error('Invalid SKILL.md: missing required field "description"');
|
|
519
|
+
}
|
|
520
|
+
if (!meta.skillId) {
|
|
521
|
+
throw new Error('Invalid SKILL.md: missing required field "skillId"');
|
|
522
|
+
}
|
|
523
|
+
if (!meta.workflowId) {
|
|
524
|
+
throw new Error('Invalid SKILL.md: missing required field "workflowId"');
|
|
525
|
+
}
|
|
526
|
+
return {
|
|
527
|
+
meta,
|
|
528
|
+
body: body.trim(),
|
|
529
|
+
raw: content
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
var fs5, path5;
|
|
533
|
+
var init_symlink = __esm({
|
|
534
|
+
"src/skill/symlink.ts"() {
|
|
535
|
+
"use strict";
|
|
536
|
+
init_cjs_shims();
|
|
537
|
+
fs5 = __toESM(require("fs"));
|
|
538
|
+
path5 = __toESM(require("path"));
|
|
539
|
+
init_paths();
|
|
540
|
+
init_logger();
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
|
|
31
544
|
// src/index.ts
|
|
32
545
|
var src_exports = {};
|
|
33
546
|
__export(src_exports, {
|
|
@@ -45,8 +558,16 @@ __export(src_exports, {
|
|
|
45
558
|
verifyConnection: () => verifyConnection
|
|
46
559
|
});
|
|
47
560
|
module.exports = __toCommonJS(src_exports);
|
|
561
|
+
init_cjs_shims();
|
|
562
|
+
|
|
563
|
+
// src/utils/output.ts
|
|
564
|
+
init_cjs_shims();
|
|
565
|
+
|
|
566
|
+
// src/utils/formatter.ts
|
|
567
|
+
init_cjs_shims();
|
|
48
568
|
|
|
49
569
|
// src/utils/ui.ts
|
|
570
|
+
init_cjs_shims();
|
|
50
571
|
var Style = {
|
|
51
572
|
// Reset
|
|
52
573
|
RESET: "\x1B[0m",
|
|
@@ -142,16 +663,20 @@ var ErrorCodes = {
|
|
|
142
663
|
CONFLICT: "CONFLICT",
|
|
143
664
|
PERMISSION_DENIED: "PERMISSION_DENIED",
|
|
144
665
|
INVALID_INPUT: "INVALID_INPUT",
|
|
145
|
-
INTERNAL_ERROR: "INTERNAL_ERROR"
|
|
666
|
+
INTERNAL_ERROR: "INTERNAL_ERROR",
|
|
667
|
+
// Variables
|
|
668
|
+
MISSING_VARIABLES: "MISSING_VARIABLES"
|
|
146
669
|
};
|
|
147
670
|
|
|
148
671
|
// src/utils/errors.ts
|
|
672
|
+
init_cjs_shims();
|
|
149
673
|
var CLIError = class extends Error {
|
|
150
|
-
constructor(code, message, details, hint) {
|
|
674
|
+
constructor(code, message, details, hint, suggestedFix) {
|
|
151
675
|
super(message);
|
|
152
676
|
this.code = code;
|
|
153
677
|
this.details = details;
|
|
154
678
|
this.hint = hint;
|
|
679
|
+
this.suggestedFix = suggestedFix;
|
|
155
680
|
this.name = "CLIError";
|
|
156
681
|
}
|
|
157
682
|
};
|
|
@@ -172,11 +697,15 @@ var NetworkError = class extends CLIError {
|
|
|
172
697
|
};
|
|
173
698
|
|
|
174
699
|
// src/config/config.ts
|
|
700
|
+
init_cjs_shims();
|
|
175
701
|
var fs2 = __toESM(require("fs"));
|
|
176
702
|
var path2 = __toESM(require("path"));
|
|
177
703
|
var os2 = __toESM(require("os"));
|
|
178
704
|
var crypto = __toESM(require("crypto"));
|
|
179
705
|
|
|
706
|
+
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/index.js
|
|
707
|
+
init_cjs_shims();
|
|
708
|
+
|
|
180
709
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/external.js
|
|
181
710
|
var external_exports = {};
|
|
182
711
|
__export(external_exports, {
|
|
@@ -288,8 +817,19 @@ __export(external_exports, {
|
|
|
288
817
|
util: () => util,
|
|
289
818
|
void: () => voidType
|
|
290
819
|
});
|
|
820
|
+
init_cjs_shims();
|
|
821
|
+
|
|
822
|
+
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/errors.js
|
|
823
|
+
init_cjs_shims();
|
|
824
|
+
|
|
825
|
+
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/locales/en.js
|
|
826
|
+
init_cjs_shims();
|
|
827
|
+
|
|
828
|
+
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/ZodError.js
|
|
829
|
+
init_cjs_shims();
|
|
291
830
|
|
|
292
831
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/util.js
|
|
832
|
+
init_cjs_shims();
|
|
293
833
|
var util;
|
|
294
834
|
(function(util2) {
|
|
295
835
|
util2.assertEqual = (_) => {
|
|
@@ -654,9 +1194,10 @@ function getErrorMap() {
|
|
|
654
1194
|
}
|
|
655
1195
|
|
|
656
1196
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
1197
|
+
init_cjs_shims();
|
|
657
1198
|
var makeIssue = (params) => {
|
|
658
|
-
const { data, path:
|
|
659
|
-
const fullPath = [...
|
|
1199
|
+
const { data, path: path7, errorMaps, issueData } = params;
|
|
1200
|
+
const fullPath = [...path7, ...issueData.path || []];
|
|
660
1201
|
const fullIssue = {
|
|
661
1202
|
...issueData,
|
|
662
1203
|
path: fullPath
|
|
@@ -763,7 +1304,11 @@ var isDirty = (x) => x.status === "dirty";
|
|
|
763
1304
|
var isValid = (x) => x.status === "valid";
|
|
764
1305
|
var isAsync = (x) => typeof Promise !== "undefined" && x instanceof Promise;
|
|
765
1306
|
|
|
1307
|
+
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
1308
|
+
init_cjs_shims();
|
|
1309
|
+
|
|
766
1310
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/errorUtil.js
|
|
1311
|
+
init_cjs_shims();
|
|
767
1312
|
var errorUtil;
|
|
768
1313
|
(function(errorUtil2) {
|
|
769
1314
|
errorUtil2.errToObj = (message) => typeof message === "string" ? { message } : message || {};
|
|
@@ -772,11 +1317,11 @@ var errorUtil;
|
|
|
772
1317
|
|
|
773
1318
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
774
1319
|
var ParseInputLazyPath = class {
|
|
775
|
-
constructor(parent, value,
|
|
1320
|
+
constructor(parent, value, path7, key) {
|
|
776
1321
|
this._cachedPath = [];
|
|
777
1322
|
this.parent = parent;
|
|
778
1323
|
this.data = value;
|
|
779
|
-
this._path =
|
|
1324
|
+
this._path = path7;
|
|
780
1325
|
this._key = key;
|
|
781
1326
|
}
|
|
782
1327
|
get path() {
|
|
@@ -4218,31 +4763,8 @@ var coerce = {
|
|
|
4218
4763
|
};
|
|
4219
4764
|
var NEVER = INVALID;
|
|
4220
4765
|
|
|
4221
|
-
// src/config/paths.ts
|
|
4222
|
-
var os = __toESM(require("os"));
|
|
4223
|
-
var path = __toESM(require("path"));
|
|
4224
|
-
var fs = __toESM(require("fs"));
|
|
4225
|
-
function getReflyDir() {
|
|
4226
|
-
const dir = path.join(os.homedir(), ".refly");
|
|
4227
|
-
ensureDir(dir);
|
|
4228
|
-
return dir;
|
|
4229
|
-
}
|
|
4230
|
-
function getClaudeSkillDir() {
|
|
4231
|
-
return path.join(os.homedir(), ".claude", "skills", "refly");
|
|
4232
|
-
}
|
|
4233
|
-
function getClaudeCommandsDir() {
|
|
4234
|
-
return path.join(os.homedir(), ".claude", "commands");
|
|
4235
|
-
}
|
|
4236
|
-
function ensureDir(dir) {
|
|
4237
|
-
if (!fs.existsSync(dir)) {
|
|
4238
|
-
fs.mkdirSync(dir, { recursive: true, mode: 448 });
|
|
4239
|
-
}
|
|
4240
|
-
}
|
|
4241
|
-
function getConfigPath() {
|
|
4242
|
-
return path.join(getReflyDir(), "config.json");
|
|
4243
|
-
}
|
|
4244
|
-
|
|
4245
4766
|
// src/config/config.ts
|
|
4767
|
+
init_paths();
|
|
4246
4768
|
var ConfigSchema = external_exports.object({
|
|
4247
4769
|
version: external_exports.number().default(1),
|
|
4248
4770
|
auth: external_exports.object({
|
|
@@ -4370,101 +4892,17 @@ function getApiKey() {
|
|
|
4370
4892
|
}
|
|
4371
4893
|
|
|
4372
4894
|
// src/api/client.ts
|
|
4895
|
+
init_cjs_shims();
|
|
4373
4896
|
var fs4 = __toESM(require("fs"));
|
|
4374
4897
|
var import_node_fs = require("fs");
|
|
4375
4898
|
var path4 = __toESM(require("path"));
|
|
4376
4899
|
var import_mime = __toESM(require("mime"));
|
|
4377
|
-
|
|
4378
|
-
// src/utils/logger.ts
|
|
4379
|
-
var fs3 = __toESM(require("fs"));
|
|
4380
|
-
var path3 = __toESM(require("path"));
|
|
4381
|
-
var LOG_FILE = "cli.log";
|
|
4382
|
-
var MAX_LOG_SIZE = 5 * 1024 * 1024;
|
|
4383
|
-
var LOG_LEVELS = {
|
|
4384
|
-
debug: 0,
|
|
4385
|
-
info: 1,
|
|
4386
|
-
warn: 2,
|
|
4387
|
-
error: 3
|
|
4388
|
-
};
|
|
4389
|
-
var SENSITIVE_PATTERNS = [
|
|
4390
|
-
/Bearer\s+[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+\.[A-Za-z0-9\-_]+/gi,
|
|
4391
|
-
/[A-Za-z0-9]{32,}/g,
|
|
4392
|
-
// API keys
|
|
4393
|
-
/"(access_?token|refresh_?token|api_?key|secret|password)":\s*"[^"]+"/gi
|
|
4394
|
-
];
|
|
4395
|
-
function redact(message) {
|
|
4396
|
-
let result = message;
|
|
4397
|
-
for (const pattern of SENSITIVE_PATTERNS) {
|
|
4398
|
-
result = result.replace(pattern, "[REDACTED]");
|
|
4399
|
-
}
|
|
4400
|
-
return result;
|
|
4401
|
-
}
|
|
4402
|
-
var Logger = class {
|
|
4403
|
-
level = "info";
|
|
4404
|
-
logToFile = false;
|
|
4405
|
-
setLevel(level) {
|
|
4406
|
-
this.level = level;
|
|
4407
|
-
}
|
|
4408
|
-
enableFileLogging() {
|
|
4409
|
-
this.logToFile = true;
|
|
4410
|
-
}
|
|
4411
|
-
shouldLog(level) {
|
|
4412
|
-
return LOG_LEVELS[level] >= LOG_LEVELS[this.level];
|
|
4413
|
-
}
|
|
4414
|
-
formatMessage(level, message) {
|
|
4415
|
-
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
4416
|
-
const safeMessage = redact(message);
|
|
4417
|
-
return `[${timestamp}] [${level.toUpperCase()}] ${safeMessage}`;
|
|
4418
|
-
}
|
|
4419
|
-
writeToFile(formatted) {
|
|
4420
|
-
if (!this.logToFile) return;
|
|
4421
|
-
try {
|
|
4422
|
-
const logPath = path3.join(getReflyDir(), LOG_FILE);
|
|
4423
|
-
try {
|
|
4424
|
-
const stats = fs3.statSync(logPath);
|
|
4425
|
-
if (stats.size > MAX_LOG_SIZE) {
|
|
4426
|
-
fs3.renameSync(logPath, `${logPath}.old`);
|
|
4427
|
-
}
|
|
4428
|
-
} catch {
|
|
4429
|
-
}
|
|
4430
|
-
fs3.appendFileSync(logPath, `${formatted}
|
|
4431
|
-
`);
|
|
4432
|
-
} catch {
|
|
4433
|
-
}
|
|
4434
|
-
}
|
|
4435
|
-
debug(message, ...args) {
|
|
4436
|
-
if (!this.shouldLog("debug")) return;
|
|
4437
|
-
const formatted = this.formatMessage("debug", this.interpolate(message, args));
|
|
4438
|
-
this.writeToFile(formatted);
|
|
4439
|
-
}
|
|
4440
|
-
info(message, ...args) {
|
|
4441
|
-
if (!this.shouldLog("info")) return;
|
|
4442
|
-
const formatted = this.formatMessage("info", this.interpolate(message, args));
|
|
4443
|
-
this.writeToFile(formatted);
|
|
4444
|
-
}
|
|
4445
|
-
warn(message, ...args) {
|
|
4446
|
-
if (!this.shouldLog("warn")) return;
|
|
4447
|
-
const formatted = this.formatMessage("warn", this.interpolate(message, args));
|
|
4448
|
-
this.writeToFile(formatted);
|
|
4449
|
-
}
|
|
4450
|
-
error(message, ...args) {
|
|
4451
|
-
if (!this.shouldLog("error")) return;
|
|
4452
|
-
const formatted = this.formatMessage("error", this.interpolate(message, args));
|
|
4453
|
-
this.writeToFile(formatted);
|
|
4454
|
-
}
|
|
4455
|
-
interpolate(message, args) {
|
|
4456
|
-
if (args.length === 0) return message;
|
|
4457
|
-
return `${message} ${args.map((a) => JSON.stringify(a)).join(" ")}`;
|
|
4458
|
-
}
|
|
4459
|
-
};
|
|
4460
|
-
var logger = new Logger();
|
|
4461
|
-
|
|
4462
|
-
// src/api/client.ts
|
|
4900
|
+
init_logger();
|
|
4463
4901
|
var DEFAULT_TIMEOUT = 3e4;
|
|
4464
|
-
async function apiRequest(
|
|
4902
|
+
async function apiRequest(path7, options = {}) {
|
|
4465
4903
|
const { method = "GET", body, query, timeout = DEFAULT_TIMEOUT, requireAuth = true } = options;
|
|
4466
4904
|
const endpoint = getApiEndpoint();
|
|
4467
|
-
let url = `${endpoint}${
|
|
4905
|
+
let url = `${endpoint}${path7}`;
|
|
4468
4906
|
if (query && Object.keys(query).length > 0) {
|
|
4469
4907
|
const params = new URLSearchParams(query);
|
|
4470
4908
|
url = `${url}?${params.toString()}`;
|
|
@@ -4502,7 +4940,7 @@ async function apiRequest(path6, options = {}) {
|
|
|
4502
4940
|
const controller = new AbortController();
|
|
4503
4941
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
4504
4942
|
try {
|
|
4505
|
-
logger.debug(`API Request: ${method} ${
|
|
4943
|
+
logger.debug(`API Request: ${method} ${path7}`);
|
|
4506
4944
|
const response = await fetch(url, {
|
|
4507
4945
|
method,
|
|
4508
4946
|
headers,
|
|
@@ -4594,7 +5032,8 @@ function mapAPIError(status, response) {
|
|
|
4594
5032
|
cliError.code || "UNKNOWN",
|
|
4595
5033
|
cliError.message || "Unknown error",
|
|
4596
5034
|
void 0,
|
|
4597
|
-
cliError.hint
|
|
5035
|
+
cliError.hint,
|
|
5036
|
+
cliError.suggestedFix
|
|
4598
5037
|
);
|
|
4599
5038
|
}
|
|
4600
5039
|
const errCode = response.errCode ?? response.error ?? "UNKNOWN";
|
|
@@ -4646,21 +5085,42 @@ async function verifyConnection() {
|
|
|
4646
5085
|
}
|
|
4647
5086
|
|
|
4648
5087
|
// src/skill/installer.ts
|
|
4649
|
-
|
|
4650
|
-
var
|
|
5088
|
+
init_cjs_shims();
|
|
5089
|
+
var fs6 = __toESM(require("fs"));
|
|
5090
|
+
var path6 = __toESM(require("path"));
|
|
5091
|
+
init_paths();
|
|
5092
|
+
init_logger();
|
|
5093
|
+
init_symlink();
|
|
5094
|
+
function removeOldSkillDirectory() {
|
|
5095
|
+
const claudeSkillPath = getClaudeSkillSymlinkPath("refly");
|
|
5096
|
+
if (!fs6.existsSync(claudeSkillPath)) {
|
|
5097
|
+
return;
|
|
5098
|
+
}
|
|
5099
|
+
try {
|
|
5100
|
+
const stat = fs6.lstatSync(claudeSkillPath);
|
|
5101
|
+
if (stat.isSymbolicLink()) {
|
|
5102
|
+
fs6.unlinkSync(claudeSkillPath);
|
|
5103
|
+
} else if (stat.isDirectory()) {
|
|
5104
|
+
fs6.rmSync(claudeSkillPath, { recursive: true, force: true });
|
|
5105
|
+
logger.info("Removed old skill directory");
|
|
5106
|
+
}
|
|
5107
|
+
} catch (err) {
|
|
5108
|
+
logger.warn("Failed to remove old directory:", err);
|
|
5109
|
+
}
|
|
5110
|
+
}
|
|
4651
5111
|
function getPackageSkillDir() {
|
|
4652
5112
|
const possiblePaths = [
|
|
4653
|
-
|
|
5113
|
+
path6.join(__dirname, "..", "..", "skill"),
|
|
4654
5114
|
// Built package: dist/bin/../../skill
|
|
4655
|
-
|
|
5115
|
+
path6.join(__dirname, "..", "..", "..", "skill"),
|
|
4656
5116
|
// Development: dist/bin/../../../skill
|
|
4657
|
-
|
|
5117
|
+
path6.join(__dirname, "..", "skill")
|
|
4658
5118
|
// Alternative: dist/../skill
|
|
4659
5119
|
];
|
|
4660
5120
|
logger.debug("Looking for skill files, __dirname:", __dirname);
|
|
4661
5121
|
for (const p of possiblePaths) {
|
|
4662
|
-
const resolved =
|
|
4663
|
-
const exists =
|
|
5122
|
+
const resolved = path6.resolve(p);
|
|
5123
|
+
const exists = fs6.existsSync(resolved);
|
|
4664
5124
|
logger.debug(` Checking path: ${resolved} - exists: ${exists}`);
|
|
4665
5125
|
if (exists) {
|
|
4666
5126
|
return resolved;
|
|
@@ -4672,42 +5132,52 @@ function installSkill() {
|
|
|
4672
5132
|
const result = {
|
|
4673
5133
|
skillInstalled: false,
|
|
4674
5134
|
skillPath: null,
|
|
5135
|
+
symlinkPath: null,
|
|
4675
5136
|
commandsInstalled: false,
|
|
4676
5137
|
commandsPath: null,
|
|
4677
5138
|
version: getSkillVersion()
|
|
4678
5139
|
};
|
|
4679
5140
|
const sourceDir = getPackageSkillDir();
|
|
4680
5141
|
logger.debug("Source skill directory:", sourceDir);
|
|
4681
|
-
|
|
5142
|
+
ensureReflySkillsDir();
|
|
5143
|
+
const targetDir = getReflyBaseSkillDir();
|
|
4682
5144
|
logger.debug("Target skill directory:", targetDir);
|
|
4683
5145
|
try {
|
|
4684
5146
|
ensureDir(targetDir);
|
|
4685
|
-
ensureDir(
|
|
5147
|
+
ensureDir(path6.join(targetDir, "rules"));
|
|
4686
5148
|
logger.debug("Created target directories");
|
|
4687
5149
|
} catch (err) {
|
|
4688
5150
|
logger.error("Failed to create target directories:", err);
|
|
4689
5151
|
throw err;
|
|
4690
5152
|
}
|
|
4691
|
-
const skillSource =
|
|
4692
|
-
const skillTarget =
|
|
5153
|
+
const skillSource = path6.join(sourceDir, "SKILL.md");
|
|
5154
|
+
const skillTarget = path6.join(targetDir, "SKILL.md");
|
|
4693
5155
|
logger.debug(`Copying SKILL.md: ${skillSource} -> ${skillTarget}`);
|
|
4694
|
-
if (
|
|
4695
|
-
|
|
5156
|
+
if (fs6.existsSync(skillSource)) {
|
|
5157
|
+
fs6.copyFileSync(skillSource, skillTarget);
|
|
4696
5158
|
result.skillInstalled = true;
|
|
4697
5159
|
result.skillPath = targetDir;
|
|
4698
5160
|
logger.debug("SKILL.md copied successfully");
|
|
4699
5161
|
} else {
|
|
4700
5162
|
logger.warn("SKILL.md source not found:", skillSource);
|
|
4701
5163
|
}
|
|
4702
|
-
const refsSource =
|
|
4703
|
-
const
|
|
4704
|
-
if (
|
|
4705
|
-
const files =
|
|
4706
|
-
logger.debug(`Copying ${files.length}
|
|
5164
|
+
const refsSource = path6.join(sourceDir, "references");
|
|
5165
|
+
const rulesTarget = path6.join(targetDir, "rules");
|
|
5166
|
+
if (fs6.existsSync(refsSource)) {
|
|
5167
|
+
const files = fs6.readdirSync(refsSource);
|
|
5168
|
+
logger.debug(`Copying ${files.length} rule files`);
|
|
4707
5169
|
for (const file of files) {
|
|
4708
|
-
|
|
5170
|
+
fs6.copyFileSync(path6.join(refsSource, file), path6.join(rulesTarget, file));
|
|
4709
5171
|
}
|
|
4710
5172
|
}
|
|
5173
|
+
removeOldSkillDirectory();
|
|
5174
|
+
const symlinkResult = createSkillSymlink("refly");
|
|
5175
|
+
if (symlinkResult.success) {
|
|
5176
|
+
result.symlinkPath = symlinkResult.claudePath;
|
|
5177
|
+
logger.info(`Created symlink: ${symlinkResult.claudePath} -> ${symlinkResult.reflyPath}`);
|
|
5178
|
+
} else {
|
|
5179
|
+
logger.warn(`Failed to create symlink: ${symlinkResult.error}`);
|
|
5180
|
+
}
|
|
4711
5181
|
const commandsDir = getClaudeCommandsDir();
|
|
4712
5182
|
logger.debug("Commands directory:", commandsDir);
|
|
4713
5183
|
ensureDir(commandsDir);
|
|
@@ -4719,20 +5189,21 @@ function installSkill() {
|
|
|
4719
5189
|
updateSkillInfo(result.version);
|
|
4720
5190
|
logger.info("Skill installation complete:", {
|
|
4721
5191
|
skillInstalled: result.skillInstalled,
|
|
5192
|
+
symlinkPath: result.symlinkPath,
|
|
4722
5193
|
commandsInstalled: result.commandsInstalled
|
|
4723
5194
|
});
|
|
4724
5195
|
return result;
|
|
4725
5196
|
}
|
|
4726
5197
|
function installSlashCommands(sourceDir, targetDir) {
|
|
4727
|
-
const commandsSource =
|
|
4728
|
-
if (!
|
|
5198
|
+
const commandsSource = path6.join(sourceDir, "..", "commands");
|
|
5199
|
+
if (!fs6.existsSync(commandsSource)) {
|
|
4729
5200
|
return false;
|
|
4730
5201
|
}
|
|
4731
5202
|
try {
|
|
4732
|
-
const files =
|
|
5203
|
+
const files = fs6.readdirSync(commandsSource);
|
|
4733
5204
|
for (const file of files) {
|
|
4734
5205
|
if (file.endsWith(".md")) {
|
|
4735
|
-
|
|
5206
|
+
fs6.copyFileSync(path6.join(commandsSource, file), path6.join(targetDir, file));
|
|
4736
5207
|
}
|
|
4737
5208
|
}
|
|
4738
5209
|
return files.length > 0;
|
|
@@ -4742,8 +5213,8 @@ function installSlashCommands(sourceDir, targetDir) {
|
|
|
4742
5213
|
}
|
|
4743
5214
|
function getSkillVersion() {
|
|
4744
5215
|
try {
|
|
4745
|
-
const skillPath =
|
|
4746
|
-
const content =
|
|
5216
|
+
const skillPath = path6.join(getPackageSkillDir(), "SKILL.md");
|
|
5217
|
+
const content = fs6.readFileSync(skillPath, "utf-8");
|
|
4747
5218
|
const versionMatch = content.match(/version:\s*(\d+\.\d+\.\d+)/);
|
|
4748
5219
|
if (versionMatch) {
|
|
4749
5220
|
return versionMatch[1];
|
|
@@ -4751,23 +5222,26 @@ function getSkillVersion() {
|
|
|
4751
5222
|
} catch {
|
|
4752
5223
|
}
|
|
4753
5224
|
try {
|
|
4754
|
-
const pkgPath =
|
|
4755
|
-
const pkg = JSON.parse(
|
|
5225
|
+
const pkgPath = path6.join(__dirname, "..", "..", "package.json");
|
|
5226
|
+
const pkg = JSON.parse(fs6.readFileSync(pkgPath, "utf-8"));
|
|
4756
5227
|
return pkg.version;
|
|
4757
5228
|
} catch {
|
|
4758
5229
|
return "0.1.0";
|
|
4759
5230
|
}
|
|
4760
5231
|
}
|
|
4761
5232
|
function isSkillInstalled() {
|
|
4762
|
-
const skillPath =
|
|
4763
|
-
if (!
|
|
5233
|
+
const skillPath = path6.join(getReflyBaseSkillDir(), "SKILL.md");
|
|
5234
|
+
if (!fs6.existsSync(skillPath)) {
|
|
4764
5235
|
return { installed: false, upToDate: false };
|
|
4765
5236
|
}
|
|
4766
5237
|
const currentVersion = getSkillVersion();
|
|
5238
|
+
const { isSkillSymlinkValid: isSkillSymlinkValid2 } = (init_symlink(), __toCommonJS(symlink_exports));
|
|
5239
|
+
const symlinkStatus = isSkillSymlinkValid2("refly");
|
|
4767
5240
|
return {
|
|
4768
5241
|
installed: true,
|
|
4769
5242
|
upToDate: true,
|
|
4770
|
-
currentVersion
|
|
5243
|
+
currentVersion,
|
|
5244
|
+
symlinkValid: symlinkStatus.isValid
|
|
4771
5245
|
};
|
|
4772
5246
|
}
|
|
4773
5247
|
// Annotate the CommonJS export names for ESM import in node:
|