apero-kit-cli 2.4.7 → 2.5.0
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/index.js +1284 -895
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/discord/README.md +54 -7
- package/templates/discord/start-bot.sh +47 -0
package/dist/index.js
CHANGED
|
@@ -163,6 +163,17 @@ var init_kits = __esm({
|
|
|
163
163
|
});
|
|
164
164
|
|
|
165
165
|
// src/utils/paths.ts
|
|
166
|
+
var paths_exports = {};
|
|
167
|
+
__export(paths_exports, {
|
|
168
|
+
CLI_ROOT: () => CLI_ROOT,
|
|
169
|
+
TARGETS: () => TARGETS,
|
|
170
|
+
TEMPLATES_DIR: () => TEMPLATES_DIR,
|
|
171
|
+
getEmbeddedTemplates: () => getEmbeddedTemplates,
|
|
172
|
+
getGlobalInstallPath: () => getGlobalInstallPath,
|
|
173
|
+
getTargetDir: () => getTargetDir,
|
|
174
|
+
isAkProject: () => isAkProject,
|
|
175
|
+
resolveSource: () => resolveSource
|
|
176
|
+
});
|
|
166
177
|
import { fileURLToPath } from "url";
|
|
167
178
|
import { dirname, join, resolve } from "path";
|
|
168
179
|
import { existsSync } from "fs";
|
|
@@ -257,643 +268,618 @@ var init_paths = __esm({
|
|
|
257
268
|
}
|
|
258
269
|
});
|
|
259
270
|
|
|
260
|
-
// src/
|
|
271
|
+
// src/targets/base-adapter.ts
|
|
261
272
|
import fs from "fs-extra";
|
|
262
273
|
import { join as join2, dirname as dirname2 } from "path";
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
}
|
|
293
|
-
async
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
srcPath = itemPathMd;
|
|
312
|
-
} else {
|
|
313
|
-
skipped.push(item);
|
|
314
|
-
continue;
|
|
315
|
-
}
|
|
316
|
-
const stat = fs.statSync(srcPath);
|
|
317
|
-
if (stat.isDirectory()) {
|
|
318
|
-
await fs.copy(srcPath, join2(destTypeDir, item), { overwrite: !mergeMode });
|
|
319
|
-
} else {
|
|
320
|
-
const destPath = srcPath.endsWith(".md") ? join2(destTypeDir, item + ".md") : join2(destTypeDir, item);
|
|
321
|
-
await fs.ensureDir(join2(destTypeDir, item.split("/").slice(0, -1).join("/")));
|
|
322
|
-
await fs.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
274
|
+
var BaseTargetAdapter;
|
|
275
|
+
var init_base_adapter = __esm({
|
|
276
|
+
"src/targets/base-adapter.ts"() {
|
|
277
|
+
"use strict";
|
|
278
|
+
BaseTargetAdapter = class {
|
|
279
|
+
supports(feature) {
|
|
280
|
+
return this.config.features[feature];
|
|
281
|
+
}
|
|
282
|
+
getSupportedFeatures() {
|
|
283
|
+
return Object.entries(this.config.features).filter(([_, supported]) => supported).map(([feature]) => feature);
|
|
284
|
+
}
|
|
285
|
+
filterInstallItems(items) {
|
|
286
|
+
return {
|
|
287
|
+
agents: this.supports("agents") ? items.agents : [],
|
|
288
|
+
skills: this.supports("skills") ? items.skills : [],
|
|
289
|
+
commands: this.supports("commands") ? items.commands : [],
|
|
290
|
+
workflows: this.supports("workflows") ? items.workflows : [],
|
|
291
|
+
includeRouter: this.supports("router") && items.includeRouter,
|
|
292
|
+
includeHooks: this.supports("hooks") && items.includeHooks
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Default: not supported - override in subclass if needed
|
|
297
|
+
*/
|
|
298
|
+
async copyWorkflows(_items, _sourceDir, _targetDir, _mergeMode) {
|
|
299
|
+
return { copied: [], skipped: [], errors: [] };
|
|
300
|
+
}
|
|
301
|
+
async copyRouter(_sourceDir, _targetDir, _mergeMode) {
|
|
302
|
+
return { success: false, error: "Router not supported by this target" };
|
|
303
|
+
}
|
|
304
|
+
async copyHooks(_sourceDir, _targetDir, _mergeMode) {
|
|
305
|
+
return { success: false, error: "Hooks not supported by this target" };
|
|
306
|
+
}
|
|
307
|
+
async copyExtras(_sourceDir, _targetDir, _mergeMode) {
|
|
308
|
+
return [];
|
|
309
|
+
}
|
|
310
|
+
// Helper methods for common operations
|
|
311
|
+
async copyDirectory(dirName, sourceDir, destDir, mergeMode) {
|
|
312
|
+
const srcPath = join2(sourceDir, dirName);
|
|
313
|
+
if (!fs.existsSync(srcPath)) {
|
|
314
|
+
return { success: false, error: `${dirName} directory not found` };
|
|
315
|
+
}
|
|
316
|
+
try {
|
|
317
|
+
await fs.copy(srcPath, join2(destDir, dirName), { overwrite: !mergeMode });
|
|
318
|
+
return { success: true };
|
|
319
|
+
} catch (err) {
|
|
320
|
+
return { success: false, error: err.message };
|
|
321
|
+
}
|
|
323
322
|
}
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
return { copied, skipped, errors };
|
|
330
|
-
}
|
|
331
|
-
async function copyAllOfType(type, sourceDir, destDir, mergeMode = false) {
|
|
332
|
-
const typeDir = join2(sourceDir, type);
|
|
333
|
-
const destTypeDir = join2(destDir, type);
|
|
334
|
-
if (!fs.existsSync(typeDir)) {
|
|
335
|
-
return { success: false, error: `${type} directory not found` };
|
|
336
|
-
}
|
|
337
|
-
try {
|
|
338
|
-
await fs.copy(typeDir, destTypeDir, { overwrite: !mergeMode });
|
|
339
|
-
return { success: true };
|
|
340
|
-
} catch (err) {
|
|
341
|
-
return { success: false, error: err.message };
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
async function copyRouter(sourceDir, destDir, mergeMode = false) {
|
|
345
|
-
const routerDir = join2(sourceDir, "router");
|
|
346
|
-
if (!fs.existsSync(routerDir)) {
|
|
347
|
-
return { success: false, error: "Router directory not found" };
|
|
348
|
-
}
|
|
349
|
-
try {
|
|
350
|
-
await fs.copy(routerDir, join2(destDir, "router"), { overwrite: !mergeMode });
|
|
351
|
-
return { success: true };
|
|
352
|
-
} catch (err) {
|
|
353
|
-
return { success: false, error: err.message };
|
|
354
|
-
}
|
|
355
|
-
}
|
|
356
|
-
async function copyHooks(sourceDir, destDir, mergeMode = false) {
|
|
357
|
-
const hooksDir = join2(sourceDir, "hooks");
|
|
358
|
-
if (!fs.existsSync(hooksDir)) {
|
|
359
|
-
return { success: false, error: "Hooks directory not found" };
|
|
360
|
-
}
|
|
361
|
-
try {
|
|
362
|
-
await fs.copy(hooksDir, join2(destDir, "hooks"), { overwrite: !mergeMode });
|
|
363
|
-
return { success: true };
|
|
364
|
-
} catch (err) {
|
|
365
|
-
return { success: false, error: err.message };
|
|
366
|
-
}
|
|
367
|
-
}
|
|
368
|
-
async function copyBaseFiles(sourceDir, destDir, mergeMode = false) {
|
|
369
|
-
const baseFiles = ["README.md", "settings.json", ".env.example", "statusline.cjs", "statusline.ps1", "statusline.sh"];
|
|
370
|
-
const copied = [];
|
|
371
|
-
for (const file of baseFiles) {
|
|
372
|
-
const srcPath = join2(sourceDir, file);
|
|
373
|
-
const destPath = join2(destDir, file);
|
|
374
|
-
if (mergeMode && fs.existsSync(destPath)) {
|
|
375
|
-
continue;
|
|
376
|
-
}
|
|
377
|
-
if (fs.existsSync(srcPath)) {
|
|
378
|
-
await fs.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
379
|
-
copied.push(file);
|
|
380
|
-
}
|
|
381
|
-
}
|
|
382
|
-
return copied;
|
|
383
|
-
}
|
|
384
|
-
async function copyDirectory(dirName, sourceDir, destDir, mergeMode = false) {
|
|
385
|
-
const srcPath = join2(sourceDir, dirName);
|
|
386
|
-
if (!fs.existsSync(srcPath)) {
|
|
387
|
-
return { success: false, error: `${dirName} directory not found` };
|
|
388
|
-
}
|
|
389
|
-
try {
|
|
390
|
-
await fs.copy(srcPath, join2(destDir, dirName), { overwrite: !mergeMode });
|
|
391
|
-
return { success: true };
|
|
392
|
-
} catch (err) {
|
|
393
|
-
return { success: false, error: err.message };
|
|
394
|
-
}
|
|
395
|
-
}
|
|
396
|
-
async function copyAgentsMd(agentsMdPath, projectDir, mergeMode = false) {
|
|
397
|
-
if (!agentsMdPath || !fs.existsSync(agentsMdPath)) {
|
|
398
|
-
return false;
|
|
399
|
-
}
|
|
400
|
-
const destPath = join2(projectDir, "AGENTS.md");
|
|
401
|
-
if (mergeMode && fs.existsSync(destPath)) {
|
|
402
|
-
return false;
|
|
403
|
-
}
|
|
404
|
-
await fs.copy(agentsMdPath, destPath, { overwrite: !mergeMode });
|
|
405
|
-
return true;
|
|
406
|
-
}
|
|
407
|
-
function listAvailable(type, sourceDir) {
|
|
408
|
-
const typeDir = join2(sourceDir, type);
|
|
409
|
-
if (!fs.existsSync(typeDir)) {
|
|
410
|
-
return [];
|
|
411
|
-
}
|
|
412
|
-
const items = fs.readdirSync(typeDir);
|
|
413
|
-
return items.map((item) => {
|
|
414
|
-
const itemPath = join2(typeDir, item);
|
|
415
|
-
const isDir = fs.statSync(itemPath).isDirectory();
|
|
416
|
-
const name = item.replace(/\.md$/, "");
|
|
417
|
-
return { name, isDir, path: itemPath };
|
|
418
|
-
});
|
|
419
|
-
}
|
|
420
|
-
async function copyCommandsForGemini(items, sourceDir, destDir, mergeMode = false) {
|
|
421
|
-
const typeDir = join2(sourceDir, "commands");
|
|
422
|
-
const destTypeDir = join2(destDir, "commands");
|
|
423
|
-
if (!fs.existsSync(typeDir)) {
|
|
424
|
-
return { copied: [], skipped: [], errors: [] };
|
|
425
|
-
}
|
|
426
|
-
await fs.ensureDir(destTypeDir);
|
|
427
|
-
const copied = [];
|
|
428
|
-
const skipped = [];
|
|
429
|
-
const errors = [];
|
|
430
|
-
let itemList;
|
|
431
|
-
if (items === "all") {
|
|
432
|
-
const entries = fs.readdirSync(typeDir);
|
|
433
|
-
itemList = entries.map((e) => e.replace(/\.md$/, ""));
|
|
434
|
-
itemList = [...new Set(itemList)];
|
|
435
|
-
} else {
|
|
436
|
-
itemList = items;
|
|
437
|
-
}
|
|
438
|
-
for (const item of itemList) {
|
|
439
|
-
try {
|
|
440
|
-
const srcPathMd = join2(typeDir, item + ".md");
|
|
441
|
-
const srcPathDir = join2(typeDir, item);
|
|
442
|
-
let copiedSomething = false;
|
|
443
|
-
if (fs.existsSync(srcPathMd) && fs.statSync(srcPathMd).isFile()) {
|
|
444
|
-
const destPath = join2(destTypeDir, item + ".toml");
|
|
445
|
-
if (!(mergeMode && fs.existsSync(destPath))) {
|
|
323
|
+
async copyFile(srcPath, destPath, mergeMode) {
|
|
324
|
+
if (mergeMode && fs.existsSync(destPath)) {
|
|
325
|
+
return false;
|
|
326
|
+
}
|
|
327
|
+
if (fs.existsSync(srcPath)) {
|
|
446
328
|
await fs.ensureDir(dirname2(destPath));
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
await fs.writeFile(destPath, tomlContent, "utf-8");
|
|
450
|
-
copiedSomething = true;
|
|
329
|
+
await fs.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
330
|
+
return true;
|
|
451
331
|
}
|
|
332
|
+
return false;
|
|
452
333
|
}
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
334
|
+
async listItems(typeDir, extension) {
|
|
335
|
+
if (!fs.existsSync(typeDir)) {
|
|
336
|
+
return [];
|
|
337
|
+
}
|
|
338
|
+
const entries = fs.readdirSync(typeDir);
|
|
339
|
+
return entries.filter((e) => {
|
|
340
|
+
if (extension) {
|
|
341
|
+
return e.endsWith(extension) && e !== "README.md";
|
|
342
|
+
}
|
|
343
|
+
return e !== "README.md";
|
|
344
|
+
}).map((e) => extension ? e.replace(extension, "") : e);
|
|
456
345
|
}
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
346
|
+
getItemList(items, typeDir, extension) {
|
|
347
|
+
if (items === "all") {
|
|
348
|
+
return this.listItemsSync(typeDir, extension);
|
|
349
|
+
}
|
|
350
|
+
return items;
|
|
461
351
|
}
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
352
|
+
listItemsSync(typeDir, extension) {
|
|
353
|
+
if (!fs.existsSync(typeDir)) {
|
|
354
|
+
return [];
|
|
355
|
+
}
|
|
356
|
+
const entries = fs.readdirSync(typeDir);
|
|
357
|
+
let result = entries.filter((e) => e !== "README.md");
|
|
358
|
+
if (extension) {
|
|
359
|
+
result = result.filter((e) => e.endsWith(extension)).map((e) => e.replace(extension, ""));
|
|
360
|
+
}
|
|
361
|
+
return [...new Set(result.map((e) => e.replace(/\.md$/, "")))];
|
|
362
|
+
}
|
|
363
|
+
};
|
|
465
364
|
}
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
// src/targets/claude-adapter.ts
|
|
368
|
+
import fs2 from "fs-extra";
|
|
369
|
+
import { join as join3 } from "path";
|
|
370
|
+
var ClaudeAdapter;
|
|
371
|
+
var init_claude_adapter = __esm({
|
|
372
|
+
"src/targets/claude-adapter.ts"() {
|
|
373
|
+
"use strict";
|
|
374
|
+
init_base_adapter();
|
|
375
|
+
ClaudeAdapter = class extends BaseTargetAdapter {
|
|
376
|
+
config = {
|
|
377
|
+
name: "claude",
|
|
378
|
+
displayName: "Claude Code",
|
|
379
|
+
directory: ".claude",
|
|
380
|
+
features: {
|
|
381
|
+
agents: true,
|
|
382
|
+
skills: true,
|
|
383
|
+
commands: true,
|
|
384
|
+
workflows: true,
|
|
385
|
+
router: true,
|
|
386
|
+
hooks: true,
|
|
387
|
+
memory: true,
|
|
388
|
+
scripts: true,
|
|
389
|
+
"output-styles": true
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
async copyAgents(items, sourceDir, targetDir, mergeMode) {
|
|
393
|
+
const typeDir = join3(sourceDir, "agents");
|
|
394
|
+
const destTypeDir = join3(targetDir, "agents");
|
|
395
|
+
if (!fs2.existsSync(typeDir)) {
|
|
396
|
+
return { copied: [], skipped: [], errors: [] };
|
|
397
|
+
}
|
|
398
|
+
await fs2.ensureDir(destTypeDir);
|
|
399
|
+
if (items === "all") {
|
|
400
|
+
await fs2.copy(typeDir, destTypeDir, { overwrite: !mergeMode });
|
|
401
|
+
const entries = fs2.readdirSync(typeDir).filter((e) => e.endsWith(".md") && e !== "README.md");
|
|
402
|
+
return { copied: entries.map((e) => e.replace(".md", "")), skipped: [], errors: [] };
|
|
403
|
+
}
|
|
404
|
+
const copied = [];
|
|
405
|
+
const skipped = [];
|
|
406
|
+
const errors = [];
|
|
407
|
+
for (const agent of items) {
|
|
408
|
+
try {
|
|
409
|
+
const srcPath = join3(typeDir, agent + ".md");
|
|
410
|
+
if (!fs2.existsSync(srcPath)) {
|
|
411
|
+
skipped.push(agent);
|
|
412
|
+
continue;
|
|
413
|
+
}
|
|
414
|
+
const destPath = join3(destTypeDir, agent + ".md");
|
|
415
|
+
if (mergeMode && fs2.existsSync(destPath)) {
|
|
416
|
+
skipped.push(agent);
|
|
417
|
+
continue;
|
|
418
|
+
}
|
|
419
|
+
await fs2.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
420
|
+
copied.push(agent);
|
|
421
|
+
} catch (err) {
|
|
422
|
+
errors.push({ item: agent, error: err.message });
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return { copied, skipped, errors };
|
|
480
426
|
}
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
427
|
+
async copySkills(items, sourceDir, targetDir, mergeMode) {
|
|
428
|
+
const typeDir = join3(sourceDir, "skills");
|
|
429
|
+
const destTypeDir = join3(targetDir, "skills");
|
|
430
|
+
if (!fs2.existsSync(typeDir)) {
|
|
431
|
+
return { copied: [], skipped: [], errors: [] };
|
|
432
|
+
}
|
|
433
|
+
await fs2.ensureDir(destTypeDir);
|
|
434
|
+
if (items === "all") {
|
|
435
|
+
await fs2.copy(typeDir, destTypeDir, { overwrite: !mergeMode });
|
|
436
|
+
const entries = fs2.readdirSync(typeDir).filter((e) => {
|
|
437
|
+
const fullPath = join3(typeDir, e);
|
|
438
|
+
return fs2.statSync(fullPath).isDirectory() && fs2.existsSync(join3(fullPath, "SKILL.md"));
|
|
439
|
+
});
|
|
440
|
+
return { copied: entries, skipped: [], errors: [] };
|
|
441
|
+
}
|
|
442
|
+
const copied = [];
|
|
443
|
+
const skipped = [];
|
|
444
|
+
const errors = [];
|
|
445
|
+
for (const skill of items) {
|
|
446
|
+
try {
|
|
447
|
+
const srcPath = join3(typeDir, skill);
|
|
448
|
+
if (!fs2.existsSync(srcPath) || !fs2.statSync(srcPath).isDirectory()) {
|
|
449
|
+
skipped.push(skill);
|
|
450
|
+
continue;
|
|
451
|
+
}
|
|
452
|
+
if (!fs2.existsSync(join3(srcPath, "SKILL.md"))) {
|
|
453
|
+
skipped.push(skill);
|
|
454
|
+
continue;
|
|
455
|
+
}
|
|
456
|
+
const destPath = join3(destTypeDir, skill);
|
|
457
|
+
if (mergeMode && fs2.existsSync(destPath)) {
|
|
458
|
+
skipped.push(skill);
|
|
459
|
+
continue;
|
|
460
|
+
}
|
|
461
|
+
await fs2.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
462
|
+
copied.push(skill);
|
|
463
|
+
} catch (err) {
|
|
464
|
+
errors.push({ item: skill, error: err.message });
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
return { copied, skipped, errors };
|
|
488
468
|
}
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
const errors = [];
|
|
532
|
-
let agentList;
|
|
533
|
-
if (items === "all") {
|
|
534
|
-
const entries = fs.readdirSync(typeDir);
|
|
535
|
-
agentList = entries.filter((e) => e.endsWith(".md") && e !== "README.md").map((e) => e.replace(/\.md$/, ""));
|
|
536
|
-
} else {
|
|
537
|
-
agentList = items;
|
|
538
|
-
}
|
|
539
|
-
for (const agent of agentList) {
|
|
540
|
-
try {
|
|
541
|
-
const srcPath = join2(typeDir, agent + ".md");
|
|
542
|
-
if (!fs.existsSync(srcPath)) {
|
|
543
|
-
skipped.push(agent);
|
|
544
|
-
continue;
|
|
469
|
+
async copyCommands(items, sourceDir, targetDir, mergeMode) {
|
|
470
|
+
const typeDir = join3(sourceDir, "commands");
|
|
471
|
+
const destTypeDir = join3(targetDir, "commands");
|
|
472
|
+
if (!fs2.existsSync(typeDir)) {
|
|
473
|
+
return { copied: [], skipped: [], errors: [] };
|
|
474
|
+
}
|
|
475
|
+
await fs2.ensureDir(destTypeDir);
|
|
476
|
+
if (items === "all") {
|
|
477
|
+
await fs2.copy(typeDir, destTypeDir, { overwrite: !mergeMode });
|
|
478
|
+
const entries = fs2.readdirSync(typeDir);
|
|
479
|
+
return { copied: [...new Set(entries.map((e) => e.replace(".md", "")))], skipped: [], errors: [] };
|
|
480
|
+
}
|
|
481
|
+
const copied = [];
|
|
482
|
+
const skipped = [];
|
|
483
|
+
const errors = [];
|
|
484
|
+
for (const item of items) {
|
|
485
|
+
try {
|
|
486
|
+
const itemPath = join3(typeDir, item);
|
|
487
|
+
const itemPathMd = itemPath + ".md";
|
|
488
|
+
let srcPath = null;
|
|
489
|
+
if (fs2.existsSync(itemPath)) {
|
|
490
|
+
srcPath = itemPath;
|
|
491
|
+
} else if (fs2.existsSync(itemPathMd)) {
|
|
492
|
+
srcPath = itemPathMd;
|
|
493
|
+
}
|
|
494
|
+
if (!srcPath) {
|
|
495
|
+
skipped.push(item);
|
|
496
|
+
continue;
|
|
497
|
+
}
|
|
498
|
+
const stat = fs2.statSync(srcPath);
|
|
499
|
+
const destPath = stat.isDirectory() ? join3(destTypeDir, item) : join3(destTypeDir, item + ".md");
|
|
500
|
+
if (mergeMode && fs2.existsSync(destPath)) {
|
|
501
|
+
skipped.push(item);
|
|
502
|
+
continue;
|
|
503
|
+
}
|
|
504
|
+
await fs2.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
505
|
+
copied.push(item);
|
|
506
|
+
} catch (err) {
|
|
507
|
+
errors.push({ item, error: err.message });
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
return { copied, skipped, errors };
|
|
545
511
|
}
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
512
|
+
async copyWorkflows(items, sourceDir, targetDir, mergeMode) {
|
|
513
|
+
const typeDir = join3(sourceDir, "workflows");
|
|
514
|
+
const destTypeDir = join3(targetDir, "workflows");
|
|
515
|
+
if (!fs2.existsSync(typeDir)) {
|
|
516
|
+
return { copied: [], skipped: [], errors: [] };
|
|
517
|
+
}
|
|
518
|
+
await fs2.ensureDir(destTypeDir);
|
|
519
|
+
if (items === "all") {
|
|
520
|
+
await fs2.copy(typeDir, destTypeDir, { overwrite: !mergeMode });
|
|
521
|
+
const entries = fs2.readdirSync(typeDir);
|
|
522
|
+
return { copied: entries.map((e) => e.replace(".md", "")), skipped: [], errors: [] };
|
|
523
|
+
}
|
|
524
|
+
const copied = [];
|
|
525
|
+
const skipped = [];
|
|
526
|
+
const errors = [];
|
|
527
|
+
for (const item of items) {
|
|
528
|
+
try {
|
|
529
|
+
const srcPath = join3(typeDir, item + ".md");
|
|
530
|
+
if (!fs2.existsSync(srcPath)) {
|
|
531
|
+
skipped.push(item);
|
|
532
|
+
continue;
|
|
533
|
+
}
|
|
534
|
+
const destPath = join3(destTypeDir, item + ".md");
|
|
535
|
+
if (mergeMode && fs2.existsSync(destPath)) {
|
|
536
|
+
skipped.push(item);
|
|
537
|
+
continue;
|
|
538
|
+
}
|
|
539
|
+
await fs2.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
540
|
+
copied.push(item);
|
|
541
|
+
} catch (err) {
|
|
542
|
+
errors.push({ item, error: err.message });
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
return { copied, skipped, errors };
|
|
550
546
|
}
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
await fs.writeFile(destPath, convertedContent, "utf-8");
|
|
554
|
-
copied.push(agent);
|
|
555
|
-
} catch (err) {
|
|
556
|
-
errors.push({ item: agent, error: err.message });
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
return { copied, skipped, errors };
|
|
560
|
-
}
|
|
561
|
-
async function copySkillsForGemini(items, sourceDir, destDir, mergeMode = false) {
|
|
562
|
-
const typeDir = join2(sourceDir, "skills");
|
|
563
|
-
const destTypeDir = join2(destDir, "skills");
|
|
564
|
-
if (!fs.existsSync(typeDir)) {
|
|
565
|
-
return { copied: [], skipped: [], errors: [] };
|
|
566
|
-
}
|
|
567
|
-
await fs.ensureDir(destTypeDir);
|
|
568
|
-
const copied = [];
|
|
569
|
-
const skipped = [];
|
|
570
|
-
const errors = [];
|
|
571
|
-
let skillList;
|
|
572
|
-
if (items === "all") {
|
|
573
|
-
const entries = fs.readdirSync(typeDir);
|
|
574
|
-
skillList = entries.filter((e) => {
|
|
575
|
-
const fullPath = join2(typeDir, e);
|
|
576
|
-
return fs.statSync(fullPath).isDirectory() && fs.existsSync(join2(fullPath, "SKILL.md"));
|
|
577
|
-
});
|
|
578
|
-
} else {
|
|
579
|
-
skillList = items;
|
|
580
|
-
}
|
|
581
|
-
for (const skill of skillList) {
|
|
582
|
-
try {
|
|
583
|
-
const srcPath = join2(typeDir, skill);
|
|
584
|
-
if (!fs.existsSync(srcPath) || !fs.statSync(srcPath).isDirectory()) {
|
|
585
|
-
skipped.push(skill);
|
|
586
|
-
continue;
|
|
547
|
+
async copyRouter(sourceDir, targetDir, mergeMode) {
|
|
548
|
+
return this.copyDirectory("router", sourceDir, targetDir, mergeMode);
|
|
587
549
|
}
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
skipped.push(skill);
|
|
591
|
-
continue;
|
|
550
|
+
async copyHooks(sourceDir, targetDir, mergeMode) {
|
|
551
|
+
return this.copyDirectory("hooks", sourceDir, targetDir, mergeMode);
|
|
592
552
|
}
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
553
|
+
async copyExtras(sourceDir, targetDir, mergeMode) {
|
|
554
|
+
const extras = ["memory", "output-styles", "scripts"];
|
|
555
|
+
const copied = [];
|
|
556
|
+
for (const extra of extras) {
|
|
557
|
+
const result = await this.copyDirectory(extra, sourceDir, targetDir, mergeMode);
|
|
558
|
+
if (result.success) {
|
|
559
|
+
copied.push(extra);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
return copied;
|
|
563
|
+
}
|
|
564
|
+
async copyBaseFiles(targetDir, mergeMode) {
|
|
565
|
+
const { CLI_ROOT: CLI_ROOT2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
566
|
+
const sourceDir = join3(CLI_ROOT2, "templates");
|
|
567
|
+
const baseFiles = ["README.md", "settings.json", ".env.example", "statusline.cjs", "statusline.ps1", "statusline.sh"];
|
|
568
|
+
const copied = [];
|
|
569
|
+
for (const file of baseFiles) {
|
|
570
|
+
const srcPath = join3(sourceDir, file);
|
|
571
|
+
const destPath = join3(targetDir, file);
|
|
572
|
+
if (await this.copyFile(srcPath, destPath, mergeMode)) {
|
|
573
|
+
copied.push(file);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
return copied;
|
|
597
577
|
}
|
|
598
|
-
|
|
599
|
-
copied.push(skill);
|
|
600
|
-
} catch (err) {
|
|
601
|
-
errors.push({ skill, error: err.message });
|
|
602
|
-
}
|
|
578
|
+
};
|
|
603
579
|
}
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
const
|
|
611
|
-
if (
|
|
612
|
-
|
|
613
|
-
return copied;
|
|
614
|
-
}
|
|
615
|
-
await fs.copy(settingsPath, destSettingsPath, { overwrite: !mergeMode });
|
|
616
|
-
copied.push("settings.json");
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
// src/targets/gemini-adapter.ts
|
|
583
|
+
import fs3 from "fs-extra";
|
|
584
|
+
import { join as join4, dirname as dirname3 } from "path";
|
|
585
|
+
function parseFrontmatter(content) {
|
|
586
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
587
|
+
if (!match) {
|
|
588
|
+
return { frontmatter: "", body: content };
|
|
617
589
|
}
|
|
618
|
-
return
|
|
590
|
+
return { frontmatter: match[1], body: match[2] };
|
|
619
591
|
}
|
|
620
|
-
function
|
|
621
|
-
|
|
622
|
-
const prompt = body.replace(/\$ARGUMENTS/g, "{{args}}");
|
|
623
|
-
return {
|
|
624
|
-
name: commandName,
|
|
625
|
-
description: description || `Execute ${commandName} command`,
|
|
626
|
-
prompt
|
|
627
|
-
};
|
|
592
|
+
function escapeTomlString(str) {
|
|
593
|
+
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\t/g, "\\t");
|
|
628
594
|
}
|
|
629
|
-
function
|
|
630
|
-
const
|
|
631
|
-
if (!
|
|
632
|
-
let
|
|
633
|
-
const
|
|
634
|
-
const modelMap = {
|
|
635
|
-
"opus": "claude-3-opus",
|
|
636
|
-
"sonnet": "claude-3-sonnet",
|
|
637
|
-
"haiku": "claude-3-haiku",
|
|
638
|
-
"inherit": ""
|
|
639
|
-
// Remove inherit
|
|
640
|
-
};
|
|
641
|
-
for (const [claudeModel, discordModel] of Object.entries(modelMap)) {
|
|
595
|
+
function convertAgentToGemini(mdContent) {
|
|
596
|
+
const { frontmatter, body } = parseFrontmatter(mdContent);
|
|
597
|
+
if (!frontmatter) return mdContent;
|
|
598
|
+
let converted = frontmatter;
|
|
599
|
+
for (const [claudeModel, geminiModel] of Object.entries(MODEL_MAP)) {
|
|
642
600
|
const regex = new RegExp(`^model:\\s*${claudeModel}\\s*$`, "m");
|
|
643
|
-
if (
|
|
644
|
-
|
|
601
|
+
if (geminiModel) {
|
|
602
|
+
converted = converted.replace(regex, `model: ${geminiModel}`);
|
|
645
603
|
} else {
|
|
646
|
-
|
|
604
|
+
converted = converted.replace(regex, "");
|
|
647
605
|
}
|
|
648
606
|
}
|
|
649
|
-
|
|
650
|
-
if (!
|
|
651
|
-
|
|
607
|
+
converted = converted.replace(/^tools:\s*.+$/m, "");
|
|
608
|
+
if (!converted.includes("kind:")) {
|
|
609
|
+
converted = converted.trim() + "\nkind: local";
|
|
652
610
|
}
|
|
653
611
|
return `---
|
|
654
|
-
${
|
|
612
|
+
${converted.trim()}
|
|
655
613
|
---
|
|
656
614
|
${body}`;
|
|
657
615
|
}
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
const
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
const skipped = [];
|
|
667
|
-
const errors = [];
|
|
668
|
-
let agentList;
|
|
669
|
-
if (items === "all") {
|
|
670
|
-
const entries = fs.readdirSync(typeDir);
|
|
671
|
-
agentList = entries.filter((e) => e.endsWith(".md") && e !== "README.md").map((e) => e.replace(/\.md$/, ""));
|
|
672
|
-
} else {
|
|
673
|
-
agentList = items;
|
|
674
|
-
}
|
|
675
|
-
for (const agent of agentList) {
|
|
676
|
-
try {
|
|
677
|
-
const srcPath = join2(typeDir, agent + ".md");
|
|
678
|
-
if (!fs.existsSync(srcPath)) {
|
|
679
|
-
skipped.push(agent);
|
|
680
|
-
continue;
|
|
681
|
-
}
|
|
682
|
-
const destPath = join2(destTypeDir, agent + ".md");
|
|
683
|
-
if (mergeMode && fs.existsSync(destPath)) {
|
|
684
|
-
skipped.push(agent);
|
|
685
|
-
continue;
|
|
686
|
-
}
|
|
687
|
-
const mdContent = fs.readFileSync(srcPath, "utf-8");
|
|
688
|
-
const convertedContent = convertAgentForDiscord(mdContent);
|
|
689
|
-
await fs.writeFile(destPath, convertedContent, "utf-8");
|
|
690
|
-
copied.push(agent);
|
|
691
|
-
} catch (err) {
|
|
692
|
-
errors.push({ item: agent, error: err.message });
|
|
693
|
-
}
|
|
694
|
-
}
|
|
695
|
-
return { copied, skipped, errors };
|
|
696
|
-
}
|
|
697
|
-
async function copyCommandsForDiscord(items, sourceDir, destDir, mergeMode = false) {
|
|
698
|
-
const typeDir = join2(sourceDir, "commands");
|
|
699
|
-
const destTypeDir = join2(destDir, "commands");
|
|
700
|
-
if (!fs.existsSync(typeDir)) {
|
|
701
|
-
return { copied: [], skipped: [], errors: [] };
|
|
702
|
-
}
|
|
703
|
-
await fs.ensureDir(destTypeDir);
|
|
704
|
-
const copied = [];
|
|
705
|
-
const skipped = [];
|
|
706
|
-
const errors = [];
|
|
707
|
-
const commandsConfig = {};
|
|
708
|
-
let itemList;
|
|
709
|
-
if (items === "all") {
|
|
710
|
-
const entries = fs.readdirSync(typeDir);
|
|
711
|
-
itemList = entries.map((e) => e.replace(/\.md$/, ""));
|
|
712
|
-
itemList = [...new Set(itemList)];
|
|
713
|
-
} else {
|
|
714
|
-
itemList = items;
|
|
715
|
-
}
|
|
716
|
-
for (const item of itemList) {
|
|
717
|
-
try {
|
|
718
|
-
const srcPathMd = join2(typeDir, item + ".md");
|
|
719
|
-
const srcPathDir = join2(typeDir, item);
|
|
720
|
-
let copiedSomething = false;
|
|
721
|
-
if (fs.existsSync(srcPathMd) && fs.statSync(srcPathMd).isFile()) {
|
|
722
|
-
const destPath = join2(destTypeDir, item + ".md");
|
|
723
|
-
if (!(mergeMode && fs.existsSync(destPath))) {
|
|
724
|
-
await fs.ensureDir(dirname2(destPath));
|
|
725
|
-
const mdContent = fs.readFileSync(srcPathMd, "utf-8");
|
|
726
|
-
await fs.copy(srcPathMd, destPath, { overwrite: !mergeMode });
|
|
727
|
-
const cmd = convertCommandForDiscord(mdContent, item);
|
|
728
|
-
commandsConfig[item] = {
|
|
729
|
-
description: cmd.description,
|
|
730
|
-
prompt: cmd.prompt
|
|
731
|
-
};
|
|
732
|
-
copiedSomething = true;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
if (fs.existsSync(srcPathDir) && fs.statSync(srcPathDir).isDirectory()) {
|
|
736
|
-
await copyDirectoryForDiscord(srcPathDir, join2(destTypeDir, item), mergeMode, commandsConfig, item);
|
|
737
|
-
copiedSomething = true;
|
|
738
|
-
}
|
|
739
|
-
if (copiedSomething) {
|
|
740
|
-
copied.push(item);
|
|
741
|
-
} else {
|
|
742
|
-
skipped.push(item);
|
|
743
|
-
}
|
|
744
|
-
} catch (err) {
|
|
745
|
-
errors.push({ item, error: err.message });
|
|
746
|
-
}
|
|
747
|
-
}
|
|
748
|
-
const configPath = join2(destDir, "commands.json5");
|
|
749
|
-
if (Object.keys(commandsConfig).length > 0 && !(mergeMode && fs.existsSync(configPath))) {
|
|
750
|
-
const json5Content = generateCommandsJson5(commandsConfig);
|
|
751
|
-
await fs.writeFile(configPath, json5Content, "utf-8");
|
|
616
|
+
function convertCommandToToml(mdContent) {
|
|
617
|
+
const { frontmatter, body } = parseFrontmatter(mdContent);
|
|
618
|
+
const descMatch = frontmatter.match(/description:\s*(.+)/);
|
|
619
|
+
const description = descMatch ? descMatch[1].trim() : "";
|
|
620
|
+
const prompt = body.trim().replace(/\$ARGUMENTS/g, "{{args}}");
|
|
621
|
+
const lines = [];
|
|
622
|
+
if (description) {
|
|
623
|
+
lines.push(`description = "${escapeTomlString(description)}"`);
|
|
752
624
|
}
|
|
753
|
-
|
|
625
|
+
lines.push(`prompt = '''
|
|
626
|
+
${prompt}
|
|
627
|
+
'''`);
|
|
628
|
+
return lines.join("\n");
|
|
754
629
|
}
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
630
|
+
var MODEL_MAP, GeminiAdapter;
|
|
631
|
+
var init_gemini_adapter = __esm({
|
|
632
|
+
"src/targets/gemini-adapter.ts"() {
|
|
633
|
+
"use strict";
|
|
634
|
+
init_base_adapter();
|
|
635
|
+
MODEL_MAP = {
|
|
636
|
+
"opus": "gemini-2.5-pro",
|
|
637
|
+
"sonnet": "gemini-2.5-flash",
|
|
638
|
+
"haiku": "gemini-2.0-flash-lite",
|
|
639
|
+
"inherit": ""
|
|
640
|
+
// Remove inherit, let Gemini use default
|
|
641
|
+
};
|
|
642
|
+
GeminiAdapter = class extends BaseTargetAdapter {
|
|
643
|
+
config = {
|
|
644
|
+
name: "gemini",
|
|
645
|
+
displayName: "Gemini CLI",
|
|
646
|
+
directory: ".gemini",
|
|
647
|
+
features: {
|
|
648
|
+
agents: true,
|
|
649
|
+
skills: true,
|
|
650
|
+
commands: true,
|
|
651
|
+
workflows: false,
|
|
652
|
+
router: false,
|
|
653
|
+
hooks: false,
|
|
654
|
+
memory: false,
|
|
655
|
+
scripts: false,
|
|
656
|
+
"output-styles": false
|
|
657
|
+
}
|
|
781
658
|
};
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
659
|
+
async copyAgents(items, sourceDir, targetDir, mergeMode) {
|
|
660
|
+
const typeDir = join4(sourceDir, "agents");
|
|
661
|
+
const destTypeDir = join4(targetDir, "agents");
|
|
662
|
+
if (!fs3.existsSync(typeDir)) {
|
|
663
|
+
return { copied: [], skipped: [], errors: [] };
|
|
664
|
+
}
|
|
665
|
+
await fs3.ensureDir(destTypeDir);
|
|
666
|
+
let agentList;
|
|
667
|
+
if (items === "all") {
|
|
668
|
+
const entries = fs3.readdirSync(typeDir);
|
|
669
|
+
agentList = entries.filter((e) => e.endsWith(".md") && e !== "README.md").map((e) => e.replace(".md", ""));
|
|
670
|
+
} else {
|
|
671
|
+
agentList = items;
|
|
672
|
+
}
|
|
673
|
+
const copied = [];
|
|
674
|
+
const skipped = [];
|
|
675
|
+
const errors = [];
|
|
676
|
+
for (const agent of agentList) {
|
|
677
|
+
try {
|
|
678
|
+
const srcPath = join4(typeDir, agent + ".md");
|
|
679
|
+
if (!fs3.existsSync(srcPath)) {
|
|
680
|
+
skipped.push(agent);
|
|
681
|
+
continue;
|
|
682
|
+
}
|
|
683
|
+
const destPath = join4(destTypeDir, agent + ".md");
|
|
684
|
+
if (mergeMode && fs3.existsSync(destPath)) {
|
|
685
|
+
skipped.push(agent);
|
|
686
|
+
continue;
|
|
687
|
+
}
|
|
688
|
+
const mdContent = fs3.readFileSync(srcPath, "utf-8");
|
|
689
|
+
const convertedContent = convertAgentToGemini(mdContent);
|
|
690
|
+
await fs3.writeFile(destPath, convertedContent, "utf-8");
|
|
691
|
+
copied.push(agent);
|
|
692
|
+
} catch (err) {
|
|
693
|
+
errors.push({ item: agent, error: err.message });
|
|
694
|
+
}
|
|
695
|
+
}
|
|
696
|
+
return { copied, skipped, errors };
|
|
786
697
|
}
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
698
|
+
async copySkills(items, sourceDir, targetDir, mergeMode) {
|
|
699
|
+
const typeDir = join4(sourceDir, "skills");
|
|
700
|
+
const destTypeDir = join4(targetDir, "skills");
|
|
701
|
+
if (!fs3.existsSync(typeDir)) {
|
|
702
|
+
return { copied: [], skipped: [], errors: [] };
|
|
703
|
+
}
|
|
704
|
+
await fs3.ensureDir(destTypeDir);
|
|
705
|
+
let skillList;
|
|
706
|
+
if (items === "all") {
|
|
707
|
+
const entries = fs3.readdirSync(typeDir);
|
|
708
|
+
skillList = entries.filter((e) => {
|
|
709
|
+
const fullPath = join4(typeDir, e);
|
|
710
|
+
return fs3.statSync(fullPath).isDirectory() && fs3.existsSync(join4(fullPath, "SKILL.md"));
|
|
711
|
+
});
|
|
712
|
+
} else {
|
|
713
|
+
skillList = items;
|
|
714
|
+
}
|
|
715
|
+
const copied = [];
|
|
716
|
+
const skipped = [];
|
|
717
|
+
const errors = [];
|
|
718
|
+
for (const skill of skillList) {
|
|
719
|
+
try {
|
|
720
|
+
const srcPath = join4(typeDir, skill);
|
|
721
|
+
if (!fs3.existsSync(srcPath) || !fs3.statSync(srcPath).isDirectory()) {
|
|
722
|
+
skipped.push(skill);
|
|
723
|
+
continue;
|
|
724
|
+
}
|
|
725
|
+
if (!fs3.existsSync(join4(srcPath, "SKILL.md"))) {
|
|
726
|
+
skipped.push(skill);
|
|
727
|
+
continue;
|
|
728
|
+
}
|
|
729
|
+
const destPath = join4(destTypeDir, skill);
|
|
730
|
+
if (mergeMode && fs3.existsSync(destPath)) {
|
|
731
|
+
skipped.push(skill);
|
|
732
|
+
continue;
|
|
733
|
+
}
|
|
734
|
+
await fs3.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
735
|
+
copied.push(skill);
|
|
736
|
+
} catch (err) {
|
|
737
|
+
errors.push({ item: skill, error: err.message });
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
return { copied, skipped, errors };
|
|
825
741
|
}
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
}
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
742
|
+
async copyCommands(items, sourceDir, targetDir, mergeMode) {
|
|
743
|
+
const typeDir = join4(sourceDir, "commands");
|
|
744
|
+
const destTypeDir = join4(targetDir, "commands");
|
|
745
|
+
if (!fs3.existsSync(typeDir)) {
|
|
746
|
+
return { copied: [], skipped: [], errors: [] };
|
|
747
|
+
}
|
|
748
|
+
await fs3.ensureDir(destTypeDir);
|
|
749
|
+
let itemList;
|
|
750
|
+
if (items === "all") {
|
|
751
|
+
const entries = fs3.readdirSync(typeDir);
|
|
752
|
+
itemList = [...new Set(entries.map((e) => e.replace(".md", "")))];
|
|
753
|
+
} else {
|
|
754
|
+
itemList = items;
|
|
755
|
+
}
|
|
756
|
+
const copied = [];
|
|
757
|
+
const skipped = [];
|
|
758
|
+
const errors = [];
|
|
759
|
+
for (const item of itemList) {
|
|
760
|
+
try {
|
|
761
|
+
const srcPathMd = join4(typeDir, item + ".md");
|
|
762
|
+
const srcPathDir = join4(typeDir, item);
|
|
763
|
+
let copiedSomething = false;
|
|
764
|
+
if (fs3.existsSync(srcPathMd) && fs3.statSync(srcPathMd).isFile()) {
|
|
765
|
+
const destPath = join4(destTypeDir, item + ".toml");
|
|
766
|
+
if (!(mergeMode && fs3.existsSync(destPath))) {
|
|
767
|
+
await fs3.ensureDir(dirname3(destPath));
|
|
768
|
+
const mdContent = fs3.readFileSync(srcPathMd, "utf-8");
|
|
769
|
+
const tomlContent = convertCommandToToml(mdContent);
|
|
770
|
+
await fs3.writeFile(destPath, tomlContent, "utf-8");
|
|
771
|
+
copiedSomething = true;
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
if (fs3.existsSync(srcPathDir) && fs3.statSync(srcPathDir).isDirectory()) {
|
|
775
|
+
await this.convertDirectoryToToml(srcPathDir, join4(destTypeDir, item), mergeMode);
|
|
776
|
+
copiedSomething = true;
|
|
777
|
+
}
|
|
778
|
+
if (copiedSomething) {
|
|
779
|
+
copied.push(item);
|
|
780
|
+
} else {
|
|
781
|
+
skipped.push(item);
|
|
782
|
+
}
|
|
783
|
+
} catch (err) {
|
|
784
|
+
errors.push({ item, error: err.message });
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
return { copied, skipped, errors };
|
|
788
|
+
}
|
|
789
|
+
async convertDirectoryToToml(srcDir, destDir, mergeMode) {
|
|
790
|
+
await fs3.ensureDir(destDir);
|
|
791
|
+
const entries = fs3.readdirSync(srcDir);
|
|
792
|
+
for (const entry of entries) {
|
|
793
|
+
const srcPath = join4(srcDir, entry);
|
|
794
|
+
const stat = fs3.statSync(srcPath);
|
|
795
|
+
if (stat.isDirectory()) {
|
|
796
|
+
await this.convertDirectoryToToml(srcPath, join4(destDir, entry), mergeMode);
|
|
797
|
+
} else if (entry.endsWith(".md")) {
|
|
798
|
+
const destPath = join4(destDir, entry.replace(".md", ".toml"));
|
|
799
|
+
if (mergeMode && fs3.existsSync(destPath)) {
|
|
800
|
+
continue;
|
|
801
|
+
}
|
|
802
|
+
const mdContent = fs3.readFileSync(srcPath, "utf-8");
|
|
803
|
+
const tomlContent = convertCommandToToml(mdContent);
|
|
804
|
+
await fs3.writeFile(destPath, tomlContent, "utf-8");
|
|
805
|
+
} else {
|
|
806
|
+
const destPath = join4(destDir, entry);
|
|
807
|
+
if (mergeMode && fs3.existsSync(destPath)) {
|
|
808
|
+
continue;
|
|
809
|
+
}
|
|
810
|
+
await fs3.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
811
|
+
}
|
|
812
|
+
}
|
|
813
|
+
}
|
|
814
|
+
async copyBaseFiles(targetDir, mergeMode) {
|
|
815
|
+
const { CLI_ROOT: CLI_ROOT2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
816
|
+
const geminiTemplates = join4(CLI_ROOT2, "templates", "gemini");
|
|
817
|
+
const copied = [];
|
|
818
|
+
const settingsPath = join4(geminiTemplates, "settings.json");
|
|
819
|
+
const destSettingsPath = join4(targetDir, "settings.json");
|
|
820
|
+
if (fs3.existsSync(settingsPath)) {
|
|
821
|
+
if (!(mergeMode && fs3.existsSync(destSettingsPath))) {
|
|
822
|
+
await fs3.copy(settingsPath, destSettingsPath, { overwrite: !mergeMode });
|
|
823
|
+
copied.push("settings.json");
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
return copied;
|
|
827
|
+
}
|
|
828
|
+
};
|
|
855
829
|
}
|
|
856
|
-
|
|
830
|
+
});
|
|
831
|
+
|
|
832
|
+
// src/targets/discord-adapter.ts
|
|
833
|
+
import fs4 from "fs-extra";
|
|
834
|
+
import { join as join5, dirname as dirname4 } from "path";
|
|
835
|
+
function parseFrontmatter2(content) {
|
|
836
|
+
const match = content.match(/^---\n([\s\S]*?)\n---\n([\s\S]*)$/);
|
|
837
|
+
if (!match) {
|
|
838
|
+
return { frontmatter: "", body: content, description: "", argumentHint: "" };
|
|
839
|
+
}
|
|
840
|
+
const frontmatter = match[1];
|
|
841
|
+
const body = match[2].trim();
|
|
842
|
+
const descMatch = frontmatter.match(/description:\s*(.+)/);
|
|
843
|
+
const argMatch = frontmatter.match(/argument-hint:\s*(.+)/);
|
|
844
|
+
return {
|
|
845
|
+
frontmatter,
|
|
846
|
+
body,
|
|
847
|
+
description: descMatch ? descMatch[1].trim() : "",
|
|
848
|
+
argumentHint: argMatch ? argMatch[1].trim() : ""
|
|
849
|
+
};
|
|
857
850
|
}
|
|
858
|
-
|
|
859
|
-
const {
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
851
|
+
function convertAgentToDiscord(mdContent) {
|
|
852
|
+
const { frontmatter, body } = parseFrontmatter2(mdContent);
|
|
853
|
+
if (!frontmatter) return mdContent;
|
|
854
|
+
let converted = frontmatter;
|
|
855
|
+
for (const [claudeModel, discordModel] of Object.entries(MODEL_MAP2)) {
|
|
856
|
+
const regex = new RegExp(`^model:\\s*${claudeModel}\\s*$`, "m");
|
|
857
|
+
if (discordModel) {
|
|
858
|
+
converted = converted.replace(regex, `model: ${discordModel}`);
|
|
859
|
+
} else {
|
|
860
|
+
converted = converted.replace(regex, "");
|
|
861
|
+
}
|
|
864
862
|
}
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
execSync3("openclaw config set gateway.mode local", { stdio: "ignore" });
|
|
869
|
-
return { success: true, message: "OpenClaw configured successfully!" };
|
|
870
|
-
} catch (error) {
|
|
871
|
-
return { success: false, message: `Failed to configure OpenClaw: ${error.message}` };
|
|
863
|
+
converted = converted.replace(/^tools:\s*.+$/m, "");
|
|
864
|
+
if (!converted.includes("kind:")) {
|
|
865
|
+
converted = converted.trim() + "\nkind: local";
|
|
872
866
|
}
|
|
867
|
+
return `---
|
|
868
|
+
${converted.trim()}
|
|
869
|
+
---
|
|
870
|
+
${body}`;
|
|
873
871
|
}
|
|
874
872
|
function extractKeywords(content, commandName) {
|
|
875
873
|
const keywords = /* @__PURE__ */ new Set();
|
|
876
874
|
keywords.add(commandName);
|
|
877
875
|
keywords.add(commandName.replace(/-/g, " "));
|
|
878
|
-
const keywordPatterns = [
|
|
879
|
-
/keywords?:\s*([^\n]+)/gi,
|
|
880
|
-
/when.*(?:says?|mentions?|asks?).*["']([^"']+)["']/gi,
|
|
881
|
-
/trigger.*["']([^"']+)["']/gi
|
|
882
|
-
];
|
|
883
|
-
for (const pattern of keywordPatterns) {
|
|
884
|
-
const matches = content.matchAll(pattern);
|
|
885
|
-
for (const match of matches) {
|
|
886
|
-
match[1].split(/[,;]/).forEach((k) => keywords.add(k.trim().toLowerCase()));
|
|
887
|
-
}
|
|
888
|
-
}
|
|
889
876
|
const intentMap = {
|
|
890
877
|
"plan": ["plan", "design", "architect", "implement", "create plan"],
|
|
891
|
-
"brainstorm": ["brainstorm", "ideas", "options", "alternatives"
|
|
878
|
+
"brainstorm": ["brainstorm", "ideas", "options", "alternatives"],
|
|
892
879
|
"fix": ["fix", "debug", "error", "broken", "issue", "bug"],
|
|
893
880
|
"code": ["code", "implement", "build", "develop", "write code"],
|
|
894
881
|
"review": ["review", "check", "audit", "look at"],
|
|
895
882
|
"test": ["test", "testing", "spec", "unit test"],
|
|
896
|
-
"cook": ["cook", "implement", "build feature", "develop"],
|
|
897
883
|
"scout": ["scout", "search", "find", "explore codebase"],
|
|
898
884
|
"debug": ["debug", "trace", "diagnose", "investigate"]
|
|
899
885
|
};
|
|
@@ -904,10 +890,10 @@ function extractKeywords(content, commandName) {
|
|
|
904
890
|
return Array.from(keywords).slice(0, 10);
|
|
905
891
|
}
|
|
906
892
|
function convertCommandToSkill(mdContent, commandName) {
|
|
907
|
-
const { description, argumentHint, body } =
|
|
893
|
+
const { description, argumentHint, body } = parseFrontmatter2(mdContent);
|
|
908
894
|
const prompt = body.replace(/\$ARGUMENTS/g, "{{args}}");
|
|
909
895
|
const keywords = extractKeywords(body, commandName);
|
|
910
|
-
|
|
896
|
+
return `---
|
|
911
897
|
name: ${commandName.replace(/\//g, "-")}
|
|
912
898
|
description: ${description || `Execute ${commandName} task`}
|
|
913
899
|
user-invocable: true
|
|
@@ -933,131 +919,394 @@ ${prompt}
|
|
|
933
919
|
|
|
934
920
|
Provide clear, actionable response based on the workflow above.
|
|
935
921
|
`;
|
|
936
|
-
return skillContent;
|
|
937
922
|
}
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
923
|
+
var MODEL_MAP2, DiscordAdapter;
|
|
924
|
+
var init_discord_adapter = __esm({
|
|
925
|
+
"src/targets/discord-adapter.ts"() {
|
|
926
|
+
"use strict";
|
|
927
|
+
init_base_adapter();
|
|
928
|
+
MODEL_MAP2 = {
|
|
929
|
+
"opus": "claude-3-opus",
|
|
930
|
+
"sonnet": "claude-3-sonnet",
|
|
931
|
+
"haiku": "claude-3-haiku",
|
|
932
|
+
"inherit": ""
|
|
933
|
+
};
|
|
934
|
+
DiscordAdapter = class extends BaseTargetAdapter {
|
|
935
|
+
config = {
|
|
936
|
+
name: "discord",
|
|
937
|
+
displayName: "Discord + OpenClaw",
|
|
938
|
+
directory: ".discord",
|
|
939
|
+
features: {
|
|
940
|
+
agents: true,
|
|
941
|
+
skills: true,
|
|
942
|
+
commands: true,
|
|
943
|
+
workflows: false,
|
|
944
|
+
router: false,
|
|
945
|
+
hooks: false,
|
|
946
|
+
memory: false,
|
|
947
|
+
scripts: false,
|
|
948
|
+
"output-styles": false
|
|
949
|
+
}
|
|
950
|
+
};
|
|
951
|
+
async copyAgents(items, sourceDir, targetDir, mergeMode) {
|
|
952
|
+
const typeDir = join5(sourceDir, "agents");
|
|
953
|
+
const destTypeDir = join5(targetDir, "agents");
|
|
954
|
+
if (!fs4.existsSync(typeDir)) {
|
|
955
|
+
return { copied: [], skipped: [], errors: [] };
|
|
956
|
+
}
|
|
957
|
+
await fs4.ensureDir(destTypeDir);
|
|
958
|
+
let agentList;
|
|
959
|
+
if (items === "all") {
|
|
960
|
+
const entries = fs4.readdirSync(typeDir);
|
|
961
|
+
agentList = entries.filter((e) => e.endsWith(".md") && e !== "README.md").map((e) => e.replace(".md", ""));
|
|
962
|
+
} else {
|
|
963
|
+
agentList = items;
|
|
964
|
+
}
|
|
965
|
+
const copied = [];
|
|
966
|
+
const skipped = [];
|
|
967
|
+
const errors = [];
|
|
968
|
+
for (const agent of agentList) {
|
|
969
|
+
try {
|
|
970
|
+
const srcPath = join5(typeDir, agent + ".md");
|
|
971
|
+
if (!fs4.existsSync(srcPath)) {
|
|
972
|
+
skipped.push(agent);
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
975
|
+
const destPath = join5(destTypeDir, agent + ".md");
|
|
976
|
+
if (mergeMode && fs4.existsSync(destPath)) {
|
|
977
|
+
skipped.push(agent);
|
|
978
|
+
continue;
|
|
979
|
+
}
|
|
980
|
+
const mdContent = fs4.readFileSync(srcPath, "utf-8");
|
|
981
|
+
const convertedContent = convertAgentToDiscord(mdContent);
|
|
982
|
+
await fs4.writeFile(destPath, convertedContent, "utf-8");
|
|
983
|
+
copied.push(agent);
|
|
984
|
+
} catch (err) {
|
|
985
|
+
errors.push({ item: agent, error: err.message });
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
return { copied, skipped, errors };
|
|
980
989
|
}
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
}
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
990
|
+
async copySkills(items, sourceDir, targetDir, mergeMode) {
|
|
991
|
+
const typeDir = join5(sourceDir, "skills");
|
|
992
|
+
const destTypeDir = join5(targetDir, "skills");
|
|
993
|
+
if (!fs4.existsSync(typeDir)) {
|
|
994
|
+
return { copied: [], skipped: [], errors: [] };
|
|
995
|
+
}
|
|
996
|
+
await fs4.ensureDir(destTypeDir);
|
|
997
|
+
let skillList;
|
|
998
|
+
if (items === "all") {
|
|
999
|
+
const entries = fs4.readdirSync(typeDir);
|
|
1000
|
+
skillList = entries.filter((e) => {
|
|
1001
|
+
const fullPath = join5(typeDir, e);
|
|
1002
|
+
return fs4.statSync(fullPath).isDirectory() && fs4.existsSync(join5(fullPath, "SKILL.md"));
|
|
1003
|
+
});
|
|
1004
|
+
} else {
|
|
1005
|
+
skillList = items;
|
|
1006
|
+
}
|
|
1007
|
+
const copied = [];
|
|
1008
|
+
const skipped = [];
|
|
1009
|
+
const errors = [];
|
|
1010
|
+
for (const skill of skillList) {
|
|
1011
|
+
try {
|
|
1012
|
+
const srcPath = join5(typeDir, skill);
|
|
1013
|
+
if (!fs4.existsSync(srcPath) || !fs4.statSync(srcPath).isDirectory()) {
|
|
1014
|
+
skipped.push(skill);
|
|
1015
|
+
continue;
|
|
1016
|
+
}
|
|
1017
|
+
if (!fs4.existsSync(join5(srcPath, "SKILL.md"))) {
|
|
1018
|
+
skipped.push(skill);
|
|
1019
|
+
continue;
|
|
1020
|
+
}
|
|
1021
|
+
const destPath = join5(destTypeDir, skill);
|
|
1022
|
+
if (mergeMode && fs4.existsSync(destPath)) {
|
|
1023
|
+
skipped.push(skill);
|
|
1024
|
+
continue;
|
|
1025
|
+
}
|
|
1026
|
+
await fs4.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
1027
|
+
copied.push(skill);
|
|
1028
|
+
} catch (err) {
|
|
1029
|
+
errors.push({ item: skill, error: err.message });
|
|
1030
|
+
}
|
|
1031
|
+
}
|
|
1032
|
+
const bundledCopied = await this.copyBundledSkills(targetDir, mergeMode);
|
|
1033
|
+
copied.push(...bundledCopied);
|
|
1034
|
+
return { copied, skipped, errors };
|
|
1035
|
+
}
|
|
1036
|
+
async copyCommands(items, sourceDir, targetDir, mergeMode) {
|
|
1037
|
+
const typeDir = join5(sourceDir, "commands");
|
|
1038
|
+
const destTypeDir = join5(targetDir, "commands");
|
|
1039
|
+
const destSkillsDir = join5(targetDir, "skills");
|
|
1040
|
+
if (!fs4.existsSync(typeDir)) {
|
|
1041
|
+
return { copied: [], skipped: [], errors: [] };
|
|
1042
|
+
}
|
|
1043
|
+
await fs4.ensureDir(destTypeDir);
|
|
1044
|
+
await fs4.ensureDir(destSkillsDir);
|
|
1045
|
+
let itemList;
|
|
1046
|
+
if (items === "all") {
|
|
1047
|
+
const entries = fs4.readdirSync(typeDir);
|
|
1048
|
+
itemList = entries.filter((e) => e.endsWith(".md") && e !== "README.md").map((e) => e.replace(".md", ""));
|
|
1049
|
+
const dirs = entries.filter((e) => {
|
|
1050
|
+
const fullPath = join5(typeDir, e);
|
|
1051
|
+
return fs4.statSync(fullPath).isDirectory();
|
|
1052
|
+
});
|
|
1053
|
+
itemList = [.../* @__PURE__ */ new Set([...itemList, ...dirs])];
|
|
1054
|
+
} else {
|
|
1055
|
+
itemList = items;
|
|
1056
|
+
}
|
|
1057
|
+
const copied = [];
|
|
1058
|
+
const skipped = [];
|
|
1059
|
+
const errors = [];
|
|
1060
|
+
const commandsConfig = {};
|
|
1061
|
+
for (const item of itemList) {
|
|
1062
|
+
try {
|
|
1063
|
+
const srcPathMd = join5(typeDir, item + ".md");
|
|
1064
|
+
const srcPathDir = join5(typeDir, item);
|
|
1065
|
+
if (fs4.existsSync(srcPathMd) && fs4.statSync(srcPathMd).isFile()) {
|
|
1066
|
+
const destPath = join5(destTypeDir, item + ".md");
|
|
1067
|
+
const skillDir = join5(destSkillsDir, item.replace(/\//g, "-"));
|
|
1068
|
+
const skillPath = join5(skillDir, "SKILL.md");
|
|
1069
|
+
if (!(mergeMode && fs4.existsSync(destPath))) {
|
|
1070
|
+
await fs4.ensureDir(dirname4(destPath));
|
|
1071
|
+
const mdContent = fs4.readFileSync(srcPathMd, "utf-8");
|
|
1072
|
+
await fs4.copy(srcPathMd, destPath, { overwrite: !mergeMode });
|
|
1073
|
+
if (!(mergeMode && fs4.existsSync(skillPath))) {
|
|
1074
|
+
await fs4.ensureDir(skillDir);
|
|
1075
|
+
const skillContent = convertCommandToSkill(mdContent, item);
|
|
1076
|
+
await fs4.writeFile(skillPath, skillContent, "utf-8");
|
|
1077
|
+
}
|
|
1078
|
+
const { description, body } = parseFrontmatter2(mdContent);
|
|
1079
|
+
commandsConfig[item] = {
|
|
1080
|
+
description: description || `Execute ${item} command`,
|
|
1081
|
+
prompt: body.replace(/\$ARGUMENTS/g, "{{args}}")
|
|
1082
|
+
};
|
|
1083
|
+
copied.push(item);
|
|
1084
|
+
} else {
|
|
1085
|
+
skipped.push(item);
|
|
1086
|
+
}
|
|
1087
|
+
}
|
|
1088
|
+
if (fs4.existsSync(srcPathDir) && fs4.statSync(srcPathDir).isDirectory()) {
|
|
1089
|
+
await this.copyNestedCommands(srcPathDir, destTypeDir, destSkillsDir, item, mergeMode, commandsConfig);
|
|
1090
|
+
copied.push(item + "/*");
|
|
1091
|
+
}
|
|
1092
|
+
} catch (err) {
|
|
1093
|
+
errors.push({ item, error: err.message });
|
|
1094
|
+
}
|
|
1095
|
+
}
|
|
1096
|
+
const configPath = join5(targetDir, "commands.json5");
|
|
1097
|
+
if (Object.keys(commandsConfig).length > 0 && !(mergeMode && fs4.existsSync(configPath))) {
|
|
1098
|
+
const json5Content = this.generateCommandsJson5(commandsConfig);
|
|
1099
|
+
await fs4.writeFile(configPath, json5Content, "utf-8");
|
|
1100
|
+
}
|
|
1101
|
+
return { copied, skipped, errors };
|
|
1102
|
+
}
|
|
1103
|
+
async copyNestedCommands(srcDir, destDir, destSkillsDir, parentName, mergeMode, commandsConfig) {
|
|
1104
|
+
const destTypeDir = join5(destDir, parentName);
|
|
1105
|
+
await fs4.ensureDir(destTypeDir);
|
|
1106
|
+
const entries = fs4.readdirSync(srcDir);
|
|
1107
|
+
for (const entry of entries) {
|
|
1108
|
+
const srcPath = join5(srcDir, entry);
|
|
1109
|
+
const stat = fs4.statSync(srcPath);
|
|
1110
|
+
if (stat.isDirectory()) {
|
|
1111
|
+
await this.copyNestedCommands(
|
|
1112
|
+
srcPath,
|
|
1113
|
+
destTypeDir,
|
|
1114
|
+
destSkillsDir,
|
|
1115
|
+
entry,
|
|
1116
|
+
mergeMode,
|
|
1117
|
+
commandsConfig
|
|
1118
|
+
);
|
|
1119
|
+
} else if (entry.endsWith(".md") && entry !== "README.md") {
|
|
1120
|
+
const destPath = join5(destTypeDir, entry);
|
|
1121
|
+
const cmdName = `${parentName}/${entry.replace(".md", "")}`;
|
|
1122
|
+
const skillName = cmdName.replace(/\//g, "-");
|
|
1123
|
+
const skillDir = join5(destSkillsDir, skillName);
|
|
1124
|
+
const skillPath = join5(skillDir, "SKILL.md");
|
|
1125
|
+
if (mergeMode && fs4.existsSync(destPath)) {
|
|
1126
|
+
continue;
|
|
1127
|
+
}
|
|
1128
|
+
const mdContent = fs4.readFileSync(srcPath, "utf-8");
|
|
1129
|
+
await fs4.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
1130
|
+
if (!(mergeMode && fs4.existsSync(skillPath))) {
|
|
1131
|
+
await fs4.ensureDir(skillDir);
|
|
1132
|
+
const skillContent = convertCommandToSkill(mdContent, skillName);
|
|
1133
|
+
await fs4.writeFile(skillPath, skillContent, "utf-8");
|
|
1134
|
+
}
|
|
1135
|
+
const { description, body } = parseFrontmatter2(mdContent);
|
|
1136
|
+
commandsConfig[cmdName] = {
|
|
1137
|
+
description: description || `Execute ${cmdName} command`,
|
|
1138
|
+
prompt: body.replace(/\$ARGUMENTS/g, "{{args}}")
|
|
1139
|
+
};
|
|
1140
|
+
}
|
|
1141
|
+
}
|
|
1005
1142
|
}
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1143
|
+
generateCommandsJson5(commands) {
|
|
1144
|
+
const lines = [
|
|
1145
|
+
"// Clawbot Commands Configuration",
|
|
1146
|
+
"// Generated by Apero Kit CLI",
|
|
1147
|
+
"{",
|
|
1148
|
+
' "commands": {'
|
|
1149
|
+
];
|
|
1150
|
+
const cmdEntries = Object.entries(commands);
|
|
1151
|
+
cmdEntries.forEach(([name, cmd], index) => {
|
|
1152
|
+
const safeName = name.replace(/\//g, ":");
|
|
1153
|
+
const isLast = index === cmdEntries.length - 1;
|
|
1154
|
+
lines.push(` "${safeName}": {`);
|
|
1155
|
+
lines.push(` "description": ${JSON.stringify(cmd.description)},`);
|
|
1156
|
+
lines.push(` "prompt": ${JSON.stringify(cmd.prompt)}`);
|
|
1157
|
+
lines.push(` }${isLast ? "" : ","}`);
|
|
1158
|
+
});
|
|
1159
|
+
lines.push(" }");
|
|
1160
|
+
lines.push("}");
|
|
1161
|
+
return lines.join("\n");
|
|
1162
|
+
}
|
|
1163
|
+
async copyBundledSkills(targetDir, mergeMode) {
|
|
1164
|
+
const { CLI_ROOT: CLI_ROOT2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
1165
|
+
const bundledSkillsDir = join5(CLI_ROOT2, "templates", "discord", "skills");
|
|
1166
|
+
const destSkillsDir = join5(targetDir, "skills");
|
|
1167
|
+
const copied = [];
|
|
1168
|
+
if (!fs4.existsSync(bundledSkillsDir)) {
|
|
1169
|
+
return copied;
|
|
1170
|
+
}
|
|
1171
|
+
await fs4.ensureDir(destSkillsDir);
|
|
1172
|
+
const skills = fs4.readdirSync(bundledSkillsDir);
|
|
1173
|
+
for (const skill of skills) {
|
|
1174
|
+
const srcPath = join5(bundledSkillsDir, skill);
|
|
1175
|
+
const destPath = join5(destSkillsDir, skill);
|
|
1176
|
+
if (fs4.statSync(srcPath).isDirectory()) {
|
|
1177
|
+
if (mergeMode && fs4.existsSync(destPath)) {
|
|
1178
|
+
continue;
|
|
1179
|
+
}
|
|
1180
|
+
await fs4.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
1181
|
+
copied.push(`bundled:${skill}`);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
return copied;
|
|
1185
|
+
}
|
|
1186
|
+
async copyBaseFiles(targetDir, mergeMode) {
|
|
1187
|
+
const { CLI_ROOT: CLI_ROOT2 } = await Promise.resolve().then(() => (init_paths(), paths_exports));
|
|
1188
|
+
const discordTemplates = join5(CLI_ROOT2, "templates", "discord");
|
|
1189
|
+
const copied = [];
|
|
1190
|
+
const filesToCopy = ["config.json5", "README.md"];
|
|
1191
|
+
for (const file of filesToCopy) {
|
|
1192
|
+
const srcPath = join5(discordTemplates, file);
|
|
1193
|
+
const destPath = join5(targetDir, file);
|
|
1194
|
+
if (fs4.existsSync(srcPath)) {
|
|
1195
|
+
if (mergeMode && fs4.existsSync(destPath)) {
|
|
1196
|
+
continue;
|
|
1197
|
+
}
|
|
1198
|
+
await fs4.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
1199
|
+
copied.push(file);
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
return copied;
|
|
1203
|
+
}
|
|
1204
|
+
/**
|
|
1205
|
+
* Update Discord config with bot token
|
|
1206
|
+
*/
|
|
1207
|
+
async updateConfig(targetDir, token, guildId) {
|
|
1208
|
+
const configPath = join5(targetDir, "config.json5");
|
|
1209
|
+
if (!fs4.existsSync(configPath)) {
|
|
1210
|
+
return;
|
|
1211
|
+
}
|
|
1212
|
+
let content = await fs4.readFile(configPath, "utf-8");
|
|
1213
|
+
content = content.replace(
|
|
1214
|
+
'"token": "${DISCORD_BOT_TOKEN}"',
|
|
1215
|
+
`"token": "${token}"`
|
|
1216
|
+
);
|
|
1217
|
+
if (guildId) {
|
|
1218
|
+
const guildConfig = `"${guildId}": {
|
|
1219
|
+
"requireMention": true,
|
|
1220
|
+
"users": [],
|
|
1221
|
+
"roles": [],
|
|
1222
|
+
"channels": {}
|
|
1223
|
+
}`;
|
|
1224
|
+
content = content.replace(
|
|
1225
|
+
'"guilds": {\n // Example guild configuration',
|
|
1226
|
+
`"guilds": {
|
|
1227
|
+
${guildConfig},
|
|
1228
|
+
// Example guild configuration`
|
|
1229
|
+
);
|
|
1230
|
+
}
|
|
1231
|
+
await fs4.writeFile(configPath, content, "utf-8");
|
|
1232
|
+
}
|
|
1233
|
+
/**
|
|
1234
|
+
* Setup OpenClaw CLI configuration
|
|
1235
|
+
*/
|
|
1236
|
+
async setupOpenClaw(token) {
|
|
1237
|
+
const { execSync: execSync3 } = await import("child_process");
|
|
1238
|
+
try {
|
|
1239
|
+
execSync3("which openclaw", { stdio: "ignore" });
|
|
1240
|
+
} catch {
|
|
1241
|
+
return { success: false, message: "OpenClaw CLI not installed. Run: npm install -g openclaw" };
|
|
1242
|
+
}
|
|
1243
|
+
try {
|
|
1244
|
+
execSync3(`openclaw config set channels.discord.token '"${token}"' --json`, { stdio: "ignore" });
|
|
1245
|
+
execSync3("openclaw config set channels.discord.enabled true --json", { stdio: "ignore" });
|
|
1246
|
+
execSync3("openclaw config set gateway.mode local", { stdio: "ignore" });
|
|
1247
|
+
return { success: true, message: "OpenClaw configured successfully!" };
|
|
1248
|
+
} catch (error) {
|
|
1249
|
+
return { success: false, message: `Failed to configure OpenClaw: ${error.message}` };
|
|
1250
|
+
}
|
|
1028
1251
|
}
|
|
1029
|
-
|
|
1030
|
-
copied.push(skill);
|
|
1031
|
-
}
|
|
1252
|
+
};
|
|
1032
1253
|
}
|
|
1033
|
-
|
|
1254
|
+
});
|
|
1255
|
+
|
|
1256
|
+
// src/targets/index.ts
|
|
1257
|
+
function getAdapter(target) {
|
|
1258
|
+
const adapter = adapters[target];
|
|
1259
|
+
if (!adapter) {
|
|
1260
|
+
throw new Error(`Unknown target: ${target}. Available: ${Object.keys(adapters).join(", ")}`);
|
|
1261
|
+
}
|
|
1262
|
+
return adapter;
|
|
1034
1263
|
}
|
|
1035
|
-
|
|
1036
|
-
|
|
1264
|
+
function isValidTarget(target) {
|
|
1265
|
+
return target in adapters;
|
|
1266
|
+
}
|
|
1267
|
+
function getTargetDirectory(target) {
|
|
1268
|
+
return adapters[target].config.directory;
|
|
1269
|
+
}
|
|
1270
|
+
function getTargetDisplayName(target) {
|
|
1271
|
+
return adapters[target].config.displayName;
|
|
1272
|
+
}
|
|
1273
|
+
var adapters;
|
|
1274
|
+
var init_targets = __esm({
|
|
1275
|
+
"src/targets/index.ts"() {
|
|
1037
1276
|
"use strict";
|
|
1038
|
-
|
|
1277
|
+
init_claude_adapter();
|
|
1278
|
+
init_gemini_adapter();
|
|
1279
|
+
init_discord_adapter();
|
|
1280
|
+
init_claude_adapter();
|
|
1281
|
+
init_gemini_adapter();
|
|
1282
|
+
init_discord_adapter();
|
|
1283
|
+
adapters = {
|
|
1284
|
+
claude: new ClaudeAdapter(),
|
|
1285
|
+
gemini: new GeminiAdapter(),
|
|
1286
|
+
discord: new DiscordAdapter()
|
|
1287
|
+
};
|
|
1039
1288
|
}
|
|
1040
1289
|
});
|
|
1041
1290
|
|
|
1042
1291
|
// src/utils/hash.ts
|
|
1043
1292
|
import { createHash } from "crypto";
|
|
1044
|
-
import
|
|
1045
|
-
import { join as
|
|
1293
|
+
import fs5 from "fs-extra";
|
|
1294
|
+
import { join as join6, relative } from "path";
|
|
1046
1295
|
function hashFile(filePath) {
|
|
1047
|
-
if (!
|
|
1296
|
+
if (!fs5.existsSync(filePath)) {
|
|
1048
1297
|
return null;
|
|
1049
1298
|
}
|
|
1050
|
-
const content =
|
|
1299
|
+
const content = fs5.readFileSync(filePath);
|
|
1051
1300
|
return createHash("md5").update(content).digest("hex");
|
|
1052
1301
|
}
|
|
1053
1302
|
async function hashDirectory(dirPath, baseDir = dirPath) {
|
|
1054
1303
|
const hashes = {};
|
|
1055
|
-
if (!
|
|
1304
|
+
if (!fs5.existsSync(dirPath)) {
|
|
1056
1305
|
return hashes;
|
|
1057
1306
|
}
|
|
1058
|
-
const items = await
|
|
1307
|
+
const items = await fs5.readdir(dirPath, { withFileTypes: true });
|
|
1059
1308
|
for (const item of items) {
|
|
1060
|
-
const itemPath =
|
|
1309
|
+
const itemPath = join6(dirPath, item.name);
|
|
1061
1310
|
const relativePath = relative(baseDir, itemPath);
|
|
1062
1311
|
if (item.isDirectory()) {
|
|
1063
1312
|
const subHashes = await hashDirectory(itemPath, baseDir);
|
|
@@ -1078,27 +1327,27 @@ var init_hash = __esm({
|
|
|
1078
1327
|
});
|
|
1079
1328
|
|
|
1080
1329
|
// src/utils/state.ts
|
|
1081
|
-
import
|
|
1082
|
-
import { join as
|
|
1330
|
+
import fs6 from "fs-extra";
|
|
1331
|
+
import { join as join7 } from "path";
|
|
1083
1332
|
function getStatePath(projectDir) {
|
|
1084
|
-
return
|
|
1333
|
+
return join7(projectDir, STATE_DIR, STATE_FILE);
|
|
1085
1334
|
}
|
|
1086
1335
|
async function loadState(projectDir) {
|
|
1087
1336
|
const statePath = getStatePath(projectDir);
|
|
1088
|
-
if (!
|
|
1337
|
+
if (!fs6.existsSync(statePath)) {
|
|
1089
1338
|
return null;
|
|
1090
1339
|
}
|
|
1091
1340
|
try {
|
|
1092
|
-
return await
|
|
1341
|
+
return await fs6.readJson(statePath);
|
|
1093
1342
|
} catch {
|
|
1094
1343
|
return null;
|
|
1095
1344
|
}
|
|
1096
1345
|
}
|
|
1097
1346
|
async function saveState(projectDir, state) {
|
|
1098
|
-
const stateDir =
|
|
1099
|
-
const statePath =
|
|
1100
|
-
await
|
|
1101
|
-
await
|
|
1347
|
+
const stateDir = join7(projectDir, STATE_DIR);
|
|
1348
|
+
const statePath = join7(stateDir, STATE_FILE);
|
|
1349
|
+
await fs6.ensureDir(stateDir);
|
|
1350
|
+
await fs6.writeJson(statePath, state, { spaces: 2 });
|
|
1102
1351
|
}
|
|
1103
1352
|
async function createInitialState(projectDir, options) {
|
|
1104
1353
|
const { kit, source, target, targets, installed } = options;
|
|
@@ -1106,8 +1355,8 @@ async function createInitialState(projectDir, options) {
|
|
|
1106
1355
|
const targetList = targets || [target.replace(".", "")];
|
|
1107
1356
|
for (const t of targetList) {
|
|
1108
1357
|
const targetDirName = t.startsWith(".") ? t : `.${t}`;
|
|
1109
|
-
const targetDir =
|
|
1110
|
-
if (
|
|
1358
|
+
const targetDir = join7(projectDir, targetDirName);
|
|
1359
|
+
if (fs6.existsSync(targetDir)) {
|
|
1111
1360
|
const hashes = await hashDirectory(targetDir);
|
|
1112
1361
|
for (const [path, hash] of Object.entries(hashes)) {
|
|
1113
1362
|
allHashes[`${targetDirName}/${path}`] = hash;
|
|
@@ -1133,7 +1382,7 @@ async function updateState(projectDir, updates) {
|
|
|
1133
1382
|
if (!state) {
|
|
1134
1383
|
throw new Error("No state found. Is this an ak project?");
|
|
1135
1384
|
}
|
|
1136
|
-
const targetDir =
|
|
1385
|
+
const targetDir = join7(projectDir, state.target || ".claude");
|
|
1137
1386
|
const newHashes = await hashDirectory(targetDir);
|
|
1138
1387
|
const updatedState = {
|
|
1139
1388
|
...state,
|
|
@@ -1149,7 +1398,7 @@ async function getFileStatuses(projectDir) {
|
|
|
1149
1398
|
if (!state) {
|
|
1150
1399
|
return { error: "No state found" };
|
|
1151
1400
|
}
|
|
1152
|
-
const targetDir =
|
|
1401
|
+
const targetDir = join7(projectDir, state.target || ".claude");
|
|
1153
1402
|
const currentHashes = await hashDirectory(targetDir);
|
|
1154
1403
|
const originalHashes = state.originalHashes || {};
|
|
1155
1404
|
const statuses = {
|
|
@@ -1188,6 +1437,78 @@ var init_state = __esm({
|
|
|
1188
1437
|
}
|
|
1189
1438
|
});
|
|
1190
1439
|
|
|
1440
|
+
// src/utils/copy.ts
|
|
1441
|
+
import fs7 from "fs-extra";
|
|
1442
|
+
import { join as join8, dirname as dirname5 } from "path";
|
|
1443
|
+
async function copyItems(items, type, sourceDir, destDir, mergeMode = false) {
|
|
1444
|
+
const typeDir = join8(sourceDir, type);
|
|
1445
|
+
const destTypeDir = join8(destDir, type);
|
|
1446
|
+
if (!fs7.existsSync(typeDir)) {
|
|
1447
|
+
return { copied: [], skipped: items, errors: [] };
|
|
1448
|
+
}
|
|
1449
|
+
await fs7.ensureDir(destTypeDir);
|
|
1450
|
+
const copied = [];
|
|
1451
|
+
const skipped = [];
|
|
1452
|
+
const errors = [];
|
|
1453
|
+
for (const item of items) {
|
|
1454
|
+
try {
|
|
1455
|
+
const itemPath = join8(typeDir, item);
|
|
1456
|
+
const itemPathMd = itemPath + ".md";
|
|
1457
|
+
let srcPath;
|
|
1458
|
+
if (fs7.existsSync(itemPath)) {
|
|
1459
|
+
srcPath = itemPath;
|
|
1460
|
+
} else if (fs7.existsSync(itemPathMd)) {
|
|
1461
|
+
srcPath = itemPathMd;
|
|
1462
|
+
} else {
|
|
1463
|
+
skipped.push(item);
|
|
1464
|
+
continue;
|
|
1465
|
+
}
|
|
1466
|
+
const stat = fs7.statSync(srcPath);
|
|
1467
|
+
if (stat.isDirectory()) {
|
|
1468
|
+
await fs7.copy(srcPath, join8(destTypeDir, item), { overwrite: !mergeMode });
|
|
1469
|
+
} else {
|
|
1470
|
+
const destPath = srcPath.endsWith(".md") ? join8(destTypeDir, item + ".md") : join8(destTypeDir, item);
|
|
1471
|
+
await fs7.ensureDir(join8(destTypeDir, item.split("/").slice(0, -1).join("/")));
|
|
1472
|
+
await fs7.copy(srcPath, destPath, { overwrite: !mergeMode });
|
|
1473
|
+
}
|
|
1474
|
+
copied.push(item);
|
|
1475
|
+
} catch (err) {
|
|
1476
|
+
errors.push({ item, error: err.message });
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
return { copied, skipped, errors };
|
|
1480
|
+
}
|
|
1481
|
+
async function copyAgentsMd(agentsMdPath, projectDir, mergeMode = false) {
|
|
1482
|
+
if (!agentsMdPath || !fs7.existsSync(agentsMdPath)) {
|
|
1483
|
+
return false;
|
|
1484
|
+
}
|
|
1485
|
+
const destPath = join8(projectDir, "AGENTS.md");
|
|
1486
|
+
if (mergeMode && fs7.existsSync(destPath)) {
|
|
1487
|
+
return false;
|
|
1488
|
+
}
|
|
1489
|
+
await fs7.copy(agentsMdPath, destPath, { overwrite: !mergeMode });
|
|
1490
|
+
return true;
|
|
1491
|
+
}
|
|
1492
|
+
function listAvailable(type, sourceDir) {
|
|
1493
|
+
const typeDir = join8(sourceDir, type);
|
|
1494
|
+
if (!fs7.existsSync(typeDir)) {
|
|
1495
|
+
return [];
|
|
1496
|
+
}
|
|
1497
|
+
const items = fs7.readdirSync(typeDir);
|
|
1498
|
+
return items.map((item) => {
|
|
1499
|
+
const itemPath = join8(typeDir, item);
|
|
1500
|
+
const isDir = fs7.statSync(itemPath).isDirectory();
|
|
1501
|
+
const name = item.replace(/\.md$/, "");
|
|
1502
|
+
return { name, isDir, path: itemPath };
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
var init_copy = __esm({
|
|
1506
|
+
"src/utils/copy.ts"() {
|
|
1507
|
+
"use strict";
|
|
1508
|
+
init_paths();
|
|
1509
|
+
}
|
|
1510
|
+
});
|
|
1511
|
+
|
|
1191
1512
|
// src/utils/prompts.ts
|
|
1192
1513
|
import * as p from "@clack/prompts";
|
|
1193
1514
|
import pc from "picocolors";
|
|
@@ -1315,6 +1636,62 @@ function isOpenClawInstalled() {
|
|
|
1315
1636
|
return false;
|
|
1316
1637
|
}
|
|
1317
1638
|
}
|
|
1639
|
+
function isGeminiCliInstalled() {
|
|
1640
|
+
try {
|
|
1641
|
+
const { execSync: execSync3 } = __require("child_process");
|
|
1642
|
+
execSync3("which gemini", { stdio: "ignore" });
|
|
1643
|
+
return true;
|
|
1644
|
+
} catch {
|
|
1645
|
+
return false;
|
|
1646
|
+
}
|
|
1647
|
+
}
|
|
1648
|
+
function isGeminiCliLoggedIn() {
|
|
1649
|
+
try {
|
|
1650
|
+
const fs15 = __require("fs");
|
|
1651
|
+
const path = __require("path");
|
|
1652
|
+
const credsPath = path.join(process.env.HOME || "", ".gemini", "oauth_creds.json");
|
|
1653
|
+
return fs15.existsSync(credsPath);
|
|
1654
|
+
} catch {
|
|
1655
|
+
return false;
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1658
|
+
async function setupGeminiCliAuth() {
|
|
1659
|
+
const { execSync: execSync3, spawnSync } = __require("child_process");
|
|
1660
|
+
try {
|
|
1661
|
+
if (!isGeminiCliLoggedIn()) {
|
|
1662
|
+
console.log(pc.cyan("Logging in to Gemini CLI..."));
|
|
1663
|
+
spawnSync("gemini", ["auth", "login"], { stdio: "inherit" });
|
|
1664
|
+
}
|
|
1665
|
+
console.log(pc.cyan("Enabling Gemini CLI auth plugin..."));
|
|
1666
|
+
execSync3("openclaw plugins enable google-gemini-cli-auth", { stdio: "ignore" });
|
|
1667
|
+
console.log(pc.cyan("Setting Gemini CLI as default model provider..."));
|
|
1668
|
+
execSync3("openclaw models auth login --provider google-gemini-cli --set-default", { stdio: "inherit" });
|
|
1669
|
+
console.log(pc.green("\u2713 Gemini CLI OAuth configured successfully!"));
|
|
1670
|
+
return true;
|
|
1671
|
+
} catch (error) {
|
|
1672
|
+
console.log(pc.red("\u2717 Failed to setup Gemini CLI auth"));
|
|
1673
|
+
console.log(pc.gray(" Try manually:"));
|
|
1674
|
+
console.log(pc.gray(" 1. gemini auth login"));
|
|
1675
|
+
console.log(pc.gray(" 2. openclaw plugins enable google-gemini-cli-auth"));
|
|
1676
|
+
console.log(pc.gray(" 3. openclaw models auth login --provider google-gemini-cli --set-default"));
|
|
1677
|
+
return false;
|
|
1678
|
+
}
|
|
1679
|
+
}
|
|
1680
|
+
async function installGeminiCli() {
|
|
1681
|
+
const { execSync: execSync3 } = __require("child_process");
|
|
1682
|
+
try {
|
|
1683
|
+
console.log(pc.cyan("Installing Gemini CLI..."));
|
|
1684
|
+
execSync3("npm install -g @anthropic-ai/gemini-cli", { stdio: "inherit" });
|
|
1685
|
+
console.log(pc.green("\u2713 Gemini CLI installed successfully!"));
|
|
1686
|
+
console.log("");
|
|
1687
|
+
return true;
|
|
1688
|
+
} catch (error) {
|
|
1689
|
+
console.log(pc.red("\u2717 Failed to install Gemini CLI"));
|
|
1690
|
+
console.log(pc.gray(" Try manually: npm install -g @anthropic-ai/gemini-cli"));
|
|
1691
|
+
console.log("");
|
|
1692
|
+
return false;
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1318
1695
|
function isDiscordConfigured() {
|
|
1319
1696
|
try {
|
|
1320
1697
|
const { execSync: execSync3 } = __require("child_process");
|
|
@@ -1327,8 +1704,9 @@ function isDiscordConfigured() {
|
|
|
1327
1704
|
function restartGateway() {
|
|
1328
1705
|
try {
|
|
1329
1706
|
const { execSync: execSync3 } = __require("child_process");
|
|
1330
|
-
|
|
1331
|
-
|
|
1707
|
+
execSync3("openclaw config set gateway.mode local", { stdio: "ignore" });
|
|
1708
|
+
console.log(pc.cyan("Starting OpenClaw gateway..."));
|
|
1709
|
+
execSync3("openclaw gateway", { stdio: "inherit" });
|
|
1332
1710
|
return true;
|
|
1333
1711
|
} catch {
|
|
1334
1712
|
return false;
|
|
@@ -1372,6 +1750,7 @@ async function promptDiscordSetup() {
|
|
|
1372
1750
|
message: "What do you want to do?",
|
|
1373
1751
|
options: [
|
|
1374
1752
|
{ value: "restart", label: "Restart gateway", hint: "Use existing config" },
|
|
1753
|
+
{ value: "gemini-cli", label: "Setup Gemini CLI OAuth", hint: "Use Gemini CLI as AI provider" },
|
|
1375
1754
|
{ value: "reconfigure", label: "Reconfigure", hint: "Enter new token" },
|
|
1376
1755
|
{ value: "skip", label: "Skip setup", hint: "Continue without changes" }
|
|
1377
1756
|
]
|
|
@@ -1386,6 +1765,30 @@ async function promptDiscordSetup() {
|
|
|
1386
1765
|
restartOnly: true
|
|
1387
1766
|
};
|
|
1388
1767
|
}
|
|
1768
|
+
if (action === "gemini-cli") {
|
|
1769
|
+
let geminiInstalled = isGeminiCliInstalled();
|
|
1770
|
+
if (!geminiInstalled) {
|
|
1771
|
+
console.log(pc.yellow("\u26A0 Gemini CLI not found."));
|
|
1772
|
+
const shouldInstall = await p.confirm({
|
|
1773
|
+
message: "Install Gemini CLI now?",
|
|
1774
|
+
initialValue: true
|
|
1775
|
+
});
|
|
1776
|
+
if (p.isCancel(shouldInstall)) process.exit(0);
|
|
1777
|
+
if (shouldInstall) {
|
|
1778
|
+
geminiInstalled = await installGeminiCli();
|
|
1779
|
+
}
|
|
1780
|
+
}
|
|
1781
|
+
if (geminiInstalled) {
|
|
1782
|
+
await setupGeminiCliAuth();
|
|
1783
|
+
}
|
|
1784
|
+
return {
|
|
1785
|
+
token: "",
|
|
1786
|
+
autoSetup: false,
|
|
1787
|
+
openclawInstalled: true,
|
|
1788
|
+
restartOnly: true,
|
|
1789
|
+
useGeminiCli: true
|
|
1790
|
+
};
|
|
1791
|
+
}
|
|
1389
1792
|
if (action === "skip") {
|
|
1390
1793
|
return {
|
|
1391
1794
|
token: "",
|
|
@@ -1395,7 +1798,37 @@ async function promptDiscordSetup() {
|
|
|
1395
1798
|
};
|
|
1396
1799
|
}
|
|
1397
1800
|
}
|
|
1398
|
-
console.log(
|
|
1801
|
+
console.log("");
|
|
1802
|
+
console.log(pc.cyan("Choose AI Model Authentication:"));
|
|
1803
|
+
const authMethod = await p.select({
|
|
1804
|
+
message: "How do you want to authenticate with AI models?",
|
|
1805
|
+
options: [
|
|
1806
|
+
{ value: "gemini-cli", label: "Gemini CLI OAuth", hint: "Recommended - uses Google OAuth via Gemini CLI" },
|
|
1807
|
+
{ value: "api-key", label: "API Key", hint: "Use your own API key" }
|
|
1808
|
+
]
|
|
1809
|
+
});
|
|
1810
|
+
if (p.isCancel(authMethod)) process.exit(0);
|
|
1811
|
+
let useGeminiCli = false;
|
|
1812
|
+
if (authMethod === "gemini-cli") {
|
|
1813
|
+
let geminiInstalled = isGeminiCliInstalled();
|
|
1814
|
+
if (!geminiInstalled) {
|
|
1815
|
+
console.log(pc.yellow("\u26A0 Gemini CLI not found."));
|
|
1816
|
+
const shouldInstall = await p.confirm({
|
|
1817
|
+
message: "Install Gemini CLI now?",
|
|
1818
|
+
initialValue: true
|
|
1819
|
+
});
|
|
1820
|
+
if (p.isCancel(shouldInstall)) process.exit(0);
|
|
1821
|
+
if (shouldInstall) {
|
|
1822
|
+
geminiInstalled = await installGeminiCli();
|
|
1823
|
+
}
|
|
1824
|
+
}
|
|
1825
|
+
if (geminiInstalled && openclawInstalled) {
|
|
1826
|
+
const setupSuccess = await setupGeminiCliAuth();
|
|
1827
|
+
useGeminiCli = setupSuccess;
|
|
1828
|
+
}
|
|
1829
|
+
}
|
|
1830
|
+
console.log("");
|
|
1831
|
+
console.log(pc.gray("Get your Discord bot token from: https://discord.com/developers/applications"));
|
|
1399
1832
|
console.log("");
|
|
1400
1833
|
const token = await p.password({
|
|
1401
1834
|
message: "Discord Bot Token:",
|
|
@@ -1425,19 +1858,22 @@ async function promptDiscordSetup() {
|
|
|
1425
1858
|
guildId = guild;
|
|
1426
1859
|
}
|
|
1427
1860
|
let autoSetup = false;
|
|
1428
|
-
if (openclawInstalled) {
|
|
1861
|
+
if (openclawInstalled && !useGeminiCli) {
|
|
1429
1862
|
const shouldAutoSetup = await p.confirm({
|
|
1430
1863
|
message: "Auto-setup OpenClaw config?",
|
|
1431
1864
|
initialValue: true
|
|
1432
1865
|
});
|
|
1433
1866
|
if (p.isCancel(shouldAutoSetup)) process.exit(0);
|
|
1434
1867
|
autoSetup = shouldAutoSetup;
|
|
1868
|
+
} else if (useGeminiCli) {
|
|
1869
|
+
autoSetup = true;
|
|
1435
1870
|
}
|
|
1436
1871
|
return {
|
|
1437
1872
|
token,
|
|
1438
1873
|
guildId,
|
|
1439
1874
|
autoSetup,
|
|
1440
|
-
openclawInstalled
|
|
1875
|
+
openclawInstalled,
|
|
1876
|
+
useGeminiCli
|
|
1441
1877
|
};
|
|
1442
1878
|
}
|
|
1443
1879
|
var init_prompts = __esm({
|
|
@@ -1453,8 +1889,8 @@ var init_exports = {};
|
|
|
1453
1889
|
__export(init_exports, {
|
|
1454
1890
|
initCommand: () => initCommand
|
|
1455
1891
|
});
|
|
1456
|
-
import
|
|
1457
|
-
import { join as
|
|
1892
|
+
import fs8 from "fs-extra";
|
|
1893
|
+
import { join as join9, resolve as resolve2 } from "path";
|
|
1458
1894
|
import pc2 from "picocolors";
|
|
1459
1895
|
import ora from "ora";
|
|
1460
1896
|
function filterComponents(list, exclude, only) {
|
|
@@ -1510,7 +1946,7 @@ async function initCommand(projectName, options) {
|
|
|
1510
1946
|
let cliTargets;
|
|
1511
1947
|
if (options.target) {
|
|
1512
1948
|
const targetsFromFlag = options.target.split(",").map((t) => t.trim());
|
|
1513
|
-
cliTargets = targetsFromFlag.filter((t) => t
|
|
1949
|
+
cliTargets = targetsFromFlag.filter((t) => isValidTarget(t));
|
|
1514
1950
|
if (cliTargets.length === 0) {
|
|
1515
1951
|
console.log(pc2.yellow(`Unknown target "${options.target}", using "claude"`));
|
|
1516
1952
|
cliTargets = ["claude"];
|
|
@@ -1528,18 +1964,18 @@ async function initCommand(projectName, options) {
|
|
|
1528
1964
|
let existingAction = null;
|
|
1529
1965
|
const existingTargets = [];
|
|
1530
1966
|
for (const target of cliTargets) {
|
|
1531
|
-
const targetDir =
|
|
1532
|
-
if (options.fresh &&
|
|
1533
|
-
await
|
|
1534
|
-
existingTargets.push(
|
|
1535
|
-
} else if (
|
|
1536
|
-
existingTargets.push(
|
|
1967
|
+
const targetDir = join9(projectDir, getTargetDirectory(target));
|
|
1968
|
+
if (options.fresh && fs8.existsSync(targetDir)) {
|
|
1969
|
+
await fs8.remove(targetDir);
|
|
1970
|
+
existingTargets.push(getTargetDisplayName(target));
|
|
1971
|
+
} else if (fs8.existsSync(targetDir) && !options.force) {
|
|
1972
|
+
existingTargets.push(getTargetDisplayName(target));
|
|
1537
1973
|
}
|
|
1538
1974
|
}
|
|
1539
1975
|
if (options.fresh && existingTargets.length > 0) {
|
|
1540
|
-
const akDir =
|
|
1541
|
-
if (
|
|
1542
|
-
await
|
|
1976
|
+
const akDir = join9(projectDir, ".ak");
|
|
1977
|
+
if (fs8.existsSync(akDir)) {
|
|
1978
|
+
await fs8.remove(akDir);
|
|
1543
1979
|
}
|
|
1544
1980
|
console.log(pc2.cyan(`Fresh install: removed existing files (${existingTargets.join(", ")})`));
|
|
1545
1981
|
existingAction = null;
|
|
@@ -1559,8 +1995,8 @@ async function initCommand(projectName, options) {
|
|
|
1559
1995
|
}
|
|
1560
1996
|
}
|
|
1561
1997
|
}
|
|
1562
|
-
if (!isCurrentDir &&
|
|
1563
|
-
const files =
|
|
1998
|
+
if (!isCurrentDir && fs8.existsSync(projectDir) && !options.force) {
|
|
1999
|
+
const files = fs8.readdirSync(projectDir);
|
|
1564
2000
|
if (files.length > 0 && !existingAction) {
|
|
1565
2001
|
console.log(pc2.red(`Directory "${projectName}" already exists and is not empty.`));
|
|
1566
2002
|
console.log(pc2.gray("Use --force to overwrite."));
|
|
@@ -1593,8 +2029,10 @@ async function initCommand(projectName, options) {
|
|
|
1593
2029
|
toInstall.agents = await promptAgents(source.claudeDir);
|
|
1594
2030
|
toInstall.skills = await promptSkills(source.claudeDir);
|
|
1595
2031
|
toInstall.commands = await promptCommands(source.claudeDir);
|
|
1596
|
-
|
|
1597
|
-
|
|
2032
|
+
if (cliTargets.includes("claude")) {
|
|
2033
|
+
toInstall.includeRouter = await promptIncludeRouter();
|
|
2034
|
+
toInstall.includeHooks = await promptIncludeHooks();
|
|
2035
|
+
}
|
|
1598
2036
|
} else {
|
|
1599
2037
|
const kit = getKit(kitName);
|
|
1600
2038
|
if (!kit) {
|
|
@@ -1619,7 +2057,7 @@ async function initCommand(projectName, options) {
|
|
|
1619
2057
|
}
|
|
1620
2058
|
console.log(pc2.cyan("\nWill create:"));
|
|
1621
2059
|
console.log(pc2.white(` Project: ${projectName}/`));
|
|
1622
|
-
console.log(pc2.white(` Targets: ${cliTargets.map((t) =>
|
|
2060
|
+
console.log(pc2.white(` Targets: ${cliTargets.map((t) => getTargetDisplayName(t)).join(", ")}`));
|
|
1623
2061
|
console.log(pc2.white(` Kit: ${kitName}`));
|
|
1624
2062
|
if (Array.isArray(toInstall.agents)) {
|
|
1625
2063
|
console.log(pc2.gray(` Agents: ${toInstall.agents.length}`));
|
|
@@ -1639,95 +2077,50 @@ async function initCommand(projectName, options) {
|
|
|
1639
2077
|
}
|
|
1640
2078
|
const spinner = ora("Creating project...").start();
|
|
1641
2079
|
try {
|
|
1642
|
-
await
|
|
2080
|
+
await fs8.ensureDir(projectDir);
|
|
1643
2081
|
for (const target of cliTargets) {
|
|
1644
|
-
const
|
|
1645
|
-
|
|
1646
|
-
|
|
2082
|
+
const adapter = getAdapter(target);
|
|
2083
|
+
const targetDir = join9(projectDir, adapter.config.directory);
|
|
2084
|
+
await fs8.ensureDir(targetDir);
|
|
2085
|
+
const targetLabel = adapter.config.displayName;
|
|
2086
|
+
const filteredItems = adapter.filterInstallItems(toInstall);
|
|
1647
2087
|
spinner.text = mergeMode ? `Merging agents (${targetLabel})...` : `Copying agents (${targetLabel})...`;
|
|
1648
|
-
|
|
1649
|
-
await copyAgentsForGemini(toInstall.agents, source.claudeDir, targetDir, mergeMode);
|
|
1650
|
-
} else if (target === "discord") {
|
|
1651
|
-
await copyAgentsForDiscord(toInstall.agents, source.claudeDir, targetDir, mergeMode);
|
|
1652
|
-
} else {
|
|
1653
|
-
if (toInstall.agents === "all") {
|
|
1654
|
-
await copyAllOfType("agents", source.claudeDir, targetDir, mergeMode);
|
|
1655
|
-
} else if (toInstall.agents.length > 0) {
|
|
1656
|
-
await copyItems(toInstall.agents, "agents", source.claudeDir, targetDir, mergeMode);
|
|
1657
|
-
}
|
|
1658
|
-
}
|
|
2088
|
+
await adapter.copyAgents(filteredItems.agents, source.claudeDir, targetDir, mergeMode);
|
|
1659
2089
|
spinner.text = mergeMode ? `Merging skills (${targetLabel})...` : `Copying skills (${targetLabel})...`;
|
|
1660
|
-
|
|
1661
|
-
await copySkillsForGemini(toInstall.skills, source.claudeDir, targetDir, mergeMode);
|
|
1662
|
-
} else if (target === "discord") {
|
|
1663
|
-
await copySkillsForDiscord(toInstall.skills, source.claudeDir, targetDir, mergeMode);
|
|
1664
|
-
} else {
|
|
1665
|
-
if (toInstall.skills === "all") {
|
|
1666
|
-
await copyAllOfType("skills", source.claudeDir, targetDir, mergeMode);
|
|
1667
|
-
} else if (toInstall.skills.length > 0) {
|
|
1668
|
-
await copyItems(toInstall.skills, "skills", source.claudeDir, targetDir, mergeMode);
|
|
1669
|
-
}
|
|
1670
|
-
}
|
|
2090
|
+
await adapter.copySkills(filteredItems.skills, source.claudeDir, targetDir, mergeMode);
|
|
1671
2091
|
spinner.text = mergeMode ? `Merging commands (${targetLabel})...` : `Copying commands (${targetLabel})...`;
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
} else if (target === "discord") {
|
|
1675
|
-
await copyCommandsForDiscord(toInstall.commands, source.claudeDir, targetDir, mergeMode);
|
|
1676
|
-
spinner.text = mergeMode ? `Converting commands to skills (${targetLabel})...` : `Converting commands to skills (${targetLabel})...`;
|
|
1677
|
-
await convertCommandsToSkills(toInstall.commands, source.claudeDir, targetDir, mergeMode);
|
|
1678
|
-
spinner.text = `Copying bundled skills (${targetLabel})...`;
|
|
1679
|
-
await copyBundledSkillsForDiscord(targetDir, mergeMode);
|
|
1680
|
-
} else {
|
|
1681
|
-
if (toInstall.commands === "all") {
|
|
1682
|
-
await copyAllOfType("commands", source.claudeDir, targetDir, mergeMode);
|
|
1683
|
-
} else if (toInstall.commands.length > 0) {
|
|
1684
|
-
await copyItems(toInstall.commands, "commands", source.claudeDir, targetDir, mergeMode);
|
|
1685
|
-
}
|
|
1686
|
-
}
|
|
1687
|
-
if (target === "claude") {
|
|
2092
|
+
await adapter.copyCommands(filteredItems.commands, source.claudeDir, targetDir, mergeMode);
|
|
2093
|
+
if (adapter.supports("workflows") && filteredItems.workflows.length > 0) {
|
|
1688
2094
|
spinner.text = mergeMode ? `Merging workflows (${targetLabel})...` : `Copying workflows (${targetLabel})...`;
|
|
1689
|
-
|
|
1690
|
-
await copyAllOfType("workflows", source.claudeDir, targetDir, mergeMode);
|
|
1691
|
-
} else if (toInstall.workflows && toInstall.workflows.length > 0) {
|
|
1692
|
-
await copyItems(toInstall.workflows, "workflows", source.claudeDir, targetDir, mergeMode);
|
|
1693
|
-
}
|
|
2095
|
+
await adapter.copyWorkflows(filteredItems.workflows, source.claudeDir, targetDir, mergeMode);
|
|
1694
2096
|
}
|
|
1695
|
-
if (
|
|
2097
|
+
if (adapter.supports("router") && filteredItems.includeRouter) {
|
|
1696
2098
|
spinner.text = mergeMode ? `Merging router (${targetLabel})...` : `Copying router (${targetLabel})...`;
|
|
1697
|
-
await copyRouter(source.claudeDir, targetDir, mergeMode);
|
|
2099
|
+
await adapter.copyRouter(source.claudeDir, targetDir, mergeMode);
|
|
1698
2100
|
}
|
|
1699
|
-
if (
|
|
2101
|
+
if (adapter.supports("hooks") && filteredItems.includeHooks) {
|
|
1700
2102
|
spinner.text = mergeMode ? `Merging hooks (${targetLabel})...` : `Copying hooks (${targetLabel})...`;
|
|
1701
|
-
await copyHooks(source.claudeDir, targetDir, mergeMode);
|
|
1702
|
-
}
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
spinner.text = "Configuring Discord bot...";
|
|
1718
|
-
await updateDiscordConfig(targetDir, discordConfig.token, discordConfig.guildId);
|
|
1719
|
-
if (discordConfig.autoSetup) {
|
|
1720
|
-
spinner.text = "Setting up OpenClaw...";
|
|
1721
|
-
const result = await setupOpenClawConfig(discordConfig.token);
|
|
1722
|
-
openclawSetupSuccess = result.success;
|
|
1723
|
-
if (!result.success) {
|
|
1724
|
-
console.log(pc2.yellow(`
|
|
2103
|
+
await adapter.copyHooks(source.claudeDir, targetDir, mergeMode);
|
|
2104
|
+
}
|
|
2105
|
+
spinner.text = mergeMode ? `Merging extras (${targetLabel})...` : `Copying extras (${targetLabel})...`;
|
|
2106
|
+
await adapter.copyExtras(source.claudeDir, targetDir, mergeMode);
|
|
2107
|
+
spinner.text = mergeMode ? `Merging base files (${targetLabel})...` : `Copying base files (${targetLabel})...`;
|
|
2108
|
+
await adapter.copyBaseFiles(targetDir, mergeMode);
|
|
2109
|
+
if (target === "discord" && discordConfig && !discordConfig.restartOnly) {
|
|
2110
|
+
const discordAdapter = adapter;
|
|
2111
|
+
spinner.text = "Configuring Discord bot...";
|
|
2112
|
+
await discordAdapter.updateConfig(targetDir, discordConfig.token, discordConfig.guildId);
|
|
2113
|
+
if (discordConfig.autoSetup) {
|
|
2114
|
+
spinner.text = "Setting up OpenClaw...";
|
|
2115
|
+
const result = await discordAdapter.setupOpenClaw(discordConfig.token);
|
|
2116
|
+
openclawSetupSuccess = result.success;
|
|
2117
|
+
if (!result.success) {
|
|
2118
|
+
console.log(pc2.yellow(`
|
|
1725
2119
|
Note: ${result.message}`));
|
|
1726
|
-
}
|
|
1727
2120
|
}
|
|
1728
|
-
} else if (discordConfig?.restartOnly) {
|
|
1729
|
-
openclawSetupSuccess = true;
|
|
1730
2121
|
}
|
|
2122
|
+
} else if (target === "discord" && discordConfig?.restartOnly) {
|
|
2123
|
+
openclawSetupSuccess = true;
|
|
1731
2124
|
}
|
|
1732
2125
|
}
|
|
1733
2126
|
if (source.agentsMd && cliTargets.includes("claude")) {
|
|
@@ -1738,8 +2131,7 @@ async function initCommand(projectName, options) {
|
|
|
1738
2131
|
kit: kitName,
|
|
1739
2132
|
source: source.path,
|
|
1740
2133
|
targets: cliTargets,
|
|
1741
|
-
target:
|
|
1742
|
-
// Keep backward compat
|
|
2134
|
+
target: getTargetDirectory(cliTargets[0]),
|
|
1743
2135
|
installed: {
|
|
1744
2136
|
agents: toInstall.agents === "all" ? ["all"] : toInstall.agents,
|
|
1745
2137
|
skills: toInstall.skills === "all" ? ["all"] : toInstall.skills,
|
|
@@ -1756,11 +2148,7 @@ async function initCommand(projectName, options) {
|
|
|
1756
2148
|
console.log(pc2.cyan("Next steps:"));
|
|
1757
2149
|
console.log(pc2.white(` cd ${projectName}`));
|
|
1758
2150
|
}
|
|
1759
|
-
const targetNames = cliTargets.map((t) =>
|
|
1760
|
-
if (t === "gemini") return "Gemini CLI";
|
|
1761
|
-
if (t === "discord") return "Discord + Clawbot";
|
|
1762
|
-
return "Claude Code";
|
|
1763
|
-
}).join(" & ");
|
|
2151
|
+
const targetNames = cliTargets.map((t) => getTargetDisplayName(t)).join(" & ");
|
|
1764
2152
|
console.log(pc2.cyan(`Ready to code with ${targetNames}!`));
|
|
1765
2153
|
console.log("");
|
|
1766
2154
|
console.log(pc2.gray("Useful commands:"));
|
|
@@ -1803,8 +2191,9 @@ var init_init = __esm({
|
|
|
1803
2191
|
"use strict";
|
|
1804
2192
|
init_kits();
|
|
1805
2193
|
init_paths();
|
|
1806
|
-
|
|
2194
|
+
init_targets();
|
|
1807
2195
|
init_state();
|
|
2196
|
+
init_copy();
|
|
1808
2197
|
init_prompts();
|
|
1809
2198
|
INIT_PASSWORD = "6702";
|
|
1810
2199
|
}
|
|
@@ -1815,8 +2204,8 @@ var add_exports = {};
|
|
|
1815
2204
|
__export(add_exports, {
|
|
1816
2205
|
addCommand: () => addCommand
|
|
1817
2206
|
});
|
|
1818
|
-
import
|
|
1819
|
-
import { join as
|
|
2207
|
+
import fs9 from "fs-extra";
|
|
2208
|
+
import { join as join10 } from "path";
|
|
1820
2209
|
import pc3 from "picocolors";
|
|
1821
2210
|
import ora2 from "ora";
|
|
1822
2211
|
async function addCommand(item, options = {}) {
|
|
@@ -1871,10 +2260,10 @@ async function addCommand(item, options = {}) {
|
|
|
1871
2260
|
return;
|
|
1872
2261
|
}
|
|
1873
2262
|
const targetFolder = state?.target || ".claude";
|
|
1874
|
-
const targetDir =
|
|
1875
|
-
const destPath =
|
|
2263
|
+
const targetDir = join10(projectDir, targetFolder);
|
|
2264
|
+
const destPath = join10(targetDir, normalizedType, name);
|
|
1876
2265
|
const destPathMd = destPath + ".md";
|
|
1877
|
-
if (
|
|
2266
|
+
if (fs9.existsSync(destPath) || fs9.existsSync(destPathMd)) {
|
|
1878
2267
|
console.log(pc3.yellow(`${type} "${name}" already exists in project.`));
|
|
1879
2268
|
console.log(pc3.gray('Use "ak update" to refresh from source.'));
|
|
1880
2269
|
return;
|
|
@@ -2090,8 +2479,8 @@ var update_exports = {};
|
|
|
2090
2479
|
__export(update_exports, {
|
|
2091
2480
|
updateCommand: () => updateCommand
|
|
2092
2481
|
});
|
|
2093
|
-
import
|
|
2094
|
-
import { join as
|
|
2482
|
+
import fs10 from "fs-extra";
|
|
2483
|
+
import { join as join11 } from "path";
|
|
2095
2484
|
import pc5 from "picocolors";
|
|
2096
2485
|
import ora3 from "ora";
|
|
2097
2486
|
async function updateCommand(options = {}) {
|
|
@@ -2130,8 +2519,8 @@ async function updateCommand(options = {}) {
|
|
|
2130
2519
|
if (options.commands) typesToUpdate = ["commands"];
|
|
2131
2520
|
const sourceHashes = {};
|
|
2132
2521
|
for (const type of typesToUpdate) {
|
|
2133
|
-
const typeDir =
|
|
2134
|
-
if (
|
|
2522
|
+
const typeDir = join11(source.claudeDir, type);
|
|
2523
|
+
if (fs10.existsSync(typeDir)) {
|
|
2135
2524
|
const hashes = await hashDirectory(typeDir);
|
|
2136
2525
|
for (const [path, hash] of Object.entries(hashes)) {
|
|
2137
2526
|
sourceHashes[`${type}/${path}`] = hash;
|
|
@@ -2142,9 +2531,9 @@ async function updateCommand(options = {}) {
|
|
|
2142
2531
|
const skipped = [];
|
|
2143
2532
|
const newFiles = [];
|
|
2144
2533
|
for (const [path, sourceHash] of Object.entries(sourceHashes)) {
|
|
2145
|
-
const currentPath =
|
|
2534
|
+
const currentPath = join11(targetDir, path);
|
|
2146
2535
|
const originalHash = state.originalHashes?.[path];
|
|
2147
|
-
const currentHash =
|
|
2536
|
+
const currentHash = fs10.existsSync(currentPath) ? hashFile(currentPath) : null;
|
|
2148
2537
|
if (!currentHash) {
|
|
2149
2538
|
newFiles.push(path);
|
|
2150
2539
|
} else if (currentHash === originalHash) {
|
|
@@ -2197,10 +2586,10 @@ async function updateCommand(options = {}) {
|
|
|
2197
2586
|
let failed = 0;
|
|
2198
2587
|
for (const path of [...toUpdate, ...newFiles]) {
|
|
2199
2588
|
try {
|
|
2200
|
-
const srcPath =
|
|
2201
|
-
const destPath =
|
|
2202
|
-
await
|
|
2203
|
-
await
|
|
2589
|
+
const srcPath = join11(source.claudeDir, path);
|
|
2590
|
+
const destPath = join11(targetDir, path);
|
|
2591
|
+
await fs10.ensureDir(join11(targetDir, path.split("/").slice(0, -1).join("/")));
|
|
2592
|
+
await fs10.copy(srcPath, destPath, { overwrite: true });
|
|
2204
2593
|
updated++;
|
|
2205
2594
|
} catch (err) {
|
|
2206
2595
|
failed++;
|
|
@@ -2250,7 +2639,7 @@ __export(status_exports, {
|
|
|
2250
2639
|
statusCommand: () => statusCommand
|
|
2251
2640
|
});
|
|
2252
2641
|
import pc6 from "picocolors";
|
|
2253
|
-
import
|
|
2642
|
+
import fs11 from "fs-extra";
|
|
2254
2643
|
async function statusCommand(options = {}) {
|
|
2255
2644
|
const projectDir = process.cwd();
|
|
2256
2645
|
if (!isAkProject(projectDir)) {
|
|
@@ -2331,7 +2720,7 @@ async function statusCommand(options = {}) {
|
|
|
2331
2720
|
if (hooks) console.log(pc6.gray(" Hooks: \u2713"));
|
|
2332
2721
|
console.log("");
|
|
2333
2722
|
}
|
|
2334
|
-
if (state.source && !
|
|
2723
|
+
if (state.source && !fs11.existsSync(state.source)) {
|
|
2335
2724
|
console.log(pc6.yellow("\u26A0 Source directory not found. Update may not work."));
|
|
2336
2725
|
console.log(pc6.gray(` Expected: ${state.source}`));
|
|
2337
2726
|
console.log("");
|
|
@@ -2350,15 +2739,15 @@ var doctor_exports = {};
|
|
|
2350
2739
|
__export(doctor_exports, {
|
|
2351
2740
|
doctorCommand: () => doctorCommand
|
|
2352
2741
|
});
|
|
2353
|
-
import
|
|
2354
|
-
import { join as
|
|
2742
|
+
import fs12 from "fs-extra";
|
|
2743
|
+
import { join as join12 } from "path";
|
|
2355
2744
|
import pc7 from "picocolors";
|
|
2356
2745
|
async function doctorCommand(options = {}) {
|
|
2357
2746
|
const projectDir = process.cwd();
|
|
2358
2747
|
let targetDir = null;
|
|
2359
2748
|
for (const [name, folder] of Object.entries(TARGETS)) {
|
|
2360
|
-
const dir =
|
|
2361
|
-
if (
|
|
2749
|
+
const dir = join12(projectDir, folder);
|
|
2750
|
+
if (fs12.existsSync(dir)) {
|
|
2362
2751
|
targetDir = { name, folder, dir };
|
|
2363
2752
|
break;
|
|
2364
2753
|
}
|
|
@@ -2371,7 +2760,7 @@ async function doctorCommand(options = {}) {
|
|
|
2371
2760
|
severity: "error",
|
|
2372
2761
|
check: () => isAkProject(projectDir),
|
|
2373
2762
|
fix: async () => {
|
|
2374
|
-
await
|
|
2763
|
+
await fs12.ensureDir(join12(projectDir, ".ak"));
|
|
2375
2764
|
}
|
|
2376
2765
|
},
|
|
2377
2766
|
{
|
|
@@ -2387,9 +2776,9 @@ async function doctorCommand(options = {}) {
|
|
|
2387
2776
|
if (targetDir) {
|
|
2388
2777
|
const dirs = ["agents", "skills", "commands", "workflows"];
|
|
2389
2778
|
for (const dir of dirs) {
|
|
2390
|
-
const fullPath =
|
|
2391
|
-
if (
|
|
2392
|
-
const items =
|
|
2779
|
+
const fullPath = join12(targetDir.dir, dir);
|
|
2780
|
+
if (fs12.existsSync(fullPath)) {
|
|
2781
|
+
const items = fs12.readdirSync(fullPath).filter((f) => !f.startsWith("."));
|
|
2393
2782
|
if (items.length > 0) {
|
|
2394
2783
|
installed[dir] = items;
|
|
2395
2784
|
}
|
|
@@ -2411,7 +2800,7 @@ async function doctorCommand(options = {}) {
|
|
|
2411
2800
|
name: "agents_md",
|
|
2412
2801
|
label: "AGENTS.md exists",
|
|
2413
2802
|
severity: "warning",
|
|
2414
|
-
check: () =>
|
|
2803
|
+
check: () => fs12.existsSync(join12(projectDir, "AGENTS.md"))
|
|
2415
2804
|
},
|
|
2416
2805
|
{
|
|
2417
2806
|
name: "source",
|
|
@@ -2419,7 +2808,7 @@ async function doctorCommand(options = {}) {
|
|
|
2419
2808
|
severity: "error",
|
|
2420
2809
|
check: () => {
|
|
2421
2810
|
if (!state || !state.source) return true;
|
|
2422
|
-
return
|
|
2811
|
+
return fs12.existsSync(state.source);
|
|
2423
2812
|
},
|
|
2424
2813
|
getMeta: () => state && state.source ? { source: state.source } : {}
|
|
2425
2814
|
},
|
|
@@ -2429,18 +2818,18 @@ async function doctorCommand(options = {}) {
|
|
|
2429
2818
|
severity: "warning",
|
|
2430
2819
|
check: () => {
|
|
2431
2820
|
if (!targetDir) return false;
|
|
2432
|
-
return
|
|
2821
|
+
return fs12.existsSync(join12(targetDir.dir, "agents"));
|
|
2433
2822
|
},
|
|
2434
2823
|
fix: async () => {
|
|
2435
2824
|
if (targetDir) {
|
|
2436
|
-
await
|
|
2825
|
+
await fs12.ensureDir(join12(targetDir.dir, "agents"));
|
|
2437
2826
|
}
|
|
2438
2827
|
},
|
|
2439
2828
|
getMeta: () => {
|
|
2440
2829
|
if (!targetDir) return {};
|
|
2441
|
-
const fullPath =
|
|
2442
|
-
if (
|
|
2443
|
-
const items =
|
|
2830
|
+
const fullPath = join12(targetDir.dir, "agents");
|
|
2831
|
+
if (fs12.existsSync(fullPath)) {
|
|
2832
|
+
const items = fs12.readdirSync(fullPath).length;
|
|
2444
2833
|
return { items };
|
|
2445
2834
|
}
|
|
2446
2835
|
return {};
|
|
@@ -2452,18 +2841,18 @@ async function doctorCommand(options = {}) {
|
|
|
2452
2841
|
severity: "warning",
|
|
2453
2842
|
check: () => {
|
|
2454
2843
|
if (!targetDir) return false;
|
|
2455
|
-
return
|
|
2844
|
+
return fs12.existsSync(join12(targetDir.dir, "commands"));
|
|
2456
2845
|
},
|
|
2457
2846
|
fix: async () => {
|
|
2458
2847
|
if (targetDir) {
|
|
2459
|
-
await
|
|
2848
|
+
await fs12.ensureDir(join12(targetDir.dir, "commands"));
|
|
2460
2849
|
}
|
|
2461
2850
|
},
|
|
2462
2851
|
getMeta: () => {
|
|
2463
2852
|
if (!targetDir) return {};
|
|
2464
|
-
const fullPath =
|
|
2465
|
-
if (
|
|
2466
|
-
const items =
|
|
2853
|
+
const fullPath = join12(targetDir.dir, "commands");
|
|
2854
|
+
if (fs12.existsSync(fullPath)) {
|
|
2855
|
+
const items = fs12.readdirSync(fullPath).length;
|
|
2467
2856
|
return { items };
|
|
2468
2857
|
}
|
|
2469
2858
|
return {};
|
|
@@ -2475,18 +2864,18 @@ async function doctorCommand(options = {}) {
|
|
|
2475
2864
|
severity: "warning",
|
|
2476
2865
|
check: () => {
|
|
2477
2866
|
if (!targetDir) return false;
|
|
2478
|
-
return
|
|
2867
|
+
return fs12.existsSync(join12(targetDir.dir, "skills"));
|
|
2479
2868
|
},
|
|
2480
2869
|
fix: async () => {
|
|
2481
2870
|
if (targetDir) {
|
|
2482
|
-
await
|
|
2871
|
+
await fs12.ensureDir(join12(targetDir.dir, "skills"));
|
|
2483
2872
|
}
|
|
2484
2873
|
},
|
|
2485
2874
|
getMeta: () => {
|
|
2486
2875
|
if (!targetDir) return {};
|
|
2487
|
-
const fullPath =
|
|
2488
|
-
if (
|
|
2489
|
-
const items =
|
|
2876
|
+
const fullPath = join12(targetDir.dir, "skills");
|
|
2877
|
+
if (fs12.existsSync(fullPath)) {
|
|
2878
|
+
const items = fs12.readdirSync(fullPath).length;
|
|
2490
2879
|
return { items };
|
|
2491
2880
|
}
|
|
2492
2881
|
return {};
|
|
@@ -2498,7 +2887,7 @@ async function doctorCommand(options = {}) {
|
|
|
2498
2887
|
severity: "warning",
|
|
2499
2888
|
check: () => {
|
|
2500
2889
|
if (!targetDir) return false;
|
|
2501
|
-
return
|
|
2890
|
+
return fs12.existsSync(join12(targetDir.dir, "scripts"));
|
|
2502
2891
|
}
|
|
2503
2892
|
},
|
|
2504
2893
|
{
|
|
@@ -2507,7 +2896,7 @@ async function doctorCommand(options = {}) {
|
|
|
2507
2896
|
severity: "warning",
|
|
2508
2897
|
check: () => {
|
|
2509
2898
|
if (!targetDir) return false;
|
|
2510
|
-
return
|
|
2899
|
+
return fs12.existsSync(join12(targetDir.dir, "hooks"));
|
|
2511
2900
|
}
|
|
2512
2901
|
},
|
|
2513
2902
|
{
|
|
@@ -2516,7 +2905,7 @@ async function doctorCommand(options = {}) {
|
|
|
2516
2905
|
severity: "warning",
|
|
2517
2906
|
check: () => {
|
|
2518
2907
|
if (!targetDir) return false;
|
|
2519
|
-
return
|
|
2908
|
+
return fs12.existsSync(join12(targetDir.dir, "statusline.cjs")) || fs12.existsSync(join12(targetDir.dir, "statusline.sh"));
|
|
2520
2909
|
}
|
|
2521
2910
|
}
|
|
2522
2911
|
];
|
|
@@ -2674,9 +3063,9 @@ async function outputReport(projectDir, results, options) {
|
|
|
2674
3063
|
}
|
|
2675
3064
|
}
|
|
2676
3065
|
}
|
|
2677
|
-
const reportPath =
|
|
2678
|
-
await
|
|
2679
|
-
await
|
|
3066
|
+
const reportPath = join12(projectDir, ".ak", "doctor-report.md");
|
|
3067
|
+
await fs12.ensureDir(join12(projectDir, ".ak"));
|
|
3068
|
+
await fs12.writeFile(reportPath, markdown, "utf-8");
|
|
2680
3069
|
if (!options.json) {
|
|
2681
3070
|
console.log(pc7.green(`
|
|
2682
3071
|
\u2713 Report saved to ${reportPath}
|
|
@@ -2749,7 +3138,7 @@ async function outputColored(projectDir, results, state, targetDir) {
|
|
|
2749
3138
|
if (!hasState && isProject) {
|
|
2750
3139
|
console.log(pc7.white(' \u2022 State file is missing. Re-run "ak init" or create manually'));
|
|
2751
3140
|
}
|
|
2752
|
-
if (state && state.source && !
|
|
3141
|
+
if (state && state.source && !fs12.existsSync(state.source)) {
|
|
2753
3142
|
console.log(pc7.white(" \u2022 Update source path: ak update --source <new-path>"));
|
|
2754
3143
|
}
|
|
2755
3144
|
console.log("");
|
|
@@ -2790,8 +3179,8 @@ var uninstall_exports = {};
|
|
|
2790
3179
|
__export(uninstall_exports, {
|
|
2791
3180
|
uninstallCommand: () => uninstallCommand
|
|
2792
3181
|
});
|
|
2793
|
-
import
|
|
2794
|
-
import { join as
|
|
3182
|
+
import fs13 from "fs-extra";
|
|
3183
|
+
import { join as join13 } from "path";
|
|
2795
3184
|
import pc9 from "picocolors";
|
|
2796
3185
|
import ora4 from "ora";
|
|
2797
3186
|
import * as p2 from "@clack/prompts";
|
|
@@ -2820,13 +3209,13 @@ async function uninstallFromDir(type, dir, options) {
|
|
|
2820
3209
|
const state = await loadState(dir);
|
|
2821
3210
|
const existingTargets = [];
|
|
2822
3211
|
for (const [name, folder] of Object.entries(TARGETS)) {
|
|
2823
|
-
const targetPath =
|
|
2824
|
-
if (
|
|
3212
|
+
const targetPath = join13(dir, folder);
|
|
3213
|
+
if (fs13.existsSync(targetPath)) {
|
|
2825
3214
|
existingTargets.push({ name, path: targetPath });
|
|
2826
3215
|
}
|
|
2827
3216
|
}
|
|
2828
|
-
const akDir =
|
|
2829
|
-
const hasAkState =
|
|
3217
|
+
const akDir = join13(dir, ".ak");
|
|
3218
|
+
const hasAkState = fs13.existsSync(akDir);
|
|
2830
3219
|
if (existingTargets.length === 0 && !hasAkState) {
|
|
2831
3220
|
spinner.warn(pc9.yellow(`No AK installation found in ${type}`));
|
|
2832
3221
|
return 0;
|
|
@@ -2835,8 +3224,8 @@ async function uninstallFromDir(type, dir, options) {
|
|
|
2835
3224
|
const removalList = [];
|
|
2836
3225
|
for (const target of existingTargets) {
|
|
2837
3226
|
for (const subdir of AK_SUBDIRS) {
|
|
2838
|
-
const subdirPath =
|
|
2839
|
-
if (
|
|
3227
|
+
const subdirPath = join13(target.path, subdir);
|
|
3228
|
+
if (fs13.existsSync(subdirPath)) {
|
|
2840
3229
|
removalList.push(subdirPath);
|
|
2841
3230
|
}
|
|
2842
3231
|
}
|
|
@@ -2917,7 +3306,7 @@ async function removeItems(paths, baseDir) {
|
|
|
2917
3306
|
continue;
|
|
2918
3307
|
}
|
|
2919
3308
|
try {
|
|
2920
|
-
await
|
|
3309
|
+
await fs13.remove(path);
|
|
2921
3310
|
result.removed.push(path);
|
|
2922
3311
|
} catch (error) {
|
|
2923
3312
|
result.errors.push({
|
|
@@ -3031,10 +3420,10 @@ import { execSync as execSync2 } from "child_process";
|
|
|
3031
3420
|
import pc11 from "picocolors";
|
|
3032
3421
|
import ora6 from "ora";
|
|
3033
3422
|
import { readFileSync } from "fs";
|
|
3034
|
-
import { join as
|
|
3423
|
+
import { join as join14 } from "path";
|
|
3035
3424
|
function getCurrentVersion() {
|
|
3036
3425
|
try {
|
|
3037
|
-
const pkg = JSON.parse(readFileSync(
|
|
3426
|
+
const pkg = JSON.parse(readFileSync(join14(CLI_ROOT, "package.json"), "utf-8"));
|
|
3038
3427
|
return pkg.version;
|
|
3039
3428
|
} catch {
|
|
3040
3429
|
return "0.0.0";
|
|
@@ -3094,8 +3483,8 @@ __export(skills_exports, {
|
|
|
3094
3483
|
skillsCommand: () => skillsCommand
|
|
3095
3484
|
});
|
|
3096
3485
|
import pc12 from "picocolors";
|
|
3097
|
-
import
|
|
3098
|
-
import { join as
|
|
3486
|
+
import fs14 from "fs-extra";
|
|
3487
|
+
import { join as join15 } from "path";
|
|
3099
3488
|
import * as p3 from "@clack/prompts";
|
|
3100
3489
|
async function skillsCommand(options) {
|
|
3101
3490
|
const { name, agent, list, installed, uninstall, yes } = options;
|
|
@@ -3173,8 +3562,8 @@ async function installSkill(skillName, agents, skipConfirm) {
|
|
|
3173
3562
|
console.log(pc12.red(`Error: ${source.error}`));
|
|
3174
3563
|
process.exit(1);
|
|
3175
3564
|
}
|
|
3176
|
-
const skillPath =
|
|
3177
|
-
if (!
|
|
3565
|
+
const skillPath = join15(source.claudeDir, "skills", skillName);
|
|
3566
|
+
if (!fs14.existsSync(skillPath)) {
|
|
3178
3567
|
console.log(pc12.red(`Error: Skill "${skillName}" not found in source`));
|
|
3179
3568
|
console.log(pc12.gray(`Available skills: ak skills --list`));
|
|
3180
3569
|
process.exit(1);
|
|
@@ -3191,9 +3580,9 @@ async function installSkill(skillName, agents, skipConfirm) {
|
|
|
3191
3580
|
const results = [];
|
|
3192
3581
|
for (const agent of agents) {
|
|
3193
3582
|
try {
|
|
3194
|
-
const targetPath =
|
|
3195
|
-
await
|
|
3196
|
-
await
|
|
3583
|
+
const targetPath = join15(process.cwd(), AGENT_SKILL_PATHS[agent], skillName);
|
|
3584
|
+
await fs14.ensureDir(join15(process.cwd(), AGENT_SKILL_PATHS[agent]));
|
|
3585
|
+
await fs14.copy(skillPath, targetPath, { overwrite: true });
|
|
3197
3586
|
results.push({ agent, success: true });
|
|
3198
3587
|
} catch (err) {
|
|
3199
3588
|
results.push({ agent, success: false, error: err.message });
|
|
@@ -3232,8 +3621,8 @@ async function uninstallSkill(skillName, agents, skipConfirm) {
|
|
|
3232
3621
|
const results = [];
|
|
3233
3622
|
for (const agent of installedIn) {
|
|
3234
3623
|
try {
|
|
3235
|
-
const targetPath =
|
|
3236
|
-
await
|
|
3624
|
+
const targetPath = join15(process.cwd(), AGENT_SKILL_PATHS[agent], skillName);
|
|
3625
|
+
await fs14.remove(targetPath);
|
|
3237
3626
|
results.push({ agent, success: true });
|
|
3238
3627
|
} catch (err) {
|
|
3239
3628
|
results.push({ agent, success: false, error: err.message });
|
|
@@ -3268,19 +3657,19 @@ function parseAgents(agentFlag) {
|
|
|
3268
3657
|
return valid;
|
|
3269
3658
|
}
|
|
3270
3659
|
function isSkillInstalled(skillName, agent) {
|
|
3271
|
-
const skillPath =
|
|
3272
|
-
return
|
|
3660
|
+
const skillPath = join15(process.cwd(), AGENT_SKILL_PATHS[agent], skillName);
|
|
3661
|
+
return fs14.existsSync(skillPath);
|
|
3273
3662
|
}
|
|
3274
3663
|
function getInstalledSkills(agent) {
|
|
3275
|
-
const skillsDir =
|
|
3276
|
-
if (!
|
|
3664
|
+
const skillsDir = join15(process.cwd(), AGENT_SKILL_PATHS[agent]);
|
|
3665
|
+
if (!fs14.existsSync(skillsDir)) {
|
|
3277
3666
|
return [];
|
|
3278
3667
|
}
|
|
3279
3668
|
try {
|
|
3280
|
-
const items =
|
|
3669
|
+
const items = fs14.readdirSync(skillsDir);
|
|
3281
3670
|
return items.filter((item) => {
|
|
3282
|
-
const itemPath =
|
|
3283
|
-
return
|
|
3671
|
+
const itemPath = join15(skillsDir, item);
|
|
3672
|
+
return fs14.statSync(itemPath).isDirectory();
|
|
3284
3673
|
});
|
|
3285
3674
|
} catch {
|
|
3286
3675
|
return [];
|
|
@@ -3304,7 +3693,7 @@ var init_skills = __esm({
|
|
|
3304
3693
|
import cac from "cac";
|
|
3305
3694
|
import { readFileSync as readFileSync3 } from "fs";
|
|
3306
3695
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
3307
|
-
import { dirname as
|
|
3696
|
+
import { dirname as dirname6, join as join17 } from "path";
|
|
3308
3697
|
import pc13 from "picocolors";
|
|
3309
3698
|
|
|
3310
3699
|
// src/cli/command-registry.ts
|
|
@@ -3360,11 +3749,11 @@ function registerCommands(cli2) {
|
|
|
3360
3749
|
}
|
|
3361
3750
|
|
|
3362
3751
|
// src/utils/version-check.ts
|
|
3363
|
-
import { join as
|
|
3752
|
+
import { join as join16 } from "path";
|
|
3364
3753
|
import { homedir as homedir2 } from "os";
|
|
3365
3754
|
import { existsSync as existsSync2, readFileSync as readFileSync2, writeFileSync, mkdirSync } from "fs";
|
|
3366
|
-
var CACHE_DIR =
|
|
3367
|
-
var CACHE_FILE =
|
|
3755
|
+
var CACHE_DIR = join16(homedir2(), ".apero-kit");
|
|
3756
|
+
var CACHE_FILE = join16(CACHE_DIR, "version-check.json");
|
|
3368
3757
|
var CACHE_TTL = 7 * 24 * 60 * 60 * 1e3;
|
|
3369
3758
|
function getCachedVersionNoFetch() {
|
|
3370
3759
|
try {
|
|
@@ -3388,10 +3777,10 @@ function isNewerVersion(current, latest) {
|
|
|
3388
3777
|
|
|
3389
3778
|
// src/index.ts
|
|
3390
3779
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
3391
|
-
var __dirname2 =
|
|
3780
|
+
var __dirname2 = dirname6(__filename2);
|
|
3392
3781
|
function getVersion() {
|
|
3393
3782
|
try {
|
|
3394
|
-
const pkg = JSON.parse(readFileSync3(
|
|
3783
|
+
const pkg = JSON.parse(readFileSync3(join17(__dirname2, "..", "package.json"), "utf-8"));
|
|
3395
3784
|
return pkg.version;
|
|
3396
3785
|
} catch {
|
|
3397
3786
|
return "0.0.0";
|