@powerformer/refly-cli 0.1.23 → 0.1.25
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 +1564 -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 +116 -13
- package/skill/references/execution.md +218 -0
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,21 @@ 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.split("").filter((char) => {
|
|
5251
|
+
const code = char.charCodeAt(0);
|
|
5252
|
+
return code >= 32 || code === 9 || code === 10 || code === 13;
|
|
5253
|
+
}).join("");
|
|
5254
|
+
}
|
|
5255
|
+
return value;
|
|
5256
|
+
};
|
|
4308
5257
|
// === Pretty Format ===
|
|
4309
5258
|
outputPretty(type, payload) {
|
|
4310
5259
|
if (type === "workflow.status" || type === "workflow.progress") {
|
|
@@ -4893,8 +5842,8 @@ var ErrorCodes = {
|
|
|
4893
5842
|
};
|
|
4894
5843
|
|
|
4895
5844
|
// src/bin/refly.ts
|
|
4896
|
-
var
|
|
4897
|
-
var
|
|
5845
|
+
var fs31 = __toESM(require("fs"));
|
|
5846
|
+
var path24 = __toESM(require("path"));
|
|
4898
5847
|
|
|
4899
5848
|
// src/commands/init.ts
|
|
4900
5849
|
init_cjs_shims();
|
|
@@ -5399,8 +6348,8 @@ function getErrorMap() {
|
|
|
5399
6348
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/helpers/parseUtil.js
|
|
5400
6349
|
init_cjs_shims();
|
|
5401
6350
|
var makeIssue = (params) => {
|
|
5402
|
-
const { data, path:
|
|
5403
|
-
const fullPath = [...
|
|
6351
|
+
const { data, path: path25, errorMaps, issueData } = params;
|
|
6352
|
+
const fullPath = [...path25, ...issueData.path || []];
|
|
5404
6353
|
const fullIssue = {
|
|
5405
6354
|
...issueData,
|
|
5406
6355
|
path: fullPath
|
|
@@ -5520,11 +6469,11 @@ var errorUtil;
|
|
|
5520
6469
|
|
|
5521
6470
|
// ../../node_modules/.pnpm/zod@3.25.76/node_modules/zod/v3/types.js
|
|
5522
6471
|
var ParseInputLazyPath = class {
|
|
5523
|
-
constructor(parent, value,
|
|
6472
|
+
constructor(parent, value, path25, key) {
|
|
5524
6473
|
this._cachedPath = [];
|
|
5525
6474
|
this.parent = parent;
|
|
5526
6475
|
this.data = value;
|
|
5527
|
-
this._path =
|
|
6476
|
+
this._path = path25;
|
|
5528
6477
|
this._key = key;
|
|
5529
6478
|
}
|
|
5530
6479
|
get path() {
|
|
@@ -8968,6 +9917,23 @@ var NEVER = INVALID;
|
|
|
8968
9917
|
|
|
8969
9918
|
// src/config/config.ts
|
|
8970
9919
|
init_paths();
|
|
9920
|
+
var AgentTypeEnum = external_exports.enum([
|
|
9921
|
+
"claude-code",
|
|
9922
|
+
"codex",
|
|
9923
|
+
"antigravity",
|
|
9924
|
+
"github-copilot",
|
|
9925
|
+
"windsurf",
|
|
9926
|
+
"opencode",
|
|
9927
|
+
"moltbot",
|
|
9928
|
+
"cursor",
|
|
9929
|
+
"continue",
|
|
9930
|
+
"trae",
|
|
9931
|
+
"qoder"
|
|
9932
|
+
]);
|
|
9933
|
+
var PlatformConfigSchema = external_exports.object({
|
|
9934
|
+
enabled: external_exports.boolean().default(true),
|
|
9935
|
+
globalPath: external_exports.string().optional()
|
|
9936
|
+
});
|
|
8971
9937
|
var ConfigSchema = external_exports.object({
|
|
8972
9938
|
version: external_exports.number().default(1),
|
|
8973
9939
|
auth: external_exports.object({
|
|
@@ -8995,7 +9961,9 @@ var ConfigSchema = external_exports.object({
|
|
|
8995
9961
|
skill: external_exports.object({
|
|
8996
9962
|
installedVersion: external_exports.string().optional(),
|
|
8997
9963
|
installedAt: external_exports.string().optional()
|
|
8998
|
-
}).optional()
|
|
9964
|
+
}).optional(),
|
|
9965
|
+
// Multi-platform configuration
|
|
9966
|
+
platforms: external_exports.record(AgentTypeEnum, PlatformConfigSchema).optional()
|
|
8999
9967
|
});
|
|
9000
9968
|
var DEFAULT_API_ENDPOINT = "https://api.refly.ai";
|
|
9001
9969
|
var DEFAULT_WEB_URL = "https://refly.ai";
|
|
@@ -9132,22 +10100,22 @@ init_paths();
|
|
|
9132
10100
|
|
|
9133
10101
|
// src/skill/installer.ts
|
|
9134
10102
|
init_cjs_shims();
|
|
9135
|
-
var
|
|
9136
|
-
var
|
|
10103
|
+
var fs9 = __toESM(require("fs"));
|
|
10104
|
+
var path8 = __toESM(require("path"));
|
|
9137
10105
|
init_paths();
|
|
9138
10106
|
init_logger();
|
|
9139
10107
|
init_symlink();
|
|
9140
10108
|
function removeOldSkillDirectory() {
|
|
9141
10109
|
const claudeSkillPath = getClaudeSkillSymlinkPath("refly");
|
|
9142
|
-
if (!
|
|
10110
|
+
if (!fs9.existsSync(claudeSkillPath)) {
|
|
9143
10111
|
return;
|
|
9144
10112
|
}
|
|
9145
10113
|
try {
|
|
9146
|
-
const stat =
|
|
10114
|
+
const stat = fs9.lstatSync(claudeSkillPath);
|
|
9147
10115
|
if (stat.isSymbolicLink()) {
|
|
9148
|
-
|
|
10116
|
+
fs9.unlinkSync(claudeSkillPath);
|
|
9149
10117
|
} else if (stat.isDirectory()) {
|
|
9150
|
-
|
|
10118
|
+
fs9.rmSync(claudeSkillPath, { recursive: true, force: true });
|
|
9151
10119
|
logger.info("Removed old skill directory");
|
|
9152
10120
|
}
|
|
9153
10121
|
} catch (err) {
|
|
@@ -9156,17 +10124,17 @@ function removeOldSkillDirectory() {
|
|
|
9156
10124
|
}
|
|
9157
10125
|
function getPackageSkillDir() {
|
|
9158
10126
|
const possiblePaths = [
|
|
9159
|
-
|
|
10127
|
+
path8.join(__dirname, "..", "..", "skill"),
|
|
9160
10128
|
// Built package: dist/bin/../../skill
|
|
9161
|
-
|
|
10129
|
+
path8.join(__dirname, "..", "..", "..", "skill"),
|
|
9162
10130
|
// Development: dist/bin/../../../skill
|
|
9163
|
-
|
|
10131
|
+
path8.join(__dirname, "..", "skill")
|
|
9164
10132
|
// Alternative: dist/../skill
|
|
9165
10133
|
];
|
|
9166
10134
|
logger.debug("Looking for skill files, __dirname:", __dirname);
|
|
9167
10135
|
for (const p of possiblePaths) {
|
|
9168
|
-
const resolved =
|
|
9169
|
-
const exists =
|
|
10136
|
+
const resolved = path8.resolve(p);
|
|
10137
|
+
const exists = fs9.existsSync(resolved);
|
|
9170
10138
|
logger.debug(` Checking path: ${resolved} - exists: ${exists}`);
|
|
9171
10139
|
if (exists) {
|
|
9172
10140
|
return resolved;
|
|
@@ -9190,30 +10158,30 @@ function installSkill() {
|
|
|
9190
10158
|
logger.debug("Target skill directory:", targetDir);
|
|
9191
10159
|
try {
|
|
9192
10160
|
ensureDir(targetDir);
|
|
9193
|
-
ensureDir(
|
|
10161
|
+
ensureDir(path8.join(targetDir, "rules"));
|
|
9194
10162
|
logger.debug("Created target directories");
|
|
9195
10163
|
} catch (err) {
|
|
9196
10164
|
logger.error("Failed to create target directories:", err);
|
|
9197
10165
|
throw err;
|
|
9198
10166
|
}
|
|
9199
|
-
const skillSource =
|
|
9200
|
-
const skillTarget =
|
|
10167
|
+
const skillSource = path8.join(sourceDir, "SKILL.md");
|
|
10168
|
+
const skillTarget = path8.join(targetDir, "SKILL.md");
|
|
9201
10169
|
logger.debug(`Copying SKILL.md: ${skillSource} -> ${skillTarget}`);
|
|
9202
|
-
if (
|
|
9203
|
-
|
|
10170
|
+
if (fs9.existsSync(skillSource)) {
|
|
10171
|
+
fs9.copyFileSync(skillSource, skillTarget);
|
|
9204
10172
|
result.skillInstalled = true;
|
|
9205
10173
|
result.skillPath = targetDir;
|
|
9206
10174
|
logger.debug("SKILL.md copied successfully");
|
|
9207
10175
|
} else {
|
|
9208
10176
|
logger.warn("SKILL.md source not found:", skillSource);
|
|
9209
10177
|
}
|
|
9210
|
-
const refsSource =
|
|
9211
|
-
const rulesTarget =
|
|
9212
|
-
if (
|
|
9213
|
-
const files =
|
|
10178
|
+
const refsSource = path8.join(sourceDir, "references");
|
|
10179
|
+
const rulesTarget = path8.join(targetDir, "rules");
|
|
10180
|
+
if (fs9.existsSync(refsSource)) {
|
|
10181
|
+
const files = fs9.readdirSync(refsSource);
|
|
9214
10182
|
logger.debug(`Copying ${files.length} rule files`);
|
|
9215
10183
|
for (const file of files) {
|
|
9216
|
-
|
|
10184
|
+
fs9.copyFileSync(path8.join(refsSource, file), path8.join(rulesTarget, file));
|
|
9217
10185
|
}
|
|
9218
10186
|
}
|
|
9219
10187
|
removeOldSkillDirectory();
|
|
@@ -9241,15 +10209,15 @@ function installSkill() {
|
|
|
9241
10209
|
return result;
|
|
9242
10210
|
}
|
|
9243
10211
|
function installSlashCommands(sourceDir, targetDir) {
|
|
9244
|
-
const commandsSource =
|
|
9245
|
-
if (!
|
|
10212
|
+
const commandsSource = path8.join(sourceDir, "..", "commands");
|
|
10213
|
+
if (!fs9.existsSync(commandsSource)) {
|
|
9246
10214
|
return false;
|
|
9247
10215
|
}
|
|
9248
10216
|
try {
|
|
9249
|
-
const files =
|
|
10217
|
+
const files = fs9.readdirSync(commandsSource);
|
|
9250
10218
|
for (const file of files) {
|
|
9251
10219
|
if (file.endsWith(".md")) {
|
|
9252
|
-
|
|
10220
|
+
fs9.copyFileSync(path8.join(commandsSource, file), path8.join(targetDir, file));
|
|
9253
10221
|
}
|
|
9254
10222
|
}
|
|
9255
10223
|
return files.length > 0;
|
|
@@ -9259,8 +10227,8 @@ function installSlashCommands(sourceDir, targetDir) {
|
|
|
9259
10227
|
}
|
|
9260
10228
|
function getSkillVersion() {
|
|
9261
10229
|
try {
|
|
9262
|
-
const skillPath =
|
|
9263
|
-
const content =
|
|
10230
|
+
const skillPath = path8.join(getPackageSkillDir(), "SKILL.md");
|
|
10231
|
+
const content = fs9.readFileSync(skillPath, "utf-8");
|
|
9264
10232
|
const versionMatch = content.match(/version:\s*(\d+\.\d+\.\d+)/);
|
|
9265
10233
|
if (versionMatch) {
|
|
9266
10234
|
return versionMatch[1];
|
|
@@ -9268,16 +10236,16 @@ function getSkillVersion() {
|
|
|
9268
10236
|
} catch {
|
|
9269
10237
|
}
|
|
9270
10238
|
try {
|
|
9271
|
-
const pkgPath =
|
|
9272
|
-
const pkg = JSON.parse(
|
|
10239
|
+
const pkgPath = path8.join(__dirname, "..", "..", "package.json");
|
|
10240
|
+
const pkg = JSON.parse(fs9.readFileSync(pkgPath, "utf-8"));
|
|
9273
10241
|
return pkg.version;
|
|
9274
10242
|
} catch {
|
|
9275
10243
|
return "0.1.0";
|
|
9276
10244
|
}
|
|
9277
10245
|
}
|
|
9278
10246
|
function isSkillInstalled() {
|
|
9279
|
-
const skillPath =
|
|
9280
|
-
if (!
|
|
10247
|
+
const skillPath = path8.join(getReflyBaseSkillDir(), "SKILL.md");
|
|
10248
|
+
if (!fs9.existsSync(skillPath)) {
|
|
9281
10249
|
return { installed: false, upToDate: false };
|
|
9282
10250
|
}
|
|
9283
10251
|
const currentVersion = getSkillVersion();
|
|
@@ -9291,6 +10259,9 @@ function isSkillInstalled() {
|
|
|
9291
10259
|
};
|
|
9292
10260
|
}
|
|
9293
10261
|
|
|
10262
|
+
// src/commands/init.ts
|
|
10263
|
+
init_manager();
|
|
10264
|
+
|
|
9294
10265
|
// src/utils/logo.ts
|
|
9295
10266
|
init_cjs_shims();
|
|
9296
10267
|
var REFLY_LOGO = `\u2588\u2580\u2588 \u2588\u2580\u2580 \u2588\u2580\u2580 \u2588 \u2588 \u2588 \u2588\u2580\u2588 \u2588
|
|
@@ -9349,7 +10320,7 @@ var import_promises = __toESM(require("fs/promises"), 1);
|
|
|
9349
10320
|
// ../../node_modules/.pnpm/is-wsl@3.1.0/node_modules/is-wsl/index.js
|
|
9350
10321
|
init_cjs_shims();
|
|
9351
10322
|
var import_node_process = __toESM(require("process"), 1);
|
|
9352
|
-
var
|
|
10323
|
+
var import_node_os3 = __toESM(require("os"), 1);
|
|
9353
10324
|
var import_node_fs3 = __toESM(require("fs"), 1);
|
|
9354
10325
|
|
|
9355
10326
|
// ../../node_modules/.pnpm/is-inside-container@1.0.0/node_modules/is-inside-container/index.js
|
|
@@ -9404,7 +10375,7 @@ var isWsl = () => {
|
|
|
9404
10375
|
if (import_node_process.default.platform !== "linux") {
|
|
9405
10376
|
return false;
|
|
9406
10377
|
}
|
|
9407
|
-
if (
|
|
10378
|
+
if (import_node_os3.default.release().toLowerCase().includes("microsoft")) {
|
|
9408
10379
|
if (isInsideContainer()) {
|
|
9409
10380
|
return false;
|
|
9410
10381
|
}
|
|
@@ -9600,7 +10571,7 @@ async function defaultBrowser2() {
|
|
|
9600
10571
|
var execFile5 = (0, import_node_util5.promisify)(import_node_child_process5.default.execFile);
|
|
9601
10572
|
var __dirname2 = import_node_path.default.dirname((0, import_node_url.fileURLToPath)(importMetaUrl));
|
|
9602
10573
|
var localXdgOpenPath = import_node_path.default.join(__dirname2, "xdg-open");
|
|
9603
|
-
var { platform:
|
|
10574
|
+
var { platform: platform3, arch } = import_node_process6.default;
|
|
9604
10575
|
async function getWindowsDefaultBrowserFromWsl() {
|
|
9605
10576
|
const powershellPath = await powerShellPath();
|
|
9606
10577
|
const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
|
|
@@ -9699,7 +10670,7 @@ var baseOpen = async (options) => {
|
|
|
9699
10670
|
let command;
|
|
9700
10671
|
const cliArguments = [];
|
|
9701
10672
|
const childProcessOptions = {};
|
|
9702
|
-
if (
|
|
10673
|
+
if (platform3 === "darwin") {
|
|
9703
10674
|
command = "open";
|
|
9704
10675
|
if (options.wait) {
|
|
9705
10676
|
cliArguments.push("--wait-apps");
|
|
@@ -9713,7 +10684,7 @@ var baseOpen = async (options) => {
|
|
|
9713
10684
|
if (app) {
|
|
9714
10685
|
cliArguments.push("-a", app);
|
|
9715
10686
|
}
|
|
9716
|
-
} else if (
|
|
10687
|
+
} else if (platform3 === "win32" || is_wsl_default && !isInsideContainer() && !app) {
|
|
9717
10688
|
command = await powerShellPath();
|
|
9718
10689
|
cliArguments.push(
|
|
9719
10690
|
"-NoProfile",
|
|
@@ -9753,7 +10724,7 @@ var baseOpen = async (options) => {
|
|
|
9753
10724
|
exeLocalXdgOpen = true;
|
|
9754
10725
|
} catch {
|
|
9755
10726
|
}
|
|
9756
|
-
const useSystemXdgOpen = import_node_process6.default.versions.electron ?? (
|
|
10727
|
+
const useSystemXdgOpen = import_node_process6.default.versions.electron ?? (platform3 === "android" || isBundled || !exeLocalXdgOpen);
|
|
9757
10728
|
command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
|
|
9758
10729
|
}
|
|
9759
10730
|
if (appArguments.length > 0) {
|
|
@@ -9764,7 +10735,7 @@ var baseOpen = async (options) => {
|
|
|
9764
10735
|
childProcessOptions.detached = true;
|
|
9765
10736
|
}
|
|
9766
10737
|
}
|
|
9767
|
-
if (
|
|
10738
|
+
if (platform3 === "darwin" && appArguments.length > 0) {
|
|
9768
10739
|
cliArguments.push("--args", ...appArguments);
|
|
9769
10740
|
}
|
|
9770
10741
|
if (options.target) {
|
|
@@ -9772,14 +10743,14 @@ var baseOpen = async (options) => {
|
|
|
9772
10743
|
}
|
|
9773
10744
|
const subprocess = import_node_child_process5.default.spawn(command, cliArguments, childProcessOptions);
|
|
9774
10745
|
if (options.wait) {
|
|
9775
|
-
return new Promise((
|
|
10746
|
+
return new Promise((resolve8, reject) => {
|
|
9776
10747
|
subprocess.once("error", reject);
|
|
9777
10748
|
subprocess.once("close", (exitCode) => {
|
|
9778
10749
|
if (!options.allowNonzeroExitCode && exitCode > 0) {
|
|
9779
10750
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
9780
10751
|
return;
|
|
9781
10752
|
}
|
|
9782
|
-
|
|
10753
|
+
resolve8(subprocess);
|
|
9783
10754
|
});
|
|
9784
10755
|
});
|
|
9785
10756
|
}
|
|
@@ -9805,12 +10776,12 @@ function detectArchBinary(binary) {
|
|
|
9805
10776
|
}
|
|
9806
10777
|
return archBinary;
|
|
9807
10778
|
}
|
|
9808
|
-
function detectPlatformBinary({ [
|
|
10779
|
+
function detectPlatformBinary({ [platform3]: platformBinary }, { wsl }) {
|
|
9809
10780
|
if (wsl && is_wsl_default) {
|
|
9810
10781
|
return detectArchBinary(wsl);
|
|
9811
10782
|
}
|
|
9812
10783
|
if (!platformBinary) {
|
|
9813
|
-
throw new Error(`${
|
|
10784
|
+
throw new Error(`${platform3} is not supported`);
|
|
9814
10785
|
}
|
|
9815
10786
|
return detectArchBinary(platformBinary);
|
|
9816
10787
|
}
|
|
@@ -9855,9 +10826,9 @@ var open_default = open;
|
|
|
9855
10826
|
|
|
9856
10827
|
// src/api/client.ts
|
|
9857
10828
|
init_cjs_shims();
|
|
9858
|
-
var
|
|
10829
|
+
var fs15 = __toESM(require("fs"));
|
|
9859
10830
|
var import_node_fs4 = require("fs");
|
|
9860
|
-
var
|
|
10831
|
+
var path10 = __toESM(require("path"));
|
|
9861
10832
|
var import_mime = __toESM(require("mime"));
|
|
9862
10833
|
|
|
9863
10834
|
// src/utils/errors.ts
|
|
@@ -9886,10 +10857,10 @@ var NetworkError = class extends CLIError {
|
|
|
9886
10857
|
// src/api/client.ts
|
|
9887
10858
|
init_logger();
|
|
9888
10859
|
var DEFAULT_TIMEOUT = 3e4;
|
|
9889
|
-
async function apiRequest(
|
|
10860
|
+
async function apiRequest(path25, options = {}) {
|
|
9890
10861
|
const { method = "GET", body, query, timeout = DEFAULT_TIMEOUT, requireAuth = true } = options;
|
|
9891
10862
|
const endpoint = getApiEndpoint();
|
|
9892
|
-
let url = `${endpoint}${
|
|
10863
|
+
let url = `${endpoint}${path25}`;
|
|
9893
10864
|
if (query && Object.keys(query).length > 0) {
|
|
9894
10865
|
const params = new URLSearchParams(query);
|
|
9895
10866
|
url = `${url}?${params.toString()}`;
|
|
@@ -9927,7 +10898,7 @@ async function apiRequest(path22, options = {}) {
|
|
|
9927
10898
|
const controller = new AbortController();
|
|
9928
10899
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
9929
10900
|
try {
|
|
9930
|
-
logger.debug(`API Request: ${method} ${
|
|
10901
|
+
logger.debug(`API Request: ${method} ${path25}`);
|
|
9931
10902
|
const response = await fetch(url, {
|
|
9932
10903
|
method,
|
|
9933
10904
|
headers,
|
|
@@ -10042,10 +11013,10 @@ function mapAPIError(status, response) {
|
|
|
10042
11013
|
}
|
|
10043
11014
|
return new CLIError(errCode, errMsg);
|
|
10044
11015
|
}
|
|
10045
|
-
async function apiRequestStream(
|
|
11016
|
+
async function apiRequestStream(path25, options = {}) {
|
|
10046
11017
|
const { timeout = 3e5 } = options;
|
|
10047
11018
|
const endpoint = getApiEndpoint();
|
|
10048
|
-
const url = `${endpoint}${
|
|
11019
|
+
const url = `${endpoint}${path25}`;
|
|
10049
11020
|
const headers = {
|
|
10050
11021
|
"User-Agent": "refly-cli/0.1.0"
|
|
10051
11022
|
};
|
|
@@ -10076,7 +11047,7 @@ async function apiRequestStream(path22, options = {}) {
|
|
|
10076
11047
|
const controller = new AbortController();
|
|
10077
11048
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
10078
11049
|
try {
|
|
10079
|
-
logger.debug(`API Stream Request: GET ${
|
|
11050
|
+
logger.debug(`API Stream Request: GET ${path25}`);
|
|
10080
11051
|
const response = await fetch(url, {
|
|
10081
11052
|
method: "GET",
|
|
10082
11053
|
headers,
|
|
@@ -10171,7 +11142,7 @@ async function uploadToPresignedUrl(presignedUrl, filePath, contentType, retryCo
|
|
|
10171
11142
|
const controller = new AbortController();
|
|
10172
11143
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
10173
11144
|
try {
|
|
10174
|
-
const fileBuffer = await
|
|
11145
|
+
const fileBuffer = await fs15.promises.readFile(filePath);
|
|
10175
11146
|
const response = await fetch(presignedUrl, {
|
|
10176
11147
|
method: "PUT",
|
|
10177
11148
|
headers: {
|
|
@@ -10229,7 +11200,7 @@ async function apiGetWorkflow(workflowId) {
|
|
|
10229
11200
|
return apiRequest(`/v1/cli/workflow/${workflowId}`);
|
|
10230
11201
|
}
|
|
10231
11202
|
async function apiUploadDriveFile(filePath, canvasId, options) {
|
|
10232
|
-
const filename =
|
|
11203
|
+
const filename = path10.basename(filePath);
|
|
10233
11204
|
const mimeType = getMimeType(filePath);
|
|
10234
11205
|
const fileStats = (0, import_node_fs4.statSync)(filePath);
|
|
10235
11206
|
logger.debug(`Starting presigned upload: ${filename} (${fileStats.size} bytes)`);
|
|
@@ -10492,7 +11463,7 @@ async function getUserInfoFromToken(accessToken) {
|
|
|
10492
11463
|
};
|
|
10493
11464
|
}
|
|
10494
11465
|
function sleep(ms) {
|
|
10495
|
-
return new Promise((
|
|
11466
|
+
return new Promise((resolve8) => setTimeout(resolve8, ms));
|
|
10496
11467
|
}
|
|
10497
11468
|
|
|
10498
11469
|
// src/commands/init.ts
|
|
@@ -10552,7 +11523,38 @@ var initCommand = new Command("init").description("Initialize Refly CLI, install
|
|
|
10552
11523
|
printError2("Slash commands installation failed");
|
|
10553
11524
|
}
|
|
10554
11525
|
println("");
|
|
10555
|
-
}
|
|
11526
|
+
}
|
|
11527
|
+
const installedAgents = await detectInstalledAgents();
|
|
11528
|
+
const deployableAgents = installedAgents.filter((a) => a.format !== "unknown");
|
|
11529
|
+
if (pretty && tty && deployableAgents.length > 0) {
|
|
11530
|
+
println(`Found ${deployableAgents.length} installed agent(s):`);
|
|
11531
|
+
for (const agent of deployableAgents) {
|
|
11532
|
+
const dir = agent.globalSkillsDir || agent.skillsDir || "N/A";
|
|
11533
|
+
println(` \u2713 ${agent.displayName.padEnd(16)} ${dir}`);
|
|
11534
|
+
}
|
|
11535
|
+
println("");
|
|
11536
|
+
}
|
|
11537
|
+
const platformResults = [];
|
|
11538
|
+
if (deployableAgents.length > 0) {
|
|
11539
|
+
const deployResult = await deploySkillToAllPlatforms("refly", { force: true });
|
|
11540
|
+
for (const [agentName, result] of deployResult.results) {
|
|
11541
|
+
platformResults.push({
|
|
11542
|
+
agent: agentName,
|
|
11543
|
+
success: result.success,
|
|
11544
|
+
path: result.deployedPath || void 0
|
|
11545
|
+
});
|
|
11546
|
+
}
|
|
11547
|
+
if (pretty && tty) {
|
|
11548
|
+
const successCount = platformResults.filter((r) => r.success).length;
|
|
11549
|
+
if (successCount === deployableAgents.length) {
|
|
11550
|
+
printSuccess(`Synced to ${successCount} agent(s)`);
|
|
11551
|
+
} else {
|
|
11552
|
+
printDim(`Synced to ${successCount}/${deployableAgents.length} agent(s)`);
|
|
11553
|
+
}
|
|
11554
|
+
println("");
|
|
11555
|
+
}
|
|
11556
|
+
}
|
|
11557
|
+
if (!pretty) {
|
|
10556
11558
|
print("init", {
|
|
10557
11559
|
message: "Refly CLI initialized successfully",
|
|
10558
11560
|
configDir: getReflyDir(),
|
|
@@ -10562,7 +11564,11 @@ var initCommand = new Command("init").description("Initialize Refly CLI, install
|
|
|
10562
11564
|
symlinkPath: installResult.symlinkPath,
|
|
10563
11565
|
commandsInstalled: installResult.commandsInstalled,
|
|
10564
11566
|
commandsPath: installResult.commandsPath,
|
|
10565
|
-
version: installResult.version
|
|
11567
|
+
version: installResult.version,
|
|
11568
|
+
platforms: {
|
|
11569
|
+
detected: installedAgents.map((a) => a.name),
|
|
11570
|
+
deployed: platformResults
|
|
11571
|
+
}
|
|
10566
11572
|
});
|
|
10567
11573
|
}
|
|
10568
11574
|
if (!skipLogin && !isAuthenticated2) {
|
|
@@ -10750,7 +11756,7 @@ var import_node_child_process6 = require("child_process");
|
|
|
10750
11756
|
var import_node_fs5 = __toESM(require("fs"));
|
|
10751
11757
|
init_logger();
|
|
10752
11758
|
init_paths();
|
|
10753
|
-
var CLI_VERSION = "0.1.
|
|
11759
|
+
var CLI_VERSION = "0.1.25";
|
|
10754
11760
|
var NPM_TAG = "latest";
|
|
10755
11761
|
function compareSemver(a, b) {
|
|
10756
11762
|
const parseVersion = (v) => {
|
|
@@ -11006,16 +12012,16 @@ configCommand.action(() => {
|
|
|
11006
12012
|
};
|
|
11007
12013
|
ok("config", safeConfig);
|
|
11008
12014
|
});
|
|
11009
|
-
function getNestedValue(obj,
|
|
11010
|
-
return
|
|
12015
|
+
function getNestedValue(obj, path25) {
|
|
12016
|
+
return path25.split(".").reduce((current, key) => {
|
|
11011
12017
|
if (current && typeof current === "object" && key in current) {
|
|
11012
12018
|
return current[key];
|
|
11013
12019
|
}
|
|
11014
12020
|
return void 0;
|
|
11015
12021
|
}, obj);
|
|
11016
12022
|
}
|
|
11017
|
-
function setNestedValue(obj,
|
|
11018
|
-
const keys =
|
|
12023
|
+
function setNestedValue(obj, path25, value) {
|
|
12024
|
+
const keys = path25.split(".");
|
|
11019
12025
|
const lastKey = keys.pop();
|
|
11020
12026
|
let current = obj;
|
|
11021
12027
|
for (const key of keys) {
|
|
@@ -11256,14 +12262,14 @@ var workflowDeleteCommand = new Command("delete").description("Delete a workflow
|
|
|
11256
12262
|
init_cjs_shims();
|
|
11257
12263
|
var readline2 = __toESM(require("readline/promises"));
|
|
11258
12264
|
var import_node_process8 = require("process");
|
|
11259
|
-
var
|
|
12265
|
+
var path12 = __toESM(require("path"));
|
|
11260
12266
|
|
|
11261
12267
|
// src/utils/prompt.ts
|
|
11262
12268
|
init_cjs_shims();
|
|
11263
12269
|
var readline = __toESM(require("readline/promises"));
|
|
11264
12270
|
var import_node_process7 = require("process");
|
|
11265
|
-
var
|
|
11266
|
-
var
|
|
12271
|
+
var fs17 = __toESM(require("fs"));
|
|
12272
|
+
var path11 = __toESM(require("path"));
|
|
11267
12273
|
function isInteractive() {
|
|
11268
12274
|
return process.stdin?.isTTY ?? false;
|
|
11269
12275
|
}
|
|
@@ -11287,12 +12293,12 @@ async function promptForFilePath(variableName, resourceTypes, isRequired) {
|
|
|
11287
12293
|
const homeDir = process.env.HOME || process.env.USERPROFILE || "";
|
|
11288
12294
|
resolvedPath = resolvedPath.replace("~", homeDir);
|
|
11289
12295
|
}
|
|
11290
|
-
resolvedPath =
|
|
11291
|
-
if (!
|
|
12296
|
+
resolvedPath = path11.resolve(resolvedPath);
|
|
12297
|
+
if (!fs17.existsSync(resolvedPath)) {
|
|
11292
12298
|
console.log(` File not found: ${resolvedPath}`);
|
|
11293
12299
|
continue;
|
|
11294
12300
|
}
|
|
11295
|
-
const stats =
|
|
12301
|
+
const stats = fs17.statSync(resolvedPath);
|
|
11296
12302
|
if (!stats.isFile()) {
|
|
11297
12303
|
console.log(` Not a file: ${resolvedPath}`);
|
|
11298
12304
|
continue;
|
|
@@ -11490,12 +12496,12 @@ async function pollToolsStatus(workflowId, maxWaitTime = 15 * 60 * 1e3, pollInte
|
|
|
11490
12496
|
);
|
|
11491
12497
|
previousRemainingCount = remainingCount;
|
|
11492
12498
|
}
|
|
11493
|
-
await new Promise((
|
|
12499
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
11494
12500
|
} catch (error) {
|
|
11495
12501
|
console.log(`
|
|
11496
12502
|
\u26A0\uFE0F Failed to check authorization status: ${error.message}`);
|
|
11497
12503
|
console.log("Continuing to wait...");
|
|
11498
|
-
await new Promise((
|
|
12504
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
11499
12505
|
}
|
|
11500
12506
|
}
|
|
11501
12507
|
console.log("\n\u23F0 Timeout waiting for tool authorization.");
|
|
@@ -11606,7 +12612,7 @@ ${details}`;
|
|
|
11606
12612
|
if (!filePath) {
|
|
11607
12613
|
continue;
|
|
11608
12614
|
}
|
|
11609
|
-
const filename =
|
|
12615
|
+
const filename = path12.basename(filePath);
|
|
11610
12616
|
process.stdout.write(` Uploading ${filename}...`);
|
|
11611
12617
|
try {
|
|
11612
12618
|
const uploadResult = await apiUploadDriveFile(filePath, workflowId);
|
|
@@ -11988,7 +12994,7 @@ var workflowStatusCommand = new Command("status").description("Get detailed work
|
|
|
11988
12994
|
});
|
|
11989
12995
|
prevStatus = status;
|
|
11990
12996
|
while (status.status === "init" || status.status === "executing") {
|
|
11991
|
-
await new Promise((
|
|
12997
|
+
await new Promise((resolve8) => setTimeout(resolve8, pollInterval));
|
|
11992
12998
|
status = await fetchStatus();
|
|
11993
12999
|
if (options.full || hasStatusChanged(prevStatus, status)) {
|
|
11994
13000
|
if (options.full) {
|
|
@@ -12116,7 +13122,75 @@ var workflowDetailCommand = new Command("detail").description("Get detailed work
|
|
|
12116
13122
|
|
|
12117
13123
|
// src/commands/workflow/toolcalls.ts
|
|
12118
13124
|
init_cjs_shims();
|
|
12119
|
-
|
|
13125
|
+
function extractNodeOutputs(toolCalls) {
|
|
13126
|
+
const outputs = [];
|
|
13127
|
+
for (const call of toolCalls) {
|
|
13128
|
+
if (!call.output || call.status !== "completed") continue;
|
|
13129
|
+
const output3 = call.output;
|
|
13130
|
+
const filesMap = /* @__PURE__ */ new Map();
|
|
13131
|
+
let content;
|
|
13132
|
+
if (Array.isArray(output3.files)) {
|
|
13133
|
+
for (const f of output3.files) {
|
|
13134
|
+
const file = f;
|
|
13135
|
+
if (file.fileId && !filesMap.has(String(file.fileId))) {
|
|
13136
|
+
filesMap.set(String(file.fileId), {
|
|
13137
|
+
fileId: String(file.fileId),
|
|
13138
|
+
name: String(file.name || ""),
|
|
13139
|
+
type: String(file.type || ""),
|
|
13140
|
+
category: file.category,
|
|
13141
|
+
size: file.size,
|
|
13142
|
+
url: file.url,
|
|
13143
|
+
source: file.source,
|
|
13144
|
+
createdAt: file.createdAt
|
|
13145
|
+
});
|
|
13146
|
+
}
|
|
13147
|
+
}
|
|
13148
|
+
}
|
|
13149
|
+
if (output3.data && typeof output3.data === "object") {
|
|
13150
|
+
const data = output3.data;
|
|
13151
|
+
if (data.fileId && !filesMap.has(String(data.fileId))) {
|
|
13152
|
+
filesMap.set(String(data.fileId), {
|
|
13153
|
+
fileId: String(data.fileId),
|
|
13154
|
+
name: String(data.name || ""),
|
|
13155
|
+
type: String(data.type || ""),
|
|
13156
|
+
category: data.category,
|
|
13157
|
+
size: data.size,
|
|
13158
|
+
url: data.url,
|
|
13159
|
+
source: data.source,
|
|
13160
|
+
createdAt: data.createdAt
|
|
13161
|
+
});
|
|
13162
|
+
}
|
|
13163
|
+
}
|
|
13164
|
+
if (output3.content) {
|
|
13165
|
+
content = String(output3.content).slice(0, 500);
|
|
13166
|
+
} else if (output3.data && typeof output3.data === "object") {
|
|
13167
|
+
const data = output3.data;
|
|
13168
|
+
if (data.candidates && Array.isArray(data.candidates)) {
|
|
13169
|
+
const parts = data.candidates[0]?.content;
|
|
13170
|
+
if (parts?.parts && Array.isArray(parts.parts)) {
|
|
13171
|
+
const textPart = parts.parts.find(
|
|
13172
|
+
(p) => typeof p.text === "string" && !p.thought
|
|
13173
|
+
);
|
|
13174
|
+
if (textPart) {
|
|
13175
|
+
content = String(textPart.text).slice(0, 500);
|
|
13176
|
+
}
|
|
13177
|
+
}
|
|
13178
|
+
}
|
|
13179
|
+
}
|
|
13180
|
+
const files = Array.from(filesMap.values());
|
|
13181
|
+
if (files.length > 0 || content) {
|
|
13182
|
+
outputs.push({
|
|
13183
|
+
nodeId: call.nodeId || "",
|
|
13184
|
+
nodeTitle: call.nodeTitle || call.toolName,
|
|
13185
|
+
toolName: call.toolName,
|
|
13186
|
+
content,
|
|
13187
|
+
files
|
|
13188
|
+
});
|
|
13189
|
+
}
|
|
13190
|
+
}
|
|
13191
|
+
return outputs;
|
|
13192
|
+
}
|
|
13193
|
+
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
13194
|
try {
|
|
12121
13195
|
const params = new URLSearchParams();
|
|
12122
13196
|
if (options.nodeId) {
|
|
@@ -12137,12 +13211,26 @@ var workflowToolcallsCommand = new Command("toolcalls").description("Get all too
|
|
|
12137
13211
|
if (options.offset) {
|
|
12138
13212
|
params.set("offset", options.offset);
|
|
12139
13213
|
}
|
|
12140
|
-
if (options.raw) {
|
|
13214
|
+
if (options.raw || options.files) {
|
|
12141
13215
|
params.set("sanitizeForDisplay", "false");
|
|
12142
13216
|
}
|
|
12143
13217
|
const idType = detectIdType2(id);
|
|
12144
13218
|
const url = buildWorkflowApiUrl(id, "toolcalls", params);
|
|
12145
13219
|
const result = await apiRequest(url);
|
|
13220
|
+
if (options.files) {
|
|
13221
|
+
let nodeOutputs = extractNodeOutputs(result.toolCalls);
|
|
13222
|
+
if (options.latest && nodeOutputs.length > 0) {
|
|
13223
|
+
const lastWithFiles = nodeOutputs.filter((n) => n.files.length > 0).pop();
|
|
13224
|
+
nodeOutputs = lastWithFiles ? [lastWithFiles] : [];
|
|
13225
|
+
}
|
|
13226
|
+
const allFiles = nodeOutputs.flatMap((n) => n.files);
|
|
13227
|
+
ok("workflow.files", {
|
|
13228
|
+
runId: result.runId,
|
|
13229
|
+
workflowId: result.workflowId,
|
|
13230
|
+
files: allFiles,
|
|
13231
|
+
nodes: nodeOutputs
|
|
13232
|
+
});
|
|
13233
|
+
}
|
|
12146
13234
|
ok("workflow.toolcalls", {
|
|
12147
13235
|
runId: result.runId,
|
|
12148
13236
|
workflowId: result.workflowId,
|
|
@@ -13305,16 +14393,16 @@ var fileGetCommand = new Command("get").description("Get file details").argument
|
|
|
13305
14393
|
|
|
13306
14394
|
// src/commands/file/download.ts
|
|
13307
14395
|
init_cjs_shims();
|
|
13308
|
-
var
|
|
13309
|
-
var
|
|
14396
|
+
var fs18 = __toESM(require("fs"));
|
|
14397
|
+
var path13 = __toESM(require("path"));
|
|
13310
14398
|
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
14399
|
try {
|
|
13312
14400
|
const { data, filename, contentType, size } = await apiRequestStream(
|
|
13313
14401
|
`/v1/cli/drive/files/${fileId}/download`
|
|
13314
14402
|
);
|
|
13315
14403
|
const outputPath = options.output || filename || `${fileId}`;
|
|
13316
|
-
const resolvedPath =
|
|
13317
|
-
|
|
14404
|
+
const resolvedPath = path13.resolve(outputPath);
|
|
14405
|
+
fs18.writeFileSync(resolvedPath, data);
|
|
13318
14406
|
ok("file.download", {
|
|
13319
14407
|
fileId,
|
|
13320
14408
|
path: resolvedPath,
|
|
@@ -13339,8 +14427,8 @@ var fileDownloadCommand = new Command("download").description("Download file to
|
|
|
13339
14427
|
|
|
13340
14428
|
// src/commands/file/upload.ts
|
|
13341
14429
|
init_cjs_shims();
|
|
13342
|
-
var
|
|
13343
|
-
var
|
|
14430
|
+
var fs19 = __toESM(require("fs"));
|
|
14431
|
+
var path14 = __toESM(require("path"));
|
|
13344
14432
|
var MAX_FILES = 10;
|
|
13345
14433
|
function formatSize(bytes) {
|
|
13346
14434
|
if (bytes < 1024) return `${bytes}B`;
|
|
@@ -13350,8 +14438,8 @@ function formatSize(bytes) {
|
|
|
13350
14438
|
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
14439
|
const formatter = getFormatter();
|
|
13352
14440
|
try {
|
|
13353
|
-
const resolvedPath =
|
|
13354
|
-
if (!
|
|
14441
|
+
const resolvedPath = path14.resolve(inputPath);
|
|
14442
|
+
if (!fs19.existsSync(resolvedPath)) {
|
|
13355
14443
|
fail(ErrorCodes.NOT_FOUND, `Path not found: ${inputPath}`, {
|
|
13356
14444
|
hint: "Check if the file or directory exists"
|
|
13357
14445
|
});
|
|
@@ -13369,8 +14457,8 @@ var fileUploadCommand = new Command("upload").description("Upload file(s) to a c
|
|
|
13369
14457
|
const errors = [];
|
|
13370
14458
|
for (let i = 0; i < files.length; i++) {
|
|
13371
14459
|
const filePath = files[i];
|
|
13372
|
-
const filename =
|
|
13373
|
-
const fileStats =
|
|
14460
|
+
const filename = path14.basename(filePath);
|
|
14461
|
+
const fileStats = fs19.statSync(filePath);
|
|
13374
14462
|
const sizeStr = formatSize(fileStats.size);
|
|
13375
14463
|
let currentStage = "presign";
|
|
13376
14464
|
const updateProgress = () => {
|
|
@@ -13451,11 +14539,11 @@ var fileUploadCommand = new Command("upload").description("Upload file(s) to a c
|
|
|
13451
14539
|
}
|
|
13452
14540
|
});
|
|
13453
14541
|
function resolveFilesToUpload(inputPath, filter) {
|
|
13454
|
-
const stats =
|
|
14542
|
+
const stats = fs19.statSync(inputPath);
|
|
13455
14543
|
if (stats.isFile()) {
|
|
13456
14544
|
if (filter) {
|
|
13457
14545
|
const filterExts = filter.split(",").map((e) => e.trim().toLowerCase());
|
|
13458
|
-
const ext =
|
|
14546
|
+
const ext = path14.extname(inputPath).slice(1).toLowerCase();
|
|
13459
14547
|
if (!filterExts.includes(ext)) {
|
|
13460
14548
|
return [];
|
|
13461
14549
|
}
|
|
@@ -13463,21 +14551,21 @@ function resolveFilesToUpload(inputPath, filter) {
|
|
|
13463
14551
|
return [inputPath];
|
|
13464
14552
|
}
|
|
13465
14553
|
if (stats.isDirectory()) {
|
|
13466
|
-
const entries =
|
|
14554
|
+
const entries = fs19.readdirSync(inputPath);
|
|
13467
14555
|
const filterExts = filter?.split(",").map((e) => e.trim().toLowerCase());
|
|
13468
|
-
const files = entries.map((e) =>
|
|
14556
|
+
const files = entries.map((e) => path14.join(inputPath, e)).filter((p) => {
|
|
13469
14557
|
try {
|
|
13470
|
-
return
|
|
14558
|
+
return fs19.statSync(p).isFile();
|
|
13471
14559
|
} catch {
|
|
13472
14560
|
return false;
|
|
13473
14561
|
}
|
|
13474
14562
|
}).filter((p) => {
|
|
13475
14563
|
if (!filterExts) return true;
|
|
13476
|
-
const ext =
|
|
14564
|
+
const ext = path14.extname(p).slice(1).toLowerCase();
|
|
13477
14565
|
return filterExts.includes(ext);
|
|
13478
14566
|
}).sort((a, b) => {
|
|
13479
14567
|
try {
|
|
13480
|
-
return
|
|
14568
|
+
return fs19.statSync(a).size - fs19.statSync(b).size;
|
|
13481
14569
|
} catch {
|
|
13482
14570
|
return 0;
|
|
13483
14571
|
}
|
|
@@ -13581,7 +14669,7 @@ var skillGetCommand = new Command("get").description("Get skill package details"
|
|
|
13581
14669
|
|
|
13582
14670
|
// src/commands/skill/create.ts
|
|
13583
14671
|
init_cjs_shims();
|
|
13584
|
-
var
|
|
14672
|
+
var fs20 = __toESM(require("fs"));
|
|
13585
14673
|
init_symlink();
|
|
13586
14674
|
init_paths();
|
|
13587
14675
|
init_logger();
|
|
@@ -13633,7 +14721,7 @@ var skillCreateCommand = new Command("create").description("Create a new skill p
|
|
|
13633
14721
|
const localName = options.name.toLowerCase().replace(/[^a-z0-9]+/g, "-").replace(/^-|-$/g, "");
|
|
13634
14722
|
const skillDir = getReflyDomainSkillDir(localName);
|
|
13635
14723
|
const symlinkStatus = isSkillSymlinkValid(localName);
|
|
13636
|
-
if (
|
|
14724
|
+
if (fs20.existsSync(skillDir) || symlinkStatus.exists) {
|
|
13637
14725
|
logger.debug(`Local skill '${localName}' already exists, skipping sync`);
|
|
13638
14726
|
} else {
|
|
13639
14727
|
const skillMdContent = generateReflySkillMd({
|
|
@@ -13695,8 +14783,8 @@ var skillCreateCommand = new Command("create").description("Create a new skill p
|
|
|
13695
14783
|
|
|
13696
14784
|
// src/commands/skill/update.ts
|
|
13697
14785
|
init_cjs_shims();
|
|
13698
|
-
var
|
|
13699
|
-
var
|
|
14786
|
+
var fs21 = __toESM(require("fs"));
|
|
14787
|
+
var path15 = __toESM(require("path"));
|
|
13700
14788
|
init_paths();
|
|
13701
14789
|
init_symlink();
|
|
13702
14790
|
var MIN_DESCRIPTION_WORDS = 20;
|
|
@@ -13726,8 +14814,8 @@ var skillUpdateCommand = new Command("update").description("Update skill install
|
|
|
13726
14814
|
try {
|
|
13727
14815
|
const name = options.name;
|
|
13728
14816
|
const skillDir = getReflyDomainSkillDir(name);
|
|
13729
|
-
const skillMdPath =
|
|
13730
|
-
if (!
|
|
14817
|
+
const skillMdPath = path15.join(skillDir, "SKILL.md");
|
|
14818
|
+
if (!fs21.existsSync(skillMdPath)) {
|
|
13731
14819
|
const skillsDir = getReflySkillsDir();
|
|
13732
14820
|
fail(ErrorCodes.NOT_FOUND, `SKILL.md not found at ${skillMdPath}`, {
|
|
13733
14821
|
hint: `Make sure the skill '${name}' exists in ${skillsDir}/
|
|
@@ -13736,7 +14824,7 @@ To see installed skills: refly skill list`
|
|
|
13736
14824
|
});
|
|
13737
14825
|
return;
|
|
13738
14826
|
}
|
|
13739
|
-
const skillContent =
|
|
14827
|
+
const skillContent = fs21.readFileSync(skillMdPath, "utf-8");
|
|
13740
14828
|
let meta;
|
|
13741
14829
|
try {
|
|
13742
14830
|
const parsed = parseReflySkillMd(skillContent);
|
|
@@ -13819,8 +14907,8 @@ To see installed skills: refly skill list`
|
|
|
13819
14907
|
|
|
13820
14908
|
// src/commands/skill/publish.ts
|
|
13821
14909
|
init_cjs_shims();
|
|
13822
|
-
var
|
|
13823
|
-
var
|
|
14910
|
+
var fs22 = __toESM(require("fs"));
|
|
14911
|
+
var path16 = __toESM(require("path"));
|
|
13824
14912
|
init_symlink();
|
|
13825
14913
|
init_paths();
|
|
13826
14914
|
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 +14916,8 @@ var skillPublishCommand = new Command("publish").description("Publish a skill pa
|
|
|
13828
14916
|
const skillsDir = getReflySkillsDir();
|
|
13829
14917
|
const name = options.name;
|
|
13830
14918
|
const skillDir = getReflyDomainSkillDir(name);
|
|
13831
|
-
const skillMdPath =
|
|
13832
|
-
if (!
|
|
14919
|
+
const skillMdPath = path16.join(skillDir, "SKILL.md");
|
|
14920
|
+
if (!fs22.existsSync(skillMdPath)) {
|
|
13833
14921
|
fail(ErrorCodes.NOT_FOUND, `SKILL.md not found at ${skillMdPath}`, {
|
|
13834
14922
|
hint: `Make sure the skill '${name}' exists in ${skillsDir}/
|
|
13835
14923
|
|
|
@@ -13838,7 +14926,7 @@ To create a new skill: refly skill create --name "${name}" --workflow-query "...
|
|
|
13838
14926
|
});
|
|
13839
14927
|
return;
|
|
13840
14928
|
}
|
|
13841
|
-
const skillContent =
|
|
14929
|
+
const skillContent = fs22.readFileSync(skillMdPath, "utf-8");
|
|
13842
14930
|
let parsedSkill;
|
|
13843
14931
|
try {
|
|
13844
14932
|
parsedSkill = parseReflySkillMd(skillContent);
|
|
@@ -13900,8 +14988,8 @@ To find available skills: refly skill list`
|
|
|
13900
14988
|
|
|
13901
14989
|
// src/commands/skill/unpublish.ts
|
|
13902
14990
|
init_cjs_shims();
|
|
13903
|
-
var
|
|
13904
|
-
var
|
|
14991
|
+
var fs23 = __toESM(require("fs"));
|
|
14992
|
+
var path17 = __toESM(require("path"));
|
|
13905
14993
|
init_symlink();
|
|
13906
14994
|
init_paths();
|
|
13907
14995
|
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 +15024,8 @@ To find your skill name:
|
|
|
13936
15024
|
return;
|
|
13937
15025
|
}
|
|
13938
15026
|
const skillDir = getReflyDomainSkillDir(name);
|
|
13939
|
-
const skillMdPath =
|
|
13940
|
-
if (!
|
|
15027
|
+
const skillMdPath = path17.join(skillDir, "SKILL.md");
|
|
15028
|
+
if (!fs23.existsSync(skillMdPath)) {
|
|
13941
15029
|
fail(ErrorCodes.NOT_FOUND, `SKILL.md not found at ${skillMdPath}`, {
|
|
13942
15030
|
hint: `Make sure the skill '${name}' exists in ${skillsDir}/
|
|
13943
15031
|
|
|
@@ -13945,7 +15033,7 @@ To see installed skills: refly skill list`
|
|
|
13945
15033
|
});
|
|
13946
15034
|
return;
|
|
13947
15035
|
}
|
|
13948
|
-
const skillContent =
|
|
15036
|
+
const skillContent = fs23.readFileSync(skillMdPath, "utf-8");
|
|
13949
15037
|
try {
|
|
13950
15038
|
const { meta } = parseReflySkillMd(skillContent);
|
|
13951
15039
|
skillId = options.id || meta.skillId;
|
|
@@ -13989,8 +15077,8 @@ To see installed skills: refly skill list`
|
|
|
13989
15077
|
|
|
13990
15078
|
// src/commands/skill/run.ts
|
|
13991
15079
|
init_cjs_shims();
|
|
13992
|
-
var
|
|
13993
|
-
var
|
|
15080
|
+
var fs24 = __toESM(require("fs"));
|
|
15081
|
+
var path18 = __toESM(require("path"));
|
|
13994
15082
|
init_symlink();
|
|
13995
15083
|
init_paths();
|
|
13996
15084
|
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 +15103,8 @@ To find your skill name:
|
|
|
14015
15103
|
if (options.name) {
|
|
14016
15104
|
name = options.name;
|
|
14017
15105
|
const skillDir = getReflyDomainSkillDir(options.name);
|
|
14018
|
-
const skillMdPath =
|
|
14019
|
-
if (!
|
|
15106
|
+
const skillMdPath = path18.join(skillDir, "SKILL.md");
|
|
15107
|
+
if (!fs24.existsSync(skillMdPath)) {
|
|
14020
15108
|
fail(ErrorCodes.NOT_FOUND, `SKILL.md not found at ${skillMdPath}`, {
|
|
14021
15109
|
hint: `Make sure the skill '${name}' exists in ${skillsDir}/
|
|
14022
15110
|
|
|
@@ -14025,7 +15113,7 @@ To install a skill: refly skill install <skillId>`
|
|
|
14025
15113
|
});
|
|
14026
15114
|
return;
|
|
14027
15115
|
}
|
|
14028
|
-
const skillContent =
|
|
15116
|
+
const skillContent = fs24.readFileSync(skillMdPath, "utf-8");
|
|
14029
15117
|
try {
|
|
14030
15118
|
const { meta } = parseReflySkillMd(skillContent);
|
|
14031
15119
|
skillId = meta.skillId;
|
|
@@ -14143,24 +15231,24 @@ To install: refly skill install ${meta.skillId}`
|
|
|
14143
15231
|
|
|
14144
15232
|
// src/commands/skill/stop.ts
|
|
14145
15233
|
init_cjs_shims();
|
|
14146
|
-
var
|
|
14147
|
-
var
|
|
15234
|
+
var fs25 = __toESM(require("fs"));
|
|
15235
|
+
var path19 = __toESM(require("path"));
|
|
14148
15236
|
init_symlink();
|
|
14149
15237
|
init_paths();
|
|
14150
15238
|
function getLocalSkillNames() {
|
|
14151
15239
|
const skillsDir = getReflySkillsDir();
|
|
14152
|
-
if (!
|
|
15240
|
+
if (!fs25.existsSync(skillsDir)) {
|
|
14153
15241
|
return [];
|
|
14154
15242
|
}
|
|
14155
|
-
return
|
|
15243
|
+
return fs25.readdirSync(skillsDir, { withFileTypes: true }).filter((dirent) => dirent.isDirectory()).map((dirent) => dirent.name);
|
|
14156
15244
|
}
|
|
14157
15245
|
var skillStopCommand = new Command("stop").description("Stop running skill executions").requiredOption("--name <name>", "Local skill name (directory in ~/.refly/skills/)").action(async (options) => {
|
|
14158
15246
|
try {
|
|
14159
15247
|
const skillsDir = getReflySkillsDir();
|
|
14160
15248
|
const name = options.name;
|
|
14161
15249
|
const skillDir = getReflyDomainSkillDir(name);
|
|
14162
|
-
const skillMdPath =
|
|
14163
|
-
if (!
|
|
15250
|
+
const skillMdPath = path19.join(skillDir, "SKILL.md");
|
|
15251
|
+
if (!fs25.existsSync(skillMdPath)) {
|
|
14164
15252
|
const availableSkills = getLocalSkillNames();
|
|
14165
15253
|
const skillList = availableSkills.length > 0 ? availableSkills.join(", ") : "(no skills installed)";
|
|
14166
15254
|
fail(ErrorCodes.NOT_FOUND, `Skill "${name}" not found`, {
|
|
@@ -14169,7 +15257,7 @@ var skillStopCommand = new Command("stop").description("Stop running skill execu
|
|
|
14169
15257
|
Skills directory: ${skillsDir}`
|
|
14170
15258
|
});
|
|
14171
15259
|
}
|
|
14172
|
-
const skillContent =
|
|
15260
|
+
const skillContent = fs25.readFileSync(skillMdPath, "utf-8");
|
|
14173
15261
|
let installationId;
|
|
14174
15262
|
try {
|
|
14175
15263
|
const { meta } = parseReflySkillMd(skillContent);
|
|
@@ -14297,7 +15385,7 @@ var skillInstallCommand = new Command("install").description("Install a skill pa
|
|
|
14297
15385
|
}
|
|
14298
15386
|
);
|
|
14299
15387
|
let localPath;
|
|
14300
|
-
|
|
15388
|
+
const platformResults = [];
|
|
14301
15389
|
const skillName = result.skillPackage?.name;
|
|
14302
15390
|
const workflowId = result.skillPackage?.workflowId;
|
|
14303
15391
|
if (skillName && workflowId) {
|
|
@@ -14315,15 +15403,23 @@ var skillInstallCommand = new Command("install").description("Install a skill pa
|
|
|
14315
15403
|
inputSchema: result.skillPackage?.inputSchema,
|
|
14316
15404
|
outputSchema: result.skillPackage?.outputSchema
|
|
14317
15405
|
});
|
|
14318
|
-
const
|
|
15406
|
+
const deployResult = await createMultiPlatformSkill(skillName, skillMdContent, {
|
|
14319
15407
|
force: options.force
|
|
14320
15408
|
});
|
|
14321
|
-
|
|
14322
|
-
|
|
14323
|
-
|
|
14324
|
-
|
|
15409
|
+
localPath = deployResult.sourcePath;
|
|
15410
|
+
for (const [agentName, agentResult] of deployResult.results) {
|
|
15411
|
+
platformResults.push({
|
|
15412
|
+
agent: agentName,
|
|
15413
|
+
success: agentResult.success,
|
|
15414
|
+
path: agentResult.deployedPath || void 0
|
|
15415
|
+
});
|
|
15416
|
+
}
|
|
15417
|
+
if (deployResult.successCount > 0) {
|
|
15418
|
+
logger.info(
|
|
15419
|
+
`Created local skill: ${localPath}, deployed to ${deployResult.successCount} platform(s)`
|
|
15420
|
+
);
|
|
14325
15421
|
} else {
|
|
14326
|
-
logger.warn(
|
|
15422
|
+
logger.warn("Failed to deploy skill to any platform");
|
|
14327
15423
|
}
|
|
14328
15424
|
} catch (err) {
|
|
14329
15425
|
logger.warn(`Failed to create local skill: ${err.message}`);
|
|
@@ -14338,7 +15434,7 @@ var skillInstallCommand = new Command("install").description("Install a skill pa
|
|
|
14338
15434
|
config: result.userConfig,
|
|
14339
15435
|
installedAt: result.createdAt,
|
|
14340
15436
|
localPath,
|
|
14341
|
-
|
|
15437
|
+
platforms: platformResults.length > 0 ? platformResults : void 0
|
|
14342
15438
|
});
|
|
14343
15439
|
} catch (error) {
|
|
14344
15440
|
if (error instanceof CLIError) {
|
|
@@ -14358,8 +15454,8 @@ var skillInstallCommand = new Command("install").description("Install a skill pa
|
|
|
14358
15454
|
|
|
14359
15455
|
// src/commands/skill/uninstall.ts
|
|
14360
15456
|
init_cjs_shims();
|
|
14361
|
-
var
|
|
14362
|
-
var
|
|
15457
|
+
var fs26 = __toESM(require("fs"));
|
|
15458
|
+
var path20 = __toESM(require("path"));
|
|
14363
15459
|
init_symlink();
|
|
14364
15460
|
init_paths();
|
|
14365
15461
|
init_logger();
|
|
@@ -14396,8 +15492,8 @@ To find your skill name:
|
|
|
14396
15492
|
return;
|
|
14397
15493
|
}
|
|
14398
15494
|
const skillDir = getReflyDomainSkillDir(name);
|
|
14399
|
-
const skillMdPath =
|
|
14400
|
-
if (!
|
|
15495
|
+
const skillMdPath = path20.join(skillDir, "SKILL.md");
|
|
15496
|
+
if (!fs26.existsSync(skillMdPath)) {
|
|
14401
15497
|
fail(ErrorCodes.NOT_FOUND, `SKILL.md not found at ${skillMdPath}`, {
|
|
14402
15498
|
hint: `Make sure the skill '${name}' exists in ${skillsDir}/
|
|
14403
15499
|
|
|
@@ -14405,7 +15501,7 @@ To see installed skills: refly skill list`
|
|
|
14405
15501
|
});
|
|
14406
15502
|
return;
|
|
14407
15503
|
}
|
|
14408
|
-
const skillContent =
|
|
15504
|
+
const skillContent = fs26.readFileSync(skillMdPath, "utf-8");
|
|
14409
15505
|
try {
|
|
14410
15506
|
const { meta } = parseReflySkillMd(skillContent);
|
|
14411
15507
|
skillId = meta.skillId;
|
|
@@ -14436,14 +15532,21 @@ To see installed skills: refly skill list`
|
|
|
14436
15532
|
}
|
|
14437
15533
|
}
|
|
14438
15534
|
}
|
|
14439
|
-
let symlinkRemoved = false;
|
|
14440
15535
|
let directoryRemoved = false;
|
|
15536
|
+
const platformResults = [];
|
|
14441
15537
|
if (name && !options.keepLocal) {
|
|
14442
15538
|
try {
|
|
14443
|
-
const cleanup =
|
|
14444
|
-
symlinkRemoved = cleanup.symlinkRemoved;
|
|
15539
|
+
const cleanup = await removeMultiPlatformSkill(name);
|
|
14445
15540
|
directoryRemoved = cleanup.directoryRemoved;
|
|
14446
|
-
|
|
15541
|
+
for (const [agentName, result] of cleanup.platformResults.results) {
|
|
15542
|
+
platformResults.push({
|
|
15543
|
+
agent: agentName,
|
|
15544
|
+
success: result.success
|
|
15545
|
+
});
|
|
15546
|
+
}
|
|
15547
|
+
logger.info(
|
|
15548
|
+
`Cleaned up local skill: ${name}, removed from ${cleanup.platformResults.successCount} platform(s)`
|
|
15549
|
+
);
|
|
14447
15550
|
} catch (err) {
|
|
14448
15551
|
logger.warn(`Failed to clean up local skill: ${err.message}`);
|
|
14449
15552
|
}
|
|
@@ -14454,8 +15557,8 @@ To see installed skills: refly skill list`
|
|
|
14454
15557
|
installationId,
|
|
14455
15558
|
uninstalled: true,
|
|
14456
15559
|
localCleanup: {
|
|
14457
|
-
|
|
14458
|
-
|
|
15560
|
+
directoryRemoved,
|
|
15561
|
+
platforms: platformResults.length > 0 ? platformResults : void 0
|
|
14459
15562
|
}
|
|
14460
15563
|
});
|
|
14461
15564
|
} catch (error) {
|
|
@@ -14521,8 +15624,8 @@ init_cjs_shims();
|
|
|
14521
15624
|
|
|
14522
15625
|
// src/skill/loader.ts
|
|
14523
15626
|
init_cjs_shims();
|
|
14524
|
-
var
|
|
14525
|
-
var
|
|
15627
|
+
var fs27 = __toESM(require("fs"));
|
|
15628
|
+
var path21 = __toESM(require("path"));
|
|
14526
15629
|
var import_gray_matter = __toESM(require("gray-matter"));
|
|
14527
15630
|
init_logger();
|
|
14528
15631
|
|
|
@@ -14702,23 +15805,23 @@ function extractSkillMetadata(content) {
|
|
|
14702
15805
|
|
|
14703
15806
|
// src/commands/skill/validate.ts
|
|
14704
15807
|
init_paths();
|
|
14705
|
-
var
|
|
14706
|
-
var
|
|
15808
|
+
var fs28 = __toESM(require("fs"));
|
|
15809
|
+
var path22 = __toESM(require("path"));
|
|
14707
15810
|
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
15811
|
try {
|
|
14709
15812
|
const results = [];
|
|
14710
15813
|
let targetPath;
|
|
14711
15814
|
if (skillPath) {
|
|
14712
|
-
targetPath =
|
|
15815
|
+
targetPath = path22.resolve(skillPath);
|
|
14713
15816
|
} else {
|
|
14714
15817
|
await ensureSkillsDir();
|
|
14715
15818
|
targetPath = getSkillsDir();
|
|
14716
15819
|
}
|
|
14717
|
-
if (!
|
|
15820
|
+
if (!fs28.existsSync(targetPath)) {
|
|
14718
15821
|
fail(ErrorCodes.NOT_FOUND, `Path not found: ${targetPath}`);
|
|
14719
15822
|
return;
|
|
14720
15823
|
}
|
|
14721
|
-
const stats =
|
|
15824
|
+
const stats = fs28.statSync(targetPath);
|
|
14722
15825
|
if (stats.isFile()) {
|
|
14723
15826
|
const result = validateSkillFile(targetPath);
|
|
14724
15827
|
results.push(result);
|
|
@@ -14751,7 +15854,7 @@ var skillValidateCommand = new Command("validate").description("Validate local s
|
|
|
14751
15854
|
});
|
|
14752
15855
|
function validateSkillFile(filePath) {
|
|
14753
15856
|
try {
|
|
14754
|
-
const content =
|
|
15857
|
+
const content = fs28.readFileSync(filePath, "utf-8");
|
|
14755
15858
|
const { frontmatter, issues } = extractSkillMetadata(content);
|
|
14756
15859
|
const errors = issues.map((i) => `${i.path}: ${i.message}`);
|
|
14757
15860
|
const warnings = [];
|
|
@@ -14777,9 +15880,9 @@ function validateSkillFile(filePath) {
|
|
|
14777
15880
|
}
|
|
14778
15881
|
}
|
|
14779
15882
|
function findSkillFiles(dir, files = []) {
|
|
14780
|
-
const entries =
|
|
15883
|
+
const entries = fs28.readdirSync(dir, { withFileTypes: true });
|
|
14781
15884
|
for (const entry of entries) {
|
|
14782
|
-
const fullPath =
|
|
15885
|
+
const fullPath = path22.join(dir, entry.name);
|
|
14783
15886
|
if (entry.isDirectory()) {
|
|
14784
15887
|
if (!entry.name.startsWith(".")) {
|
|
14785
15888
|
findSkillFiles(fullPath, files);
|
|
@@ -14793,12 +15896,73 @@ function findSkillFiles(dir, files = []) {
|
|
|
14793
15896
|
|
|
14794
15897
|
// src/commands/skill/sync.ts
|
|
14795
15898
|
init_cjs_shims();
|
|
15899
|
+
var fs29 = __toESM(require("fs"));
|
|
15900
|
+
var path23 = __toESM(require("path"));
|
|
14796
15901
|
init_symlink();
|
|
15902
|
+
init_manager();
|
|
15903
|
+
init_registry();
|
|
14797
15904
|
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) => {
|
|
15905
|
+
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
15906
|
try {
|
|
15907
|
+
let targetAgents;
|
|
15908
|
+
if (options.platform) {
|
|
15909
|
+
const platformList = options.platform.flatMap((p) => p.split(","));
|
|
15910
|
+
targetAgents = [];
|
|
15911
|
+
for (const platform4 of platformList) {
|
|
15912
|
+
const trimmed = platform4.trim();
|
|
15913
|
+
if (!isValidAgentType(trimmed)) {
|
|
15914
|
+
return fail(ErrorCodes.INVALID_INPUT, `Unknown platform: ${trimmed}`, {
|
|
15915
|
+
hint: `Valid platforms: ${Object.keys(agents).join(", ")}`
|
|
15916
|
+
});
|
|
15917
|
+
}
|
|
15918
|
+
targetAgents.push(trimmed);
|
|
15919
|
+
}
|
|
15920
|
+
}
|
|
15921
|
+
if (options.allPlatforms) {
|
|
15922
|
+
const installedAgents = await detectInstalledAgents();
|
|
15923
|
+
const deployableAgents = installedAgents.filter((a) => a.format !== "unknown");
|
|
15924
|
+
const skillsDir2 = getReflySkillsDir();
|
|
15925
|
+
const baseSkillDir = getReflyBaseSkillDir();
|
|
15926
|
+
const skillsToSync = [];
|
|
15927
|
+
if (fs29.existsSync(baseSkillDir)) {
|
|
15928
|
+
skillsToSync.push("refly");
|
|
15929
|
+
}
|
|
15930
|
+
if (fs29.existsSync(skillsDir2)) {
|
|
15931
|
+
const entries = fs29.readdirSync(skillsDir2, { withFileTypes: true });
|
|
15932
|
+
for (const entry of entries) {
|
|
15933
|
+
if (entry.isDirectory() && entry.name !== "base") {
|
|
15934
|
+
skillsToSync.push(entry.name);
|
|
15935
|
+
}
|
|
15936
|
+
}
|
|
15937
|
+
}
|
|
15938
|
+
const platformResults = [];
|
|
15939
|
+
for (const skillName of skillsToSync) {
|
|
15940
|
+
const { needsSync, synced } = await syncSkillToAllPlatforms(skillName, {
|
|
15941
|
+
agents: targetAgents,
|
|
15942
|
+
dryRun: options.dryRun
|
|
15943
|
+
});
|
|
15944
|
+
platformResults.push({
|
|
15945
|
+
skillName,
|
|
15946
|
+
needsSync: Array.from(needsSync.entries()).map(([agent, status]) => ({
|
|
15947
|
+
agent,
|
|
15948
|
+
deployed: status.deployed,
|
|
15949
|
+
valid: status.valid
|
|
15950
|
+
})),
|
|
15951
|
+
synced: Array.from(synced.entries()).map(([agent, result]) => ({
|
|
15952
|
+
agent,
|
|
15953
|
+
success: result.success,
|
|
15954
|
+
path: result.deployedPath || void 0
|
|
15955
|
+
}))
|
|
15956
|
+
});
|
|
15957
|
+
}
|
|
15958
|
+
return ok("skill.sync", {
|
|
15959
|
+
dryRun: Boolean(options.dryRun),
|
|
15960
|
+
allPlatforms: true,
|
|
15961
|
+
installedAgents: deployableAgents.map((a) => a.name),
|
|
15962
|
+
skillsCount: skillsToSync.length,
|
|
15963
|
+
results: platformResults
|
|
15964
|
+
});
|
|
15965
|
+
}
|
|
14802
15966
|
const symlinks = listSkillSymlinks();
|
|
14803
15967
|
const warnings = [];
|
|
14804
15968
|
const errors = [];
|
|
@@ -14823,14 +15987,14 @@ var skillSyncCommand = new Command("sync").description("Validate and repair skil
|
|
|
14823
15987
|
}
|
|
14824
15988
|
}
|
|
14825
15989
|
const skillsDir = getReflySkillsDir();
|
|
14826
|
-
if (
|
|
14827
|
-
const entries =
|
|
15990
|
+
if (fs29.existsSync(skillsDir)) {
|
|
15991
|
+
const entries = fs29.readdirSync(skillsDir, { withFileTypes: true });
|
|
14828
15992
|
const symlinkNames = new Set(symlinks.map((s) => s.name));
|
|
14829
15993
|
for (const entry of entries) {
|
|
14830
15994
|
if (entry.isDirectory() && entry.name !== "base") {
|
|
14831
15995
|
if (!symlinkNames.has(entry.name)) {
|
|
14832
15996
|
orphans += 1;
|
|
14833
|
-
warnings.push(`Orphan directory (no symlink): ${
|
|
15997
|
+
warnings.push(`Orphan directory (no symlink): ${path23.join(skillsDir, entry.name)}`);
|
|
14834
15998
|
if (options.prune && !options.dryRun) {
|
|
14835
15999
|
const result = createSkillSymlink(entry.name);
|
|
14836
16000
|
if (result.success) {
|
|
@@ -14877,11 +16041,178 @@ var skillSyncCommand = new Command("sync").description("Validate and repair skil
|
|
|
14877
16041
|
// src/commands/skill/index.ts
|
|
14878
16042
|
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
16043
|
|
|
16044
|
+
// src/commands/platform/index.ts
|
|
16045
|
+
init_cjs_shims();
|
|
16046
|
+
|
|
16047
|
+
// src/commands/platform/sync.ts
|
|
16048
|
+
init_cjs_shims();
|
|
16049
|
+
var fs30 = __toESM(require("fs"));
|
|
16050
|
+
init_manager();
|
|
16051
|
+
init_registry();
|
|
16052
|
+
init_paths();
|
|
16053
|
+
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) => {
|
|
16054
|
+
try {
|
|
16055
|
+
const pretty = isPrettyOutput();
|
|
16056
|
+
const tty = isTTY();
|
|
16057
|
+
let targetAgents;
|
|
16058
|
+
if (options.agent) {
|
|
16059
|
+
const agentList = options.agent.flatMap((a) => a.split(","));
|
|
16060
|
+
const validatedAgents = [];
|
|
16061
|
+
for (const agent of agentList) {
|
|
16062
|
+
const trimmed = agent.trim();
|
|
16063
|
+
if (!isValidAgentType(trimmed)) {
|
|
16064
|
+
return fail(ErrorCodes.INVALID_INPUT, `Unknown agent: ${trimmed}`, {
|
|
16065
|
+
hint: `Valid agents: ${Object.keys(agents).join(", ")}`
|
|
16066
|
+
});
|
|
16067
|
+
}
|
|
16068
|
+
validatedAgents.push(trimmed);
|
|
16069
|
+
}
|
|
16070
|
+
targetAgents = validatedAgents;
|
|
16071
|
+
}
|
|
16072
|
+
if (pretty && tty) {
|
|
16073
|
+
println("Scanning for installed agents...");
|
|
16074
|
+
println("");
|
|
16075
|
+
}
|
|
16076
|
+
const installedAgents = targetAgents ? targetAgents.map((name) => agents[name]) : await detectInstalledAgents();
|
|
16077
|
+
const deployableAgents = installedAgents.filter((a) => a.format !== "unknown");
|
|
16078
|
+
if (deployableAgents.length === 0) {
|
|
16079
|
+
if (pretty && tty) {
|
|
16080
|
+
printError2("No supported agents found");
|
|
16081
|
+
printDim("Install an AI coding assistant and try again.");
|
|
16082
|
+
} else {
|
|
16083
|
+
ok("platform.sync", {
|
|
16084
|
+
message: "No supported agents found",
|
|
16085
|
+
installedAgents: [],
|
|
16086
|
+
skillsSynced: 0
|
|
16087
|
+
});
|
|
16088
|
+
}
|
|
16089
|
+
return;
|
|
16090
|
+
}
|
|
16091
|
+
if (pretty && tty) {
|
|
16092
|
+
println(`Found ${deployableAgents.length} installed agent(s):`);
|
|
16093
|
+
for (const agent of deployableAgents) {
|
|
16094
|
+
const dir = agent.globalSkillsDir || agent.skillsDir || "N/A";
|
|
16095
|
+
println(` \u2713 ${agent.displayName.padEnd(16)} ${dir}`);
|
|
16096
|
+
}
|
|
16097
|
+
println("");
|
|
16098
|
+
}
|
|
16099
|
+
const skillsDir = getReflySkillsDir();
|
|
16100
|
+
const baseSkillDir = getReflyBaseSkillDir();
|
|
16101
|
+
const skillsToSync = [];
|
|
16102
|
+
if (fs30.existsSync(baseSkillDir)) {
|
|
16103
|
+
skillsToSync.push("refly");
|
|
16104
|
+
}
|
|
16105
|
+
if (fs30.existsSync(skillsDir)) {
|
|
16106
|
+
const entries = fs30.readdirSync(skillsDir, { withFileTypes: true });
|
|
16107
|
+
for (const entry of entries) {
|
|
16108
|
+
if (entry.isDirectory() && entry.name !== "base") {
|
|
16109
|
+
skillsToSync.push(entry.name);
|
|
16110
|
+
}
|
|
16111
|
+
}
|
|
16112
|
+
}
|
|
16113
|
+
if (skillsToSync.length === 0) {
|
|
16114
|
+
if (pretty && tty) {
|
|
16115
|
+
printDim("No skills found to sync.");
|
|
16116
|
+
printDim("Run `refly init` to install the base skill.");
|
|
16117
|
+
} else {
|
|
16118
|
+
ok("platform.sync", {
|
|
16119
|
+
message: "No skills found to sync",
|
|
16120
|
+
installedAgents: deployableAgents.map((a) => a.name),
|
|
16121
|
+
skillsSynced: 0
|
|
16122
|
+
});
|
|
16123
|
+
}
|
|
16124
|
+
return;
|
|
16125
|
+
}
|
|
16126
|
+
if (pretty && tty) {
|
|
16127
|
+
println(`Syncing ${skillsToSync.length} skill(s) to all installed agents...`);
|
|
16128
|
+
}
|
|
16129
|
+
if (options.dryRun) {
|
|
16130
|
+
if (pretty && tty) {
|
|
16131
|
+
println("");
|
|
16132
|
+
println("Dry run - no changes made:");
|
|
16133
|
+
for (const skillName of skillsToSync) {
|
|
16134
|
+
const agentNames = deployableAgents.map((a) => a.displayName).join(", ");
|
|
16135
|
+
println(` ${skillName} -> ${agentNames}`);
|
|
16136
|
+
}
|
|
16137
|
+
} else {
|
|
16138
|
+
ok("platform.sync", {
|
|
16139
|
+
dryRun: true,
|
|
16140
|
+
installedAgents: deployableAgents.map((a) => a.name),
|
|
16141
|
+
skillsToSync
|
|
16142
|
+
});
|
|
16143
|
+
}
|
|
16144
|
+
return;
|
|
16145
|
+
}
|
|
16146
|
+
const results = [];
|
|
16147
|
+
for (const skillName of skillsToSync) {
|
|
16148
|
+
const deployResult = await deploySkillToAllPlatforms(skillName, {
|
|
16149
|
+
force: true,
|
|
16150
|
+
// Force to ensure repair
|
|
16151
|
+
agents: targetAgents
|
|
16152
|
+
});
|
|
16153
|
+
const details = [];
|
|
16154
|
+
for (const [agentName, result] of deployResult.results) {
|
|
16155
|
+
details.push({
|
|
16156
|
+
agent: agentName,
|
|
16157
|
+
success: result.success,
|
|
16158
|
+
path: result.deployedPath || void 0,
|
|
16159
|
+
error: result.error
|
|
16160
|
+
});
|
|
16161
|
+
}
|
|
16162
|
+
results.push({
|
|
16163
|
+
skillName,
|
|
16164
|
+
success: deployResult.successCount,
|
|
16165
|
+
failed: deployResult.failureCount,
|
|
16166
|
+
details
|
|
16167
|
+
});
|
|
16168
|
+
if (pretty && tty) {
|
|
16169
|
+
const statusParts = deployableAgents.map((agent) => {
|
|
16170
|
+
const result = deployResult.results.get(agent.name);
|
|
16171
|
+
return result?.success ? "\u2713" : "\u2717";
|
|
16172
|
+
});
|
|
16173
|
+
println(` ${skillName.padEnd(20)} ${statusParts.join(" ")}`);
|
|
16174
|
+
}
|
|
16175
|
+
}
|
|
16176
|
+
const totalSuccess = results.reduce((sum, r) => sum + r.success, 0);
|
|
16177
|
+
const totalFailed = results.reduce((sum, r) => sum + r.failed, 0);
|
|
16178
|
+
if (pretty && tty) {
|
|
16179
|
+
println("");
|
|
16180
|
+
printSuccess(
|
|
16181
|
+
`Done! ${deployableAgents.length} agent(s), ${skillsToSync.length} skill(s) synced.`
|
|
16182
|
+
);
|
|
16183
|
+
if (totalFailed > 0) {
|
|
16184
|
+
printError2(`${totalFailed} deployment(s) failed. Check logs for details.`);
|
|
16185
|
+
}
|
|
16186
|
+
} else {
|
|
16187
|
+
ok("platform.sync", {
|
|
16188
|
+
installedAgents: deployableAgents.map((a) => ({
|
|
16189
|
+
name: a.name,
|
|
16190
|
+
displayName: a.displayName,
|
|
16191
|
+
format: a.format,
|
|
16192
|
+
globalSkillsDir: a.globalSkillsDir
|
|
16193
|
+
})),
|
|
16194
|
+
skillsSynced: skillsToSync.length,
|
|
16195
|
+
totalSuccess,
|
|
16196
|
+
totalFailed,
|
|
16197
|
+
results
|
|
16198
|
+
});
|
|
16199
|
+
}
|
|
16200
|
+
} catch (error) {
|
|
16201
|
+
fail(
|
|
16202
|
+
ErrorCodes.INTERNAL_ERROR,
|
|
16203
|
+
error instanceof Error ? error.message : "Failed to sync platforms"
|
|
16204
|
+
);
|
|
16205
|
+
}
|
|
16206
|
+
});
|
|
16207
|
+
|
|
16208
|
+
// src/commands/platform/index.ts
|
|
16209
|
+
var platformCommand = new Command("platform").description("Manage multi-platform skill deployment").addCommand(platformSyncCommand);
|
|
16210
|
+
|
|
14880
16211
|
// src/bin/refly.ts
|
|
14881
16212
|
function getVersion() {
|
|
14882
16213
|
try {
|
|
14883
|
-
const pkgPath =
|
|
14884
|
-
const pkg = JSON.parse(
|
|
16214
|
+
const pkgPath = path24.join(__dirname, "..", "..", "package.json");
|
|
16215
|
+
const pkg = JSON.parse(fs31.readFileSync(pkgPath, "utf-8"));
|
|
14885
16216
|
return pkg.version || "0.1.0";
|
|
14886
16217
|
} catch {
|
|
14887
16218
|
return "0.1.0";
|
|
@@ -14922,6 +16253,7 @@ program2.addCommand(workflowCommand);
|
|
|
14922
16253
|
program2.addCommand(toolCommand);
|
|
14923
16254
|
program2.addCommand(fileCommand);
|
|
14924
16255
|
program2.addCommand(skillCommand);
|
|
16256
|
+
program2.addCommand(platformCommand);
|
|
14925
16257
|
program2.exitOverride((err) => {
|
|
14926
16258
|
if (err.code === "commander.helpDisplayed" || err.code === "commander.version") {
|
|
14927
16259
|
process.exit(0);
|