@eve-horizon/cli 0.2.17 → 0.2.19
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/README.md +1 -0
- package/dist/index.js +129 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -111,6 +111,7 @@ eve org update org_xxx --name "New Name"
|
|
|
111
111
|
### Projects
|
|
112
112
|
|
|
113
113
|
```bash
|
|
114
|
+
eve project ensure --name my-project --slug MyProj
|
|
114
115
|
eve project ensure --name my-project --slug MyProj --repo-url https://github.com/org/repo
|
|
115
116
|
eve project list
|
|
116
117
|
eve project get proj_xxx
|
package/dist/index.js
CHANGED
|
@@ -48850,16 +48850,17 @@ var HELP = {
|
|
|
48850
48850
|
},
|
|
48851
48851
|
ensure: {
|
|
48852
48852
|
description: "Create project if it doesn't exist, or return existing",
|
|
48853
|
-
usage: "eve project ensure --name <name> --repo-url <url> [--org <org_id>] [--branch <branch>] [--slug <slug>]",
|
|
48853
|
+
usage: "eve project ensure --name <name> [--repo-url <url>] [--org <org_id>] [--branch <branch>] [--slug <slug>]",
|
|
48854
48854
|
options: [
|
|
48855
48855
|
"--name <name> Project name (required)",
|
|
48856
|
-
"--repo-url <url> Git repository URL (
|
|
48856
|
+
"--repo-url <url> Git repository URL (optional, can be set later)",
|
|
48857
48857
|
"--org <id> Organization ID",
|
|
48858
48858
|
"--branch <branch> Default branch (default: main)",
|
|
48859
48859
|
"--slug <slug> Short memorable slug (4-8 chars, e.g., MyProj)",
|
|
48860
48860
|
"--force Re-clone repo even if project exists"
|
|
48861
48861
|
],
|
|
48862
48862
|
examples: [
|
|
48863
|
+
"eve project ensure --name my-app --slug MyApp",
|
|
48863
48864
|
"eve project ensure --name my-app --slug MyApp --repo-url https://github.com/org/repo",
|
|
48864
48865
|
"eve project ensure --name my-app --repo-url file:///path/to/repo --force # dev/test only"
|
|
48865
48866
|
]
|
|
@@ -50901,7 +50902,7 @@ function showMainHelp() {
|
|
|
50901
50902
|
console.log("");
|
|
50902
50903
|
console.log("Examples:");
|
|
50903
50904
|
console.log(' eve org ensure "My Company"');
|
|
50904
|
-
console.log(" eve project ensure --name my-app --slug MyApp
|
|
50905
|
+
console.log(" eve project ensure --name my-app --slug MyApp");
|
|
50905
50906
|
console.log(' eve job create --description "Fix the bug in auth.ts"');
|
|
50906
50907
|
console.log(" eve job list --phase ready");
|
|
50907
50908
|
console.log(" eve job show MyProj-abc123");
|
|
@@ -51300,18 +51301,19 @@ async function handleProject(subcommand, positionals, flags, context2) {
|
|
|
51300
51301
|
switch (subcommand) {
|
|
51301
51302
|
case "ensure": {
|
|
51302
51303
|
const name = typeof flags.name === "string" ? flags.name : "";
|
|
51303
|
-
const repoUrl = typeof flags["repo-url"] === "string" ? flags["repo-url"] :
|
|
51304
|
+
const repoUrl = typeof flags["repo-url"] === "string" ? flags["repo-url"] : void 0;
|
|
51304
51305
|
const branch = typeof flags.branch === "string" ? flags.branch : "main";
|
|
51305
51306
|
const slug = typeof flags.slug === "string" ? flags.slug : void 0;
|
|
51306
51307
|
const orgIdRaw = typeof flags.org === "string" ? flags.org : context2.orgId;
|
|
51307
51308
|
const force = toBoolean(flags.force) ?? false;
|
|
51308
|
-
if (!name
|
|
51309
|
-
throw new Error("Usage: eve project ensure --name <name> --repo-url <url> [--branch <branch>] [--slug <slug>]");
|
|
51309
|
+
if (!name) {
|
|
51310
|
+
throw new Error("Usage: eve project ensure --name <name> [--repo-url <url>] [--branch <branch>] [--slug <slug>]");
|
|
51310
51311
|
}
|
|
51311
51312
|
if (!orgIdRaw) {
|
|
51312
51313
|
throw new Error("Missing org id. Provide --org or set a profile default.");
|
|
51313
51314
|
}
|
|
51314
|
-
const body = { org_id: orgIdRaw, name,
|
|
51315
|
+
const body = { org_id: orgIdRaw, name, branch, force };
|
|
51316
|
+
if (repoUrl) body.repo_url = repoUrl;
|
|
51315
51317
|
if (slug) body.slug = slug;
|
|
51316
51318
|
const project = await requestJson(context2, "/projects/ensure", {
|
|
51317
51319
|
method: "POST",
|
|
@@ -56190,6 +56192,7 @@ var RepoUrlSchema = external_exports.string().refine((value) => {
|
|
|
56190
56192
|
return false;
|
|
56191
56193
|
}
|
|
56192
56194
|
}, "repo_url must be an http(s), file://, or SSH git URL");
|
|
56195
|
+
var RepoUrlOrUnsetSchema = external_exports.union([RepoUrlSchema, external_exports.literal("")]);
|
|
56193
56196
|
var SlugSchema = external_exports.string().regex(/^[A-Za-z][A-Za-z0-9]{3,7}$/, "slug must be 4-8 alphanumeric characters starting with a letter");
|
|
56194
56197
|
var CreateProjectRequestSchema = external_exports.object({
|
|
56195
56198
|
org_id: external_exports.string().regex(/^org_[a-zA-Z0-9]+$/, "Invalid org_id format"),
|
|
@@ -56200,6 +56203,7 @@ var CreateProjectRequestSchema = external_exports.object({
|
|
|
56200
56203
|
branch: external_exports.string().min(1).default("main")
|
|
56201
56204
|
});
|
|
56202
56205
|
var EnsureProjectRequestSchema = CreateProjectRequestSchema.extend({
|
|
56206
|
+
repo_url: RepoUrlSchema.optional(),
|
|
56203
56207
|
force: external_exports.boolean().optional()
|
|
56204
56208
|
});
|
|
56205
56209
|
var UpdateProjectRequestSchema = external_exports.object({
|
|
@@ -56213,7 +56217,7 @@ var ProjectResponseSchema = external_exports.object({
|
|
|
56213
56217
|
org_id: external_exports.string(),
|
|
56214
56218
|
name: external_exports.string(),
|
|
56215
56219
|
slug: external_exports.string(),
|
|
56216
|
-
repo_url:
|
|
56220
|
+
repo_url: RepoUrlOrUnsetSchema,
|
|
56217
56221
|
branch: external_exports.string(),
|
|
56218
56222
|
deleted: external_exports.boolean(),
|
|
56219
56223
|
created_at: external_exports.string(),
|
|
@@ -68055,6 +68059,8 @@ function padRight5(str, width) {
|
|
|
68055
68059
|
var fs2 = __toESM(require("node:fs"));
|
|
68056
68060
|
var path4 = __toESM(require("node:path"));
|
|
68057
68061
|
var import_node_child_process7 = require("node:child_process");
|
|
68062
|
+
var UNIVERSAL_SKILLS_DIR = path4.join(".agents", "skills");
|
|
68063
|
+
var PRIVATE_SKILLS_DIRNAME = "private-skills";
|
|
68058
68064
|
async function handleSkills(subcommand, positionals, flags) {
|
|
68059
68065
|
switch (subcommand) {
|
|
68060
68066
|
case "install":
|
|
@@ -68070,7 +68076,7 @@ async function handleInstall(positionals, flags) {
|
|
|
68070
68076
|
const projectRoot = process.cwd();
|
|
68071
68077
|
const skillsBin = resolveSkillsBinary();
|
|
68072
68078
|
const manifestPath = path4.join(projectRoot, "skills.txt");
|
|
68073
|
-
const skillsDir = path4.join(projectRoot,
|
|
68079
|
+
const skillsDir = path4.join(projectRoot, UNIVERSAL_SKILLS_DIR);
|
|
68074
68080
|
const source = positionals[0];
|
|
68075
68081
|
if (source) {
|
|
68076
68082
|
const parsed = parseSkillSource(source);
|
|
@@ -68102,10 +68108,32 @@ async function handleInstall(positionals, flags) {
|
|
|
68102
68108
|
}
|
|
68103
68109
|
function installSkill(skillsBin, skill, projectRoot) {
|
|
68104
68110
|
console.log(` Installing: ${skill.source} (${skill.type})`);
|
|
68111
|
+
const localDir = resolveLocalDirIfExists(skill, projectRoot);
|
|
68112
|
+
const wantsExcludePrivate = localDir !== null && fs2.existsSync(path4.join(localDir, PRIVATE_SKILLS_DIRNAME)) && !sourcePathExplicitlyTargetsPrivate(skill.source);
|
|
68105
68113
|
try {
|
|
68106
68114
|
const agents = ["claude-code", "codex", "gemini-cli"];
|
|
68115
|
+
if (wantsExcludePrivate && localDir) {
|
|
68116
|
+
const skillDirs = findSkillDirs(localDir, { fullDepth: true, excludePrivate: true });
|
|
68117
|
+
if (skillDirs.length === 0) {
|
|
68118
|
+
console.log(` No skills found under ${skill.source} (after excluding ${PRIVATE_SKILLS_DIRNAME}/)`);
|
|
68119
|
+
return;
|
|
68120
|
+
}
|
|
68121
|
+
console.log(` Installing ${skillDirs.length} public skill(s) (excluding ${PRIVATE_SKILLS_DIRNAME}/)...`);
|
|
68122
|
+
for (const dir of skillDirs) {
|
|
68123
|
+
const rel = path4.relative(projectRoot, dir);
|
|
68124
|
+
const installSource = rel.startsWith(".") ? rel : `./${rel}`;
|
|
68125
|
+
for (const agent of agents) {
|
|
68126
|
+
(0, import_node_child_process7.execSync)(`${skillsBin} add ${JSON.stringify(installSource)} -a ${agent} -s '*' -y --full-depth`, {
|
|
68127
|
+
cwd: projectRoot,
|
|
68128
|
+
stdio: "inherit",
|
|
68129
|
+
timeout: 12e4
|
|
68130
|
+
});
|
|
68131
|
+
}
|
|
68132
|
+
}
|
|
68133
|
+
return;
|
|
68134
|
+
}
|
|
68107
68135
|
for (const agent of agents) {
|
|
68108
|
-
(0, import_node_child_process7.execSync)(`${skillsBin} add ${JSON.stringify(skill.source)} -a ${agent} -s '*' -y`, {
|
|
68136
|
+
(0, import_node_child_process7.execSync)(`${skillsBin} add ${JSON.stringify(skill.source)} -a ${agent} -s '*' -y --full-depth`, {
|
|
68109
68137
|
cwd: projectRoot,
|
|
68110
68138
|
stdio: "inherit",
|
|
68111
68139
|
timeout: 12e4
|
|
@@ -68173,7 +68201,7 @@ function expandGlobPattern(pattern, basePath) {
|
|
|
68173
68201
|
console.warn(`Warning: Glob pattern base directory not found: ${searchRoot}`);
|
|
68174
68202
|
return sources;
|
|
68175
68203
|
}
|
|
68176
|
-
const
|
|
68204
|
+
const findSkillDirs2 = (dir, depth) => {
|
|
68177
68205
|
try {
|
|
68178
68206
|
const entries = fs2.readdirSync(dir, { withFileTypes: true });
|
|
68179
68207
|
for (const entry of entries) {
|
|
@@ -68194,14 +68222,14 @@ function expandGlobPattern(pattern, basePath) {
|
|
|
68194
68222
|
});
|
|
68195
68223
|
}
|
|
68196
68224
|
if (isRecursive || depth === 0) {
|
|
68197
|
-
|
|
68225
|
+
findSkillDirs2(fullPath, depth + 1);
|
|
68198
68226
|
}
|
|
68199
68227
|
}
|
|
68200
68228
|
} catch (err) {
|
|
68201
68229
|
console.warn(`Warning: Error reading directory ${dir}:`, err);
|
|
68202
68230
|
}
|
|
68203
68231
|
};
|
|
68204
|
-
|
|
68232
|
+
findSkillDirs2(searchRoot, 0);
|
|
68205
68233
|
return sources;
|
|
68206
68234
|
}
|
|
68207
68235
|
function parseSkillsManifest(manifestPath) {
|
|
@@ -68276,7 +68304,7 @@ function getInstalledSkills(skillsDir) {
|
|
|
68276
68304
|
return installed;
|
|
68277
68305
|
}
|
|
68278
68306
|
function ensureSkillsSymlink(projectRoot) {
|
|
68279
|
-
const agentSkills = path4.join(projectRoot,
|
|
68307
|
+
const agentSkills = path4.join(projectRoot, UNIVERSAL_SKILLS_DIR);
|
|
68280
68308
|
const claudeDir = path4.join(projectRoot, ".claude");
|
|
68281
68309
|
const claudeSkills = path4.join(claudeDir, "skills");
|
|
68282
68310
|
if (!fs2.existsSync(agentSkills)) {
|
|
@@ -68285,11 +68313,27 @@ function ensureSkillsSymlink(projectRoot) {
|
|
|
68285
68313
|
if (!fs2.existsSync(claudeDir)) {
|
|
68286
68314
|
fs2.mkdirSync(claudeDir, { recursive: true });
|
|
68287
68315
|
}
|
|
68316
|
+
if (fs2.existsSync(claudeSkills) && !fs2.lstatSync(claudeSkills).isSymbolicLink()) {
|
|
68317
|
+
try {
|
|
68318
|
+
const claudeStat = fs2.lstatSync(claudeSkills);
|
|
68319
|
+
if (claudeStat.isDirectory()) {
|
|
68320
|
+
const entries = fs2.readdirSync(agentSkills, { withFileTypes: true });
|
|
68321
|
+
for (const entry of entries) {
|
|
68322
|
+
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
68323
|
+
const dst = path4.join(claudeSkills, entry.name);
|
|
68324
|
+
if (fs2.existsSync(dst)) continue;
|
|
68325
|
+
fs2.symlinkSync(path4.join("..", "..", UNIVERSAL_SKILLS_DIR, entry.name), dst);
|
|
68326
|
+
}
|
|
68327
|
+
}
|
|
68328
|
+
} catch {
|
|
68329
|
+
}
|
|
68330
|
+
return;
|
|
68331
|
+
}
|
|
68288
68332
|
if (fs2.existsSync(claudeSkills)) {
|
|
68289
68333
|
const stat = fs2.lstatSync(claudeSkills);
|
|
68290
68334
|
if (stat.isSymbolicLink()) {
|
|
68291
68335
|
const target = fs2.readlinkSync(claudeSkills);
|
|
68292
|
-
if (target ===
|
|
68336
|
+
if (target === `../${UNIVERSAL_SKILLS_DIR}` || target === agentSkills) {
|
|
68293
68337
|
return;
|
|
68294
68338
|
}
|
|
68295
68339
|
fs2.unlinkSync(claudeSkills);
|
|
@@ -68299,12 +68343,61 @@ function ensureSkillsSymlink(projectRoot) {
|
|
|
68299
68343
|
}
|
|
68300
68344
|
}
|
|
68301
68345
|
try {
|
|
68302
|
-
fs2.symlinkSync(
|
|
68303
|
-
console.log(
|
|
68346
|
+
fs2.symlinkSync(`../${UNIVERSAL_SKILLS_DIR}`, claudeSkills);
|
|
68347
|
+
console.log(`Linked .claude/skills -> ${UNIVERSAL_SKILLS_DIR}`);
|
|
68304
68348
|
} catch (err) {
|
|
68305
68349
|
console.warn("Warning: Failed to create symlink:", err);
|
|
68306
68350
|
}
|
|
68307
68351
|
}
|
|
68352
|
+
function resolveLocalDirIfExists(skill, projectRoot) {
|
|
68353
|
+
if (skill.type !== "local") return null;
|
|
68354
|
+
let source = skill.source;
|
|
68355
|
+
if (source.startsWith("~")) {
|
|
68356
|
+
source = source.replace(/^~/, process.env.HOME || "~");
|
|
68357
|
+
}
|
|
68358
|
+
const abs = path4.isAbsolute(source) ? source : path4.resolve(projectRoot, source);
|
|
68359
|
+
try {
|
|
68360
|
+
if (!fs2.existsSync(abs)) return null;
|
|
68361
|
+
if (!fs2.statSync(abs).isDirectory()) return null;
|
|
68362
|
+
return abs;
|
|
68363
|
+
} catch {
|
|
68364
|
+
return null;
|
|
68365
|
+
}
|
|
68366
|
+
}
|
|
68367
|
+
function sourcePathExplicitlyTargetsPrivate(source) {
|
|
68368
|
+
const normalized = source.replace(/\\/g, "/");
|
|
68369
|
+
return normalized === PRIVATE_SKILLS_DIRNAME || normalized.includes(`/${PRIVATE_SKILLS_DIRNAME}/`);
|
|
68370
|
+
}
|
|
68371
|
+
function findSkillDirs(rootDir, opts) {
|
|
68372
|
+
const out = [];
|
|
68373
|
+
const shouldSkipDir = (_parentAbsDir, name) => {
|
|
68374
|
+
if (name.startsWith(".")) return true;
|
|
68375
|
+
if (name === "node_modules" || name === ".git") return true;
|
|
68376
|
+
if (opts.excludePrivate && name === PRIVATE_SKILLS_DIRNAME) return true;
|
|
68377
|
+
if (name === ".agents" || name === ".agent" || name === ".claude") return true;
|
|
68378
|
+
return false;
|
|
68379
|
+
};
|
|
68380
|
+
const walk = (dir) => {
|
|
68381
|
+
let entries;
|
|
68382
|
+
try {
|
|
68383
|
+
entries = fs2.readdirSync(dir, { withFileTypes: true });
|
|
68384
|
+
} catch {
|
|
68385
|
+
return;
|
|
68386
|
+
}
|
|
68387
|
+
const hasSkillMd = entries.some((e) => e.isFile() && e.name === "SKILL.md");
|
|
68388
|
+
if (hasSkillMd) {
|
|
68389
|
+
out.push(dir);
|
|
68390
|
+
if (!opts.fullDepth) return;
|
|
68391
|
+
}
|
|
68392
|
+
for (const entry of entries) {
|
|
68393
|
+
if (!entry.isDirectory()) continue;
|
|
68394
|
+
if (shouldSkipDir(dir, entry.name)) continue;
|
|
68395
|
+
walk(path4.join(dir, entry.name));
|
|
68396
|
+
}
|
|
68397
|
+
};
|
|
68398
|
+
walk(rootDir);
|
|
68399
|
+
return out;
|
|
68400
|
+
}
|
|
68308
68401
|
|
|
68309
68402
|
// src/commands/admin.ts
|
|
68310
68403
|
async function handleAdmin(subcommand, positionals, flags, context2) {
|
|
@@ -69377,7 +69470,7 @@ async function installSkills(projectRoot) {
|
|
|
69377
69470
|
}
|
|
69378
69471
|
}
|
|
69379
69472
|
function ensureSkillsSymlink2(projectRoot) {
|
|
69380
|
-
const agentSkills = path5.join(projectRoot, ".
|
|
69473
|
+
const agentSkills = path5.join(projectRoot, ".agents", "skills");
|
|
69381
69474
|
const claudeDir = path5.join(projectRoot, ".claude");
|
|
69382
69475
|
const claudeSkills = path5.join(claudeDir, "skills");
|
|
69383
69476
|
if (!fs3.existsSync(agentSkills)) {
|
|
@@ -69386,11 +69479,27 @@ function ensureSkillsSymlink2(projectRoot) {
|
|
|
69386
69479
|
if (!fs3.existsSync(claudeDir)) {
|
|
69387
69480
|
fs3.mkdirSync(claudeDir, { recursive: true });
|
|
69388
69481
|
}
|
|
69482
|
+
if (fs3.existsSync(claudeSkills) && !fs3.lstatSync(claudeSkills).isSymbolicLink()) {
|
|
69483
|
+
try {
|
|
69484
|
+
const stat = fs3.lstatSync(claudeSkills);
|
|
69485
|
+
if (stat.isDirectory()) {
|
|
69486
|
+
const entries = fs3.readdirSync(agentSkills, { withFileTypes: true });
|
|
69487
|
+
for (const entry of entries) {
|
|
69488
|
+
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
69489
|
+
const dst = path5.join(claudeSkills, entry.name);
|
|
69490
|
+
if (fs3.existsSync(dst)) continue;
|
|
69491
|
+
fs3.symlinkSync(path5.join("..", "..", ".agents", "skills", entry.name), dst);
|
|
69492
|
+
}
|
|
69493
|
+
}
|
|
69494
|
+
} catch {
|
|
69495
|
+
}
|
|
69496
|
+
return;
|
|
69497
|
+
}
|
|
69389
69498
|
if (fs3.existsSync(claudeSkills)) {
|
|
69390
69499
|
const stat = fs3.lstatSync(claudeSkills);
|
|
69391
69500
|
if (stat.isSymbolicLink()) {
|
|
69392
69501
|
const target = fs3.readlinkSync(claudeSkills);
|
|
69393
|
-
if (target === "../.
|
|
69502
|
+
if (target === "../.agents/skills" || target === agentSkills) {
|
|
69394
69503
|
return;
|
|
69395
69504
|
}
|
|
69396
69505
|
fs3.unlinkSync(claudeSkills);
|
|
@@ -69399,7 +69508,7 @@ function ensureSkillsSymlink2(projectRoot) {
|
|
|
69399
69508
|
}
|
|
69400
69509
|
}
|
|
69401
69510
|
try {
|
|
69402
|
-
fs3.symlinkSync("../.
|
|
69511
|
+
fs3.symlinkSync("../.agents/skills", claudeSkills);
|
|
69403
69512
|
} catch {
|
|
69404
69513
|
}
|
|
69405
69514
|
}
|