@eve-horizon/cli 0.2.12 → 0.2.13
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 +65918 -137
- package/package.json +6 -5
- package/dist/commands/admin.js +0 -81
- package/dist/commands/agents.js +0 -445
- package/dist/commands/api.js +0 -350
- package/dist/commands/auth.js +0 -852
- package/dist/commands/build.js +0 -397
- package/dist/commands/chat.js +0 -55
- package/dist/commands/db.js +0 -204
- package/dist/commands/env.js +0 -812
- package/dist/commands/event.js +0 -273
- package/dist/commands/harness.js +0 -158
- package/dist/commands/init.js +0 -280
- package/dist/commands/integrations.js +0 -73
- package/dist/commands/job.js +0 -2557
- package/dist/commands/manifest.js +0 -86
- package/dist/commands/migrate.js +0 -136
- package/dist/commands/org.js +0 -148
- package/dist/commands/packs.js +0 -197
- package/dist/commands/pipeline.js +0 -629
- package/dist/commands/profile.js +0 -155
- package/dist/commands/project.js +0 -249
- package/dist/commands/release.js +0 -69
- package/dist/commands/secrets.js +0 -218
- package/dist/commands/skills.js +0 -307
- package/dist/commands/supervise.js +0 -60
- package/dist/commands/system.js +0 -649
- package/dist/commands/thread.js +0 -153
- package/dist/commands/workflow.js +0 -337
- package/dist/lib/args.js +0 -57
- package/dist/lib/client.js +0 -116
- package/dist/lib/config.js +0 -49
- package/dist/lib/context.js +0 -187
- package/dist/lib/git.js +0 -158
- package/dist/lib/harness-capabilities.js +0 -74
- package/dist/lib/help.js +0 -1821
- package/dist/lib/logs.js +0 -51
- package/dist/lib/output.js +0 -14
package/dist/commands/secrets.js
DELETED
|
@@ -1,218 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleSecrets = handleSecrets;
|
|
4
|
-
const node_fs_1 = require("node:fs");
|
|
5
|
-
const client_1 = require("../lib/client");
|
|
6
|
-
const output_1 = require("../lib/output");
|
|
7
|
-
async function handleSecrets(subcommand, positionals, flags, context) {
|
|
8
|
-
const json = Boolean(flags.json);
|
|
9
|
-
switch (subcommand) {
|
|
10
|
-
case 'set': {
|
|
11
|
-
const scope = resolveScope(flags, context);
|
|
12
|
-
const key = positionals[0] ?? (typeof flags.key === 'string' ? flags.key : undefined);
|
|
13
|
-
const value = positionals[1] ?? (typeof flags.value === 'string' ? flags.value : undefined);
|
|
14
|
-
const type = typeof flags.type === 'string' ? flags.type : undefined;
|
|
15
|
-
if (!key || !value) {
|
|
16
|
-
throw new Error('Usage: eve secrets set <key> <value> [--project <id>|--org <id>|--user <id>|--system] [--type <type>]');
|
|
17
|
-
}
|
|
18
|
-
const body = { key, value };
|
|
19
|
-
if (type)
|
|
20
|
-
body.type = type;
|
|
21
|
-
const response = await (0, client_1.requestJson)(context, `${scopeBasePath(scope)}`, {
|
|
22
|
-
method: 'POST',
|
|
23
|
-
body,
|
|
24
|
-
});
|
|
25
|
-
(0, output_1.outputJson)(response, json, `✓ Secret set: ${key}`);
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
case 'list': {
|
|
29
|
-
const scope = resolveScope(flags, context);
|
|
30
|
-
const query = buildQuery({
|
|
31
|
-
limit: typeof flags.limit === 'string' ? flags.limit : undefined,
|
|
32
|
-
offset: typeof flags.offset === 'string' ? flags.offset : undefined,
|
|
33
|
-
});
|
|
34
|
-
const response = await (0, client_1.requestJson)(context, `${scopeBasePath(scope)}${query}`);
|
|
35
|
-
(0, output_1.outputJson)(response, json);
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
case 'show': {
|
|
39
|
-
const scope = resolveScope(flags, context);
|
|
40
|
-
const key = positionals[0] ?? (typeof flags.key === 'string' ? flags.key : undefined);
|
|
41
|
-
if (!key) {
|
|
42
|
-
throw new Error('Usage: eve secrets show <key> [--project <id>|--org <id>|--user <id>|--system]');
|
|
43
|
-
}
|
|
44
|
-
const response = await (0, client_1.requestJson)(context, `${scopeBasePath(scope)}/${encodeURIComponent(key)}`);
|
|
45
|
-
(0, output_1.outputJson)(response, json);
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
case 'delete': {
|
|
49
|
-
const scope = resolveScope(flags, context);
|
|
50
|
-
const key = positionals[0] ?? (typeof flags.key === 'string' ? flags.key : undefined);
|
|
51
|
-
if (!key) {
|
|
52
|
-
throw new Error('Usage: eve secrets delete <key> [--project <id>|--org <id>|--user <id>|--system]');
|
|
53
|
-
}
|
|
54
|
-
await (0, client_1.requestJson)(context, `${scopeBasePath(scope)}/${encodeURIComponent(key)}`, { method: 'DELETE' });
|
|
55
|
-
(0, output_1.outputJson)({ ok: true }, json, `✓ Secret deleted: ${key}`);
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
case 'import': {
|
|
59
|
-
const scope = resolveScope(flags, context);
|
|
60
|
-
const filePath = typeof flags.file === 'string' ? flags.file : '.env';
|
|
61
|
-
const fileContents = (0, node_fs_1.readFileSync)(filePath, 'utf8');
|
|
62
|
-
const entries = parseEnvFile(fileContents);
|
|
63
|
-
if (entries.length === 0) {
|
|
64
|
-
throw new Error(`No entries found in ${filePath}`);
|
|
65
|
-
}
|
|
66
|
-
for (const [key, value] of entries) {
|
|
67
|
-
await (0, client_1.requestJson)(context, `${scopeBasePath(scope)}`, {
|
|
68
|
-
method: 'POST',
|
|
69
|
-
body: { key, value },
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
(0, output_1.outputJson)({ imported: entries.length }, json, `✓ Imported ${entries.length} secrets`);
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
case 'validate': {
|
|
76
|
-
const projectId = resolveProjectScope(flags, context);
|
|
77
|
-
const keys = parseKeys(positionals, flags);
|
|
78
|
-
const body = {};
|
|
79
|
-
if (keys.length > 0)
|
|
80
|
-
body.keys = keys;
|
|
81
|
-
const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/secrets/validate`, {
|
|
82
|
-
method: 'POST',
|
|
83
|
-
body,
|
|
84
|
-
});
|
|
85
|
-
if (json) {
|
|
86
|
-
(0, output_1.outputJson)(response, json);
|
|
87
|
-
}
|
|
88
|
-
else if (response.missing.length === 0) {
|
|
89
|
-
console.log('✓ All required secrets are present');
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
console.log('Missing secrets:');
|
|
93
|
-
response.missing.forEach((item) => {
|
|
94
|
-
console.log(`- ${item.key}`);
|
|
95
|
-
item.hints.forEach((hint) => console.log(` ${hint}`));
|
|
96
|
-
});
|
|
97
|
-
}
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
100
|
-
case 'ensure': {
|
|
101
|
-
const projectId = resolveProjectScope(flags, context);
|
|
102
|
-
const keys = parseKeys(positionals, flags);
|
|
103
|
-
if (keys.length === 0) {
|
|
104
|
-
throw new Error('Usage: eve secrets ensure --project <id> --keys <key1,key2>');
|
|
105
|
-
}
|
|
106
|
-
const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/secrets/ensure`, {
|
|
107
|
-
method: 'POST',
|
|
108
|
-
body: { keys },
|
|
109
|
-
});
|
|
110
|
-
(0, output_1.outputJson)(response, json, `✓ Secrets ensured (${response.created.length} created)`);
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
case 'export': {
|
|
114
|
-
const projectId = resolveProjectScope(flags, context);
|
|
115
|
-
const keys = parseKeys(positionals, flags);
|
|
116
|
-
if (keys.length === 0) {
|
|
117
|
-
throw new Error('Usage: eve secrets export --project <id> --keys <key1,key2>');
|
|
118
|
-
}
|
|
119
|
-
const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/secrets/export`, {
|
|
120
|
-
method: 'POST',
|
|
121
|
-
body: { keys },
|
|
122
|
-
});
|
|
123
|
-
if (json) {
|
|
124
|
-
(0, output_1.outputJson)(response, json);
|
|
125
|
-
}
|
|
126
|
-
else {
|
|
127
|
-
console.log('Exported secrets (handle carefully):');
|
|
128
|
-
response.data.forEach((item) => {
|
|
129
|
-
console.log(`${item.key}=${item.value}`);
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
default:
|
|
135
|
-
throw new Error('Usage: eve secrets <set|list|show|delete|import|validate|ensure|export>');
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
function resolveScope(flags, context) {
|
|
139
|
-
// Explicit flags take priority in the order: system > project > org > user
|
|
140
|
-
const explicitSystem = Boolean(flags.system);
|
|
141
|
-
const explicitProject = typeof flags.project === 'string' ? flags.project : undefined;
|
|
142
|
-
const explicitOrg = typeof flags.org === 'string' ? flags.org : undefined;
|
|
143
|
-
const explicitUser = typeof flags.user === 'string' ? flags.user : undefined;
|
|
144
|
-
// Check for mutual exclusivity
|
|
145
|
-
const explicitFlags = [explicitSystem, explicitProject, explicitOrg, explicitUser].filter(Boolean);
|
|
146
|
-
if (explicitFlags.length > 1) {
|
|
147
|
-
throw new Error('Cannot specify multiple scope flags. Use only one of: --system, --project, --org, or --user');
|
|
148
|
-
}
|
|
149
|
-
// If explicit flags are provided, use them in priority order
|
|
150
|
-
if (explicitSystem)
|
|
151
|
-
return { scopeType: 'system', scopeId: 'system' };
|
|
152
|
-
if (explicitProject)
|
|
153
|
-
return { scopeType: 'project', scopeId: explicitProject };
|
|
154
|
-
if (explicitOrg)
|
|
155
|
-
return { scopeType: 'org', scopeId: explicitOrg };
|
|
156
|
-
if (explicitUser)
|
|
157
|
-
return { scopeType: 'user', scopeId: explicitUser };
|
|
158
|
-
// Fall back to profile defaults
|
|
159
|
-
if (context.projectId)
|
|
160
|
-
return { scopeType: 'project', scopeId: context.projectId };
|
|
161
|
-
if (context.orgId)
|
|
162
|
-
return { scopeType: 'org', scopeId: context.orgId };
|
|
163
|
-
throw new Error('Missing scope. Provide --system, --project, --org, or --user (or set profile defaults).');
|
|
164
|
-
}
|
|
165
|
-
function scopeBasePath(scope) {
|
|
166
|
-
switch (scope.scopeType) {
|
|
167
|
-
case 'system':
|
|
168
|
-
return `/system/secrets`;
|
|
169
|
-
case 'project':
|
|
170
|
-
return `/projects/${scope.scopeId}/secrets`;
|
|
171
|
-
case 'org':
|
|
172
|
-
return `/orgs/${scope.scopeId}/secrets`;
|
|
173
|
-
case 'user':
|
|
174
|
-
return `/users/${scope.scopeId}/secrets`;
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
function resolveProjectScope(flags, context) {
|
|
178
|
-
const scope = resolveScope(flags, context);
|
|
179
|
-
if (scope.scopeType !== 'project') {
|
|
180
|
-
throw new Error('This command requires --project (or a project default profile).');
|
|
181
|
-
}
|
|
182
|
-
return scope.scopeId;
|
|
183
|
-
}
|
|
184
|
-
function buildQuery(params) {
|
|
185
|
-
const search = new URLSearchParams();
|
|
186
|
-
Object.entries(params).forEach(([key, value]) => {
|
|
187
|
-
if (value === undefined || value === '')
|
|
188
|
-
return;
|
|
189
|
-
search.set(key, String(value));
|
|
190
|
-
});
|
|
191
|
-
const query = search.toString();
|
|
192
|
-
return query ? `?${query}` : '';
|
|
193
|
-
}
|
|
194
|
-
function parseEnvFile(contents) {
|
|
195
|
-
const lines = contents.split(/\r?\n/);
|
|
196
|
-
const entries = [];
|
|
197
|
-
for (const line of lines) {
|
|
198
|
-
const trimmed = line.trim();
|
|
199
|
-
if (!trimmed || trimmed.startsWith('#'))
|
|
200
|
-
continue;
|
|
201
|
-
const eqIndex = trimmed.indexOf('=');
|
|
202
|
-
if (eqIndex === -1)
|
|
203
|
-
continue;
|
|
204
|
-
const key = trimmed.slice(0, eqIndex).trim();
|
|
205
|
-
const value = trimmed.slice(eqIndex + 1).trim();
|
|
206
|
-
if (!key)
|
|
207
|
-
continue;
|
|
208
|
-
entries.push([key, value]);
|
|
209
|
-
}
|
|
210
|
-
return entries;
|
|
211
|
-
}
|
|
212
|
-
function parseKeys(positionals, flags) {
|
|
213
|
-
const positionalKeys = positionals.filter((value) => typeof value === 'string' && value.length > 0);
|
|
214
|
-
const flagKeys = typeof flags.keys === 'string'
|
|
215
|
-
? flags.keys.split(',').map((value) => value.trim()).filter(Boolean)
|
|
216
|
-
: [];
|
|
217
|
-
return Array.from(new Set([...positionalKeys, ...flagKeys]));
|
|
218
|
-
}
|
package/dist/commands/skills.js
DELETED
|
@@ -1,307 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.handleSkills = handleSkills;
|
|
37
|
-
const fs = __importStar(require("node:fs"));
|
|
38
|
-
const path = __importStar(require("node:path"));
|
|
39
|
-
const node_child_process_1 = require("node:child_process");
|
|
40
|
-
// ============================================================================
|
|
41
|
-
// Main Handler
|
|
42
|
-
// ============================================================================
|
|
43
|
-
async function handleSkills(subcommand, positionals, flags) {
|
|
44
|
-
switch (subcommand) {
|
|
45
|
-
case 'install':
|
|
46
|
-
return handleInstall(flags);
|
|
47
|
-
default:
|
|
48
|
-
throw new Error('Usage: eve skills <install>\n' +
|
|
49
|
-
' install Install skills from skills.txt using skills CLI');
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
// ============================================================================
|
|
53
|
-
// Subcommand Handlers
|
|
54
|
-
// ============================================================================
|
|
55
|
-
/**
|
|
56
|
-
* eve skills install [--skip-installed]
|
|
57
|
-
* Install skills from skills.txt manifest using skills CLI
|
|
58
|
-
*/
|
|
59
|
-
async function handleInstall(flags) {
|
|
60
|
-
const skipInstalled = Boolean(flags['skip-installed']);
|
|
61
|
-
const projectRoot = process.cwd();
|
|
62
|
-
// Check if skills CLI is available
|
|
63
|
-
if (!commandExists('skills')) {
|
|
64
|
-
throw new Error('skills CLI not found. Install it with:\n' +
|
|
65
|
-
' npm install -g skills');
|
|
66
|
-
}
|
|
67
|
-
const manifestPath = path.join(projectRoot, 'skills.txt');
|
|
68
|
-
const skillsDir = path.join(projectRoot, '.agent', 'skills');
|
|
69
|
-
// Parse manifest
|
|
70
|
-
const manifest = parseSkillsManifest(manifestPath);
|
|
71
|
-
if (manifest.length === 0) {
|
|
72
|
-
console.log('No skills.txt found or empty; nothing to install');
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
// Filter to skills that need installation
|
|
76
|
-
const toInstall = skipInstalled
|
|
77
|
-
? manifest.filter((s) => !getInstalledSkills(skillsDir).has(s.name))
|
|
78
|
-
: manifest;
|
|
79
|
-
if (toInstall.length === 0) {
|
|
80
|
-
console.log('All skills already installed (use without --skip-installed to update)');
|
|
81
|
-
}
|
|
82
|
-
else {
|
|
83
|
-
console.log(`Installing ${toInstall.length} skill(s)...`);
|
|
84
|
-
for (const skill of toInstall) {
|
|
85
|
-
console.log(` Installing: ${skill.source} (${skill.type})`);
|
|
86
|
-
try {
|
|
87
|
-
const agents = ['claude-code', 'codex', 'gemini-cli'];
|
|
88
|
-
for (const agent of agents) {
|
|
89
|
-
(0, node_child_process_1.execSync)(`skills add ${JSON.stringify(skill.source)} -a ${agent} -y --all`, {
|
|
90
|
-
cwd: projectRoot,
|
|
91
|
-
stdio: 'inherit',
|
|
92
|
-
timeout: 120000,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch (err) {
|
|
97
|
-
console.error(` Failed to install ${skill.name}`);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
// Ensure .claude/skills symlink exists
|
|
102
|
-
ensureSkillsSymlink(projectRoot);
|
|
103
|
-
console.log('Skills install complete');
|
|
104
|
-
}
|
|
105
|
-
// ============================================================================
|
|
106
|
-
// Helper Functions
|
|
107
|
-
// ============================================================================
|
|
108
|
-
/**
|
|
109
|
-
* Check if a command exists in PATH
|
|
110
|
-
*/
|
|
111
|
-
function commandExists(cmd) {
|
|
112
|
-
try {
|
|
113
|
-
const result = (0, node_child_process_1.spawnSync)('which', [cmd], { encoding: 'utf8' });
|
|
114
|
-
return result.status === 0;
|
|
115
|
-
}
|
|
116
|
-
catch {
|
|
117
|
-
return false;
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
/**
|
|
121
|
-
* Check if a line contains a glob pattern.
|
|
122
|
-
*/
|
|
123
|
-
function isGlobPattern(line) {
|
|
124
|
-
return line.includes('*');
|
|
125
|
-
}
|
|
126
|
-
/**
|
|
127
|
-
* Expand a glob pattern to find all subdirectories containing SKILL.md.
|
|
128
|
-
*/
|
|
129
|
-
function expandGlobPattern(pattern, basePath) {
|
|
130
|
-
const sources = [];
|
|
131
|
-
const isRecursive = pattern.endsWith('/**');
|
|
132
|
-
const basePattern = pattern.replace(/\/\*+$/, '');
|
|
133
|
-
let searchRoot;
|
|
134
|
-
if (basePattern.startsWith('./') || basePattern.startsWith('../')) {
|
|
135
|
-
searchRoot = path.resolve(path.dirname(basePath), basePattern);
|
|
136
|
-
}
|
|
137
|
-
else if (basePattern.startsWith('/')) {
|
|
138
|
-
searchRoot = basePattern;
|
|
139
|
-
}
|
|
140
|
-
else if (basePattern.startsWith('~')) {
|
|
141
|
-
searchRoot = basePattern.replace(/^~/, process.env.HOME || '~');
|
|
142
|
-
}
|
|
143
|
-
else {
|
|
144
|
-
searchRoot = path.resolve(path.dirname(basePath), basePattern);
|
|
145
|
-
}
|
|
146
|
-
if (!fs.existsSync(searchRoot)) {
|
|
147
|
-
console.warn(`Warning: Glob pattern base directory not found: ${searchRoot}`);
|
|
148
|
-
return sources;
|
|
149
|
-
}
|
|
150
|
-
const findSkillDirs = (dir, depth) => {
|
|
151
|
-
try {
|
|
152
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
153
|
-
for (const entry of entries) {
|
|
154
|
-
if (!entry.isDirectory() || entry.name.startsWith('.')) {
|
|
155
|
-
continue;
|
|
156
|
-
}
|
|
157
|
-
const fullPath = path.join(dir, entry.name);
|
|
158
|
-
const skillMdPath = path.join(fullPath, 'SKILL.md');
|
|
159
|
-
if (fs.existsSync(skillMdPath)) {
|
|
160
|
-
const name = entry.name;
|
|
161
|
-
const relativePath = path.relative(path.dirname(basePath), fullPath);
|
|
162
|
-
const source = relativePath.startsWith('.') ? relativePath : `./${relativePath}`;
|
|
163
|
-
sources.push({
|
|
164
|
-
raw: pattern,
|
|
165
|
-
source: source,
|
|
166
|
-
type: 'local',
|
|
167
|
-
name: name,
|
|
168
|
-
});
|
|
169
|
-
}
|
|
170
|
-
if (isRecursive || depth === 0) {
|
|
171
|
-
findSkillDirs(fullPath, depth + 1);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
catch (err) {
|
|
176
|
-
console.warn(`Warning: Error reading directory ${dir}:`, err);
|
|
177
|
-
}
|
|
178
|
-
};
|
|
179
|
-
findSkillDirs(searchRoot, 0);
|
|
180
|
-
return sources;
|
|
181
|
-
}
|
|
182
|
-
/**
|
|
183
|
-
* Parse skills.txt and return skill sources.
|
|
184
|
-
*/
|
|
185
|
-
function parseSkillsManifest(manifestPath) {
|
|
186
|
-
if (!fs.existsSync(manifestPath)) {
|
|
187
|
-
return [];
|
|
188
|
-
}
|
|
189
|
-
const content = fs.readFileSync(manifestPath, 'utf-8');
|
|
190
|
-
const sources = [];
|
|
191
|
-
for (const rawLine of content.split('\n')) {
|
|
192
|
-
const line = rawLine.split('#')[0].trim();
|
|
193
|
-
if (!line)
|
|
194
|
-
continue;
|
|
195
|
-
if (isGlobPattern(line)) {
|
|
196
|
-
const expanded = expandGlobPattern(line, manifestPath);
|
|
197
|
-
sources.push(...expanded);
|
|
198
|
-
}
|
|
199
|
-
else {
|
|
200
|
-
sources.push(parseSkillSource(line));
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
return sources;
|
|
204
|
-
}
|
|
205
|
-
/**
|
|
206
|
-
* Parse a single skill source line.
|
|
207
|
-
*/
|
|
208
|
-
function parseSkillSource(line) {
|
|
209
|
-
// URL
|
|
210
|
-
if (line.startsWith('https://') || line.startsWith('http://')) {
|
|
211
|
-
const name = extractNameFromUrl(line);
|
|
212
|
-
return { raw: line, source: line, type: 'url', name };
|
|
213
|
-
}
|
|
214
|
-
// Explicit GitHub prefix
|
|
215
|
-
if (line.startsWith('github:')) {
|
|
216
|
-
const repo = line.slice(7);
|
|
217
|
-
const name = extractNameFromRepo(repo);
|
|
218
|
-
return { raw: line, source: line, type: 'github', name };
|
|
219
|
-
}
|
|
220
|
-
// Local absolute path
|
|
221
|
-
if (line.startsWith('/') || line.startsWith('~')) {
|
|
222
|
-
const name = path.basename(line);
|
|
223
|
-
return { raw: line, source: line, type: 'local', name };
|
|
224
|
-
}
|
|
225
|
-
// Local relative path
|
|
226
|
-
if (line.startsWith('./') || line.startsWith('../')) {
|
|
227
|
-
const name = path.basename(line);
|
|
228
|
-
return { raw: line, source: line, type: 'local', name };
|
|
229
|
-
}
|
|
230
|
-
// Check if it's a local path that exists
|
|
231
|
-
if (fs.existsSync(line)) {
|
|
232
|
-
const name = path.basename(line);
|
|
233
|
-
return { raw: line, source: `./${line}`, type: 'local', name };
|
|
234
|
-
}
|
|
235
|
-
// Assume GitHub shorthand
|
|
236
|
-
if (line.includes('/') && !line.includes(' ')) {
|
|
237
|
-
const name = extractNameFromRepo(line);
|
|
238
|
-
return { raw: line, source: line, type: 'github', name };
|
|
239
|
-
}
|
|
240
|
-
// Fallback: treat as local path
|
|
241
|
-
const name = path.basename(line);
|
|
242
|
-
return { raw: line, source: `./${line}`, type: 'local', name };
|
|
243
|
-
}
|
|
244
|
-
function extractNameFromUrl(url) {
|
|
245
|
-
const match = url.match(/github\.com\/[^/]+\/([^/]+)/);
|
|
246
|
-
if (match) {
|
|
247
|
-
return match[1].replace(/\.git$/, '');
|
|
248
|
-
}
|
|
249
|
-
return path.basename(new URL(url).pathname).replace(/\.git$/, '');
|
|
250
|
-
}
|
|
251
|
-
function extractNameFromRepo(repo) {
|
|
252
|
-
const parts = repo.split('/');
|
|
253
|
-
return parts[parts.length - 1].replace(/\.git$/, '');
|
|
254
|
-
}
|
|
255
|
-
/**
|
|
256
|
-
* Get list of installed skill names from .agent/skills directory.
|
|
257
|
-
*/
|
|
258
|
-
function getInstalledSkills(skillsDir) {
|
|
259
|
-
const installed = new Set();
|
|
260
|
-
if (!fs.existsSync(skillsDir)) {
|
|
261
|
-
return installed;
|
|
262
|
-
}
|
|
263
|
-
const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
264
|
-
for (const entry of entries) {
|
|
265
|
-
if (entry.isDirectory() && !entry.name.startsWith('.')) {
|
|
266
|
-
installed.add(entry.name);
|
|
267
|
-
}
|
|
268
|
-
}
|
|
269
|
-
return installed;
|
|
270
|
-
}
|
|
271
|
-
/**
|
|
272
|
-
* Ensure .claude/skills symlink points to .agent/skills
|
|
273
|
-
*/
|
|
274
|
-
function ensureSkillsSymlink(projectRoot) {
|
|
275
|
-
const agentSkills = path.join(projectRoot, '.agent', 'skills');
|
|
276
|
-
const claudeDir = path.join(projectRoot, '.claude');
|
|
277
|
-
const claudeSkills = path.join(claudeDir, 'skills');
|
|
278
|
-
// Ensure directories exist
|
|
279
|
-
if (!fs.existsSync(agentSkills)) {
|
|
280
|
-
fs.mkdirSync(agentSkills, { recursive: true });
|
|
281
|
-
}
|
|
282
|
-
if (!fs.existsSync(claudeDir)) {
|
|
283
|
-
fs.mkdirSync(claudeDir, { recursive: true });
|
|
284
|
-
}
|
|
285
|
-
// Check existing symlink
|
|
286
|
-
if (fs.existsSync(claudeSkills)) {
|
|
287
|
-
const stat = fs.lstatSync(claudeSkills);
|
|
288
|
-
if (stat.isSymbolicLink()) {
|
|
289
|
-
const target = fs.readlinkSync(claudeSkills);
|
|
290
|
-
if (target === '../.agent/skills' || target === agentSkills) {
|
|
291
|
-
return; // Already correct
|
|
292
|
-
}
|
|
293
|
-
fs.unlinkSync(claudeSkills);
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
console.log('.claude/skills exists and is not a symlink; skipping');
|
|
297
|
-
return;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
try {
|
|
301
|
-
fs.symlinkSync('../.agent/skills', claudeSkills);
|
|
302
|
-
console.log('Linked .claude/skills -> .agent/skills');
|
|
303
|
-
}
|
|
304
|
-
catch (err) {
|
|
305
|
-
console.warn('Warning: Failed to create symlink:', err);
|
|
306
|
-
}
|
|
307
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.handleSupervise = handleSupervise;
|
|
4
|
-
const args_1 = require("../lib/args");
|
|
5
|
-
const client_1 = require("../lib/client");
|
|
6
|
-
const output_1 = require("../lib/output");
|
|
7
|
-
async function handleSupervise(positionals, flags, context) {
|
|
8
|
-
const json = Boolean(flags.json);
|
|
9
|
-
const jobId = positionals[0] ?? process.env.EVE_JOB_ID;
|
|
10
|
-
if (!jobId) {
|
|
11
|
-
throw new Error('Usage: eve supervise [job-id] [--timeout <seconds>] [--since <cursor>] [--json]');
|
|
12
|
-
}
|
|
13
|
-
const timeout = (0, args_1.getStringFlag)(flags, ['timeout']) ?? '30';
|
|
14
|
-
const since = (0, args_1.getStringFlag)(flags, ['since']);
|
|
15
|
-
const params = new URLSearchParams();
|
|
16
|
-
params.set('timeout', timeout);
|
|
17
|
-
if (since) {
|
|
18
|
-
params.set('since', since);
|
|
19
|
-
}
|
|
20
|
-
const result = await (0, client_1.requestJson)(context, `/jobs/${jobId}/supervise?${params.toString()}`);
|
|
21
|
-
if (json) {
|
|
22
|
-
(0, output_1.outputJson)(result, true);
|
|
23
|
-
return;
|
|
24
|
-
}
|
|
25
|
-
// Pretty print
|
|
26
|
-
if (result.events.length === 0) {
|
|
27
|
-
console.log('No new events (timeout).');
|
|
28
|
-
}
|
|
29
|
-
else {
|
|
30
|
-
console.log(`${result.events.length} event(s):\n`);
|
|
31
|
-
for (const evt of result.events) {
|
|
32
|
-
const time = new Date(evt.timestamp).toLocaleTimeString();
|
|
33
|
-
if (evt.type === 'child_update') {
|
|
34
|
-
console.log(` [child] ${evt.job_id} → ${evt.phase} (${time})`);
|
|
35
|
-
}
|
|
36
|
-
else if (evt.type === 'message') {
|
|
37
|
-
console.log(` [msg] ${time}`);
|
|
38
|
-
}
|
|
39
|
-
else {
|
|
40
|
-
console.log(` [${evt.type}] ${time}`);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
if (result.children.length > 0) {
|
|
45
|
-
console.log(`\nChildren (${result.children.length}):`);
|
|
46
|
-
for (const child of result.children) {
|
|
47
|
-
const assignee = child.assignee ? ` (${child.assignee})` : '';
|
|
48
|
-
console.log(` ${child.id} [${child.phase}]${assignee} ${child.title}`);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
if (result.inbox.length > 0) {
|
|
52
|
-
console.log(`\nInbox (${result.inbox.length}):`);
|
|
53
|
-
for (const msg of result.inbox) {
|
|
54
|
-
const actor = msg.actor_id ?? 'unknown';
|
|
55
|
-
const time = new Date(msg.created_at).toLocaleTimeString();
|
|
56
|
-
console.log(` ${time} ${actor}: ${msg.body.slice(0, 120)}`);
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
console.log(`\nCursor: ${result.cursor}`);
|
|
60
|
-
}
|