@eve-horizon/cli 0.0.1 → 0.1.1
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 +31 -8
- package/dist/commands/admin.js +84 -0
- package/dist/commands/agents.js +78 -0
- package/dist/commands/auth.js +468 -41
- package/dist/commands/db.js +120 -65
- package/dist/commands/env.js +61 -17
- package/dist/commands/harness.js +50 -2
- package/dist/commands/init.js +290 -0
- package/dist/commands/job.js +221 -4
- package/dist/commands/pipeline.js +21 -2
- package/dist/commands/profile.js +5 -0
- package/dist/commands/project.js +29 -2
- package/dist/commands/secrets.js +79 -8
- package/dist/commands/skills.js +390 -0
- package/dist/commands/system.js +72 -1
- package/dist/index.js +17 -0
- package/dist/lib/context.js +29 -1
- package/dist/lib/help.js +266 -22
- package/package.json +2 -1
package/README.md
CHANGED
|
@@ -19,7 +19,7 @@ Profiles store API URL, default org/project IDs, default harness, and Supabase a
|
|
|
19
19
|
```bash
|
|
20
20
|
# Create or update a profile
|
|
21
21
|
eve profile set local \
|
|
22
|
-
--api-url http://localhost:
|
|
22
|
+
--api-url http://localhost:4801 \
|
|
23
23
|
--org org_defaulttestorg \
|
|
24
24
|
--project proj_xxx
|
|
25
25
|
|
|
@@ -51,16 +51,19 @@ eve profile set prod \
|
|
|
51
51
|
|
|
52
52
|
## Auth
|
|
53
53
|
|
|
54
|
-
Auth is **
|
|
55
|
-
|
|
56
|
-
`EVE_SUPABASE_ANON_KEY`.
|
|
54
|
+
Auth is **required** for cloud stacks. The default flow uses GitHub SSH keys; Supabase remains an
|
|
55
|
+
optional adapter for legacy deployments.
|
|
57
56
|
|
|
58
|
-
The CLI will refresh access tokens automatically if a refresh token is available.
|
|
57
|
+
The CLI will refresh Supabase access tokens automatically if a refresh token is available.
|
|
59
58
|
|
|
60
59
|
```bash
|
|
61
|
-
#
|
|
60
|
+
# SSH login (default)
|
|
61
|
+
eve auth login --email you@example.com --ssh-key ~/.ssh/id_ed25519
|
|
62
|
+
|
|
63
|
+
# Supabase login (optional)
|
|
62
64
|
eve auth login --email you@example.com --password '...' \
|
|
63
|
-
--
|
|
65
|
+
--supabase-url https://your-project.supabase.co \
|
|
66
|
+
--supabase-anon-key <anon-key>
|
|
64
67
|
|
|
65
68
|
# Status / whoami
|
|
66
69
|
eve auth status
|
|
@@ -100,6 +103,15 @@ Jobs created without a `--phase` flag default to `ready`, making them immediatel
|
|
|
100
103
|
eve job create --description "Fix the login bug in auth.ts"
|
|
101
104
|
eve job create --description "Add dark mode" --priority 1 --harness mclaude
|
|
102
105
|
|
|
106
|
+
# Create a job with git controls
|
|
107
|
+
eve job create \
|
|
108
|
+
--description "Fix checkout" \
|
|
109
|
+
--git-ref main \
|
|
110
|
+
--git-branch job/fix-checkout \
|
|
111
|
+
--git-create-branch if_missing \
|
|
112
|
+
--git-commit auto \
|
|
113
|
+
--git-push on_success
|
|
114
|
+
|
|
103
115
|
# List and filter jobs
|
|
104
116
|
eve job list --phase ready
|
|
105
117
|
eve job ready # Schedulable jobs (ready, not blocked)
|
|
@@ -252,8 +264,20 @@ Environment variables for agent context:
|
|
|
252
264
|
```bash
|
|
253
265
|
eve harness list # List available harnesses
|
|
254
266
|
eve harness get mclaude # Show harness details and auth status
|
|
267
|
+
eve harness list --capabilities # Include model/reasoning capability hints
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
### Agents (Orchestration Config)
|
|
271
|
+
|
|
272
|
+
Provide policy + harness context for orchestrating agents (profiles, councils, availability):
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
eve agents config --json
|
|
276
|
+
eve agents config --path /path/to/repo --no-harnesses
|
|
255
277
|
```
|
|
256
278
|
|
|
279
|
+
Recommended default policy profile name: `primary-orchestrator`.
|
|
280
|
+
|
|
257
281
|
## Pagination
|
|
258
282
|
|
|
259
283
|
List endpoints accept `--limit` and `--offset`. Default limit is **10**, newest first.
|
|
@@ -271,5 +295,4 @@ Local dev/ops tooling:
|
|
|
271
295
|
./bin/eh dev start
|
|
272
296
|
./bin/eh k8s start # Default runtime
|
|
273
297
|
./bin/eh docker start # Quick dev loop
|
|
274
|
-
./bin/eh db migrate
|
|
275
298
|
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleAdmin = handleAdmin;
|
|
4
|
+
const args_1 = require("../lib/args");
|
|
5
|
+
const client_1 = require("../lib/client");
|
|
6
|
+
const output_1 = require("../lib/output");
|
|
7
|
+
async function handleAdmin(subcommand, positionals, flags, context) {
|
|
8
|
+
const json = Boolean(flags.json);
|
|
9
|
+
switch (subcommand) {
|
|
10
|
+
case 'invite': {
|
|
11
|
+
const githubUsername = (0, args_1.getStringFlag)(flags, ['github']);
|
|
12
|
+
const email = (0, args_1.getStringFlag)(flags, ['email']);
|
|
13
|
+
const role = (0, args_1.getStringFlag)(flags, ['role']) ?? 'member';
|
|
14
|
+
const orgId = (0, args_1.getStringFlag)(flags, ['org']) ?? context.orgId;
|
|
15
|
+
if (!email) {
|
|
16
|
+
throw new Error('Usage: eve admin invite --email <email> [--github <username>] [--role <role>] [--org <org_id>]');
|
|
17
|
+
}
|
|
18
|
+
if (!['owner', 'admin', 'member'].includes(role)) {
|
|
19
|
+
throw new Error(`Invalid role: ${role}. Must be one of: owner, admin, member`);
|
|
20
|
+
}
|
|
21
|
+
const results = {
|
|
22
|
+
keys_registered: 0,
|
|
23
|
+
identities: [],
|
|
24
|
+
};
|
|
25
|
+
// Fetch and register GitHub SSH keys if username provided
|
|
26
|
+
if (githubUsername) {
|
|
27
|
+
const keys = await fetchGitHubKeys(githubUsername);
|
|
28
|
+
if (keys.length === 0) {
|
|
29
|
+
throw new Error(`No SSH keys found for GitHub user: ${githubUsername}`);
|
|
30
|
+
}
|
|
31
|
+
for (const publicKey of keys) {
|
|
32
|
+
const identity = await (0, client_1.requestJson)(context, '/auth/identities', {
|
|
33
|
+
method: 'POST',
|
|
34
|
+
body: {
|
|
35
|
+
email,
|
|
36
|
+
public_key: publicKey,
|
|
37
|
+
label: `github-${githubUsername}`,
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
results.identities.push(identity);
|
|
41
|
+
results.keys_registered += 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
// Add user to org if org_id provided
|
|
45
|
+
if (orgId) {
|
|
46
|
+
// Get user_id from the first registered identity, or look up by email
|
|
47
|
+
let userId;
|
|
48
|
+
if (results.identities.length > 0) {
|
|
49
|
+
userId = results.identities[0].user_id;
|
|
50
|
+
}
|
|
51
|
+
if (userId) {
|
|
52
|
+
const membership = await (0, client_1.requestJson)(context, `/orgs/${orgId}/members`, {
|
|
53
|
+
method: 'POST',
|
|
54
|
+
body: {
|
|
55
|
+
user_id: userId,
|
|
56
|
+
role,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
results.membership = membership;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
const summary = [
|
|
63
|
+
`Invited ${email}`,
|
|
64
|
+
results.keys_registered > 0 ? `${results.keys_registered} SSH key(s) registered` : null,
|
|
65
|
+
results.membership ? `Added to ${orgId} as ${role}` : null,
|
|
66
|
+
].filter(Boolean).join(', ');
|
|
67
|
+
(0, output_1.outputJson)(results, json, `+ ${summary}`);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
default:
|
|
71
|
+
throw new Error('Usage: eve admin <invite>');
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function fetchGitHubKeys(username) {
|
|
75
|
+
const response = await fetch(`https://github.com/${username}.keys`);
|
|
76
|
+
if (!response.ok) {
|
|
77
|
+
if (response.status === 404) {
|
|
78
|
+
throw new Error(`GitHub user not found: ${username}`);
|
|
79
|
+
}
|
|
80
|
+
throw new Error(`Failed to fetch GitHub keys: HTTP ${response.status}`);
|
|
81
|
+
}
|
|
82
|
+
const text = await response.text();
|
|
83
|
+
return text.trim().split('\n').filter(k => k.length > 0);
|
|
84
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleAgents = handleAgents;
|
|
4
|
+
const node_fs_1 = require("node:fs");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const yaml_1 = require("yaml");
|
|
7
|
+
const shared_1 = require("@eve/shared");
|
|
8
|
+
const args_1 = require("../lib/args");
|
|
9
|
+
const client_1 = require("../lib/client");
|
|
10
|
+
const output_1 = require("../lib/output");
|
|
11
|
+
function readYamlFile(filePath) {
|
|
12
|
+
const raw = (0, node_fs_1.readFileSync)(filePath, 'utf-8');
|
|
13
|
+
const parsed = (0, yaml_1.parse)(raw);
|
|
14
|
+
if (!parsed || typeof parsed !== 'object') {
|
|
15
|
+
throw new Error(`Invalid YAML in ${filePath}`);
|
|
16
|
+
}
|
|
17
|
+
return parsed;
|
|
18
|
+
}
|
|
19
|
+
function loadAgentsConfig(repoRoot) {
|
|
20
|
+
const eveDir = (0, node_path_1.join)(repoRoot, '.eve');
|
|
21
|
+
const manifestPath = (0, node_path_1.join)(eveDir, 'manifest.yaml');
|
|
22
|
+
if ((0, node_fs_1.existsSync)(manifestPath)) {
|
|
23
|
+
const manifest = readYamlFile(manifestPath);
|
|
24
|
+
const xEve = manifest['x-eve'] ||
|
|
25
|
+
manifest['x_eve'] ||
|
|
26
|
+
{};
|
|
27
|
+
const policy = xEve['agents'] || null;
|
|
28
|
+
const defaults = xEve['defaults'] || null;
|
|
29
|
+
return { source: { type: 'manifest', path: manifestPath }, policy, manifest_defaults: defaults };
|
|
30
|
+
}
|
|
31
|
+
return { source: { type: 'none' }, policy: null };
|
|
32
|
+
}
|
|
33
|
+
async function handleAgents(subcommand, positionals, flags, context) {
|
|
34
|
+
const command = subcommand ?? 'config';
|
|
35
|
+
const json = Boolean(flags.json);
|
|
36
|
+
const includeHarnesses = !((0, args_1.getBooleanFlag)(flags, ['no-harnesses']) ?? false);
|
|
37
|
+
const repoRoot = (0, node_path_1.resolve)((0, args_1.getStringFlag)(flags, ['path']) ?? process.cwd());
|
|
38
|
+
if (command !== 'config') {
|
|
39
|
+
throw new Error('Usage: eve agents config [--path <dir>] [--no-harnesses]');
|
|
40
|
+
}
|
|
41
|
+
const result = loadAgentsConfig(repoRoot);
|
|
42
|
+
const response = {
|
|
43
|
+
repo_root: repoRoot,
|
|
44
|
+
source: result.source,
|
|
45
|
+
policy: result.policy,
|
|
46
|
+
};
|
|
47
|
+
if (result.manifest_defaults) {
|
|
48
|
+
response.manifest_defaults = result.manifest_defaults;
|
|
49
|
+
}
|
|
50
|
+
if (includeHarnesses) {
|
|
51
|
+
const harnesses = await (0, client_1.requestJson)(context, '/harnesses');
|
|
52
|
+
response.harnesses = harnesses.data;
|
|
53
|
+
response.capabilities = shared_1.HARNESS_CAPABILITIES;
|
|
54
|
+
}
|
|
55
|
+
if (json) {
|
|
56
|
+
(0, output_1.outputJson)(response, json);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
console.log(`Agents config source: ${result.source.type}`);
|
|
60
|
+
if ('path' in result.source) {
|
|
61
|
+
console.log(`Path: ${result.source.path}`);
|
|
62
|
+
}
|
|
63
|
+
if (!result.policy) {
|
|
64
|
+
console.log('No policy found. Add x-eve.agents to .eve/manifest.yaml.');
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
const profiles = result.policy.profiles || {};
|
|
68
|
+
const profileNames = Object.keys(profiles);
|
|
69
|
+
console.log(`Profiles: ${profileNames.length ? profileNames.join(', ') : 'none'}`);
|
|
70
|
+
}
|
|
71
|
+
if (includeHarnesses) {
|
|
72
|
+
const harnesses = response.harnesses;
|
|
73
|
+
if (harnesses?.length) {
|
|
74
|
+
const ready = harnesses.filter((h) => h.auth.available).length;
|
|
75
|
+
console.log(`Harnesses: ${harnesses.length} (${ready} ready)`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|