@powerformer/refly-cli 0.1.23 → 0.1.24
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 +1561 -232
- package/dist/bin/refly.js.map +1 -1
- package/dist/index.d.ts +18 -0
- package/dist/index.js +1011 -92
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/skill/SKILL.md +114 -13
package/dist/bin/refly.js
CHANGED
|
@@ -989,8 +989,8 @@ var require_command = __commonJS({
|
|
|
989
989
|
init_cjs_shims();
|
|
990
990
|
var EventEmitter = require("events").EventEmitter;
|
|
991
991
|
var childProcess2 = require("child_process");
|
|
992
|
-
var
|
|
993
|
-
var
|
|
992
|
+
var path25 = require("path");
|
|
993
|
+
var fs32 = require("fs");
|
|
994
994
|
var process8 = require("process");
|
|
995
995
|
var { Argument: Argument2, humanReadableArgName } = require_argument();
|
|
996
996
|
var { CommanderError: CommanderError2 } = require_error();
|
|
@@ -1922,11 +1922,11 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1922
1922
|
let launchWithNode = false;
|
|
1923
1923
|
const sourceExt = [".js", ".ts", ".tsx", ".mjs", ".cjs"];
|
|
1924
1924
|
function findFile(baseDir, baseName) {
|
|
1925
|
-
const localBin =
|
|
1926
|
-
if (
|
|
1927
|
-
if (sourceExt.includes(
|
|
1925
|
+
const localBin = path25.resolve(baseDir, baseName);
|
|
1926
|
+
if (fs32.existsSync(localBin)) return localBin;
|
|
1927
|
+
if (sourceExt.includes(path25.extname(baseName))) return void 0;
|
|
1928
1928
|
const foundExt = sourceExt.find(
|
|
1929
|
-
(ext) =>
|
|
1929
|
+
(ext) => fs32.existsSync(`${localBin}${ext}`)
|
|
1930
1930
|
);
|
|
1931
1931
|
if (foundExt) return `${localBin}${foundExt}`;
|
|
1932
1932
|
return void 0;
|
|
@@ -1938,21 +1938,21 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1938
1938
|
if (this._scriptPath) {
|
|
1939
1939
|
let resolvedScriptPath;
|
|
1940
1940
|
try {
|
|
1941
|
-
resolvedScriptPath =
|
|
1941
|
+
resolvedScriptPath = fs32.realpathSync(this._scriptPath);
|
|
1942
1942
|
} catch (err) {
|
|
1943
1943
|
resolvedScriptPath = this._scriptPath;
|
|
1944
1944
|
}
|
|
1945
|
-
executableDir =
|
|
1946
|
-
|
|
1945
|
+
executableDir = path25.resolve(
|
|
1946
|
+
path25.dirname(resolvedScriptPath),
|
|
1947
1947
|
executableDir
|
|
1948
1948
|
);
|
|
1949
1949
|
}
|
|
1950
1950
|
if (executableDir) {
|
|
1951
1951
|
let localFile = findFile(executableDir, executableFile);
|
|
1952
1952
|
if (!localFile && !subcommand._executableFile && this._scriptPath) {
|
|
1953
|
-
const legacyName =
|
|
1953
|
+
const legacyName = path25.basename(
|
|
1954
1954
|
this._scriptPath,
|
|
1955
|
-
|
|
1955
|
+
path25.extname(this._scriptPath)
|
|
1956
1956
|
);
|
|
1957
1957
|
if (legacyName !== this._name) {
|
|
1958
1958
|
localFile = findFile(
|
|
@@ -1963,7 +1963,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
1963
1963
|
}
|
|
1964
1964
|
executableFile = localFile || executableFile;
|
|
1965
1965
|
}
|
|
1966
|
-
launchWithNode = sourceExt.includes(
|
|
1966
|
+
launchWithNode = sourceExt.includes(path25.extname(executableFile));
|
|
1967
1967
|
let proc;
|
|
1968
1968
|
if (process8.platform !== "win32") {
|
|
1969
1969
|
if (launchWithNode) {
|
|
@@ -2803,7 +2803,7 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2803
2803
|
* @return {Command}
|
|
2804
2804
|
*/
|
|
2805
2805
|
nameFromFilename(filename) {
|
|
2806
|
-
this._name =
|
|
2806
|
+
this._name = path25.basename(filename, path25.extname(filename));
|
|
2807
2807
|
return this;
|
|
2808
2808
|
}
|
|
2809
2809
|
/**
|
|
@@ -2817,9 +2817,9 @@ Expecting one of '${allowedValues.join("', '")}'`);
|
|
|
2817
2817
|
* @param {string} [path]
|
|
2818
2818
|
* @return {(string|null|Command)}
|
|
2819
2819
|
*/
|
|
2820
|
-
executableDir(
|
|
2821
|
-
if (
|
|
2822
|
-
this._executableDir =
|
|
2820
|
+
executableDir(path26) {
|
|
2821
|
+
if (path26 === void 0) return this._executableDir;
|
|
2822
|
+
this._executableDir = path26;
|
|
2823
2823
|
return this;
|
|
2824
2824
|
}
|
|
2825
2825
|
/**
|
|
@@ -3260,17 +3260,865 @@ var init_logger = __esm({
|
|
|
3260
3260
|
}
|
|
3261
3261
|
});
|
|
3262
3262
|
|
|
3263
|
+
// src/platform/registry.ts
|
|
3264
|
+
function pathExists(p) {
|
|
3265
|
+
try {
|
|
3266
|
+
return fs4.existsSync(p);
|
|
3267
|
+
} catch {
|
|
3268
|
+
return false;
|
|
3269
|
+
}
|
|
3270
|
+
}
|
|
3271
|
+
function isValidAgentType(name) {
|
|
3272
|
+
return name in agents;
|
|
3273
|
+
}
|
|
3274
|
+
var fs4, path4, import_node_os, home, agents;
|
|
3275
|
+
var init_registry = __esm({
|
|
3276
|
+
"src/platform/registry.ts"() {
|
|
3277
|
+
"use strict";
|
|
3278
|
+
init_cjs_shims();
|
|
3279
|
+
fs4 = __toESM(require("fs"));
|
|
3280
|
+
path4 = __toESM(require("path"));
|
|
3281
|
+
import_node_os = require("os");
|
|
3282
|
+
home = (0, import_node_os.homedir)();
|
|
3283
|
+
agents = {
|
|
3284
|
+
// === SKILL.md Format (Symlink Compatible) ===
|
|
3285
|
+
"claude-code": {
|
|
3286
|
+
name: "claude-code",
|
|
3287
|
+
displayName: "Claude Code",
|
|
3288
|
+
format: "skill-md",
|
|
3289
|
+
skillsDir: ".claude/skills",
|
|
3290
|
+
globalSkillsDir: path4.join(home, ".claude", "skills"),
|
|
3291
|
+
detectInstalled: async () => pathExists(path4.join(home, ".claude"))
|
|
3292
|
+
},
|
|
3293
|
+
codex: {
|
|
3294
|
+
name: "codex",
|
|
3295
|
+
displayName: "Codex",
|
|
3296
|
+
format: "skill-md",
|
|
3297
|
+
skillsDir: ".codex/skills",
|
|
3298
|
+
globalSkillsDir: process.env.CODEX_HOME ? path4.join(process.env.CODEX_HOME, "skills") : path4.join(home, ".codex", "skills"),
|
|
3299
|
+
detectInstalled: async () => pathExists(path4.join(home, ".codex"))
|
|
3300
|
+
},
|
|
3301
|
+
antigravity: {
|
|
3302
|
+
name: "antigravity",
|
|
3303
|
+
displayName: "Antigravity",
|
|
3304
|
+
format: "skill-md",
|
|
3305
|
+
skillsDir: ".agent/skills",
|
|
3306
|
+
globalSkillsDir: path4.join(home, ".gemini", "antigravity", "skills"),
|
|
3307
|
+
detectInstalled: async () => pathExists(path4.join(home, ".gemini", "antigravity"))
|
|
3308
|
+
},
|
|
3309
|
+
"github-copilot": {
|
|
3310
|
+
name: "github-copilot",
|
|
3311
|
+
displayName: "GitHub Copilot",
|
|
3312
|
+
format: "skill-md",
|
|
3313
|
+
skillsDir: ".github/skills",
|
|
3314
|
+
globalSkillsDir: path4.join(home, ".copilot", "skills"),
|
|
3315
|
+
detectInstalled: async () => pathExists(path4.join(home, ".copilot"))
|
|
3316
|
+
},
|
|
3317
|
+
windsurf: {
|
|
3318
|
+
name: "windsurf",
|
|
3319
|
+
displayName: "Windsurf",
|
|
3320
|
+
format: "skill-md",
|
|
3321
|
+
skillsDir: ".windsurf/skills",
|
|
3322
|
+
globalSkillsDir: path4.join(home, ".codeium", "windsurf", "skills"),
|
|
3323
|
+
detectInstalled: async () => pathExists(path4.join(home, ".codeium", "windsurf"))
|
|
3324
|
+
},
|
|
3325
|
+
opencode: {
|
|
3326
|
+
name: "opencode",
|
|
3327
|
+
displayName: "OpenCode",
|
|
3328
|
+
format: "skill-md",
|
|
3329
|
+
skillsDir: ".opencode/skill",
|
|
3330
|
+
globalSkillsDir: path4.join(home, ".config", "opencode", "skill"),
|
|
3331
|
+
detectInstalled: async () => pathExists(path4.join(home, ".config", "opencode"))
|
|
3332
|
+
},
|
|
3333
|
+
moltbot: {
|
|
3334
|
+
name: "moltbot",
|
|
3335
|
+
displayName: "Moltbot",
|
|
3336
|
+
format: "skill-md",
|
|
3337
|
+
skillsDir: "skills",
|
|
3338
|
+
// <workspace>/skills
|
|
3339
|
+
globalSkillsDir: path4.join(home, ".clawdbot", "skills"),
|
|
3340
|
+
// Note: .clawdbot not .moltbot
|
|
3341
|
+
detectInstalled: async () => pathExists(path4.join(home, ".clawdbot"))
|
|
3342
|
+
},
|
|
3343
|
+
// === Different Formats (Require Conversion) ===
|
|
3344
|
+
cursor: {
|
|
3345
|
+
name: "cursor",
|
|
3346
|
+
displayName: "Cursor",
|
|
3347
|
+
format: "cursor-mdc",
|
|
3348
|
+
skillsDir: ".cursor/rules",
|
|
3349
|
+
globalSkillsDir: null,
|
|
3350
|
+
// Cursor has no global rules directory
|
|
3351
|
+
detectInstalled: async () => pathExists(path4.join(home, ".cursor")),
|
|
3352
|
+
fileExtension: ".mdc",
|
|
3353
|
+
skillsAsFiles: true
|
|
3354
|
+
},
|
|
3355
|
+
continue: {
|
|
3356
|
+
name: "continue",
|
|
3357
|
+
displayName: "Continue",
|
|
3358
|
+
format: "rules-md",
|
|
3359
|
+
skillsDir: ".continue/rules",
|
|
3360
|
+
globalSkillsDir: path4.join(home, ".continue", "rules"),
|
|
3361
|
+
detectInstalled: async () => pathExists(path4.join(home, ".continue")),
|
|
3362
|
+
fileExtension: ".md",
|
|
3363
|
+
skillsAsFiles: true
|
|
3364
|
+
},
|
|
3365
|
+
trae: {
|
|
3366
|
+
name: "trae",
|
|
3367
|
+
displayName: "Trae",
|
|
3368
|
+
format: "rules-md",
|
|
3369
|
+
skillsDir: ".trae/rules",
|
|
3370
|
+
globalSkillsDir: path4.join(home, ".trae", "rules"),
|
|
3371
|
+
detectInstalled: async () => pathExists(path4.join(home, ".trae")),
|
|
3372
|
+
fileExtension: ".md",
|
|
3373
|
+
skillsAsFiles: true
|
|
3374
|
+
},
|
|
3375
|
+
// === Unverified ===
|
|
3376
|
+
qoder: {
|
|
3377
|
+
name: "qoder",
|
|
3378
|
+
displayName: "Qoder",
|
|
3379
|
+
format: "unknown",
|
|
3380
|
+
skillsDir: ".qoder/skills",
|
|
3381
|
+
// Assumed, not verified
|
|
3382
|
+
globalSkillsDir: path4.join(home, ".qoder", "skills"),
|
|
3383
|
+
detectInstalled: async () => pathExists(path4.join(home, ".qoder"))
|
|
3384
|
+
}
|
|
3385
|
+
};
|
|
3386
|
+
}
|
|
3387
|
+
});
|
|
3388
|
+
|
|
3389
|
+
// src/platform/symlink-adapter.ts
|
|
3390
|
+
async function createSymlinkSafe(target, linkPath) {
|
|
3391
|
+
try {
|
|
3392
|
+
const linkDir = path5.dirname(linkPath);
|
|
3393
|
+
ensureDir(linkDir);
|
|
3394
|
+
if (fs5.existsSync(linkPath)) {
|
|
3395
|
+
const stat = fs5.lstatSync(linkPath);
|
|
3396
|
+
if (stat.isSymbolicLink()) {
|
|
3397
|
+
fs5.unlinkSync(linkPath);
|
|
3398
|
+
logger.debug(`Removed existing symlink: ${linkPath}`);
|
|
3399
|
+
} else if (stat.isDirectory()) {
|
|
3400
|
+
return {
|
|
3401
|
+
success: false,
|
|
3402
|
+
error: `Target path is a directory, not a symlink: ${linkPath}`
|
|
3403
|
+
};
|
|
3404
|
+
}
|
|
3405
|
+
}
|
|
3406
|
+
const symlinkType = (0, import_node_os2.platform)() === "win32" ? "junction" : "dir";
|
|
3407
|
+
fs5.symlinkSync(target, linkPath, symlinkType);
|
|
3408
|
+
logger.debug(`Created symlink: ${linkPath} -> ${target}`);
|
|
3409
|
+
return { success: true };
|
|
3410
|
+
} catch (err) {
|
|
3411
|
+
if (err.code === "ENOENT") {
|
|
3412
|
+
try {
|
|
3413
|
+
const symlinkType = (0, import_node_os2.platform)() === "win32" ? "junction" : "dir";
|
|
3414
|
+
fs5.symlinkSync(target, linkPath, symlinkType);
|
|
3415
|
+
logger.debug(`Created symlink: ${linkPath} -> ${target}`);
|
|
3416
|
+
return { success: true };
|
|
3417
|
+
} catch (innerErr) {
|
|
3418
|
+
return {
|
|
3419
|
+
success: false,
|
|
3420
|
+
error: innerErr.message
|
|
3421
|
+
};
|
|
3422
|
+
}
|
|
3423
|
+
}
|
|
3424
|
+
return {
|
|
3425
|
+
success: false,
|
|
3426
|
+
error: err.message
|
|
3427
|
+
};
|
|
3428
|
+
}
|
|
3429
|
+
}
|
|
3430
|
+
var fs5, path5, import_node_os2, SymlinkAdapter, symlinkAdapter;
|
|
3431
|
+
var init_symlink_adapter = __esm({
|
|
3432
|
+
"src/platform/symlink-adapter.ts"() {
|
|
3433
|
+
"use strict";
|
|
3434
|
+
init_cjs_shims();
|
|
3435
|
+
fs5 = __toESM(require("fs"));
|
|
3436
|
+
path5 = __toESM(require("path"));
|
|
3437
|
+
import_node_os2 = require("os");
|
|
3438
|
+
init_logger();
|
|
3439
|
+
init_paths();
|
|
3440
|
+
SymlinkAdapter = class {
|
|
3441
|
+
async deploy(skillName, sourcePath, agent, options) {
|
|
3442
|
+
const result = {
|
|
3443
|
+
success: false,
|
|
3444
|
+
agent: agent.name,
|
|
3445
|
+
skillName,
|
|
3446
|
+
deployedPath: null,
|
|
3447
|
+
sourcePath,
|
|
3448
|
+
isSymlink: true
|
|
3449
|
+
};
|
|
3450
|
+
let targetDir = null;
|
|
3451
|
+
if (options?.projectPath && agent.skillsDir) {
|
|
3452
|
+
targetDir = path5.join(options.projectPath, agent.skillsDir);
|
|
3453
|
+
} else {
|
|
3454
|
+
targetDir = agent.globalSkillsDir;
|
|
3455
|
+
}
|
|
3456
|
+
if (!targetDir) {
|
|
3457
|
+
result.error = `Agent ${agent.displayName} has no skills directory configured`;
|
|
3458
|
+
return result;
|
|
3459
|
+
}
|
|
3460
|
+
if (!fs5.existsSync(sourcePath)) {
|
|
3461
|
+
result.error = `Source skill directory does not exist: ${sourcePath}`;
|
|
3462
|
+
return result;
|
|
3463
|
+
}
|
|
3464
|
+
const linkPath = path5.join(targetDir, skillName);
|
|
3465
|
+
result.deployedPath = linkPath;
|
|
3466
|
+
if (fs5.existsSync(linkPath) && !options?.force) {
|
|
3467
|
+
const stat = fs5.lstatSync(linkPath);
|
|
3468
|
+
if (stat.isSymbolicLink()) {
|
|
3469
|
+
const existingTarget = fs5.readlinkSync(linkPath);
|
|
3470
|
+
const resolvedTarget = path5.resolve(path5.dirname(linkPath), existingTarget);
|
|
3471
|
+
if (resolvedTarget === sourcePath) {
|
|
3472
|
+
result.success = true;
|
|
3473
|
+
return result;
|
|
3474
|
+
}
|
|
3475
|
+
}
|
|
3476
|
+
result.error = `Skill already exists at ${linkPath}. Use --force to overwrite.`;
|
|
3477
|
+
return result;
|
|
3478
|
+
}
|
|
3479
|
+
const symlinkResult = await createSymlinkSafe(sourcePath, linkPath);
|
|
3480
|
+
if (!symlinkResult.success) {
|
|
3481
|
+
result.error = symlinkResult.error;
|
|
3482
|
+
return result;
|
|
3483
|
+
}
|
|
3484
|
+
result.success = true;
|
|
3485
|
+
logger.info(`Deployed ${skillName} to ${agent.displayName}: ${linkPath} -> ${sourcePath}`);
|
|
3486
|
+
return result;
|
|
3487
|
+
}
|
|
3488
|
+
async remove(skillName, agent, options) {
|
|
3489
|
+
const result = {
|
|
3490
|
+
success: false,
|
|
3491
|
+
agent: agent.name,
|
|
3492
|
+
skillName,
|
|
3493
|
+
removedPath: null
|
|
3494
|
+
};
|
|
3495
|
+
let targetDir = null;
|
|
3496
|
+
if (options?.projectPath && agent.skillsDir) {
|
|
3497
|
+
targetDir = path5.join(options.projectPath, agent.skillsDir);
|
|
3498
|
+
} else {
|
|
3499
|
+
targetDir = agent.globalSkillsDir;
|
|
3500
|
+
}
|
|
3501
|
+
if (!targetDir) {
|
|
3502
|
+
result.error = `Agent ${agent.displayName} has no skills directory configured`;
|
|
3503
|
+
return result;
|
|
3504
|
+
}
|
|
3505
|
+
const linkPath = path5.join(targetDir, skillName);
|
|
3506
|
+
result.removedPath = linkPath;
|
|
3507
|
+
try {
|
|
3508
|
+
if (!fs5.existsSync(linkPath)) {
|
|
3509
|
+
result.success = true;
|
|
3510
|
+
return result;
|
|
3511
|
+
}
|
|
3512
|
+
const stat = fs5.lstatSync(linkPath);
|
|
3513
|
+
if (!stat.isSymbolicLink()) {
|
|
3514
|
+
result.error = `Path is not a symlink: ${linkPath}`;
|
|
3515
|
+
return result;
|
|
3516
|
+
}
|
|
3517
|
+
fs5.unlinkSync(linkPath);
|
|
3518
|
+
result.success = true;
|
|
3519
|
+
logger.info(`Removed ${skillName} from ${agent.displayName}: ${linkPath}`);
|
|
3520
|
+
} catch (err) {
|
|
3521
|
+
result.error = err.message;
|
|
3522
|
+
}
|
|
3523
|
+
return result;
|
|
3524
|
+
}
|
|
3525
|
+
async list(agent, options) {
|
|
3526
|
+
const results = [];
|
|
3527
|
+
let targetDir = null;
|
|
3528
|
+
if (options?.projectPath && agent.skillsDir) {
|
|
3529
|
+
targetDir = path5.join(options.projectPath, agent.skillsDir);
|
|
3530
|
+
} else {
|
|
3531
|
+
targetDir = agent.globalSkillsDir;
|
|
3532
|
+
}
|
|
3533
|
+
if (!targetDir || !fs5.existsSync(targetDir)) {
|
|
3534
|
+
return results;
|
|
3535
|
+
}
|
|
3536
|
+
try {
|
|
3537
|
+
const entries = fs5.readdirSync(targetDir, { withFileTypes: true });
|
|
3538
|
+
for (const entry of entries) {
|
|
3539
|
+
const fullPath = path5.join(targetDir, entry.name);
|
|
3540
|
+
try {
|
|
3541
|
+
const stat = fs5.lstatSync(fullPath);
|
|
3542
|
+
if (stat.isSymbolicLink()) {
|
|
3543
|
+
const target = fs5.readlinkSync(fullPath);
|
|
3544
|
+
const resolvedTarget = path5.resolve(path5.dirname(fullPath), target);
|
|
3545
|
+
const isValid2 = fs5.existsSync(resolvedTarget);
|
|
3546
|
+
results.push({
|
|
3547
|
+
name: entry.name,
|
|
3548
|
+
agent: agent.name,
|
|
3549
|
+
path: fullPath,
|
|
3550
|
+
isValid: isValid2,
|
|
3551
|
+
target: resolvedTarget,
|
|
3552
|
+
isSymlink: true
|
|
3553
|
+
});
|
|
3554
|
+
} else if (stat.isDirectory()) {
|
|
3555
|
+
const skillMdPath = path5.join(fullPath, "SKILL.md");
|
|
3556
|
+
results.push({
|
|
3557
|
+
name: entry.name,
|
|
3558
|
+
agent: agent.name,
|
|
3559
|
+
path: fullPath,
|
|
3560
|
+
isValid: fs5.existsSync(skillMdPath),
|
|
3561
|
+
isSymlink: false
|
|
3562
|
+
});
|
|
3563
|
+
}
|
|
3564
|
+
} catch {
|
|
3565
|
+
}
|
|
3566
|
+
}
|
|
3567
|
+
} catch {
|
|
3568
|
+
}
|
|
3569
|
+
return results;
|
|
3570
|
+
}
|
|
3571
|
+
async isDeployed(skillName, agent, options) {
|
|
3572
|
+
let targetDir = null;
|
|
3573
|
+
if (options?.projectPath && agent.skillsDir) {
|
|
3574
|
+
targetDir = path5.join(options.projectPath, agent.skillsDir);
|
|
3575
|
+
} else {
|
|
3576
|
+
targetDir = agent.globalSkillsDir;
|
|
3577
|
+
}
|
|
3578
|
+
if (!targetDir) {
|
|
3579
|
+
return { deployed: false, valid: false };
|
|
3580
|
+
}
|
|
3581
|
+
const linkPath = path5.join(targetDir, skillName);
|
|
3582
|
+
try {
|
|
3583
|
+
if (!fs5.existsSync(linkPath)) {
|
|
3584
|
+
return { deployed: false, valid: false };
|
|
3585
|
+
}
|
|
3586
|
+
const stat = fs5.lstatSync(linkPath);
|
|
3587
|
+
if (!stat.isSymbolicLink()) {
|
|
3588
|
+
const skillMdPath = path5.join(linkPath, "SKILL.md");
|
|
3589
|
+
return {
|
|
3590
|
+
deployed: true,
|
|
3591
|
+
valid: fs5.existsSync(skillMdPath),
|
|
3592
|
+
path: linkPath
|
|
3593
|
+
};
|
|
3594
|
+
}
|
|
3595
|
+
const target = fs5.readlinkSync(linkPath);
|
|
3596
|
+
const resolvedTarget = path5.resolve(path5.dirname(linkPath), target);
|
|
3597
|
+
const isValid2 = fs5.existsSync(resolvedTarget);
|
|
3598
|
+
return {
|
|
3599
|
+
deployed: true,
|
|
3600
|
+
valid: isValid2,
|
|
3601
|
+
path: linkPath
|
|
3602
|
+
};
|
|
3603
|
+
} catch {
|
|
3604
|
+
return { deployed: false, valid: false };
|
|
3605
|
+
}
|
|
3606
|
+
}
|
|
3607
|
+
};
|
|
3608
|
+
symlinkAdapter = new SymlinkAdapter();
|
|
3609
|
+
}
|
|
3610
|
+
});
|
|
3611
|
+
|
|
3612
|
+
// src/platform/format-converter.ts
|
|
3613
|
+
function convertToMdc(skill) {
|
|
3614
|
+
const lines = [];
|
|
3615
|
+
lines.push("---");
|
|
3616
|
+
lines.push(`description: "${skill.description.replace(/"/g, '\\"')}"`);
|
|
3617
|
+
lines.push("globs:");
|
|
3618
|
+
lines.push("alwaysApply: false");
|
|
3619
|
+
lines.push("---");
|
|
3620
|
+
lines.push("");
|
|
3621
|
+
lines.push(`# ${skill.displayName || formatSkillName(skill.name)}`);
|
|
3622
|
+
lines.push("");
|
|
3623
|
+
lines.push(skill.description);
|
|
3624
|
+
lines.push("");
|
|
3625
|
+
lines.push(skill.body);
|
|
3626
|
+
if (skill.skillId || skill.workflowId) {
|
|
3627
|
+
lines.push("");
|
|
3628
|
+
lines.push("---");
|
|
3629
|
+
lines.push("");
|
|
3630
|
+
lines.push("## Refly Skill");
|
|
3631
|
+
lines.push("");
|
|
3632
|
+
if (skill.skillId) {
|
|
3633
|
+
lines.push(`- **Skill ID**: ${skill.skillId}`);
|
|
3634
|
+
}
|
|
3635
|
+
if (skill.workflowId) {
|
|
3636
|
+
lines.push(`- **Workflow ID**: ${skill.workflowId}`);
|
|
3637
|
+
}
|
|
3638
|
+
if (skill.installationId) {
|
|
3639
|
+
lines.push(`- **Installation ID**: ${skill.installationId}`);
|
|
3640
|
+
}
|
|
3641
|
+
const runId = skill.installationId || skill.workflowId || skill.name;
|
|
3642
|
+
lines.push(`- **Run**: \`refly skill run ${runId}\``);
|
|
3643
|
+
}
|
|
3644
|
+
return lines.join("\n");
|
|
3645
|
+
}
|
|
3646
|
+
function convertToRules(skill) {
|
|
3647
|
+
const lines = [];
|
|
3648
|
+
lines.push(`# ${skill.displayName || formatSkillName(skill.name)}`);
|
|
3649
|
+
lines.push("");
|
|
3650
|
+
lines.push(`> ${skill.description}`);
|
|
3651
|
+
lines.push("");
|
|
3652
|
+
if (skill.triggers && skill.triggers.length > 0) {
|
|
3653
|
+
lines.push("## Triggers");
|
|
3654
|
+
lines.push("");
|
|
3655
|
+
for (const trigger of skill.triggers) {
|
|
3656
|
+
lines.push(`- ${trigger}`);
|
|
3657
|
+
}
|
|
3658
|
+
lines.push("");
|
|
3659
|
+
}
|
|
3660
|
+
lines.push(skill.body);
|
|
3661
|
+
if (skill.skillId || skill.workflowId) {
|
|
3662
|
+
lines.push("");
|
|
3663
|
+
lines.push("---");
|
|
3664
|
+
lines.push("");
|
|
3665
|
+
lines.push("## Refly Skill");
|
|
3666
|
+
lines.push("");
|
|
3667
|
+
if (skill.skillId) {
|
|
3668
|
+
lines.push(`- **Skill ID**: ${skill.skillId}`);
|
|
3669
|
+
}
|
|
3670
|
+
if (skill.workflowId) {
|
|
3671
|
+
lines.push(`- **Workflow ID**: ${skill.workflowId}`);
|
|
3672
|
+
}
|
|
3673
|
+
if (skill.installationId) {
|
|
3674
|
+
lines.push(`- **Installation ID**: ${skill.installationId}`);
|
|
3675
|
+
}
|
|
3676
|
+
const runId = skill.installationId || skill.workflowId || skill.name;
|
|
3677
|
+
lines.push(`- **Run**: \`refly skill run ${runId}\``);
|
|
3678
|
+
}
|
|
3679
|
+
return lines.join("\n");
|
|
3680
|
+
}
|
|
3681
|
+
function formatSkillName(name) {
|
|
3682
|
+
return name.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
3683
|
+
}
|
|
3684
|
+
function parseSkillMdLenient(content) {
|
|
3685
|
+
const frontmatterRegex = /^---\n([\s\S]*?)\n---\n?([\s\S]*)$/;
|
|
3686
|
+
const match = content.match(frontmatterRegex);
|
|
3687
|
+
if (!match) {
|
|
3688
|
+
return null;
|
|
3689
|
+
}
|
|
3690
|
+
const [, frontmatterStr, body] = match;
|
|
3691
|
+
const meta = {};
|
|
3692
|
+
const lines = frontmatterStr.split("\n");
|
|
3693
|
+
let currentKey = null;
|
|
3694
|
+
let currentArray = [];
|
|
3695
|
+
for (const line of lines) {
|
|
3696
|
+
const trimmed = line.trim();
|
|
3697
|
+
if (trimmed.startsWith("- ")) {
|
|
3698
|
+
if (currentKey) {
|
|
3699
|
+
currentArray.push(trimmed.slice(2).trim());
|
|
3700
|
+
}
|
|
3701
|
+
continue;
|
|
3702
|
+
}
|
|
3703
|
+
if (currentKey && currentArray.length > 0) {
|
|
3704
|
+
meta[currentKey] = currentArray;
|
|
3705
|
+
currentArray = [];
|
|
3706
|
+
currentKey = null;
|
|
3707
|
+
}
|
|
3708
|
+
const colonIndex = trimmed.indexOf(":");
|
|
3709
|
+
if (colonIndex > 0) {
|
|
3710
|
+
const key = trimmed.slice(0, colonIndex).trim();
|
|
3711
|
+
const value = trimmed.slice(colonIndex + 1).trim();
|
|
3712
|
+
if (value === "") {
|
|
3713
|
+
currentKey = key;
|
|
3714
|
+
currentArray = [];
|
|
3715
|
+
} else {
|
|
3716
|
+
meta[key] = value;
|
|
3717
|
+
}
|
|
3718
|
+
}
|
|
3719
|
+
}
|
|
3720
|
+
if (currentKey && currentArray.length > 0) {
|
|
3721
|
+
meta[currentKey] = currentArray;
|
|
3722
|
+
}
|
|
3723
|
+
if (!meta.name || !meta.description) {
|
|
3724
|
+
return null;
|
|
3725
|
+
}
|
|
3726
|
+
return {
|
|
3727
|
+
name: meta.name,
|
|
3728
|
+
displayName: meta.displayName,
|
|
3729
|
+
description: meta.description,
|
|
3730
|
+
skillId: meta.skillId,
|
|
3731
|
+
workflowId: meta.workflowId,
|
|
3732
|
+
installationId: meta.installationId,
|
|
3733
|
+
triggers: meta.triggers,
|
|
3734
|
+
tags: meta.tags,
|
|
3735
|
+
version: meta.version,
|
|
3736
|
+
body: body.trim()
|
|
3737
|
+
};
|
|
3738
|
+
}
|
|
3739
|
+
function readSkillMd(sourcePath) {
|
|
3740
|
+
const skillMdPath = path6.join(sourcePath, "SKILL.md");
|
|
3741
|
+
if (!fs6.existsSync(skillMdPath)) {
|
|
3742
|
+
return null;
|
|
3743
|
+
}
|
|
3744
|
+
try {
|
|
3745
|
+
const content = fs6.readFileSync(skillMdPath, "utf-8");
|
|
3746
|
+
return parseSkillMdLenient(content);
|
|
3747
|
+
} catch {
|
|
3748
|
+
return null;
|
|
3749
|
+
}
|
|
3750
|
+
}
|
|
3751
|
+
var fs6, path6, FormatConverterAdapter, formatConverterAdapter;
|
|
3752
|
+
var init_format_converter = __esm({
|
|
3753
|
+
"src/platform/format-converter.ts"() {
|
|
3754
|
+
"use strict";
|
|
3755
|
+
init_cjs_shims();
|
|
3756
|
+
fs6 = __toESM(require("fs"));
|
|
3757
|
+
path6 = __toESM(require("path"));
|
|
3758
|
+
init_logger();
|
|
3759
|
+
init_paths();
|
|
3760
|
+
FormatConverterAdapter = class {
|
|
3761
|
+
async deploy(skillName, sourcePath, agent, options) {
|
|
3762
|
+
const result = {
|
|
3763
|
+
success: false,
|
|
3764
|
+
agent: agent.name,
|
|
3765
|
+
skillName,
|
|
3766
|
+
deployedPath: null,
|
|
3767
|
+
sourcePath,
|
|
3768
|
+
isSymlink: false
|
|
3769
|
+
// We generate files, not symlinks
|
|
3770
|
+
};
|
|
3771
|
+
let targetDir = null;
|
|
3772
|
+
if (options?.projectPath && agent.skillsDir) {
|
|
3773
|
+
targetDir = path6.join(options.projectPath, agent.skillsDir);
|
|
3774
|
+
} else {
|
|
3775
|
+
targetDir = agent.globalSkillsDir;
|
|
3776
|
+
}
|
|
3777
|
+
if (!targetDir) {
|
|
3778
|
+
result.success = true;
|
|
3779
|
+
logger.debug(`Skipping ${skillName} for ${agent.displayName}: no global skills directory`);
|
|
3780
|
+
return result;
|
|
3781
|
+
}
|
|
3782
|
+
const skill = readSkillMd(sourcePath);
|
|
3783
|
+
if (!skill) {
|
|
3784
|
+
result.error = `Failed to read SKILL.md from ${sourcePath}`;
|
|
3785
|
+
return result;
|
|
3786
|
+
}
|
|
3787
|
+
const extension = agent.fileExtension || ".md";
|
|
3788
|
+
const filePath = path6.join(targetDir, `${skillName}${extension}`);
|
|
3789
|
+
result.deployedPath = filePath;
|
|
3790
|
+
if (fs6.existsSync(filePath) && !options?.force) {
|
|
3791
|
+
result.error = `Skill already exists at ${filePath}. Use --force to overwrite.`;
|
|
3792
|
+
return result;
|
|
3793
|
+
}
|
|
3794
|
+
let content;
|
|
3795
|
+
switch (agent.format) {
|
|
3796
|
+
case "cursor-mdc":
|
|
3797
|
+
content = convertToMdc(skill);
|
|
3798
|
+
break;
|
|
3799
|
+
case "rules-md":
|
|
3800
|
+
content = convertToRules(skill);
|
|
3801
|
+
break;
|
|
3802
|
+
default:
|
|
3803
|
+
result.error = `Unsupported format: ${agent.format}`;
|
|
3804
|
+
return result;
|
|
3805
|
+
}
|
|
3806
|
+
try {
|
|
3807
|
+
ensureDir(targetDir);
|
|
3808
|
+
fs6.writeFileSync(filePath, content, { encoding: "utf-8", mode: 420 });
|
|
3809
|
+
result.success = true;
|
|
3810
|
+
logger.info(`Deployed ${skillName} to ${agent.displayName}: ${filePath}`);
|
|
3811
|
+
} catch (err) {
|
|
3812
|
+
result.error = err.message;
|
|
3813
|
+
}
|
|
3814
|
+
return result;
|
|
3815
|
+
}
|
|
3816
|
+
async remove(skillName, agent, options) {
|
|
3817
|
+
const result = {
|
|
3818
|
+
success: false,
|
|
3819
|
+
agent: agent.name,
|
|
3820
|
+
skillName,
|
|
3821
|
+
removedPath: null
|
|
3822
|
+
};
|
|
3823
|
+
let targetDir = null;
|
|
3824
|
+
if (options?.projectPath && agent.skillsDir) {
|
|
3825
|
+
targetDir = path6.join(options.projectPath, agent.skillsDir);
|
|
3826
|
+
} else {
|
|
3827
|
+
targetDir = agent.globalSkillsDir;
|
|
3828
|
+
}
|
|
3829
|
+
if (!targetDir) {
|
|
3830
|
+
result.success = true;
|
|
3831
|
+
logger.debug(
|
|
3832
|
+
`Skipping ${skillName} removal for ${agent.displayName}: no global skills directory`
|
|
3833
|
+
);
|
|
3834
|
+
return result;
|
|
3835
|
+
}
|
|
3836
|
+
const extension = agent.fileExtension || ".md";
|
|
3837
|
+
const filePath = path6.join(targetDir, `${skillName}${extension}`);
|
|
3838
|
+
result.removedPath = filePath;
|
|
3839
|
+
try {
|
|
3840
|
+
if (!fs6.existsSync(filePath)) {
|
|
3841
|
+
result.success = true;
|
|
3842
|
+
return result;
|
|
3843
|
+
}
|
|
3844
|
+
fs6.unlinkSync(filePath);
|
|
3845
|
+
result.success = true;
|
|
3846
|
+
logger.info(`Removed ${skillName} from ${agent.displayName}: ${filePath}`);
|
|
3847
|
+
} catch (err) {
|
|
3848
|
+
result.error = err.message;
|
|
3849
|
+
}
|
|
3850
|
+
return result;
|
|
3851
|
+
}
|
|
3852
|
+
async list(agent, options) {
|
|
3853
|
+
const results = [];
|
|
3854
|
+
let targetDir = null;
|
|
3855
|
+
if (options?.projectPath && agent.skillsDir) {
|
|
3856
|
+
targetDir = path6.join(options.projectPath, agent.skillsDir);
|
|
3857
|
+
} else {
|
|
3858
|
+
targetDir = agent.globalSkillsDir;
|
|
3859
|
+
}
|
|
3860
|
+
if (!targetDir || !fs6.existsSync(targetDir)) {
|
|
3861
|
+
return results;
|
|
3862
|
+
}
|
|
3863
|
+
const extension = agent.fileExtension || ".md";
|
|
3864
|
+
try {
|
|
3865
|
+
const entries = fs6.readdirSync(targetDir, { withFileTypes: true });
|
|
3866
|
+
for (const entry of entries) {
|
|
3867
|
+
if (entry.isFile() && entry.name.endsWith(extension)) {
|
|
3868
|
+
const fullPath = path6.join(targetDir, entry.name);
|
|
3869
|
+
const skillName = entry.name.slice(0, -extension.length);
|
|
3870
|
+
let isReflySkill = false;
|
|
3871
|
+
try {
|
|
3872
|
+
const content = fs6.readFileSync(fullPath, "utf-8");
|
|
3873
|
+
isReflySkill = content.includes("## Refly Skill") || content.includes("Skill ID:");
|
|
3874
|
+
} catch {
|
|
3875
|
+
}
|
|
3876
|
+
results.push({
|
|
3877
|
+
name: skillName,
|
|
3878
|
+
agent: agent.name,
|
|
3879
|
+
path: fullPath,
|
|
3880
|
+
isValid: isReflySkill,
|
|
3881
|
+
isSymlink: false
|
|
3882
|
+
});
|
|
3883
|
+
}
|
|
3884
|
+
}
|
|
3885
|
+
} catch {
|
|
3886
|
+
}
|
|
3887
|
+
return results;
|
|
3888
|
+
}
|
|
3889
|
+
async isDeployed(skillName, agent, options) {
|
|
3890
|
+
let targetDir = null;
|
|
3891
|
+
if (options?.projectPath && agent.skillsDir) {
|
|
3892
|
+
targetDir = path6.join(options.projectPath, agent.skillsDir);
|
|
3893
|
+
} else {
|
|
3894
|
+
targetDir = agent.globalSkillsDir;
|
|
3895
|
+
}
|
|
3896
|
+
if (!targetDir) {
|
|
3897
|
+
return { deployed: false, valid: false };
|
|
3898
|
+
}
|
|
3899
|
+
const extension = agent.fileExtension || ".md";
|
|
3900
|
+
const filePath = path6.join(targetDir, `${skillName}${extension}`);
|
|
3901
|
+
if (!fs6.existsSync(filePath)) {
|
|
3902
|
+
return { deployed: false, valid: false };
|
|
3903
|
+
}
|
|
3904
|
+
let isValid2 = false;
|
|
3905
|
+
try {
|
|
3906
|
+
const content = fs6.readFileSync(filePath, "utf-8");
|
|
3907
|
+
isValid2 = content.includes("## Refly Skill") || content.includes("Skill ID:");
|
|
3908
|
+
} catch {
|
|
3909
|
+
}
|
|
3910
|
+
return {
|
|
3911
|
+
deployed: true,
|
|
3912
|
+
valid: isValid2,
|
|
3913
|
+
path: filePath
|
|
3914
|
+
};
|
|
3915
|
+
}
|
|
3916
|
+
};
|
|
3917
|
+
formatConverterAdapter = new FormatConverterAdapter();
|
|
3918
|
+
}
|
|
3919
|
+
});
|
|
3920
|
+
|
|
3921
|
+
// src/platform/manager.ts
|
|
3922
|
+
function getAdapter(agent) {
|
|
3923
|
+
switch (agent.format) {
|
|
3924
|
+
case "skill-md":
|
|
3925
|
+
return symlinkAdapter;
|
|
3926
|
+
case "cursor-mdc":
|
|
3927
|
+
case "rules-md":
|
|
3928
|
+
return formatConverterAdapter;
|
|
3929
|
+
default:
|
|
3930
|
+
return symlinkAdapter;
|
|
3931
|
+
}
|
|
3932
|
+
}
|
|
3933
|
+
async function detectInstalledAgents() {
|
|
3934
|
+
const installed = [];
|
|
3935
|
+
for (const agent of Object.values(agents)) {
|
|
3936
|
+
try {
|
|
3937
|
+
const isInstalled = await agent.detectInstalled();
|
|
3938
|
+
if (isInstalled) {
|
|
3939
|
+
installed.push(agent);
|
|
3940
|
+
}
|
|
3941
|
+
} catch (err) {
|
|
3942
|
+
logger.debug(`Error detecting ${agent.displayName}: ${err.message}`);
|
|
3943
|
+
}
|
|
3944
|
+
}
|
|
3945
|
+
return installed;
|
|
3946
|
+
}
|
|
3947
|
+
async function getDeployableAgents(options) {
|
|
3948
|
+
const installed = await detectInstalledAgents();
|
|
3949
|
+
if (options?.includeUnknown) {
|
|
3950
|
+
return installed;
|
|
3951
|
+
}
|
|
3952
|
+
return installed.filter((agent) => agent.format !== "unknown");
|
|
3953
|
+
}
|
|
3954
|
+
async function deploySkillToAllPlatforms(skillName, options) {
|
|
3955
|
+
const sourcePath = skillName === "refly" ? getReflyBaseSkillDir() : getReflyDomainSkillDir(skillName);
|
|
3956
|
+
const result = {
|
|
3957
|
+
skillName,
|
|
3958
|
+
sourcePath,
|
|
3959
|
+
results: /* @__PURE__ */ new Map(),
|
|
3960
|
+
successCount: 0,
|
|
3961
|
+
failureCount: 0
|
|
3962
|
+
};
|
|
3963
|
+
if (!fs7.existsSync(sourcePath)) {
|
|
3964
|
+
logger.error(`Source skill directory does not exist: ${sourcePath}`);
|
|
3965
|
+
return result;
|
|
3966
|
+
}
|
|
3967
|
+
let targetAgents;
|
|
3968
|
+
if (options?.agents && options.agents.length > 0) {
|
|
3969
|
+
targetAgents = options.agents.map((name) => agents[name]).filter(Boolean);
|
|
3970
|
+
} else {
|
|
3971
|
+
targetAgents = await getDeployableAgents();
|
|
3972
|
+
}
|
|
3973
|
+
for (const agent of targetAgents) {
|
|
3974
|
+
const adapter = getAdapter(agent);
|
|
3975
|
+
try {
|
|
3976
|
+
const deployResult = await adapter.deploy(skillName, sourcePath, agent, {
|
|
3977
|
+
force: options?.force,
|
|
3978
|
+
projectPath: options?.projectPath
|
|
3979
|
+
});
|
|
3980
|
+
result.results.set(agent.name, deployResult);
|
|
3981
|
+
if (deployResult.success) {
|
|
3982
|
+
result.successCount++;
|
|
3983
|
+
} else {
|
|
3984
|
+
result.failureCount++;
|
|
3985
|
+
}
|
|
3986
|
+
} catch (err) {
|
|
3987
|
+
result.results.set(agent.name, {
|
|
3988
|
+
success: false,
|
|
3989
|
+
agent: agent.name,
|
|
3990
|
+
skillName,
|
|
3991
|
+
deployedPath: null,
|
|
3992
|
+
sourcePath,
|
|
3993
|
+
isSymlink: false,
|
|
3994
|
+
error: err.message
|
|
3995
|
+
});
|
|
3996
|
+
result.failureCount++;
|
|
3997
|
+
}
|
|
3998
|
+
}
|
|
3999
|
+
return result;
|
|
4000
|
+
}
|
|
4001
|
+
async function removeSkillFromAllPlatforms(skillName, options) {
|
|
4002
|
+
const result = {
|
|
4003
|
+
skillName,
|
|
4004
|
+
results: /* @__PURE__ */ new Map(),
|
|
4005
|
+
successCount: 0,
|
|
4006
|
+
failureCount: 0
|
|
4007
|
+
};
|
|
4008
|
+
let targetAgents;
|
|
4009
|
+
if (options?.agents && options.agents.length > 0) {
|
|
4010
|
+
targetAgents = options.agents.map((name) => agents[name]).filter(Boolean);
|
|
4011
|
+
} else {
|
|
4012
|
+
targetAgents = await getDeployableAgents();
|
|
4013
|
+
}
|
|
4014
|
+
for (const agent of targetAgents) {
|
|
4015
|
+
const adapter = getAdapter(agent);
|
|
4016
|
+
try {
|
|
4017
|
+
const removeResult = await adapter.remove(skillName, agent, {
|
|
4018
|
+
projectPath: options?.projectPath
|
|
4019
|
+
});
|
|
4020
|
+
result.results.set(agent.name, removeResult);
|
|
4021
|
+
if (removeResult.success) {
|
|
4022
|
+
result.successCount++;
|
|
4023
|
+
} else {
|
|
4024
|
+
result.failureCount++;
|
|
4025
|
+
}
|
|
4026
|
+
} catch (err) {
|
|
4027
|
+
result.results.set(agent.name, {
|
|
4028
|
+
success: false,
|
|
4029
|
+
agent: agent.name,
|
|
4030
|
+
skillName,
|
|
4031
|
+
removedPath: null,
|
|
4032
|
+
error: err.message
|
|
4033
|
+
});
|
|
4034
|
+
result.failureCount++;
|
|
4035
|
+
}
|
|
4036
|
+
}
|
|
4037
|
+
return result;
|
|
4038
|
+
}
|
|
4039
|
+
async function listAllDeployedSkills(options) {
|
|
4040
|
+
const result = /* @__PURE__ */ new Map();
|
|
4041
|
+
let targetAgents;
|
|
4042
|
+
if (options?.agents && options.agents.length > 0) {
|
|
4043
|
+
targetAgents = options.agents.map((name) => agents[name]).filter(Boolean);
|
|
4044
|
+
} else {
|
|
4045
|
+
targetAgents = await getDeployableAgents();
|
|
4046
|
+
}
|
|
4047
|
+
for (const agent of targetAgents) {
|
|
4048
|
+
const adapter = getAdapter(agent);
|
|
4049
|
+
try {
|
|
4050
|
+
const skills = await adapter.list(agent, {
|
|
4051
|
+
projectPath: options?.projectPath
|
|
4052
|
+
});
|
|
4053
|
+
result.set(agent.name, skills);
|
|
4054
|
+
} catch (err) {
|
|
4055
|
+
logger.debug(`Error listing skills for ${agent.displayName}: ${err.message}`);
|
|
4056
|
+
result.set(agent.name, []);
|
|
4057
|
+
}
|
|
4058
|
+
}
|
|
4059
|
+
return result;
|
|
4060
|
+
}
|
|
4061
|
+
async function syncSkillToAllPlatforms(skillName, options) {
|
|
4062
|
+
const needsSync = /* @__PURE__ */ new Map();
|
|
4063
|
+
const synced = /* @__PURE__ */ new Map();
|
|
4064
|
+
const sourcePath = skillName === "refly" ? getReflyBaseSkillDir() : getReflyDomainSkillDir(skillName);
|
|
4065
|
+
let targetAgents;
|
|
4066
|
+
if (options?.agents && options.agents.length > 0) {
|
|
4067
|
+
targetAgents = options.agents.map((name) => agents[name]).filter(Boolean);
|
|
4068
|
+
} else {
|
|
4069
|
+
targetAgents = await getDeployableAgents();
|
|
4070
|
+
}
|
|
4071
|
+
for (const agent of targetAgents) {
|
|
4072
|
+
const adapter = getAdapter(agent);
|
|
4073
|
+
try {
|
|
4074
|
+
const status = await adapter.isDeployed(skillName, agent, {
|
|
4075
|
+
projectPath: options?.projectPath
|
|
4076
|
+
});
|
|
4077
|
+
needsSync.set(agent.name, status);
|
|
4078
|
+
if ((!status.deployed || !status.valid) && !options?.dryRun) {
|
|
4079
|
+
const deployResult = await adapter.deploy(skillName, sourcePath, agent, {
|
|
4080
|
+
force: true,
|
|
4081
|
+
// Force to repair
|
|
4082
|
+
projectPath: options?.projectPath
|
|
4083
|
+
});
|
|
4084
|
+
synced.set(agent.name, deployResult);
|
|
4085
|
+
}
|
|
4086
|
+
} catch (err) {
|
|
4087
|
+
logger.debug(
|
|
4088
|
+
`Error checking/syncing ${skillName} for ${agent.displayName}: ${err.message}`
|
|
4089
|
+
);
|
|
4090
|
+
}
|
|
4091
|
+
}
|
|
4092
|
+
return { needsSync, synced };
|
|
4093
|
+
}
|
|
4094
|
+
var fs7;
|
|
4095
|
+
var init_manager = __esm({
|
|
4096
|
+
"src/platform/manager.ts"() {
|
|
4097
|
+
"use strict";
|
|
4098
|
+
init_cjs_shims();
|
|
4099
|
+
fs7 = __toESM(require("fs"));
|
|
4100
|
+
init_registry();
|
|
4101
|
+
init_symlink_adapter();
|
|
4102
|
+
init_format_converter();
|
|
4103
|
+
init_paths();
|
|
4104
|
+
init_logger();
|
|
4105
|
+
}
|
|
4106
|
+
});
|
|
4107
|
+
|
|
3263
4108
|
// src/skill/symlink.ts
|
|
3264
4109
|
var symlink_exports = {};
|
|
3265
4110
|
__export(symlink_exports, {
|
|
4111
|
+
createMultiPlatformSkill: () => createMultiPlatformSkill,
|
|
3266
4112
|
createReflySkillWithSymlink: () => createReflySkillWithSymlink,
|
|
3267
4113
|
createSkillSymlink: () => createSkillSymlink,
|
|
3268
4114
|
deleteDomainSkillWithSymlink: () => deleteDomainSkillWithSymlink,
|
|
3269
4115
|
generateReflySkillMd: () => generateReflySkillMd,
|
|
3270
4116
|
initializeBaseSkillSymlink: () => initializeBaseSkillSymlink,
|
|
3271
4117
|
isSkillSymlinkValid: () => isSkillSymlinkValid,
|
|
4118
|
+
listMultiPlatformSkills: () => listMultiPlatformSkills,
|
|
3272
4119
|
listSkillSymlinks: () => listSkillSymlinks,
|
|
3273
4120
|
parseReflySkillMd: () => parseReflySkillMd,
|
|
4121
|
+
removeMultiPlatformSkill: () => removeMultiPlatformSkill,
|
|
3274
4122
|
removeSkillSymlink: () => removeSkillSymlink
|
|
3275
4123
|
});
|
|
3276
4124
|
function createSkillSymlink(skillName) {
|
|
@@ -3279,7 +4127,7 @@ function createSkillSymlink(skillName) {
|
|
|
3279
4127
|
try {
|
|
3280
4128
|
ensureReflySkillsDir();
|
|
3281
4129
|
ensureClaudeSkillsDir();
|
|
3282
|
-
if (!
|
|
4130
|
+
if (!fs8.existsSync(reflyPath)) {
|
|
3283
4131
|
return {
|
|
3284
4132
|
success: false,
|
|
3285
4133
|
skillName,
|
|
@@ -3288,10 +4136,10 @@ function createSkillSymlink(skillName) {
|
|
|
3288
4136
|
error: `Source skill directory does not exist: ${reflyPath}`
|
|
3289
4137
|
};
|
|
3290
4138
|
}
|
|
3291
|
-
if (
|
|
3292
|
-
const stat =
|
|
4139
|
+
if (fs8.existsSync(claudePath) || fs8.lstatSync(claudePath).isSymbolicLink()) {
|
|
4140
|
+
const stat = fs8.lstatSync(claudePath);
|
|
3293
4141
|
if (stat.isSymbolicLink()) {
|
|
3294
|
-
|
|
4142
|
+
fs8.unlinkSync(claudePath);
|
|
3295
4143
|
logger.debug(`Removed existing symlink: ${claudePath}`);
|
|
3296
4144
|
} else if (stat.isDirectory()) {
|
|
3297
4145
|
logger.warn(`Cannot create symlink: ${claudePath} is a directory, not a symlink`);
|
|
@@ -3304,7 +4152,7 @@ function createSkillSymlink(skillName) {
|
|
|
3304
4152
|
};
|
|
3305
4153
|
}
|
|
3306
4154
|
}
|
|
3307
|
-
|
|
4155
|
+
fs8.symlinkSync(reflyPath, claudePath, "dir");
|
|
3308
4156
|
logger.info(`Created symlink: ${claudePath} -> ${reflyPath}`);
|
|
3309
4157
|
return {
|
|
3310
4158
|
success: true,
|
|
@@ -3315,7 +4163,7 @@ function createSkillSymlink(skillName) {
|
|
|
3315
4163
|
} catch (err) {
|
|
3316
4164
|
if (err.code === "ENOENT") {
|
|
3317
4165
|
try {
|
|
3318
|
-
|
|
4166
|
+
fs8.symlinkSync(reflyPath, claudePath, "dir");
|
|
3319
4167
|
logger.info(`Created symlink: ${claudePath} -> ${reflyPath}`);
|
|
3320
4168
|
return {
|
|
3321
4169
|
success: true,
|
|
@@ -3345,16 +4193,16 @@ function createSkillSymlink(skillName) {
|
|
|
3345
4193
|
function removeSkillSymlink(skillName) {
|
|
3346
4194
|
const claudePath = getClaudeSkillSymlinkPath(skillName);
|
|
3347
4195
|
try {
|
|
3348
|
-
if (!
|
|
4196
|
+
if (!fs8.existsSync(claudePath)) {
|
|
3349
4197
|
logger.debug(`Symlink not found: ${claudePath}`);
|
|
3350
4198
|
return false;
|
|
3351
4199
|
}
|
|
3352
|
-
const stat =
|
|
4200
|
+
const stat = fs8.lstatSync(claudePath);
|
|
3353
4201
|
if (!stat.isSymbolicLink()) {
|
|
3354
4202
|
logger.warn(`Not a symlink: ${claudePath}`);
|
|
3355
4203
|
return false;
|
|
3356
4204
|
}
|
|
3357
|
-
|
|
4205
|
+
fs8.unlinkSync(claudePath);
|
|
3358
4206
|
logger.info(`Removed symlink: ${claudePath}`);
|
|
3359
4207
|
return true;
|
|
3360
4208
|
} catch (err) {
|
|
@@ -3366,16 +4214,16 @@ function isSkillSymlinkValid(skillName) {
|
|
|
3366
4214
|
const claudePath = getClaudeSkillSymlinkPath(skillName);
|
|
3367
4215
|
const expectedTarget = skillName === "refly" ? getReflyBaseSkillDir() : getReflyDomainSkillDir(skillName);
|
|
3368
4216
|
try {
|
|
3369
|
-
if (!
|
|
4217
|
+
if (!fs8.existsSync(claudePath)) {
|
|
3370
4218
|
return { exists: false, isSymlink: false, isValid: false };
|
|
3371
4219
|
}
|
|
3372
|
-
const stat =
|
|
4220
|
+
const stat = fs8.lstatSync(claudePath);
|
|
3373
4221
|
if (!stat.isSymbolicLink()) {
|
|
3374
4222
|
return { exists: true, isSymlink: false, isValid: false };
|
|
3375
4223
|
}
|
|
3376
|
-
const target =
|
|
3377
|
-
const resolvedTarget =
|
|
3378
|
-
const isValid2 = resolvedTarget === expectedTarget &&
|
|
4224
|
+
const target = fs8.readlinkSync(claudePath);
|
|
4225
|
+
const resolvedTarget = path7.resolve(path7.dirname(claudePath), target);
|
|
4226
|
+
const isValid2 = resolvedTarget === expectedTarget && fs8.existsSync(resolvedTarget);
|
|
3379
4227
|
return {
|
|
3380
4228
|
exists: true,
|
|
3381
4229
|
isSymlink: true,
|
|
@@ -3389,17 +4237,17 @@ function isSkillSymlinkValid(skillName) {
|
|
|
3389
4237
|
function initializeBaseSkillSymlink() {
|
|
3390
4238
|
const baseDir = getReflyBaseSkillDir();
|
|
3391
4239
|
ensureDir(baseDir);
|
|
3392
|
-
ensureDir(
|
|
4240
|
+
ensureDir(path7.join(baseDir, "rules"));
|
|
3393
4241
|
return createSkillSymlink("refly");
|
|
3394
4242
|
}
|
|
3395
4243
|
function createReflySkillWithSymlink(skillName, skillMdContent, options) {
|
|
3396
4244
|
const skillDir = getReflyDomainSkillDir(skillName);
|
|
3397
4245
|
try {
|
|
3398
4246
|
ensureReflySkillsDir();
|
|
3399
|
-
if (
|
|
4247
|
+
if (fs8.existsSync(skillDir)) {
|
|
3400
4248
|
if (options?.force) {
|
|
3401
|
-
const skillMdPath2 =
|
|
3402
|
-
|
|
4249
|
+
const skillMdPath2 = path7.join(skillDir, "SKILL.md");
|
|
4250
|
+
fs8.writeFileSync(skillMdPath2, skillMdContent, { encoding: "utf-8", mode: 420 });
|
|
3403
4251
|
logger.debug(`Updated SKILL.md (force): ${skillMdPath2}`);
|
|
3404
4252
|
return createSkillSymlink(skillName);
|
|
3405
4253
|
}
|
|
@@ -3411,9 +4259,9 @@ function createReflySkillWithSymlink(skillName, skillMdContent, options) {
|
|
|
3411
4259
|
error: `Skill directory already exists: ${skillDir}`
|
|
3412
4260
|
};
|
|
3413
4261
|
}
|
|
3414
|
-
|
|
3415
|
-
const skillMdPath =
|
|
3416
|
-
|
|
4262
|
+
fs8.mkdirSync(skillDir, { recursive: true, mode: 493 });
|
|
4263
|
+
const skillMdPath = path7.join(skillDir, "SKILL.md");
|
|
4264
|
+
fs8.writeFileSync(skillMdPath, skillMdContent, { encoding: "utf-8", mode: 420 });
|
|
3417
4265
|
logger.debug(`Created SKILL.md: ${skillMdPath}`);
|
|
3418
4266
|
return createSkillSymlink(skillName);
|
|
3419
4267
|
} catch (err) {
|
|
@@ -3431,8 +4279,8 @@ function deleteDomainSkillWithSymlink(skillName) {
|
|
|
3431
4279
|
const skillDir = getReflyDomainSkillDir(skillName);
|
|
3432
4280
|
let directoryRemoved = false;
|
|
3433
4281
|
try {
|
|
3434
|
-
if (
|
|
3435
|
-
|
|
4282
|
+
if (fs8.existsSync(skillDir)) {
|
|
4283
|
+
fs8.rmSync(skillDir, { recursive: true, force: true });
|
|
3436
4284
|
directoryRemoved = true;
|
|
3437
4285
|
logger.info(`Removed skill directory: ${skillDir}`);
|
|
3438
4286
|
}
|
|
@@ -3444,19 +4292,19 @@ function deleteDomainSkillWithSymlink(skillName) {
|
|
|
3444
4292
|
function listSkillSymlinks() {
|
|
3445
4293
|
const claudeSkillsDir = getClaudeSkillsDir();
|
|
3446
4294
|
const results = [];
|
|
3447
|
-
if (!
|
|
4295
|
+
if (!fs8.existsSync(claudeSkillsDir)) {
|
|
3448
4296
|
return results;
|
|
3449
4297
|
}
|
|
3450
4298
|
try {
|
|
3451
|
-
const entries =
|
|
4299
|
+
const entries = fs8.readdirSync(claudeSkillsDir, { withFileTypes: true });
|
|
3452
4300
|
for (const entry of entries) {
|
|
3453
|
-
const fullPath =
|
|
4301
|
+
const fullPath = path7.join(claudeSkillsDir, entry.name);
|
|
3454
4302
|
try {
|
|
3455
|
-
const stat =
|
|
4303
|
+
const stat = fs8.lstatSync(fullPath);
|
|
3456
4304
|
if (stat.isSymbolicLink()) {
|
|
3457
|
-
const target =
|
|
3458
|
-
const resolvedTarget =
|
|
3459
|
-
const isValid2 =
|
|
4305
|
+
const target = fs8.readlinkSync(fullPath);
|
|
4306
|
+
const resolvedTarget = path7.resolve(path7.dirname(fullPath), target);
|
|
4307
|
+
const isValid2 = fs8.existsSync(resolvedTarget);
|
|
3460
4308
|
results.push({
|
|
3461
4309
|
name: entry.name,
|
|
3462
4310
|
claudePath: fullPath,
|
|
@@ -3471,6 +4319,12 @@ function listSkillSymlinks() {
|
|
|
3471
4319
|
}
|
|
3472
4320
|
return results;
|
|
3473
4321
|
}
|
|
4322
|
+
function escapeYamlValue(value) {
|
|
4323
|
+
if (value.includes(":") || value.includes("#") || value.includes("'") || value.includes('"') || value.includes("\n") || value.startsWith(" ") || value.endsWith(" ") || value.startsWith("[") || value.startsWith("{")) {
|
|
4324
|
+
return `"${value.replace(/\\/g, "\\\\").replace(/"/g, '\\"')}"`;
|
|
4325
|
+
}
|
|
4326
|
+
return value;
|
|
4327
|
+
}
|
|
3474
4328
|
function generateReflySkillMd(options) {
|
|
3475
4329
|
const {
|
|
3476
4330
|
name,
|
|
@@ -3485,21 +4339,21 @@ function generateReflySkillMd(options) {
|
|
|
3485
4339
|
inputSchema,
|
|
3486
4340
|
outputSchema
|
|
3487
4341
|
} = options;
|
|
3488
|
-
const frontmatterLines = ["---", `name: ${name}`];
|
|
3489
|
-
frontmatterLines.push(`description: ${description}`);
|
|
4342
|
+
const frontmatterLines = ["---", `name: ${escapeYamlValue(name)}`];
|
|
4343
|
+
frontmatterLines.push(`description: ${escapeYamlValue(description)}`);
|
|
3490
4344
|
if (tags.length > 0) {
|
|
3491
4345
|
frontmatterLines.push("tags:");
|
|
3492
|
-
frontmatterLines.push(...tags.map((t) => ` - ${t}`));
|
|
4346
|
+
frontmatterLines.push(...tags.map((t) => ` - ${escapeYamlValue(t)}`));
|
|
3493
4347
|
}
|
|
3494
|
-
frontmatterLines.push(`version: ${version}`);
|
|
3495
|
-
frontmatterLines.push(`skillId: ${skillId}`);
|
|
3496
|
-
frontmatterLines.push(`workflowId: ${workflowId}`);
|
|
4348
|
+
frontmatterLines.push(`version: ${escapeYamlValue(version)}`);
|
|
4349
|
+
frontmatterLines.push(`skillId: ${escapeYamlValue(skillId)}`);
|
|
4350
|
+
frontmatterLines.push(`workflowId: ${escapeYamlValue(workflowId)}`);
|
|
3497
4351
|
if (installationId) {
|
|
3498
|
-
frontmatterLines.push(`installationId: ${installationId}`);
|
|
4352
|
+
frontmatterLines.push(`installationId: ${escapeYamlValue(installationId)}`);
|
|
3499
4353
|
}
|
|
3500
4354
|
if (triggers.length > 0) {
|
|
3501
4355
|
frontmatterLines.push("triggers:");
|
|
3502
|
-
frontmatterLines.push(...triggers.map((t) => ` - ${t}`));
|
|
4356
|
+
frontmatterLines.push(...triggers.map((t) => ` - ${escapeYamlValue(t)}`));
|
|
3503
4357
|
}
|
|
3504
4358
|
frontmatterLines.push("---");
|
|
3505
4359
|
const title = displayName || name.split("-").map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
|
|
@@ -3518,14 +4372,6 @@ ${JSON.stringify(outputSchema, null, 2)}
|
|
|
3518
4372
|
|
|
3519
4373
|
${description}
|
|
3520
4374
|
|
|
3521
|
-
## Usage
|
|
3522
|
-
|
|
3523
|
-
This skill is executed via Refly CLI:
|
|
3524
|
-
|
|
3525
|
-
\`\`\`bash
|
|
3526
|
-
${runCommand}
|
|
3527
|
-
\`\`\`
|
|
3528
|
-
|
|
3529
4375
|
## Input
|
|
3530
4376
|
|
|
3531
4377
|
Provide input as JSON:
|
|
@@ -3534,16 +4380,42 @@ Provide input as JSON:
|
|
|
3534
4380
|
${inputExample}
|
|
3535
4381
|
\`\`\`
|
|
3536
4382
|
|
|
4383
|
+
## Execution
|
|
4384
|
+
|
|
4385
|
+
**Follow this exact 4-step pattern:**
|
|
4386
|
+
|
|
4387
|
+
\`\`\`bash
|
|
4388
|
+
# Step 1: Run and capture RUN_ID (we-xxx format)
|
|
4389
|
+
RESULT=$(${runCommand})
|
|
4390
|
+
RUN_ID=$(echo "$RESULT" | jq -r '.payload.workflowExecutions[0].id')
|
|
4391
|
+
# RUN_ID is we-xxx format, use this for workflow commands below
|
|
4392
|
+
|
|
4393
|
+
# Step 2: Wait for completion (use RUN_ID, not installationId)
|
|
4394
|
+
refly workflow status "$RUN_ID" --watch --interval 30000
|
|
4395
|
+
|
|
4396
|
+
# Step 3: Get files from this run (use RUN_ID)
|
|
4397
|
+
FILES=$(refly workflow toolcalls "$RUN_ID" --files --latest | jq -r '.payload.files[]')
|
|
4398
|
+
|
|
4399
|
+
# Step 4: Download and open each file
|
|
4400
|
+
echo "$FILES" | jq -c '.' | while read -r file; do
|
|
4401
|
+
FILE_ID=$(echo "$file" | jq -r '.fileId')
|
|
4402
|
+
FILE_NAME=$(echo "$file" | jq -r '.name')
|
|
4403
|
+
if [ -n "$FILE_ID" ] && [ "$FILE_ID" != "null" ]; then
|
|
4404
|
+
OUTPUT_PATH="$HOME/Desktop/$FILE_NAME"
|
|
4405
|
+
refly file download "$FILE_ID" -o "$OUTPUT_PATH"
|
|
4406
|
+
open "$OUTPUT_PATH"
|
|
4407
|
+
fi
|
|
4408
|
+
done
|
|
4409
|
+
\`\`\`
|
|
4410
|
+
|
|
3537
4411
|
## Output
|
|
3538
4412
|
|
|
3539
4413
|
${outputSection}
|
|
3540
4414
|
|
|
3541
4415
|
## Rules
|
|
3542
4416
|
|
|
3543
|
-
For workflow operations, refer to the base skill
|
|
3544
|
-
-
|
|
3545
|
-
- Node: \`~/.claude/skills/refly/rules/node.md\`
|
|
3546
|
-
- File: \`~/.claude/skills/refly/rules/file.md\`
|
|
4417
|
+
For workflow operations, refer to the base skill:
|
|
4418
|
+
- Base skill: \`~/.claude/skills/refly/SKILL.md\`
|
|
3547
4419
|
`;
|
|
3548
4420
|
return frontmatterLines.join("\n") + content;
|
|
3549
4421
|
}
|
|
@@ -3604,15 +4476,79 @@ function parseReflySkillMd(content) {
|
|
|
3604
4476
|
raw: content
|
|
3605
4477
|
};
|
|
3606
4478
|
}
|
|
3607
|
-
|
|
4479
|
+
async function createMultiPlatformSkill(skillName, skillMdContent, options) {
|
|
4480
|
+
const skillDir = getReflyDomainSkillDir(skillName);
|
|
4481
|
+
ensureReflySkillsDir();
|
|
4482
|
+
if (fs8.existsSync(skillDir)) {
|
|
4483
|
+
if (options?.force) {
|
|
4484
|
+
const skillMdPath = path7.join(skillDir, "SKILL.md");
|
|
4485
|
+
fs8.writeFileSync(skillMdPath, skillMdContent, { encoding: "utf-8", mode: 420 });
|
|
4486
|
+
logger.debug(`Updated SKILL.md (force): ${skillMdPath}`);
|
|
4487
|
+
} else {
|
|
4488
|
+
return {
|
|
4489
|
+
skillName,
|
|
4490
|
+
sourcePath: skillDir,
|
|
4491
|
+
results: /* @__PURE__ */ new Map(),
|
|
4492
|
+
successCount: 0,
|
|
4493
|
+
failureCount: 1
|
|
4494
|
+
};
|
|
4495
|
+
}
|
|
4496
|
+
} else {
|
|
4497
|
+
fs8.mkdirSync(skillDir, { recursive: true, mode: 493 });
|
|
4498
|
+
const skillMdPath = path7.join(skillDir, "SKILL.md");
|
|
4499
|
+
fs8.writeFileSync(skillMdPath, skillMdContent, { encoding: "utf-8", mode: 420 });
|
|
4500
|
+
logger.debug(`Created SKILL.md: ${skillMdPath}`);
|
|
4501
|
+
}
|
|
4502
|
+
return deploySkillToAllPlatforms(skillName, {
|
|
4503
|
+
force: options?.force,
|
|
4504
|
+
agents: options?.agents
|
|
4505
|
+
});
|
|
4506
|
+
}
|
|
4507
|
+
async function removeMultiPlatformSkill(skillName, options) {
|
|
4508
|
+
const platformResults = await removeSkillFromAllPlatforms(skillName, {
|
|
4509
|
+
agents: options?.agents
|
|
4510
|
+
});
|
|
4511
|
+
let directoryRemoved = false;
|
|
4512
|
+
if (!options?.keepLocal) {
|
|
4513
|
+
const skillDir = getReflyDomainSkillDir(skillName);
|
|
4514
|
+
try {
|
|
4515
|
+
if (fs8.existsSync(skillDir)) {
|
|
4516
|
+
fs8.rmSync(skillDir, { recursive: true, force: true });
|
|
4517
|
+
directoryRemoved = true;
|
|
4518
|
+
logger.info(`Removed skill directory: ${skillDir}`);
|
|
4519
|
+
}
|
|
4520
|
+
} catch (err) {
|
|
4521
|
+
logger.error(`Failed to remove skill directory ${skillDir}:`, err);
|
|
4522
|
+
}
|
|
4523
|
+
}
|
|
4524
|
+
return { platformResults, directoryRemoved };
|
|
4525
|
+
}
|
|
4526
|
+
async function listMultiPlatformSkills(options) {
|
|
4527
|
+
const allDeployed = await listAllDeployedSkills({ agents: options?.agents });
|
|
4528
|
+
const result = /* @__PURE__ */ new Map();
|
|
4529
|
+
for (const [agent, skills] of allDeployed) {
|
|
4530
|
+
result.set(
|
|
4531
|
+
agent,
|
|
4532
|
+
skills.map((s) => ({
|
|
4533
|
+
name: s.name,
|
|
4534
|
+
path: s.path,
|
|
4535
|
+
isValid: s.isValid,
|
|
4536
|
+
isSymlink: s.isSymlink
|
|
4537
|
+
}))
|
|
4538
|
+
);
|
|
4539
|
+
}
|
|
4540
|
+
return result;
|
|
4541
|
+
}
|
|
4542
|
+
var fs8, path7;
|
|
3608
4543
|
var init_symlink = __esm({
|
|
3609
4544
|
"src/skill/symlink.ts"() {
|
|
3610
4545
|
"use strict";
|
|
3611
4546
|
init_cjs_shims();
|
|
3612
|
-
|
|
3613
|
-
|
|
4547
|
+
fs8 = __toESM(require("fs"));
|
|
4548
|
+
path7 = __toESM(require("path"));
|
|
3614
4549
|
init_paths();
|
|
3615
4550
|
init_logger();
|
|
4551
|
+
init_manager();
|
|
3616
4552
|
}
|
|
3617
4553
|
});
|
|
3618
4554
|
|
|
@@ -4303,8 +5239,18 @@ var OutputFormatter = class {
|
|
|
4303
5239
|
}
|
|
4304
5240
|
// === JSON Format ===
|
|
4305
5241
|
outputJson(data) {
|
|
4306
|
-
console.log(JSON.stringify(data,
|
|
5242
|
+
console.log(JSON.stringify(data, this.sanitizeJsonReplacer, 2));
|
|
4307
5243
|
}
|
|
5244
|
+
/**
|
|
5245
|
+
* JSON replacer that sanitizes control characters in strings.
|
|
5246
|
+
* Control characters (U+0000 to U+001F) can break jq parsing.
|
|
5247
|
+
*/
|
|
5248
|
+
sanitizeJsonReplacer = (_key, value) => {
|
|
5249
|
+
if (typeof value === "string") {
|
|
5250
|
+
return value.replace(/[\x00-\x08\x0B\x0C\x0E-\x1F]/g, "");
|
|
5251
|
+
}
|
|
5252
|
+
return value;
|
|
5253
|
+
};
|
|
4308
5254
|
// === Pretty Format ===
|
|
4309
5255
|
outputPretty(type, payload) {
|
|
4310
5256
|
if (type === "workflow.status" || type === "workflow.progress") {
|
|
@@ -4893,8 +5839,8 @@ var ErrorCodes = {
|
|
|
4893
5839
|
};
|
|
4894
5840
|
|
|
4895
5841
|
// src/bin/refly.ts
|
|
4896
|
-
var
|
|
4897
|
-
var
|
|
5842
|
+
var fs31 = __toESM(require("fs"));
|
|
5843
|
+
var path24 = __toESM(require("path"));
|
|
4898
5844
|
|
|
4899
5845
|
// src/commands/init.ts
|
|
4900
5846
|
init_cjs_shims();
|
|
@@ -5399,8 +6345,8 @@ function getErrorMap() {
|
|
|
5399
6345
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
5400
6346
|
init_cjs_shims();
|
|
5401
6347
|
var makeIssue = (params) => {
|
|
5402
|
-
const { data, path:
|
|
5403
|
-
const fullPath = [...
|
|
6348
|
+
const { data, path: path25, errorMaps, issueData } = params;
|
|
6349
|
+
const fullPath = [...path25, ...issueData.path || []];
|
|
5404
6350
|
const fullIssue = {
|
|
5405
6351
|
...issueData,
|
|
5406
6352
|
path: fullPath
|
|
@@ -5520,11 +6466,11 @@ var errorUtil;
|
|
|
5520
6466
|
|
|
5521
6467
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
5522
6468
|
var ParseInputLazyPath = class {
|
|
5523
|
-
constructor(parent, value,
|
|
6469
|
+
constructor(parent, value, path25, key) {
|
|
5524
6470
|
this._cachedPath = [];
|
|
5525
6471
|
this.parent = parent;
|
|
5526
6472
|
this.data = value;
|
|
5527
|
-
this._path =
|
|
6473
|
+
this._path = path25;
|
|
5528
6474
|
this._key = key;
|
|
5529
6475
|
}
|
|
5530
6476
|
get path() {
|
|
@@ -8968,6 +9914,23 @@ var NEVER = INVALID;
|
|
|
8968
9914
|
|
|
8969
9915
|
// src/config/config.ts
|
|
8970
9916
|
init_paths();
|
|
9917
|
+
var AgentTypeEnum = external_exports.enum([
|
|
9918
|
+
"claude-code",
|
|
9919
|
+
"codex",
|
|
9920
|
+
"antigravity",
|
|
9921
|
+
"github-copilot",
|
|
9922
|
+
"windsurf",
|
|
9923
|
+
"opencode",
|
|
9924
|
+
"moltbot",
|
|
9925
|
+
"cursor",
|
|
9926
|
+
"continue",
|
|
9927
|
+
"trae",
|
|
9928
|
+
"qoder"
|
|
9929
|
+
]);
|
|
9930
|
+
var PlatformConfigSchema = external_exports.object({
|
|
9931
|
+
enabled: external_exports.boolean().default(true),
|
|
9932
|
+
globalPath: external_exports.string().optional()
|
|
9933
|
+
});
|
|
8971
9934
|
var ConfigSchema = external_exports.object({
|
|
8972
9935
|
version: external_exports.number().default(1),
|
|
8973
9936
|
auth: external_exports.object({
|
|
@@ -8995,7 +9958,9 @@ var ConfigSchema = external_exports.object({
|
|
|
8995
9958
|
skill: external_exports.object({
|
|
8996
9959
|
installedVersion: external_exports.string().optional(),
|
|
8997
9960
|
installedAt: external_exports.string().optional()
|
|
8998
|
-
}).optional()
|
|
9961
|
+
}).optional(),
|
|
9962
|
+
// Multi-platform configuration
|
|
9963
|
+
platforms: external_exports.record(AgentTypeEnum, PlatformConfigSchema).optional()
|
|
8999
9964
|
});
|
|
9000
9965
|
var DEFAULT_API_ENDPOINT = "https://api.refly.ai";
|
|
9001
9966
|
var DEFAULT_WEB_URL = "https://refly.ai";
|
|
@@ -9132,22 +10097,22 @@ init_paths();
|
|
|
9132
10097
|
|
|
9133
10098
|
// src/skill/installer.ts
|
|
9134
10099
|
init_cjs_shims();
|
|
9135
|
-
var
|
|
9136
|
-
var
|
|
10100
|
+
var fs9 = __toESM(require("fs"));
|
|
10101
|
+
var path8 = __toESM(require("path"));
|
|
9137
10102
|
init_paths();
|
|
9138
10103
|
init_logger();
|
|
9139
10104
|
init_symlink();
|
|
9140
10105
|
function removeOldSkillDirectory() {
|
|
9141
10106
|
const claudeSkillPath = getClaudeSkillSymlinkPath("refly");
|
|
9142
|
-
if (!
|
|
10107
|
+
if (!fs9.existsSync(claudeSkillPath)) {
|
|
9143
10108
|
return;
|
|
9144
10109
|
}
|
|
9145
10110
|
try {
|
|
9146
|
-
const stat =
|
|
10111
|
+
const stat = fs9.lstatSync(claudeSkillPath);
|
|
9147
10112
|
if (stat.isSymbolicLink()) {
|
|
9148
|
-
|
|
10113
|
+
fs9.unlinkSync(claudeSkillPath);
|
|
9149
10114
|
} else if (stat.isDirectory()) {
|
|
9150
|
-
|
|
10115
|
+
fs9.rmSync(claudeSkillPath, { recursive: true, force: true });
|
|
9151
10116
|
logger.info("Removed old skill directory");
|
|
9152
10117
|
}
|
|
9153
10118
|
} catch (err) {
|
|
@@ -9156,17 +10121,17 @@ function removeOldSkillDirectory() {
|
|
|
9156
10121
|
}
|
|
9157
10122
|
function getPackageSkillDir() {
|
|
9158
10123
|
const possiblePaths = [
|
|
9159
|
-
|
|
10124
|
+
path8.join(__dirname, "..", "..", "skill"),
|
|
9160
10125
|
// Built package: dist/bin/../../skill
|
|
9161
|
-
|
|
10126
|
+
path8.join(__dirname, "..", "..", "..", "skill"),
|
|
9162
10127
|
// Development: dist/bin/../../../skill
|
|
9163
|
-
|
|
10128
|
+
path8.join(__dirname, "..", "skill")
|
|
9164
10129
|
// Alternative: dist/../skill
|
|
9165
10130
|
];
|
|
9166
10131
|
logger.debug("Looking for skill files, __dirname:", __dirname);
|
|
9167
10132
|
for (const p of possiblePaths) {
|
|
9168
|
-
const resolved =
|
|
9169
|
-
const exists =
|
|
10133
|
+
const resolved = path8.resolve(p);
|
|
10134
|
+
const exists = fs9.existsSync(resolved);
|
|
9170
10135
|
logger.debug(` Checking path: ${resolved} - exists: ${exists}`);
|
|
9171
10136
|
if (exists) {
|
|
9172
10137
|
return resolved;
|
|
@@ -9190,30 +10155,30 @@ function installSkill() {
|
|
|
9190
10155
|
logger.debug("Target skill directory:", targetDir);
|
|
9191
10156
|
try {
|
|
9192
10157
|
ensureDir(targetDir);
|
|
9193
|
-
ensureDir(
|
|
10158
|
+
ensureDir(path8.join(targetDir, "rules"));
|
|
9194
10159
|
logger.debug("Created target directories");
|
|
9195
10160
|
} catch (err) {
|
|
9196
10161
|
logger.error("Failed to create target directories:", err);
|
|
9197
10162
|
throw err;
|
|
9198
10163
|
}
|
|
9199
|
-
const skillSource =
|
|
9200
|
-
const skillTarget =
|
|
10164
|
+
const skillSource = path8.join(sourceDir, "SKILL.md");
|
|
10165
|
+
const skillTarget = path8.join(targetDir, "SKILL.md");
|
|
9201
10166
|
logger.debug(`Copying SKILL.md: ${skillSource} -> ${skillTarget}`);
|
|
9202
|
-
if (
|
|
9203
|
-
|
|
10167
|
+
if (fs9.existsSync(skillSource)) {
|
|
10168
|
+
fs9.copyFileSync(skillSource, skillTarget);
|
|
9204
10169
|
result.skillInstalled = true;
|
|
9205
10170
|
result.skillPath = targetDir;
|
|
9206
10171
|
logger.debug("SKILL.md copied successfully");
|
|
9207
10172
|
} else {
|
|
9208
10173
|
logger.warn("SKILL.md source not found:", skillSource);
|
|
9209
10174
|
}
|
|
9210
|
-
const refsSource =
|
|
9211
|
-
const rulesTarget =
|
|
9212
|
-
if (
|
|
9213
|
-
const files =
|
|
10175
|
+
const refsSource = path8.join(sourceDir, "references");
|
|
10176
|
+
const rulesTarget = path8.join(targetDir, "rules");
|
|
10177
|
+
if (fs9.existsSync(refsSource)) {
|
|
10178
|
+
const files = fs9.readdirSync(refsSource);
|
|
9214
10179
|
logger.debug(`Copying ${files.length} rule files`);
|
|
9215
10180
|
for (const file of files) {
|
|
9216
|
-
|
|
10181
|
+
fs9.copyFileSync(path8.join(refsSource, file), path8.join(rulesTarget, file));
|
|
9217
10182
|
}
|
|
9218
10183
|
}
|
|
9219
10184
|
removeOldSkillDirectory();
|
|
@@ -9241,15 +10206,15 @@ function installSkill() {
|
|
|
9241
10206
|
return result;
|
|
9242
10207
|
}
|
|
9243
10208
|
function installSlashCommands(sourceDir, targetDir) {
|
|
9244
|
-
const commandsSource =
|
|
9245
|
-
if (!
|
|
10209
|
+
const commandsSource = path8.join(sourceDir, "..", "commands");
|
|
10210
|
+
if (!fs9.existsSync(commandsSource)) {
|
|
9246
10211
|
return false;
|
|
9247
10212
|
}
|
|
9248
10213
|
try {
|
|
9249
|
-
const files =
|
|
10214
|
+
const files = fs9.readdirSync(commandsSource);
|
|
9250
10215
|
for (const file of files) {
|
|
9251
10216
|
if (file.endsWith(".md")) {
|
|
9252
|
-
|
|
10217
|
+
fs9.copyFileSync(path8.join(commandsSource, file), path8.join(targetDir, file));
|
|
9253
10218
|
}
|
|
9254
10219
|
}
|
|
9255
10220
|
return files.length > 0;
|
|
@@ -9259,8 +10224,8 @@ function installSlashCommands(sourceDir, targetDir) {
|
|
|
9259
10224
|
}
|
|
9260
10225
|
function getSkillVersion() {
|
|
9261
10226
|
try {
|
|
9262
|
-
const skillPath =
|
|
9263
|
-
const content =
|
|
10227
|
+
const skillPath = path8.join(getPackageSkillDir(), "SKILL.md");
|
|
10228
|
+
const content = fs9.readFileSync(skillPath, "utf-8");
|
|
9264
10229
|
const versionMatch = content.match(/version:\s*(\d+\.\d+\.\d+)/);
|
|
9265
10230
|
if (versionMatch) {
|
|
9266
10231
|
return versionMatch[1];
|
|
@@ -9268,16 +10233,16 @@ function getSkillVersion() {
|
|
|
9268
10233
|
} catch {
|
|
9269
10234
|
}
|
|
9270
10235
|
try {
|
|
9271
|
-
const pkgPath =
|
|
9272
|
-
const pkg = JSON.parse(
|
|
10236
|
+
const pkgPath = path8.join(__dirname, "..", "..", "package.json");
|
|
10237
|
+
const pkg = JSON.parse(fs9.readFileSync(pkgPath, "utf-8"));
|
|
9273
10238
|
return pkg.version;
|
|
9274
10239
|
} catch {
|
|
9275
10240
|
return "0.1.0";
|
|
9276
10241
|
}
|
|
9277
10242
|
}
|
|
9278
10243
|
function isSkillInstalled() {
|
|
9279
|
-
const skillPath =
|
|
9280
|
-
if (!
|
|
10244
|
+
const skillPath = path8.join(getReflyBaseSkillDir(), "SKILL.md");
|
|
10245
|
+
if (!fs9.existsSync(skillPath)) {
|
|
9281
10246
|
return { installed: false, upToDate: false };
|
|
9282
10247
|
}
|
|
9283
10248
|
const currentVersion = getSkillVersion();
|
|
@@ -9291,6 +10256,9 @@ function isSkillInstalled() {
|
|
|
9291
10256
|
};
|
|
9292
10257
|
}
|
|
9293
10258
|
|
|
10259
|
+
// src/commands/init.ts
|
|
10260
|
+
init_manager();
|
|
10261
|
+
|
|
9294
10262
|
// src/utils/logo.ts
|
|
9295
10263
|
init_cjs_shims();
|
|
9296
10264
|
var REFLY_LOGO = `\u2588\u2580\u2588 \u2588\u2580\u2580 \u2588\u2580\u2580 \u2588 \u2588 \u2588 \u2588\u2580\u2588 \u2588
|
|
@@ -9349,7 +10317,7 @@ var import_promises = __toESM(require("fs/promises"), 1);
|
|
|
9349
10317
|
// ../../node_modules/.pnpm/is-wsl@3.1.0/node_modules/is-wsl/index.js
|
|
9350
10318
|
init_cjs_shims();
|
|
9351
10319
|
var import_node_process = __toESM(require("process"), 1);
|
|
9352
|
-
var
|
|
10320
|
+
var import_node_os3 = __toESM(require("os"), 1);
|
|
9353
10321
|
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
9354
10322
|
|
|
9355
10323
|
// ../../node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
|
|
@@ -9404,7 +10372,7 @@ var isWsl = () => {
|
|
|
9404
10372
|
if (import_node_process.default.platform !== "linux") {
|
|
9405
10373
|
return false;
|
|
9406
10374
|
}
|
|
9407
|
-
if (
|
|
10375
|
+
if (import_node_os3.default.release().toLowerCase().includes("microsoft")) {
|
|
9408
10376
|
if (isInsideContainer()) {
|
|
9409
10377
|
return false;
|
|
9410
10378
|
}
|
|
@@ -9600,7 +10568,7 @@ async function defaultBrowser2() {
|
|
|
9600
10568
|
var execFile5 = (0, import_node_util5.promisify)(import_node_child_process5.default.execFile);
|
|
9601
10569
|
var __dirname2 = import_node_path.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
9602
10570
|
var localXdgOpenPath = import_node_path.default.join(__dirname2, "xdg-open");
|
|
9603
|
-
var { platform:
|
|
10571
|
+
var { platform: platform3, arch } = import_node_process6.default;
|
|
9604
10572
|
async function getWindowsDefaultBrowserFromWsl() {
|
|
9605
10573
|
const powershellPath = await powerShellPath();
|
|
9606
10574
|
const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
|
|
@@ -9699,7 +10667,7 @@ var baseOpen = async (options) => {
|
|
|
9699
10667
|
let command;
|
|
9700
10668
|
const cliArguments = [];
|
|
9701
10669
|
const childProcessOptions = {};
|
|
9702
|
-
if (
|
|
10670
|
+
if (platform3 === "darwin") {
|
|
9703
10671
|
command = "open";
|
|
9704
10672
|
if (options.wait) {
|
|
9705
10673
|
cliArguments.push("--wait-apps");
|
|
@@ -9713,7 +10681,7 @@ var baseOpen = async (options) => {
|
|
|
9713
10681
|
if (app) {
|
|
9714
10682
|
cliArguments.push("-a", app);
|
|
9715
10683
|
}
|
|
9716
|
-
} else if (
|
|
10684
|
+
} else if (platform3 === "win32" || is_wsl_default && !isInsideContainer() && !app) {
|
|
9717
10685
|
command = await powerShellPath();
|
|
9718
10686
|
cliArguments.push(
|
|
9719
10687
|
"-NoProfile",
|
|
@@ -9753,7 +10721,7 @@ var baseOpen = async (options) => {
|
|
|
9753
10721
|
exeLocalXdgOpen = true;
|
|
9754
10722
|
} catch {
|
|
9755
10723
|
}
|
|
9756
|
-
const useSystemXdgOpen = import_node_process6.default.versions.electron ?? (
|
|
10724
|
+
const useSystemXdgOpen = import_node_process6.default.versions.electron ?? (platform3 === "android" || isBundled || !exeLocalXdgOpen);
|
|
9757
10725
|
command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
|
|
9758
10726
|
}
|
|
9759
10727
|
if (appArguments.length > 0) {
|
|
@@ -9764,7 +10732,7 @@ var baseOpen = async (options) => {
|
|
|
9764
10732
|
childProcessOptions.detached = true;
|
|
9765
10733
|
}
|
|
9766
10734
|
}
|
|
9767
|
-
if (
|
|
10735
|
+
if (platform3 === "darwin" && appArguments.length > 0) {
|
|
9768
10736
|
cliArguments.push("--args", ...appArguments);
|
|
9769
10737
|
}
|
|
9770
10738
|
if (options.target) {
|
|
@@ -9772,14 +10740,14 @@ var baseOpen = async (options) => {
|
|
|
9772
10740
|
}
|
|
9773
10741
|
const subprocess = import_node_child_process5.default.spawn(command, cliArguments, childProcessOptions);
|
|
9774
10742
|
if (options.wait) {
|
|
9775
|
-
return new Promise((
|
|
10743
|
+
return new Promise((resolve8, reject) => {
|
|
9776
10744
|
subprocess.once("error", reject);
|
|
9777
10745
|
subprocess.once("close", (exitCode) => {
|
|
9778
10746
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
9779
10747
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
9780
10748
|
return;
|
|
9781
10749
|
}
|
|
9782
|
-
|
|
10750
|
+
resolve8(subprocess);
|
|
9783
10751
|
});
|
|
9784
10752
|
});
|
|
9785
10753
|
}
|
|
@@ -9805,12 +10773,12 @@ function detectArchBinary(binary) {
|
|
|
9805
10773
|
}
|
|
9806
10774
|
return archBinary;
|
|
9807
10775
|
}
|
|
9808
|
-
function detectPlatformBinary({ [
|
|
10776
|
+
function detectPlatformBinary({ [platform3]: platformBinary }, { wsl }) {
|
|
9809
10777
|
if (wsl && is_wsl_default) {
|
|
9810
10778
|
return detectArchBinary(wsl);
|
|
9811
10779
|
}
|
|
9812
10780
|
if (!platformBinary) {
|
|
9813
|
-
throw new Error(`${
|
|
10781
|
+
throw new Error(`${platform3} is not supported`);
|
|
9814
10782
|
}
|
|
9815
10783
|
return detectArchBinary(platformBinary);
|
|
9816
10784
|
}
|
|
@@ -9855,9 +10823,9 @@ var open_default = open;
|
|
|
9855
10823
|
|
|
9856
10824
|
// src/api/client.ts
|
|
9857
10825
|
init_cjs_shims();
|
|
9858
|
-
var
|
|
10826
|
+
var fs15 = __toESM(require("fs"));
|
|
9859
10827
|
var import_node_fs4 = require("fs");
|
|
9860
|
-
var
|
|
10828
|
+
var path10 = __toESM(require("path"));
|
|
9861
10829
|
var import_mime = __toESM(require("mime"));
|
|
9862
10830
|
|
|
9863
10831
|
// src/utils/errors.ts
|
|
@@ -9886,10 +10854,10 @@ var NetworkError = class extends CLIError {
|
|
|
9886
10854
|
// src/api/client.ts
|
|
9887
10855
|
init_logger();
|
|
9888
10856
|
var DEFAULT_TIMEOUT = 3e4;
|
|
9889
|
-
async function apiRequest(
|
|
10857
|
+
async function apiRequest(path25, options = {}) {
|
|
9890
10858
|
const { method = "GET", body, query, timeout = DEFAULT_TIMEOUT, requireAuth = true } = options;
|
|
9891
10859
|
const endpoint = getApiEndpoint();
|
|
9892
|
-
let url = `${endpoint}${
|
|
10860
|
+
let url = `${endpoint}${path25}`;
|
|
9893
10861
|
if (query && Object.keys(query).length > 0) {
|
|
9894
10862
|
const params = new URLSearchParams(query);
|
|
9895
10863
|
url = `${url}?${params.toString()}`;
|
|
@@ -9927,7 +10895,7 @@ async function apiRequest(path22, options = {}) {
|
|
|
9927
10895
|
const controller = new AbortController();
|
|
9928
10896
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
9929
10897
|
try {
|
|
9930
|
-
logger.debug(`API Request: ${method} ${
|
|
10898
|
+
logger.debug(`API Request: ${method} ${path25}`);
|
|
9931
10899
|
const response = await fetch(url, {
|
|
9932
10900
|
method,
|
|
9933
10901
|
headers,
|
|
@@ -10042,10 +11010,10 @@ function mapAPIError(status, response) {
|
|
|
10042
11010
|
}
|
|
10043
11011
|
return new CLIError(errCode, errMsg);
|
|
10044
11012
|
}
|
|
10045
|
-
async function apiRequestStream(
|
|
11013
|
+
async function apiRequestStream(path25, options = {}) {
|
|
10046
11014
|
const { timeout = 3e5 } = options;
|
|
10047
11015
|
const endpoint = getApiEndpoint();
|
|
10048
|
-
const url = `${endpoint}${
|
|
11016
|
+
const url = `${endpoint}${path25}`;
|
|
10049
11017
|
const headers = {
|
|
10050
11018
|
"User-Agent": "refly-cli/0.1.0"
|
|
10051
11019
|
};
|
|
@@ -10076,7 +11044,7 @@ async function apiRequestStream(path22, options = {}) {
|
|
|
10076
11044
|
const controller = new AbortController();
|
|
10077
11045
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
10078
11046
|
try {
|
|
10079
|
-
logger.debug(`API Stream Request: GET ${
|
|
11047
|
+
logger.debug(`API Stream Request: GET ${path25}`);
|
|
10080
11048
|
const response = await fetch(url, {
|
|
10081
11049
|
method: "GET",
|
|
10082
11050
|
headers,
|
|
@@ -10171,7 +11139,7 @@ async function uploadToPresignedUrl(presignedUrl, filePath, contentType, retryCo
|
|
|
10171
11139
|
const controller = new AbortController();
|
|
10172
11140
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
10173
11141
|
try {
|
|
10174
|
-
const fileBuffer = await
|
|
11142
|
+
const fileBuffer = await fs15.promises.readFile(filePath);
|
|
10175
11143
|
const response = await fetch(presignedUrl, {
|
|
10176
11144
|
method: "PUT",
|
|
10177
11145
|
headers: {
|
|
@@ -10229,7 +11197,7 @@ async function apiGetWorkflow(workflowId) {
|
|
|
10229
11197
|
return apiRequest(`/v1/cli/workflow/${workflowId}`);
|
|
10230
11198
|
}
|
|
10231
11199
|
async function apiUploadDriveFile(filePath, canvasId, options) {
|
|
10232
|
-
const filename =
|
|
11200
|
+
const filename = path10.basename(filePath);
|
|
10233
11201
|
const mimeType = getMimeType(filePath);
|
|
10234
11202
|
const fileStats = (0, import_node_fs4.statSync)(filePath);
|
|
10235
11203
|
logger.debug(`Starting presigned upload: ${filename} (${fileStats.size} bytes)`);
|
|
@@ -10492,7 +11460,7 @@ async function getUserInfoFromToken(accessToken) {
|
|
|
10492
11460
|
};
|
|
10493
11461
|
}
|
|
10494
11462
|
function sleep(ms) {
|
|
10495
|
-
return new Promise((
|
|
11463
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
10496
11464
|
}
|
|
10497
11465
|
|
|
10498
11466
|
// src/commands/init.ts
|
|
@@ -10552,7 +11520,38 @@ var initCommand = new Command("init").description("Initialize Refly CLI, install
|
|
|
10552
11520
|
printError2("Slash commands installation failed");
|
|
10553
11521
|
}
|
|
10554
11522
|
println("");
|
|
10555
|
-
}
|
|
11523
|
+
}
|
|
11524
|
+
const installedAgents = await detectInstalledAgents();
|
|
11525
|
+
const deployableAgents = installedAgents.filter((a) => a.format !== "unknown");
|
|
11526
|
+
if (pretty && tty && deployableAgents.length > 0) {
|
|
11527
|
+
println(`Found ${deployableAgents.length} installed agent(s):`);
|
|
11528
|
+
for (const agent of deployableAgents) {
|
|
11529
|
+
const dir = agent.globalSkillsDir || agent.skillsDir || "N/A";
|
|
11530
|
+
println(` \u2713 ${agent.displayName.padEnd(16)} ${dir}`);
|
|
11531
|
+
}
|
|
11532
|
+
println("");
|
|
11533
|
+
}
|
|
11534
|
+
const platformResults = [];
|
|
11535
|
+
if (deployableAgents.length > 0) {
|
|
11536
|
+
const deployResult = await deploySkillToAllPlatforms("refly", { force: true });
|
|
11537
|
+
for (const [agentName, result] of deployResult.results) {
|
|
11538
|
+
platformResults.push({
|
|
11539
|
+
agent: agentName,
|
|
11540
|
+
success: result.success,
|
|
11541
|
+
path: result.deployedPath || void 0
|
|
11542
|
+
});
|
|
11543
|
+
}
|
|
11544
|
+
if (pretty && tty) {
|
|
11545
|
+
const successCount = platformResults.filter((r) => r.success).length;
|
|
11546
|
+
if (successCount === deployableAgents.length) {
|
|
11547
|
+
printSuccess(`Synced to ${successCount} agent(s)`);
|
|
11548
|
+
} else {
|
|
11549
|
+
printDim(`Synced to ${successCount}/${deployableAgents.length} agent(s)`);
|
|
11550
|
+
}
|
|
11551
|
+
println("");
|
|
11552
|
+
}
|
|
11553
|
+
}
|
|
11554
|
+
if (!pretty) {
|
|
10556
11555
|
print("init", {
|
|
10557
11556
|
message: "Refly CLI initialized successfully",
|
|
10558
11557
|
configDir: getReflyDir(),
|
|
@@ -10562,7 +11561,11 @@ var initCommand = new Command("init").description("Initialize Refly CLI, install
|
|
|
10562
11561
|
symlinkPath: installResult.symlinkPath,
|
|
10563
11562
|
commandsInstalled: installResult.commandsInstalled,
|
|
10564
11563
|
commandsPath: installResult.commandsPath,
|
|
10565
|
-
version: installResult.version
|
|
11564
|
+
version: installResult.version,
|
|
11565
|
+
platforms: {
|
|
11566
|
+
detected: installedAgents.map((a) => a.name),
|
|
11567
|
+
deployed: platformResults
|
|
11568
|
+
}
|
|
10566
11569
|
});
|
|
10567
11570
|
}
|
|
10568
11571
|
if (!skipLogin && !isAuthenticated2) {
|
|
@@ -10750,7 +11753,7 @@ var import_node_child_process6 = require("child_process");
|
|
|
10750
11753
|
var import_node_fs5 = __toESM(require("fs"));
|
|
10751
11754
|
init_logger();
|
|
10752
11755
|
init_paths();
|
|
10753
|
-
var CLI_VERSION = "0.1.
|
|
11756
|
+
var CLI_VERSION = "0.1.24";
|
|
10754
11757
|
var NPM_TAG = "latest";
|
|
10755
11758
|
function compareSemver(a, b) {
|
|
10756
11759
|
const parseVersion = (v) => {
|
|
@@ -11006,16 +12009,16 @@ configCommand.action(() => {
|
|
|
11006
12009
|
};
|
|
11007
12010
|
ok("config", safeConfig);
|
|
11008
12011
|
});
|
|
11009
|
-
function getNestedValue(obj,
|
|
11010
|
-
return
|
|
12012
|
+
function getNestedValue(obj, path25) {
|
|
12013
|
+
return path25.split(".").reduce((current, key) => {
|
|
11011
12014
|
if (current && typeof current === "object" && key in current) {
|
|
11012
12015
|
return current[key];
|
|
11013
12016
|
}
|
|
11014
12017
|
return void 0;
|
|
11015
12018
|
}, obj);
|
|
11016
12019
|
}
|
|
11017
|
-
function setNestedValue(obj,
|
|
11018
|
-
const keys =
|
|
12020
|
+
function setNestedValue(obj, path25, value) {
|
|
12021
|
+
const keys = path25.split(".");
|
|
11019
12022
|
const lastKey = keys.pop();
|
|
11020
12023
|
let current = obj;
|
|
11021
12024
|
for (const key of keys) {
|
|
@@ -11256,14 +12259,14 @@ var workflowDeleteCommand = new Command("delete").description("Delete a workflow
|
|
|
11256
12259
|
init_cjs_shims();
|
|
11257
12260
|
var readline2 = __toESM(require("readline/promises"));
|
|
11258
12261
|
var import_node_process8 = require("process");
|
|
11259
|
-
var
|
|
12262
|
+
var path12 = __toESM(require("path"));
|
|
11260
12263
|
|
|
11261
12264
|
// src/utils/prompt.ts
|
|
11262
12265
|
init_cjs_shims();
|
|
11263
12266
|
var readline = __toESM(require("readline/promises"));
|
|
11264
12267
|
var import_node_process7 = require("process");
|
|
11265
|
-
var
|
|
11266
|
-
var
|
|
12268
|
+
var fs17 = __toESM(require("fs"));
|
|
12269
|
+
var path11 = __toESM(require("path"));
|
|
11267
12270
|
function isInteractive() {
|
|
11268
12271
|
return process.stdin?.isTTY ?? false;
|
|
11269
12272
|
}
|
|
@@ -11287,12 +12290,12 @@ async function promptForFilePath(variableName, resourceTypes, isRequired) {
|
|
|
11287
12290
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
11288
12291
|
resolvedPath = resolvedPath.replace("~", homeDir);
|
|
11289
12292
|
}
|
|
11290
|
-
resolvedPath =
|
|
11291
|
-
if (!
|
|
12293
|
+
resolvedPath = path11.resolve(resolvedPath);
|
|
12294
|
+
if (!fs17.existsSync(resolvedPath)) {
|
|
11292
12295
|
console.log(` File not found: ${resolvedPath}`);
|
|
11293
12296
|
continue;
|
|
11294
12297
|
}
|
|
11295
|
-
const stats =
|
|
12298
|
+
const stats = fs17.statSync(resolvedPath);
|
|
11296
12299
|
if (!stats.isFile()) {
|
|
11297
12300
|
console.log(` Not a file: ${resolvedPath}`);
|
|
11298
12301
|
continue;
|
|
@@ -11490,12 +12493,12 @@ async function pollToolsStatus(workflowId, maxWaitTime = 15 * 60 * 1e3, pollInte
|
|
|
11490
12493
|
);
|
|
11491
12494
|
previousRemainingCount = remainingCount;
|
|
11492
12495
|
}
|
|
11493
|
-
await new Promise((
|
|
12496
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
11494
12497
|
} catch (error) {
|
|
11495
12498
|
console.log(`
|
|
11496
12499
|
\u26A0\uFE0F Failed to check authorization status: ${error.message}`);
|
|
11497
12500
|
console.log("Continuing to wait...");
|
|
11498
|
-
await new Promise((
|
|
12501
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
11499
12502
|
}
|
|
11500
12503
|
}
|
|
11501
12504
|
console.log("\n\u23F0 Timeout waiting for tool authorization.");
|
|
@@ -11606,7 +12609,7 @@ ${details}`;
|
|
|
11606
12609
|
if (!filePath) {
|
|
11607
12610
|
continue;
|
|
11608
12611
|
}
|
|
11609
|
-
const filename =
|
|
12612
|
+
const filename = path12.basename(filePath);
|
|
11610
12613
|
process.stdout.write(` Uploading ${filename}...`);
|
|
11611
12614
|
try {
|
|
11612
12615
|
const uploadResult = await apiUploadDriveFile(filePath, workflowId);
|
|
@@ -11988,7 +12991,7 @@ var workflowStatusCommand = new Command("status").description("Get detailed work
|
|
|
11988
12991
|
});
|
|
11989
12992
|
prevStatus = status;
|
|
11990
12993
|
while (status.status === "init" || status.status === "executing") {
|
|
11991
|
-
await new Promise((
|
|
12994
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
11992
12995
|
status = await fetchStatus();
|
|
11993
12996
|
if (options.full || hasStatusChanged(prevStatus, status)) {
|
|
11994
12997
|
if (options.full) {
|
|
@@ -12116,7 +13119,75 @@ var workflowDetailCommand = new Command("detail").description("Get detailed work
|
|
|
12116
13119
|
|
|
12117
13120
|
// src/commands/workflow/toolcalls.ts
|
|
12118
13121
|
init_cjs_shims();
|
|
12119
|
-
|
|
13122
|
+
function extractNodeOutputs(toolCalls) {
|
|
13123
|
+
const outputs = [];
|
|
13124
|
+
for (const call of toolCalls) {
|
|
13125
|
+
if (!call.output || call.status !== "completed") continue;
|
|
13126
|
+
const output3 = call.output;
|
|
13127
|
+
const filesMap = /* @__PURE__ */ new Map();
|
|
13128
|
+
let content;
|
|
13129
|
+
if (Array.isArray(output3.files)) {
|
|
13130
|
+
for (const f of output3.files) {
|
|
13131
|
+
const file = f;
|
|
13132
|
+
if (file.fileId && !filesMap.has(String(file.fileId))) {
|
|
13133
|
+
filesMap.set(String(file.fileId), {
|
|
13134
|
+
fileId: String(file.fileId),
|
|
13135
|
+
name: String(file.name || ""),
|
|
13136
|
+
type: String(file.type || ""),
|
|
13137
|
+
category: file.category,
|
|
13138
|
+
size: file.size,
|
|
13139
|
+
url: file.url,
|
|
13140
|
+
source: file.source,
|
|
13141
|
+
createdAt: file.createdAt
|
|
13142
|
+
});
|
|
13143
|
+
}
|
|
13144
|
+
}
|
|
13145
|
+
}
|
|
13146
|
+
if (output3.data && typeof output3.data === "object") {
|
|
13147
|
+
const data = output3.data;
|
|
13148
|
+
if (data.fileId && !filesMap.has(String(data.fileId))) {
|
|
13149
|
+
filesMap.set(String(data.fileId), {
|
|
13150
|
+
fileId: String(data.fileId),
|
|
13151
|
+
name: String(data.name || ""),
|
|
13152
|
+
type: String(data.type || ""),
|
|
13153
|
+
category: data.category,
|
|
13154
|
+
size: data.size,
|
|
13155
|
+
url: data.url,
|
|
13156
|
+
source: data.source,
|
|
13157
|
+
createdAt: data.createdAt
|
|
13158
|
+
});
|
|
13159
|
+
}
|
|
13160
|
+
}
|
|
13161
|
+
if (output3.content) {
|
|
13162
|
+
content = String(output3.content).slice(0, 500);
|
|
13163
|
+
} else if (output3.data && typeof output3.data === "object") {
|
|
13164
|
+
const data = output3.data;
|
|
13165
|
+
if (data.candidates && Array.isArray(data.candidates)) {
|
|
13166
|
+
const parts = data.candidates[0]?.content;
|
|
13167
|
+
if (parts?.parts && Array.isArray(parts.parts)) {
|
|
13168
|
+
const textPart = parts.parts.find(
|
|
13169
|
+
(p) => typeof p.text === "string" && !p.thought
|
|
13170
|
+
);
|
|
13171
|
+
if (textPart) {
|
|
13172
|
+
content = String(textPart.text).slice(0, 500);
|
|
13173
|
+
}
|
|
13174
|
+
}
|
|
13175
|
+
}
|
|
13176
|
+
}
|
|
13177
|
+
const files = Array.from(filesMap.values());
|
|
13178
|
+
if (files.length > 0 || content) {
|
|
13179
|
+
outputs.push({
|
|
13180
|
+
nodeId: call.nodeId || "",
|
|
13181
|
+
nodeTitle: call.nodeTitle || call.toolName,
|
|
13182
|
+
toolName: call.toolName,
|
|
13183
|
+
content,
|
|
13184
|
+
files
|
|
13185
|
+
});
|
|
13186
|
+
}
|
|
13187
|
+
}
|
|
13188
|
+
return outputs;
|
|
13189
|
+
}
|
|
13190
|
+
var workflowToolcallsCommand = new Command("toolcalls").description("Get all tool calls for workflow execution").argument("<id>", "Workflow ID (c-xxx) or Run ID (we-xxx)").option("--node-id <nodeId>", "Filter by node ID").option("--toolset-id <toolsetId>", "Filter by toolset ID").option("--tool-name <toolName>", "Filter by tool name").option("--status <status>", "Filter by status (executing, completed, failed)").option("--limit <limit>", "Maximum number of results (default: 100)", "100").option("--offset <offset>", "Pagination offset (default: 0)", "0").option("--raw", "Disable output sanitization (show full tool outputs)").option("--files", "Show only files and content from each node (simplified output)").option("--latest", "With --files, only show files from the most recent toolcall").action(async (id, options) => {
|
|
12120
13191
|
try {
|
|
12121
13192
|
const params = new URLSearchParams();
|
|
12122
13193
|
if (options.nodeId) {
|
|
@@ -12137,12 +13208,26 @@ var workflowToolcallsCommand = new Command("toolcalls").description("Get all too
|
|
|
12137
13208
|
if (options.offset) {
|
|
12138
13209
|
params.set("offset", options.offset);
|
|
12139
13210
|
}
|
|
12140
|
-
if (options.raw) {
|
|
13211
|
+
if (options.raw || options.files) {
|
|
12141
13212
|
params.set("sanitizeForDisplay", "false");
|
|
12142
13213
|
}
|
|
12143
13214
|
const idType = detectIdType2(id);
|
|
12144
13215
|
const url = buildWorkflowApiUrl(id, "toolcalls", params);
|
|
12145
13216
|
const result = await apiRequest(url);
|
|
13217
|
+
if (options.files) {
|
|
13218
|
+
let nodeOutputs = extractNodeOutputs(result.toolCalls);
|
|
13219
|
+
if (options.latest && nodeOutputs.length > 0) {
|
|
13220
|
+
const lastWithFiles = nodeOutputs.filter((n) => n.files.length > 0).pop();
|
|
13221
|
+
nodeOutputs = lastWithFiles ? [lastWithFiles] : [];
|
|
13222
|
+
}
|
|
13223
|
+
const allFiles = nodeOutputs.flatMap((n) => n.files);
|
|
13224
|
+
ok("workflow.files", {
|
|
13225
|
+
runId: result.runId,
|
|
13226
|
+
workflowId: result.workflowId,
|
|
13227
|
+
files: allFiles,
|
|
13228
|
+
nodes: nodeOutputs
|
|
13229
|
+
});
|
|
13230
|
+
}
|
|
12146
13231
|
ok("workflow.toolcalls", {
|
|
12147
13232
|
runId: result.runId,
|
|
12148
13233
|
workflowId: result.workflowId,
|
|
@@ -13305,16 +14390,16 @@ var fileGetCommand = new Command("get").description("Get file details").argument
|
|
|
13305
14390
|
|
|
13306
14391
|
// src/commands/file/download.ts
|
|
13307
14392
|
init_cjs_shims();
|
|
13308
|
-
var
|
|
13309
|
-
var
|
|
14393
|
+
var fs18 = __toESM(require("fs"));
|
|
14394
|
+
var path13 = __toESM(require("path"));
|
|
13310
14395
|
var fileDownloadCommand = new Command("download").description("Download file to local filesystem").argument("<fileId>", "File ID").option("-o, --output <path>", "Output file path (defaults to original filename)").action(async (fileId, options) => {
|
|
13311
14396
|
try {
|
|
13312
14397
|
const { data, filename, contentType, size } = await apiRequestStream(
|
|
13313
14398
|
`/v1/cli/drive/files/${fileId}/download`
|
|
13314
14399
|
);
|
|
13315
14400
|
const outputPath = options.output || filename || `${fileId}`;
|
|
13316
|
-
const resolvedPath =
|
|
13317
|
-
|
|
14401
|
+
const resolvedPath = path13.resolve(outputPath);
|
|
14402
|
+
fs18.writeFileSync(resolvedPath, data);
|
|
13318
14403
|
ok("file.download", {
|
|
13319
14404
|
fileId,
|
|
13320
14405
|
path: resolvedPath,
|
|
@@ -13339,8 +14424,8 @@ var fileDownloadCommand = new Command("download").description("Download file to
|
|
|
13339
14424
|
|
|
13340
14425
|
// src/commands/file/upload.ts
|
|
13341
14426
|
init_cjs_shims();
|
|
13342
|
-
var
|
|
13343
|
-
var
|
|
14427
|
+
var fs19 = __toESM(require("fs"));
|
|
14428
|
+
var path14 = __toESM(require("path"));
|
|
13344
14429
|
var MAX_FILES = 10;
|
|
13345
14430
|
function formatSize(bytes) {
|
|
13346
14431
|
if (bytes < 1024) return `${bytes}B`;
|
|
@@ -13350,8 +14435,8 @@ function formatSize(bytes) {
|
|
|
13350
14435
|
var fileUploadCommand = new Command("upload").description("Upload file(s) to a canvas").argument("<path>", "File or directory path").requiredOption("--canvas-id <id>", "Canvas ID (required)").option("--filter <extensions>", "Filter by extensions (e.g., pdf,docx,png)").action(async (inputPath, options) => {
|
|
13351
14436
|
const formatter = getFormatter();
|
|
13352
14437
|
try {
|
|
13353
|
-
const resolvedPath =
|
|
13354
|
-
if (!
|
|
14438
|
+
const resolvedPath = path14.resolve(inputPath);
|
|
14439
|
+
if (!fs19.existsSync(resolvedPath)) {
|
|
13355
14440
|
fail(ErrorCodes.NOT_FOUND, `Path not found: ${inputPath}`, {
|
|
13356
14441
|
hint: "Check if the file or directory exists"
|
|
13357
14442
|
});
|
|
@@ -13369,8 +14454,8 @@ var fileUploadCommand = new Command("upload").description("Upload file(s) to a c
|
|
|
13369
14454
|
const errors = [];
|
|
13370
14455
|
for (let i = 0; i < files.length; i++) {
|
|
13371
14456
|
const filePath = files[i];
|
|
13372
|
-
const filename =
|
|
13373
|
-
const fileStats =
|
|
14457
|
+
const filename = path14.basename(filePath);
|
|
14458
|
+
const fileStats = fs19.statSync(filePath);
|
|
13374
14459
|
const sizeStr = formatSize(fileStats.size);
|
|
13375
14460
|
let currentStage = "presign";
|
|
13376
14461
|
const updateProgress = () => {
|
|
@@ -13451,11 +14536,11 @@ var fileUploadCommand = new Command("upload").description("Upload file(s) to a c
|
|
|
13451
14536
|
}
|
|
13452
14537
|
});
|
|
13453
14538
|
function resolveFilesToUpload(inputPath, filter) {
|
|
13454
|
-
const stats =
|
|
14539
|
+
const stats = fs19.statSync(inputPath);
|
|
13455
14540
|
if (stats.isFile()) {
|
|
13456
14541
|
if (filter) {
|
|
13457
14542
|
const filterExts = filter.split(",").map((e) => e.trim().toLowerCase());
|
|
13458
|
-
const ext =
|
|
14543
|
+
const ext = path14.extname(inputPath).slice(1).toLowerCase();
|
|
13459
14544
|
if (!filterExts.includes(ext)) {
|
|
13460
14545
|
return [];
|
|
13461
14546
|
}
|
|
@@ -13463,21 +14548,21 @@ function resolveFilesToUpload(inputPath, filter) {
|
|
|
13463
14548
|
return [inputPath];
|
|
13464
14549
|
}
|
|
13465
14550
|
if (stats.isDirectory()) {
|
|
13466
|
-
const entries =
|
|
14551
|
+
const entries = fs19.readdirSync(inputPath);
|
|
13467
14552
|
const filterExts = filter?.split(",").map((e) => e.trim().toLowerCase());
|
|
13468
|
-
const files = entries.map((e) =>
|
|
14553
|
+
const files = entries.map((e) => path14.join(inputPath, e)).filter((p) => {
|
|
13469
14554
|
try {
|
|
13470
|
-
return
|
|
14555
|
+
return fs19.statSync(p).isFile();
|
|
13471
14556
|
} catch {
|
|
13472
14557
|
return false;
|
|
13473
14558
|
}
|
|
13474
14559
|
}).filter((p) => {
|
|
13475
14560
|
if (!filterExts) return true;
|
|
13476
|
-
const ext =
|
|
14561
|
+
const ext = path14.extname(p).slice(1).toLowerCase();
|
|
13477
14562
|
return filterExts.includes(ext);
|
|
13478
14563
|
}).sort((a, b) => {
|
|
13479
14564
|
try {
|
|
13480
|
-
return
|
|
14565
|
+
return fs19.statSync(a).size - fs19.statSync(b).size;
|
|
13481
14566
|
} catch {
|
|
13482
14567
|
return 0;
|
|
13483
14568
|
}
|
|
@@ -13581,7 +14666,7 @@ var skillGetCommand = new Command("get").description("Get skill package details"
|
|
|
13581
14666
|
|
|
13582
14667
|
// src/commands/skill/create.ts
|
|
13583
14668
|
init_cjs_shims();
|
|
13584
|
-
var
|
|
14669
|
+
var fs20 = __toESM(require("fs"));
|
|
13585
14670
|
init_symlink();
|
|
13586
14671
|
init_paths();
|
|
13587
14672
|
init_logger();
|
|
@@ -13633,7 +14718,7 @@ var skillCreateCommand = new Command("create").description("Create a new skill p
|
|
|
13633
14718
|
const localName = options.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
13634
14719
|
const skillDir = getReflyDomainSkillDir(localName);
|
|
13635
14720
|
const symlinkStatus = isSkillSymlinkValid(localName);
|
|
13636
|
-
if (
|
|
14721
|
+
if (fs20.existsSync(skillDir) || symlinkStatus.exists) {
|
|
13637
14722
|
logger.debug(`Local skill '${localName}' already exists, skipping sync`);
|
|
13638
14723
|
} else {
|
|
13639
14724
|
const skillMdContent = generateReflySkillMd({
|
|
@@ -13695,8 +14780,8 @@ var skillCreateCommand = new Command("create").description("Create a new skill p
|
|
|
13695
14780
|
|
|
13696
14781
|
// src/commands/skill/update.ts
|
|
13697
14782
|
init_cjs_shims();
|
|
13698
|
-
var
|
|
13699
|
-
var
|
|
14783
|
+
var fs21 = __toESM(require("fs"));
|
|
14784
|
+
var path15 = __toESM(require("path"));
|
|
13700
14785
|
init_paths();
|
|
13701
14786
|
init_symlink();
|
|
13702
14787
|
var MIN_DESCRIPTION_WORDS = 20;
|
|
@@ -13726,8 +14811,8 @@ var skillUpdateCommand = new Command("update").description("Update skill install
|
|
|
13726
14811
|
try {
|
|
13727
14812
|
const name = options.name;
|
|
13728
14813
|
const skillDir = getReflyDomainSkillDir(name);
|
|
13729
|
-
const skillMdPath =
|
|
13730
|
-
if (!
|
|
14814
|
+
const skillMdPath = path15.join(skillDir, "SKILL.md");
|
|
14815
|
+
if (!fs21.existsSync(skillMdPath)) {
|
|
13731
14816
|
const skillsDir = getReflySkillsDir();
|
|
13732
14817
|
fail(ErrorCodes.NOT_FOUND, `SKILL.md not found at ${skillMdPath}`, {
|
|
13733
14818
|
hint: `Make sure the skill '${name}' exists in ${skillsDir}/
|
|
@@ -13736,7 +14821,7 @@ To see installed skills: refly skill list`
|
|
|
13736
14821
|
});
|
|
13737
14822
|
return;
|
|
13738
14823
|
}
|
|
13739
|
-
const skillContent =
|
|
14824
|
+
const skillContent = fs21.readFileSync(skillMdPath, "utf-8");
|
|
13740
14825
|
let meta;
|
|
13741
14826
|
try {
|
|
13742
14827
|
const parsed = parseReflySkillMd(skillContent);
|
|
@@ -13819,8 +14904,8 @@ To see installed skills: refly skill list`
|
|
|
13819
14904
|
|
|
13820
14905
|
// src/commands/skill/publish.ts
|
|
13821
14906
|
init_cjs_shims();
|
|
13822
|
-
var
|
|
13823
|
-
var
|
|
14907
|
+
var fs22 = __toESM(require("fs"));
|
|
14908
|
+
var path16 = __toESM(require("path"));
|
|
13824
14909
|
init_symlink();
|
|
13825
14910
|
init_paths();
|
|
13826
14911
|
var skillPublishCommand = new Command("publish").description("Publish a skill package using local SKILL.md").requiredOption("--name <name>", "Local skill name (directory in ~/.refly/skills/)").action(async (options) => {
|
|
@@ -13828,8 +14913,8 @@ var skillPublishCommand = new Command("publish").description("Publish a skill pa
|
|
|
13828
14913
|
const skillsDir = getReflySkillsDir();
|
|
13829
14914
|
const name = options.name;
|
|
13830
14915
|
const skillDir = getReflyDomainSkillDir(name);
|
|
13831
|
-
const skillMdPath =
|
|
13832
|
-
if (!
|
|
14916
|
+
const skillMdPath = path16.join(skillDir, "SKILL.md");
|
|
14917
|
+
if (!fs22.existsSync(skillMdPath)) {
|
|
13833
14918
|
fail(ErrorCodes.NOT_FOUND, `SKILL.md not found at ${skillMdPath}`, {
|
|
13834
14919
|
hint: `Make sure the skill '${name}' exists in ${skillsDir}/
|
|
13835
14920
|
|
|
@@ -13838,7 +14923,7 @@ To create a new skill: refly skill create --name "${name}" --workflow-query "...
|
|
|
13838
14923
|
});
|
|
13839
14924
|
return;
|
|
13840
14925
|
}
|
|
13841
|
-
const skillContent =
|
|
14926
|
+
const skillContent = fs22.readFileSync(skillMdPath, "utf-8");
|
|
13842
14927
|
let parsedSkill;
|
|
13843
14928
|
try {
|
|
13844
14929
|
parsedSkill = parseReflySkillMd(skillContent);
|
|
@@ -13900,8 +14985,8 @@ To find available skills: refly skill list`
|
|
|
13900
14985
|
|
|
13901
14986
|
// src/commands/skill/unpublish.ts
|
|
13902
14987
|
init_cjs_shims();
|
|
13903
|
-
var
|
|
13904
|
-
var
|
|
14988
|
+
var fs23 = __toESM(require("fs"));
|
|
14989
|
+
var path17 = __toESM(require("path"));
|
|
13905
14990
|
init_symlink();
|
|
13906
14991
|
init_paths();
|
|
13907
14992
|
var skillUnpublishCommand = new Command("unpublish").description("Unpublish a skill package to make it private").option("--id <skillId>", "Skill ID (skp-xxx)").option("--name <name>", "Local skill name (directory in ~/.refly/skills/)").action(async (options) => {
|
|
@@ -13936,8 +15021,8 @@ To find your skill name:
|
|
|
13936
15021
|
return;
|
|
13937
15022
|
}
|
|
13938
15023
|
const skillDir = getReflyDomainSkillDir(name);
|
|
13939
|
-
const skillMdPath =
|
|
13940
|
-
if (!
|
|
15024
|
+
const skillMdPath = path17.join(skillDir, "SKILL.md");
|
|
15025
|
+
if (!fs23.existsSync(skillMdPath)) {
|
|
13941
15026
|
fail(ErrorCodes.NOT_FOUND, `SKILL.md not found at ${skillMdPath}`, {
|
|
13942
15027
|
hint: `Make sure the skill '${name}' exists in ${skillsDir}/
|
|
13943
15028
|
|
|
@@ -13945,7 +15030,7 @@ To see installed skills: refly skill list`
|
|
|
13945
15030
|
});
|
|
13946
15031
|
return;
|
|
13947
15032
|
}
|
|
13948
|
-
const skillContent =
|
|
15033
|
+
const skillContent = fs23.readFileSync(skillMdPath, "utf-8");
|
|
13949
15034
|
try {
|
|
13950
15035
|
const { meta } = parseReflySkillMd(skillContent);
|
|
13951
15036
|
skillId = options.id || meta.skillId;
|
|
@@ -13989,8 +15074,8 @@ To see installed skills: refly skill list`
|
|
|
13989
15074
|
|
|
13990
15075
|
// src/commands/skill/run.ts
|
|
13991
15076
|
init_cjs_shims();
|
|
13992
|
-
var
|
|
13993
|
-
var
|
|
15077
|
+
var fs24 = __toESM(require("fs"));
|
|
15078
|
+
var path18 = __toESM(require("path"));
|
|
13994
15079
|
init_symlink();
|
|
13995
15080
|
init_paths();
|
|
13996
15081
|
var skillRunCommand = new Command("run").description("Run an installed skill").option("--id <installationId>", "Installation ID (skpi-xxx)").option("--name <name>", "Local skill name (directory in ~/.refly/skills/)").option("--input <json>", "Input JSON for the skill").option("--workflow <skillWorkflowId>", "Run specific workflow only").option("--async", "Run asynchronously").option("--no-prompt", "Disable interactive prompts (fail if required variables are missing)").action(async (options) => {
|
|
@@ -14015,8 +15100,8 @@ To find your skill name:
|
|
|
14015
15100
|
if (options.name) {
|
|
14016
15101
|
name = options.name;
|
|
14017
15102
|
const skillDir = getReflyDomainSkillDir(options.name);
|
|
14018
|
-
const skillMdPath =
|
|
14019
|
-
if (!
|
|
15103
|
+
const skillMdPath = path18.join(skillDir, "SKILL.md");
|
|
15104
|
+
if (!fs24.existsSync(skillMdPath)) {
|
|
14020
15105
|
fail(ErrorCodes.NOT_FOUND, `SKILL.md not found at ${skillMdPath}`, {
|
|
14021
15106
|
hint: `Make sure the skill '${name}' exists in ${skillsDir}/
|
|
14022
15107
|
|
|
@@ -14025,7 +15110,7 @@ To install a skill: refly skill install <skillId>`
|
|
|
14025
15110
|
});
|
|
14026
15111
|
return;
|
|
14027
15112
|
}
|
|
14028
|
-
const skillContent =
|
|
15113
|
+
const skillContent = fs24.readFileSync(skillMdPath, "utf-8");
|
|
14029
15114
|
try {
|
|
14030
15115
|
const { meta } = parseReflySkillMd(skillContent);
|
|
14031
15116
|
skillId = meta.skillId;
|
|
@@ -14143,24 +15228,24 @@ To install: refly skill install ${meta.skillId}`
|
|
|
14143
15228
|
|
|
14144
15229
|
// src/commands/skill/stop.ts
|
|
14145
15230
|
init_cjs_shims();
|
|
14146
|
-
var
|
|
14147
|
-
var
|
|
15231
|
+
var fs25 = __toESM(require("fs"));
|
|
15232
|
+
var path19 = __toESM(require("path"));
|
|
14148
15233
|
init_symlink();
|
|
14149
15234
|
init_paths();
|
|
14150
15235
|
function getLocalSkillNames() {
|
|
14151
15236
|
const skillsDir = getReflySkillsDir();
|
|
14152
|
-
if (!
|
|
15237
|
+
if (!fs25.existsSync(skillsDir)) {
|
|
14153
15238
|
return [];
|
|
14154
15239
|
}
|
|
14155
|
-
return
|
|
15240
|
+
return fs25.readdirSync(skillsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
14156
15241
|
}
|
|
14157
15242
|
var skillStopCommand = new Command("stop").description("Stop running skill executions").requiredOption("--name <name>", "Local skill name (directory in ~/.refly/skills/)").action(async (options) => {
|
|
14158
15243
|
try {
|
|
14159
15244
|
const skillsDir = getReflySkillsDir();
|
|
14160
15245
|
const name = options.name;
|
|
14161
15246
|
const skillDir = getReflyDomainSkillDir(name);
|
|
14162
|
-
const skillMdPath =
|
|
14163
|
-
if (!
|
|
15247
|
+
const skillMdPath = path19.join(skillDir, "SKILL.md");
|
|
15248
|
+
if (!fs25.existsSync(skillMdPath)) {
|
|
14164
15249
|
const availableSkills = getLocalSkillNames();
|
|
14165
15250
|
const skillList = availableSkills.length > 0 ? availableSkills.join(", ") : "(no skills installed)";
|
|
14166
15251
|
fail(ErrorCodes.NOT_FOUND, `Skill "${name}" not found`, {
|
|
@@ -14169,7 +15254,7 @@ var skillStopCommand = new Command("stop").description("Stop running skill execu
|
|
|
14169
15254
|
Skills directory: ${skillsDir}`
|
|
14170
15255
|
});
|
|
14171
15256
|
}
|
|
14172
|
-
const skillContent =
|
|
15257
|
+
const skillContent = fs25.readFileSync(skillMdPath, "utf-8");
|
|
14173
15258
|
let installationId;
|
|
14174
15259
|
try {
|
|
14175
15260
|
const { meta } = parseReflySkillMd(skillContent);
|
|
@@ -14297,7 +15382,7 @@ var skillInstallCommand = new Command("install").description("Install a skill pa
|
|
|
14297
15382
|
}
|
|
14298
15383
|
);
|
|
14299
15384
|
let localPath;
|
|
14300
|
-
|
|
15385
|
+
const platformResults = [];
|
|
14301
15386
|
const skillName = result.skillPackage?.name;
|
|
14302
15387
|
const workflowId = result.skillPackage?.workflowId;
|
|
14303
15388
|
if (skillName && workflowId) {
|
|
@@ -14315,15 +15400,23 @@ var skillInstallCommand = new Command("install").description("Install a skill pa
|
|
|
14315
15400
|
inputSchema: result.skillPackage?.inputSchema,
|
|
14316
15401
|
outputSchema: result.skillPackage?.outputSchema
|
|
14317
15402
|
});
|
|
14318
|
-
const
|
|
15403
|
+
const deployResult = await createMultiPlatformSkill(skillName, skillMdContent, {
|
|
14319
15404
|
force: options.force
|
|
14320
15405
|
});
|
|
14321
|
-
|
|
14322
|
-
|
|
14323
|
-
|
|
14324
|
-
|
|
15406
|
+
localPath = deployResult.sourcePath;
|
|
15407
|
+
for (const [agentName, agentResult] of deployResult.results) {
|
|
15408
|
+
platformResults.push({
|
|
15409
|
+
agent: agentName,
|
|
15410
|
+
success: agentResult.success,
|
|
15411
|
+
path: agentResult.deployedPath || void 0
|
|
15412
|
+
});
|
|
15413
|
+
}
|
|
15414
|
+
if (deployResult.successCount > 0) {
|
|
15415
|
+
logger.info(
|
|
15416
|
+
`Created local skill: ${localPath}, deployed to ${deployResult.successCount} platform(s)`
|
|
15417
|
+
);
|
|
14325
15418
|
} else {
|
|
14326
|
-
logger.warn(
|
|
15419
|
+
logger.warn("Failed to deploy skill to any platform");
|
|
14327
15420
|
}
|
|
14328
15421
|
} catch (err) {
|
|
14329
15422
|
logger.warn(`Failed to create local skill: ${err.message}`);
|
|
@@ -14338,7 +15431,7 @@ var skillInstallCommand = new Command("install").description("Install a skill pa
|
|
|
14338
15431
|
config: result.userConfig,
|
|
14339
15432
|
installedAt: result.createdAt,
|
|
14340
15433
|
localPath,
|
|
14341
|
-
|
|
15434
|
+
platforms: platformResults.length > 0 ? platformResults : void 0
|
|
14342
15435
|
});
|
|
14343
15436
|
} catch (error) {
|
|
14344
15437
|
if (error instanceof CLIError) {
|
|
@@ -14358,8 +15451,8 @@ var skillInstallCommand = new Command("install").description("Install a skill pa
|
|
|
14358
15451
|
|
|
14359
15452
|
// src/commands/skill/uninstall.ts
|
|
14360
15453
|
init_cjs_shims();
|
|
14361
|
-
var
|
|
14362
|
-
var
|
|
15454
|
+
var fs26 = __toESM(require("fs"));
|
|
15455
|
+
var path20 = __toESM(require("path"));
|
|
14363
15456
|
init_symlink();
|
|
14364
15457
|
init_paths();
|
|
14365
15458
|
init_logger();
|
|
@@ -14396,8 +15489,8 @@ To find your skill name:
|
|
|
14396
15489
|
return;
|
|
14397
15490
|
}
|
|
14398
15491
|
const skillDir = getReflyDomainSkillDir(name);
|
|
14399
|
-
const skillMdPath =
|
|
14400
|
-
if (!
|
|
15492
|
+
const skillMdPath = path20.join(skillDir, "SKILL.md");
|
|
15493
|
+
if (!fs26.existsSync(skillMdPath)) {
|
|
14401
15494
|
fail(ErrorCodes.NOT_FOUND, `SKILL.md not found at ${skillMdPath}`, {
|
|
14402
15495
|
hint: `Make sure the skill '${name}' exists in ${skillsDir}/
|
|
14403
15496
|
|
|
@@ -14405,7 +15498,7 @@ To see installed skills: refly skill list`
|
|
|
14405
15498
|
});
|
|
14406
15499
|
return;
|
|
14407
15500
|
}
|
|
14408
|
-
const skillContent =
|
|
15501
|
+
const skillContent = fs26.readFileSync(skillMdPath, "utf-8");
|
|
14409
15502
|
try {
|
|
14410
15503
|
const { meta } = parseReflySkillMd(skillContent);
|
|
14411
15504
|
skillId = meta.skillId;
|
|
@@ -14436,14 +15529,21 @@ To see installed skills: refly skill list`
|
|
|
14436
15529
|
}
|
|
14437
15530
|
}
|
|
14438
15531
|
}
|
|
14439
|
-
let symlinkRemoved = false;
|
|
14440
15532
|
let directoryRemoved = false;
|
|
15533
|
+
const platformResults = [];
|
|
14441
15534
|
if (name && !options.keepLocal) {
|
|
14442
15535
|
try {
|
|
14443
|
-
const cleanup =
|
|
14444
|
-
symlinkRemoved = cleanup.symlinkRemoved;
|
|
15536
|
+
const cleanup = await removeMultiPlatformSkill(name);
|
|
14445
15537
|
directoryRemoved = cleanup.directoryRemoved;
|
|
14446
|
-
|
|
15538
|
+
for (const [agentName, result] of cleanup.platformResults.results) {
|
|
15539
|
+
platformResults.push({
|
|
15540
|
+
agent: agentName,
|
|
15541
|
+
success: result.success
|
|
15542
|
+
});
|
|
15543
|
+
}
|
|
15544
|
+
logger.info(
|
|
15545
|
+
`Cleaned up local skill: ${name}, removed from ${cleanup.platformResults.successCount} platform(s)`
|
|
15546
|
+
);
|
|
14447
15547
|
} catch (err) {
|
|
14448
15548
|
logger.warn(`Failed to clean up local skill: ${err.message}`);
|
|
14449
15549
|
}
|
|
@@ -14454,8 +15554,8 @@ To see installed skills: refly skill list`
|
|
|
14454
15554
|
installationId,
|
|
14455
15555
|
uninstalled: true,
|
|
14456
15556
|
localCleanup: {
|
|
14457
|
-
|
|
14458
|
-
|
|
15557
|
+
directoryRemoved,
|
|
15558
|
+
platforms: platformResults.length > 0 ? platformResults : void 0
|
|
14459
15559
|
}
|
|
14460
15560
|
});
|
|
14461
15561
|
} catch (error) {
|
|
@@ -14521,8 +15621,8 @@ init_cjs_shims();
|
|
|
14521
15621
|
|
|
14522
15622
|
// src/skill/loader.ts
|
|
14523
15623
|
init_cjs_shims();
|
|
14524
|
-
var
|
|
14525
|
-
var
|
|
15624
|
+
var fs27 = __toESM(require("fs"));
|
|
15625
|
+
var path21 = __toESM(require("path"));
|
|
14526
15626
|
var import_gray_matter = __toESM(require("gray-matter"));
|
|
14527
15627
|
init_logger();
|
|
14528
15628
|
|
|
@@ -14702,23 +15802,23 @@ function extractSkillMetadata(content) {
|
|
|
14702
15802
|
|
|
14703
15803
|
// src/commands/skill/validate.ts
|
|
14704
15804
|
init_paths();
|
|
14705
|
-
var
|
|
14706
|
-
var
|
|
15805
|
+
var fs28 = __toESM(require("fs"));
|
|
15806
|
+
var path22 = __toESM(require("path"));
|
|
14707
15807
|
var skillValidateCommand = new Command("validate").description("Validate local skill files").argument("[skillPath]", "Path to skill file or directory (defaults to ~/.refly/skills)").option("--fix", "Attempt to fix common issues").action(async (skillPath, _options) => {
|
|
14708
15808
|
try {
|
|
14709
15809
|
const results = [];
|
|
14710
15810
|
let targetPath;
|
|
14711
15811
|
if (skillPath) {
|
|
14712
|
-
targetPath =
|
|
15812
|
+
targetPath = path22.resolve(skillPath);
|
|
14713
15813
|
} else {
|
|
14714
15814
|
await ensureSkillsDir();
|
|
14715
15815
|
targetPath = getSkillsDir();
|
|
14716
15816
|
}
|
|
14717
|
-
if (!
|
|
15817
|
+
if (!fs28.existsSync(targetPath)) {
|
|
14718
15818
|
fail(ErrorCodes.NOT_FOUND, `Path not found: ${targetPath}`);
|
|
14719
15819
|
return;
|
|
14720
15820
|
}
|
|
14721
|
-
const stats =
|
|
15821
|
+
const stats = fs28.statSync(targetPath);
|
|
14722
15822
|
if (stats.isFile()) {
|
|
14723
15823
|
const result = validateSkillFile(targetPath);
|
|
14724
15824
|
results.push(result);
|
|
@@ -14751,7 +15851,7 @@ var skillValidateCommand = new Command("validate").description("Validate local s
|
|
|
14751
15851
|
});
|
|
14752
15852
|
function validateSkillFile(filePath) {
|
|
14753
15853
|
try {
|
|
14754
|
-
const content =
|
|
15854
|
+
const content = fs28.readFileSync(filePath, "utf-8");
|
|
14755
15855
|
const { frontmatter, issues } = extractSkillMetadata(content);
|
|
14756
15856
|
const errors = issues.map((i) => `${i.path}: ${i.message}`);
|
|
14757
15857
|
const warnings = [];
|
|
@@ -14777,9 +15877,9 @@ function validateSkillFile(filePath) {
|
|
|
14777
15877
|
}
|
|
14778
15878
|
}
|
|
14779
15879
|
function findSkillFiles(dir, files = []) {
|
|
14780
|
-
const entries =
|
|
15880
|
+
const entries = fs28.readdirSync(dir, { withFileTypes: true });
|
|
14781
15881
|
for (const entry of entries) {
|
|
14782
|
-
const fullPath =
|
|
15882
|
+
const fullPath = path22.join(dir, entry.name);
|
|
14783
15883
|
if (entry.isDirectory()) {
|
|
14784
15884
|
if (!entry.name.startsWith(".")) {
|
|
14785
15885
|
findSkillFiles(fullPath, files);
|
|
@@ -14793,12 +15893,73 @@ function findSkillFiles(dir, files = []) {
|
|
|
14793
15893
|
|
|
14794
15894
|
// src/commands/skill/sync.ts
|
|
14795
15895
|
init_cjs_shims();
|
|
15896
|
+
var fs29 = __toESM(require("fs"));
|
|
15897
|
+
var path23 = __toESM(require("path"));
|
|
14796
15898
|
init_symlink();
|
|
15899
|
+
init_manager();
|
|
15900
|
+
init_registry();
|
|
14797
15901
|
init_paths();
|
|
14798
|
-
var
|
|
14799
|
-
var path20 = __toESM(require("path"));
|
|
14800
|
-
var skillSyncCommand = new Command("sync").description("Validate and repair skill symlinks").option("--dry-run", "Show issues without making changes").option("--fix", "Attempt to repair broken symlinks").option("--prune", "Remove orphan symlinks (symlinks without source directory)").action(async (options) => {
|
|
15902
|
+
var skillSyncCommand = new Command("sync").description("Validate and repair skill symlinks across all platforms").option("--dry-run", "Show issues without making changes").option("--fix", "Attempt to repair broken symlinks").option("--prune", "Remove orphan symlinks (symlinks without source directory)").option("--platform <platforms...>", "Sync to specific platforms only (comma-separated)").option("--all-platforms", "Sync to all installed platforms (not just Claude Code)").action(async (options) => {
|
|
14801
15903
|
try {
|
|
15904
|
+
let targetAgents;
|
|
15905
|
+
if (options.platform) {
|
|
15906
|
+
const platformList = options.platform.flatMap((p) => p.split(","));
|
|
15907
|
+
targetAgents = [];
|
|
15908
|
+
for (const platform4 of platformList) {
|
|
15909
|
+
const trimmed = platform4.trim();
|
|
15910
|
+
if (!isValidAgentType(trimmed)) {
|
|
15911
|
+
return fail(ErrorCodes.INVALID_INPUT, `Unknown platform: ${trimmed}`, {
|
|
15912
|
+
hint: `Valid platforms: ${Object.keys(agents).join(", ")}`
|
|
15913
|
+
});
|
|
15914
|
+
}
|
|
15915
|
+
targetAgents.push(trimmed);
|
|
15916
|
+
}
|
|
15917
|
+
}
|
|
15918
|
+
if (options.allPlatforms) {
|
|
15919
|
+
const installedAgents = await detectInstalledAgents();
|
|
15920
|
+
const deployableAgents = installedAgents.filter((a) => a.format !== "unknown");
|
|
15921
|
+
const skillsDir2 = getReflySkillsDir();
|
|
15922
|
+
const baseSkillDir = getReflyBaseSkillDir();
|
|
15923
|
+
const skillsToSync = [];
|
|
15924
|
+
if (fs29.existsSync(baseSkillDir)) {
|
|
15925
|
+
skillsToSync.push("refly");
|
|
15926
|
+
}
|
|
15927
|
+
if (fs29.existsSync(skillsDir2)) {
|
|
15928
|
+
const entries = fs29.readdirSync(skillsDir2, { withFileTypes: true });
|
|
15929
|
+
for (const entry of entries) {
|
|
15930
|
+
if (entry.isDirectory() && entry.name !== "base") {
|
|
15931
|
+
skillsToSync.push(entry.name);
|
|
15932
|
+
}
|
|
15933
|
+
}
|
|
15934
|
+
}
|
|
15935
|
+
const platformResults = [];
|
|
15936
|
+
for (const skillName of skillsToSync) {
|
|
15937
|
+
const { needsSync, synced } = await syncSkillToAllPlatforms(skillName, {
|
|
15938
|
+
agents: targetAgents,
|
|
15939
|
+
dryRun: options.dryRun
|
|
15940
|
+
});
|
|
15941
|
+
platformResults.push({
|
|
15942
|
+
skillName,
|
|
15943
|
+
needsSync: Array.from(needsSync.entries()).map(([agent, status]) => ({
|
|
15944
|
+
agent,
|
|
15945
|
+
deployed: status.deployed,
|
|
15946
|
+
valid: status.valid
|
|
15947
|
+
})),
|
|
15948
|
+
synced: Array.from(synced.entries()).map(([agent, result]) => ({
|
|
15949
|
+
agent,
|
|
15950
|
+
success: result.success,
|
|
15951
|
+
path: result.deployedPath || void 0
|
|
15952
|
+
}))
|
|
15953
|
+
});
|
|
15954
|
+
}
|
|
15955
|
+
return ok("skill.sync", {
|
|
15956
|
+
dryRun: Boolean(options.dryRun),
|
|
15957
|
+
allPlatforms: true,
|
|
15958
|
+
installedAgents: deployableAgents.map((a) => a.name),
|
|
15959
|
+
skillsCount: skillsToSync.length,
|
|
15960
|
+
results: platformResults
|
|
15961
|
+
});
|
|
15962
|
+
}
|
|
14802
15963
|
const symlinks = listSkillSymlinks();
|
|
14803
15964
|
const warnings = [];
|
|
14804
15965
|
const errors = [];
|
|
@@ -14823,14 +15984,14 @@ var skillSyncCommand = new Command("sync").description("Validate and repair skil
|
|
|
14823
15984
|
}
|
|
14824
15985
|
}
|
|
14825
15986
|
const skillsDir = getReflySkillsDir();
|
|
14826
|
-
if (
|
|
14827
|
-
const entries =
|
|
15987
|
+
if (fs29.existsSync(skillsDir)) {
|
|
15988
|
+
const entries = fs29.readdirSync(skillsDir, { withFileTypes: true });
|
|
14828
15989
|
const symlinkNames = new Set(symlinks.map((s) => s.name));
|
|
14829
15990
|
for (const entry of entries) {
|
|
14830
15991
|
if (entry.isDirectory() && entry.name !== "base") {
|
|
14831
15992
|
if (!symlinkNames.has(entry.name)) {
|
|
14832
15993
|
orphans += 1;
|
|
14833
|
-
warnings.push(`Orphan directory (no symlink): ${
|
|
15994
|
+
warnings.push(`Orphan directory (no symlink): ${path23.join(skillsDir, entry.name)}`);
|
|
14834
15995
|
if (options.prune && !options.dryRun) {
|
|
14835
15996
|
const result = createSkillSymlink(entry.name);
|
|
14836
15997
|
if (result.success) {
|
|
@@ -14877,11 +16038,178 @@ var skillSyncCommand = new Command("sync").description("Validate and repair skil
|
|
|
14877
16038
|
// src/commands/skill/index.ts
|
|
14878
16039
|
var skillCommand = new Command("skill").description("Manage skill packages and local skills").addCommand(skillListCommand).addCommand(skillGetCommand).addCommand(skillCreateCommand).addCommand(skillUpdateCommand).addCommand(skillPublishCommand).addCommand(skillUnpublishCommand).addCommand(skillSearchCommand).addCommand(skillInstallCommand).addCommand(skillUninstallCommand).addCommand(skillInstallationsCommand).addCommand(skillRunCommand).addCommand(skillStopCommand).addCommand(skillValidateCommand).addCommand(skillSyncCommand);
|
|
14879
16040
|
|
|
16041
|
+
// src/commands/platform/index.ts
|
|
16042
|
+
init_cjs_shims();
|
|
16043
|
+
|
|
16044
|
+
// src/commands/platform/sync.ts
|
|
16045
|
+
init_cjs_shims();
|
|
16046
|
+
var fs30 = __toESM(require("fs"));
|
|
16047
|
+
init_manager();
|
|
16048
|
+
init_registry();
|
|
16049
|
+
init_paths();
|
|
16050
|
+
var platformSyncCommand = new Command("sync").description("Detect installed agents and sync skills to all platforms").option("--agent <agents...>", "Specific agents to sync to (comma-separated)").option("--dry-run", "Show what would be done without making changes").option("--yes", "Skip confirmation prompts").action(async (options) => {
|
|
16051
|
+
try {
|
|
16052
|
+
const pretty = isPrettyOutput();
|
|
16053
|
+
const tty = isTTY();
|
|
16054
|
+
let targetAgents;
|
|
16055
|
+
if (options.agent) {
|
|
16056
|
+
const agentList = options.agent.flatMap((a) => a.split(","));
|
|
16057
|
+
const validatedAgents = [];
|
|
16058
|
+
for (const agent of agentList) {
|
|
16059
|
+
const trimmed = agent.trim();
|
|
16060
|
+
if (!isValidAgentType(trimmed)) {
|
|
16061
|
+
return fail(ErrorCodes.INVALID_INPUT, `Unknown agent: ${trimmed}`, {
|
|
16062
|
+
hint: `Valid agents: ${Object.keys(agents).join(", ")}`
|
|
16063
|
+
});
|
|
16064
|
+
}
|
|
16065
|
+
validatedAgents.push(trimmed);
|
|
16066
|
+
}
|
|
16067
|
+
targetAgents = validatedAgents;
|
|
16068
|
+
}
|
|
16069
|
+
if (pretty && tty) {
|
|
16070
|
+
println("Scanning for installed agents...");
|
|
16071
|
+
println("");
|
|
16072
|
+
}
|
|
16073
|
+
const installedAgents = targetAgents ? targetAgents.map((name) => agents[name]) : await detectInstalledAgents();
|
|
16074
|
+
const deployableAgents = installedAgents.filter((a) => a.format !== "unknown");
|
|
16075
|
+
if (deployableAgents.length === 0) {
|
|
16076
|
+
if (pretty && tty) {
|
|
16077
|
+
printError2("No supported agents found");
|
|
16078
|
+
printDim("Install an AI coding assistant and try again.");
|
|
16079
|
+
} else {
|
|
16080
|
+
ok("platform.sync", {
|
|
16081
|
+
message: "No supported agents found",
|
|
16082
|
+
installedAgents: [],
|
|
16083
|
+
skillsSynced: 0
|
|
16084
|
+
});
|
|
16085
|
+
}
|
|
16086
|
+
return;
|
|
16087
|
+
}
|
|
16088
|
+
if (pretty && tty) {
|
|
16089
|
+
println(`Found ${deployableAgents.length} installed agent(s):`);
|
|
16090
|
+
for (const agent of deployableAgents) {
|
|
16091
|
+
const dir = agent.globalSkillsDir || agent.skillsDir || "N/A";
|
|
16092
|
+
println(` \u2713 ${agent.displayName.padEnd(16)} ${dir}`);
|
|
16093
|
+
}
|
|
16094
|
+
println("");
|
|
16095
|
+
}
|
|
16096
|
+
const skillsDir = getReflySkillsDir();
|
|
16097
|
+
const baseSkillDir = getReflyBaseSkillDir();
|
|
16098
|
+
const skillsToSync = [];
|
|
16099
|
+
if (fs30.existsSync(baseSkillDir)) {
|
|
16100
|
+
skillsToSync.push("refly");
|
|
16101
|
+
}
|
|
16102
|
+
if (fs30.existsSync(skillsDir)) {
|
|
16103
|
+
const entries = fs30.readdirSync(skillsDir, { withFileTypes: true });
|
|
16104
|
+
for (const entry of entries) {
|
|
16105
|
+
if (entry.isDirectory() && entry.name !== "base") {
|
|
16106
|
+
skillsToSync.push(entry.name);
|
|
16107
|
+
}
|
|
16108
|
+
}
|
|
16109
|
+
}
|
|
16110
|
+
if (skillsToSync.length === 0) {
|
|
16111
|
+
if (pretty && tty) {
|
|
16112
|
+
printDim("No skills found to sync.");
|
|
16113
|
+
printDim("Run `refly init` to install the base skill.");
|
|
16114
|
+
} else {
|
|
16115
|
+
ok("platform.sync", {
|
|
16116
|
+
message: "No skills found to sync",
|
|
16117
|
+
installedAgents: deployableAgents.map((a) => a.name),
|
|
16118
|
+
skillsSynced: 0
|
|
16119
|
+
});
|
|
16120
|
+
}
|
|
16121
|
+
return;
|
|
16122
|
+
}
|
|
16123
|
+
if (pretty && tty) {
|
|
16124
|
+
println(`Syncing ${skillsToSync.length} skill(s) to all installed agents...`);
|
|
16125
|
+
}
|
|
16126
|
+
if (options.dryRun) {
|
|
16127
|
+
if (pretty && tty) {
|
|
16128
|
+
println("");
|
|
16129
|
+
println("Dry run - no changes made:");
|
|
16130
|
+
for (const skillName of skillsToSync) {
|
|
16131
|
+
const agentNames = deployableAgents.map((a) => a.displayName).join(", ");
|
|
16132
|
+
println(` ${skillName} -> ${agentNames}`);
|
|
16133
|
+
}
|
|
16134
|
+
} else {
|
|
16135
|
+
ok("platform.sync", {
|
|
16136
|
+
dryRun: true,
|
|
16137
|
+
installedAgents: deployableAgents.map((a) => a.name),
|
|
16138
|
+
skillsToSync
|
|
16139
|
+
});
|
|
16140
|
+
}
|
|
16141
|
+
return;
|
|
16142
|
+
}
|
|
16143
|
+
const results = [];
|
|
16144
|
+
for (const skillName of skillsToSync) {
|
|
16145
|
+
const deployResult = await deploySkillToAllPlatforms(skillName, {
|
|
16146
|
+
force: true,
|
|
16147
|
+
// Force to ensure repair
|
|
16148
|
+
agents: targetAgents
|
|
16149
|
+
});
|
|
16150
|
+
const details = [];
|
|
16151
|
+
for (const [agentName, result] of deployResult.results) {
|
|
16152
|
+
details.push({
|
|
16153
|
+
agent: agentName,
|
|
16154
|
+
success: result.success,
|
|
16155
|
+
path: result.deployedPath || void 0,
|
|
16156
|
+
error: result.error
|
|
16157
|
+
});
|
|
16158
|
+
}
|
|
16159
|
+
results.push({
|
|
16160
|
+
skillName,
|
|
16161
|
+
success: deployResult.successCount,
|
|
16162
|
+
failed: deployResult.failureCount,
|
|
16163
|
+
details
|
|
16164
|
+
});
|
|
16165
|
+
if (pretty && tty) {
|
|
16166
|
+
const statusParts = deployableAgents.map((agent) => {
|
|
16167
|
+
const result = deployResult.results.get(agent.name);
|
|
16168
|
+
return result?.success ? "\u2713" : "\u2717";
|
|
16169
|
+
});
|
|
16170
|
+
println(` ${skillName.padEnd(20)} ${statusParts.join(" ")}`);
|
|
16171
|
+
}
|
|
16172
|
+
}
|
|
16173
|
+
const totalSuccess = results.reduce((sum, r) => sum + r.success, 0);
|
|
16174
|
+
const totalFailed = results.reduce((sum, r) => sum + r.failed, 0);
|
|
16175
|
+
if (pretty && tty) {
|
|
16176
|
+
println("");
|
|
16177
|
+
printSuccess(
|
|
16178
|
+
`Done! ${deployableAgents.length} agent(s), ${skillsToSync.length} skill(s) synced.`
|
|
16179
|
+
);
|
|
16180
|
+
if (totalFailed > 0) {
|
|
16181
|
+
printError2(`${totalFailed} deployment(s) failed. Check logs for details.`);
|
|
16182
|
+
}
|
|
16183
|
+
} else {
|
|
16184
|
+
ok("platform.sync", {
|
|
16185
|
+
installedAgents: deployableAgents.map((a) => ({
|
|
16186
|
+
name: a.name,
|
|
16187
|
+
displayName: a.displayName,
|
|
16188
|
+
format: a.format,
|
|
16189
|
+
globalSkillsDir: a.globalSkillsDir
|
|
16190
|
+
})),
|
|
16191
|
+
skillsSynced: skillsToSync.length,
|
|
16192
|
+
totalSuccess,
|
|
16193
|
+
totalFailed,
|
|
16194
|
+
results
|
|
16195
|
+
});
|
|
16196
|
+
}
|
|
16197
|
+
} catch (error) {
|
|
16198
|
+
fail(
|
|
16199
|
+
ErrorCodes.INTERNAL_ERROR,
|
|
16200
|
+
error instanceof Error ? error.message : "Failed to sync platforms"
|
|
16201
|
+
);
|
|
16202
|
+
}
|
|
16203
|
+
});
|
|
16204
|
+
|
|
16205
|
+
// src/commands/platform/index.ts
|
|
16206
|
+
var platformCommand = new Command("platform").description("Manage multi-platform skill deployment").addCommand(platformSyncCommand);
|
|
16207
|
+
|
|
14880
16208
|
// src/bin/refly.ts
|
|
14881
16209
|
function getVersion() {
|
|
14882
16210
|
try {
|
|
14883
|
-
const pkgPath =
|
|
14884
|
-
const pkg = JSON.parse(
|
|
16211
|
+
const pkgPath = path24.join(__dirname, "..", "..", "package.json");
|
|
16212
|
+
const pkg = JSON.parse(fs31.readFileSync(pkgPath, "utf-8"));
|
|
14885
16213
|
return pkg.version || "0.1.0";
|
|
14886
16214
|
} catch {
|
|
14887
16215
|
return "0.1.0";
|
|
@@ -14922,6 +16250,7 @@ program2.addCommand(workflowCommand);
|
|
|
14922
16250
|
program2.addCommand(toolCommand);
|
|
14923
16251
|
program2.addCommand(fileCommand);
|
|
14924
16252
|
program2.addCommand(skillCommand);
|
|
16253
|
+
program2.addCommand(platformCommand);
|
|
14925
16254
|
program2.exitOverride((err) => {
|
|
14926
16255
|
if (err.code === "commander.helpDisplayed" || err.code === "commander.version") {
|
|
14927
16256
|
process.exit(0);
|