@eve-horizon/cli 0.2.10 → 0.2.11
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 +26 -0
- package/dist/commands/agents.js +157 -39
- package/dist/commands/chat.js +55 -0
- package/dist/commands/integrations.js +73 -0
- package/dist/index.js +8 -0
- package/dist/lib/git.js +48 -1
- package/dist/lib/help.js +74 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -175,6 +175,32 @@ eve job approve MyProj-abc123 --comment "LGTM"
|
|
|
175
175
|
eve job reject MyProj-abc123 --reason "Missing tests"
|
|
176
176
|
```
|
|
177
177
|
|
|
178
|
+
### Agents
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
# Inspect agent policy + harness readiness
|
|
182
|
+
eve agents config --json
|
|
183
|
+
|
|
184
|
+
# Sync agents/teams/chat config from repo (deterministic)
|
|
185
|
+
eve agents sync --project proj_xxx --ref main
|
|
186
|
+
|
|
187
|
+
# Local dev sync (requires local API + allow dirty)
|
|
188
|
+
eve agents sync --project proj_xxx --local --allow-dirty
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### Integrations + Chat
|
|
192
|
+
|
|
193
|
+
```bash
|
|
194
|
+
# Connect Slack workspace (stub OAuth)
|
|
195
|
+
eve integrations slack connect --org org_xxx --team-id T123 --token xoxb-...
|
|
196
|
+
|
|
197
|
+
# List integrations for org
|
|
198
|
+
eve integrations list --org org_xxx
|
|
199
|
+
|
|
200
|
+
# Simulate inbound Slack message
|
|
201
|
+
eve chat simulate --project proj_xxx --team-id T123 --channel-id C123 --user-id U123 --text "hello"
|
|
202
|
+
```
|
|
203
|
+
|
|
178
204
|
#### Job Results
|
|
179
205
|
|
|
180
206
|
Fetch and display completed job results:
|
package/dist/commands/agents.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.handleAgents = handleAgents;
|
|
4
|
+
const node_child_process_1 = require("node:child_process");
|
|
4
5
|
const node_fs_1 = require("node:fs");
|
|
5
6
|
const node_path_1 = require("node:path");
|
|
6
7
|
const yaml_1 = require("yaml");
|
|
@@ -8,6 +9,7 @@ const harness_capabilities_js_1 = require("../lib/harness-capabilities.js");
|
|
|
8
9
|
const args_1 = require("../lib/args");
|
|
9
10
|
const client_1 = require("../lib/client");
|
|
10
11
|
const output_1 = require("../lib/output");
|
|
12
|
+
const git_js_1 = require("../lib/git.js");
|
|
11
13
|
function readYamlFile(filePath) {
|
|
12
14
|
const raw = (0, node_fs_1.readFileSync)(filePath, 'utf-8');
|
|
13
15
|
const parsed = (0, yaml_1.parse)(raw);
|
|
@@ -16,6 +18,41 @@ function readYamlFile(filePath) {
|
|
|
16
18
|
}
|
|
17
19
|
return parsed;
|
|
18
20
|
}
|
|
21
|
+
function resolveAgentsConfigPaths(repoRoot, manifest) {
|
|
22
|
+
const xEve = manifest['x-eve'] ||
|
|
23
|
+
manifest['x_eve'] ||
|
|
24
|
+
{};
|
|
25
|
+
const agentsBlock = xEve['agents'] || {};
|
|
26
|
+
const chatBlock = xEve['chat'] || {};
|
|
27
|
+
const manifestChat = manifest['chat'] || {};
|
|
28
|
+
const agentsPath = (0, node_path_1.resolve)(repoRoot, pickString(agentsBlock.config_path) ?? 'agents/agents.yaml');
|
|
29
|
+
const teamsPath = (0, node_path_1.resolve)(repoRoot, pickString(agentsBlock.teams_path) ?? 'agents/teams.yaml');
|
|
30
|
+
const chatPath = (0, node_path_1.resolve)(repoRoot, pickString(chatBlock.config_path) ?? pickString(manifestChat.config_path) ?? 'agents/chat.yaml');
|
|
31
|
+
return { agentsPath, teamsPath, chatPath };
|
|
32
|
+
}
|
|
33
|
+
function pickString(value) {
|
|
34
|
+
return typeof value === 'string' && value.trim().length > 0 ? value : undefined;
|
|
35
|
+
}
|
|
36
|
+
function ensureFileExists(path, label) {
|
|
37
|
+
if (!(0, node_fs_1.existsSync)(path)) {
|
|
38
|
+
throw new Error(`Missing ${label} at ${path}. Update manifest config_path or add the file.`);
|
|
39
|
+
}
|
|
40
|
+
return path;
|
|
41
|
+
}
|
|
42
|
+
function isLocalApiUrl(apiUrl) {
|
|
43
|
+
try {
|
|
44
|
+
const url = new URL(apiUrl);
|
|
45
|
+
const host = url.hostname.toLowerCase();
|
|
46
|
+
return (host === 'localhost' ||
|
|
47
|
+
host === '127.0.0.1' ||
|
|
48
|
+
host === '0.0.0.0' ||
|
|
49
|
+
host.endsWith('.lvh.me') ||
|
|
50
|
+
host.endsWith('.localhost'));
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
19
56
|
function loadAgentsConfig(repoRoot) {
|
|
20
57
|
const eveDir = (0, node_path_1.join)(repoRoot, '.eve');
|
|
21
58
|
const manifestPath = (0, node_path_1.join)(eveDir, 'manifest.yaml');
|
|
@@ -34,45 +71,126 @@ async function handleAgents(subcommand, positionals, flags, context) {
|
|
|
34
71
|
const command = subcommand ?? 'config';
|
|
35
72
|
const json = Boolean(flags.json);
|
|
36
73
|
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
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
74
|
+
const repoRoot = (0, node_path_1.resolve)((0, args_1.getStringFlag)(flags, ['repo-dir', 'repo_dir', 'dir', 'path']) ?? process.cwd());
|
|
75
|
+
switch (command) {
|
|
76
|
+
case 'config': {
|
|
77
|
+
const result = loadAgentsConfig(repoRoot);
|
|
78
|
+
const response = {
|
|
79
|
+
repo_root: repoRoot,
|
|
80
|
+
source: result.source,
|
|
81
|
+
policy: result.policy,
|
|
82
|
+
};
|
|
83
|
+
if (result.manifest_defaults) {
|
|
84
|
+
response.manifest_defaults = result.manifest_defaults;
|
|
85
|
+
}
|
|
86
|
+
if (includeHarnesses) {
|
|
87
|
+
const harnesses = await (0, client_1.requestJson)(context, '/harnesses');
|
|
88
|
+
response.harnesses = harnesses.data;
|
|
89
|
+
response.capabilities = harness_capabilities_js_1.HARNESS_CAPABILITIES;
|
|
90
|
+
}
|
|
91
|
+
if (json) {
|
|
92
|
+
(0, output_1.outputJson)(response, json);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
console.log(`Agents config source: ${result.source.type}`);
|
|
96
|
+
if ('path' in result.source) {
|
|
97
|
+
console.log(`Path: ${result.source.path}`);
|
|
98
|
+
}
|
|
99
|
+
if (!result.policy) {
|
|
100
|
+
console.log('No policy found. Add x-eve.agents to .eve/manifest.yaml.');
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
const profiles = result.policy.profiles || {};
|
|
104
|
+
const profileNames = Object.keys(profiles);
|
|
105
|
+
console.log(`Profiles: ${profileNames.length ? profileNames.join(', ') : 'none'}`);
|
|
106
|
+
}
|
|
107
|
+
if (includeHarnesses) {
|
|
108
|
+
const harnesses = response.harnesses;
|
|
109
|
+
if (harnesses?.length) {
|
|
110
|
+
const ready = harnesses.filter((h) => h.auth.available).length;
|
|
111
|
+
console.log(`Harnesses: ${harnesses.length} (${ready} ready)`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
case 'sync': {
|
|
117
|
+
const projectId = (0, args_1.getStringFlag)(flags, ['project']) ?? context.projectId;
|
|
118
|
+
if (!projectId) {
|
|
119
|
+
throw new Error('Missing project id. Provide --project or set a profile default.');
|
|
120
|
+
}
|
|
121
|
+
const ref = (0, args_1.getStringFlag)(flags, ['ref']);
|
|
122
|
+
const local = (0, args_1.getBooleanFlag)(flags, ['local']) ?? false;
|
|
123
|
+
const allowDirty = (0, args_1.getBooleanFlag)(flags, ['allow-dirty', 'allow_dirty']) ?? false;
|
|
124
|
+
const forceNonlocal = (0, args_1.getBooleanFlag)(flags, ['force-nonlocal', 'force_nonlocal']) ?? false;
|
|
125
|
+
if (local && ref) {
|
|
126
|
+
throw new Error('Use either --local or --ref, not both.');
|
|
127
|
+
}
|
|
128
|
+
if (!local && !ref) {
|
|
129
|
+
throw new Error('Missing --ref. Use --ref <sha|branch> or --local for dev sync.');
|
|
130
|
+
}
|
|
131
|
+
if (local && !forceNonlocal && !isLocalApiUrl(context.apiUrl)) {
|
|
132
|
+
throw new Error(`--local sync is only allowed for local API URLs (localhost or *.lvh.me). ` +
|
|
133
|
+
`Current API: ${context.apiUrl}. Use --force-nonlocal to override.`);
|
|
134
|
+
}
|
|
135
|
+
const gitRoot = (0, git_js_1.getGitRoot)(repoRoot);
|
|
136
|
+
if (!gitRoot) {
|
|
137
|
+
throw new Error('Not a git repository. Run from the repo root or pass --repo-dir <path>.');
|
|
138
|
+
}
|
|
139
|
+
const dirty = (0, git_js_1.isGitDirty)(gitRoot);
|
|
140
|
+
if (dirty && !allowDirty) {
|
|
141
|
+
throw new Error('Working tree is dirty. Commit changes or pass --allow-dirty to sync anyway.');
|
|
142
|
+
}
|
|
143
|
+
const manifestPath = (0, node_path_1.join)(repoRoot, '.eve', 'manifest.yaml');
|
|
144
|
+
if (!(0, node_fs_1.existsSync)(manifestPath)) {
|
|
145
|
+
throw new Error(`Missing manifest at ${manifestPath}. Expected .eve/manifest.yaml.`);
|
|
146
|
+
}
|
|
147
|
+
const manifest = readYamlFile(manifestPath);
|
|
148
|
+
const configPaths = resolveAgentsConfigPaths(repoRoot, manifest);
|
|
149
|
+
const agentsYaml = (0, node_fs_1.readFileSync)(ensureFileExists(configPaths.agentsPath, 'agents config'), 'utf-8');
|
|
150
|
+
const teamsYaml = (0, node_fs_1.readFileSync)(ensureFileExists(configPaths.teamsPath, 'teams config'), 'utf-8');
|
|
151
|
+
const chatYaml = (0, node_fs_1.readFileSync)(ensureFileExists(configPaths.chatPath, 'chat config'), 'utf-8');
|
|
152
|
+
let gitSha;
|
|
153
|
+
let branch;
|
|
154
|
+
let gitRef = ref ?? 'local';
|
|
155
|
+
if (ref) {
|
|
156
|
+
gitSha = await (0, git_js_1.resolveGitRef)(context, projectId, ref, repoRoot);
|
|
157
|
+
branch = (0, git_js_1.resolveGitBranch)(gitRoot, ref) ?? undefined;
|
|
158
|
+
}
|
|
159
|
+
else {
|
|
160
|
+
gitSha = (0, node_child_process_1.execSync)('git rev-parse HEAD', { cwd: gitRoot, encoding: 'utf-8' }).trim();
|
|
161
|
+
branch = (0, git_js_1.getGitBranch)(gitRoot) ?? undefined;
|
|
162
|
+
}
|
|
163
|
+
if (dirty) {
|
|
164
|
+
gitRef = `dirty:${gitRef}`;
|
|
165
|
+
}
|
|
166
|
+
const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/agents/sync`, {
|
|
167
|
+
method: 'POST',
|
|
168
|
+
body: {
|
|
169
|
+
agents_yaml: agentsYaml,
|
|
170
|
+
teams_yaml: teamsYaml,
|
|
171
|
+
chat_yaml: chatYaml,
|
|
172
|
+
git_sha: gitSha,
|
|
173
|
+
branch,
|
|
174
|
+
git_ref: gitRef,
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
if (json) {
|
|
178
|
+
(0, output_1.outputJson)(response, json);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
console.log(`✓ Agents config synced to ${projectId}`);
|
|
182
|
+
console.log(` Agents: ${configPaths.agentsPath}`);
|
|
183
|
+
console.log(` Teams: ${configPaths.teamsPath}`);
|
|
184
|
+
console.log(` Chat: ${configPaths.chatPath}`);
|
|
185
|
+
if (gitSha)
|
|
186
|
+
console.log(` Git SHA: ${gitSha.substring(0, 8)}`);
|
|
187
|
+
if (branch)
|
|
188
|
+
console.log(` Branch: ${branch}`);
|
|
189
|
+
if (dirty)
|
|
190
|
+
console.log(' Warning: working tree dirty — marked non-deployable');
|
|
191
|
+
return;
|
|
76
192
|
}
|
|
193
|
+
default:
|
|
194
|
+
throw new Error('Usage: eve agents <config|sync>');
|
|
77
195
|
}
|
|
78
196
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleChat = handleChat;
|
|
4
|
+
const args_1 = require("../lib/args");
|
|
5
|
+
const client_1 = require("../lib/client");
|
|
6
|
+
const output_1 = require("../lib/output");
|
|
7
|
+
async function handleChat(subcommand, _positionals, flags, context) {
|
|
8
|
+
const json = Boolean(flags.json);
|
|
9
|
+
switch (subcommand) {
|
|
10
|
+
case 'simulate': {
|
|
11
|
+
const projectId = (0, args_1.getStringFlag)(flags, ['project']) ?? context.projectId;
|
|
12
|
+
if (!projectId) {
|
|
13
|
+
throw new Error('Missing project id. Provide --project or set a profile default.');
|
|
14
|
+
}
|
|
15
|
+
const provider = (0, args_1.getStringFlag)(flags, ['provider']) ?? 'slack';
|
|
16
|
+
const teamId = (0, args_1.getStringFlag)(flags, ['team-id']);
|
|
17
|
+
const text = (0, args_1.getStringFlag)(flags, ['text']);
|
|
18
|
+
if (!teamId || !text) {
|
|
19
|
+
throw new Error('Usage: eve chat simulate --project <id> --team-id <team> --text <message>');
|
|
20
|
+
}
|
|
21
|
+
const channelId = (0, args_1.getStringFlag)(flags, ['channel-id']);
|
|
22
|
+
const userId = (0, args_1.getStringFlag)(flags, ['user-id']);
|
|
23
|
+
const threadKey = (0, args_1.getStringFlag)(flags, ['thread-key']);
|
|
24
|
+
const metadataFlag = (0, args_1.getStringFlag)(flags, ['metadata']);
|
|
25
|
+
let metadata;
|
|
26
|
+
if (metadataFlag) {
|
|
27
|
+
try {
|
|
28
|
+
const parsed = JSON.parse(metadataFlag);
|
|
29
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
30
|
+
metadata = parsed;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
throw new Error('Invalid --metadata (must be JSON object)');
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const response = await (0, client_1.requestJson)(context, `/projects/${projectId}/chat/simulate`, {
|
|
38
|
+
method: 'POST',
|
|
39
|
+
body: {
|
|
40
|
+
provider,
|
|
41
|
+
team_id: teamId,
|
|
42
|
+
channel_id: channelId,
|
|
43
|
+
user_id: userId,
|
|
44
|
+
text,
|
|
45
|
+
thread_key: threadKey,
|
|
46
|
+
metadata,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
(0, output_1.outputJson)(response, json, `✓ Chat simulated (thread: ${response.thread_id})`);
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
default:
|
|
53
|
+
throw new Error('Usage: eve chat <simulate>');
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.handleIntegrations = handleIntegrations;
|
|
4
|
+
const args_1 = require("../lib/args");
|
|
5
|
+
const client_1 = require("../lib/client");
|
|
6
|
+
const output_1 = require("../lib/output");
|
|
7
|
+
async function handleIntegrations(subcommand, positionals, flags, context) {
|
|
8
|
+
const json = Boolean(flags.json);
|
|
9
|
+
const orgId = (0, args_1.getStringFlag)(flags, ['org']) ?? context.orgId;
|
|
10
|
+
switch (subcommand) {
|
|
11
|
+
case 'list': {
|
|
12
|
+
if (!orgId) {
|
|
13
|
+
throw new Error('Usage: eve integrations list --org <org_id>');
|
|
14
|
+
}
|
|
15
|
+
const response = await (0, client_1.requestJson)(context, `/orgs/${orgId}/integrations`);
|
|
16
|
+
(0, output_1.outputJson)(response, json);
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
case 'slack': {
|
|
20
|
+
const action = positionals[0];
|
|
21
|
+
if (action !== 'connect') {
|
|
22
|
+
throw new Error('Usage: eve integrations slack connect --org <org_id> --team-id <team_id> [--token <token>]');
|
|
23
|
+
}
|
|
24
|
+
if (!orgId) {
|
|
25
|
+
throw new Error('Missing org id. Provide --org or set a profile default.');
|
|
26
|
+
}
|
|
27
|
+
const teamId = (0, args_1.getStringFlag)(flags, ['team-id']);
|
|
28
|
+
if (!teamId) {
|
|
29
|
+
throw new Error('Missing --team-id');
|
|
30
|
+
}
|
|
31
|
+
const token = (0, args_1.getStringFlag)(flags, ['token']);
|
|
32
|
+
const tokensJsonFlag = (0, args_1.getStringFlag)(flags, ['tokens-json']);
|
|
33
|
+
const status = (0, args_1.getStringFlag)(flags, ['status']);
|
|
34
|
+
let tokensJson;
|
|
35
|
+
if (tokensJsonFlag) {
|
|
36
|
+
try {
|
|
37
|
+
const parsed = JSON.parse(tokensJsonFlag);
|
|
38
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
|
39
|
+
tokensJson = parsed;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
catch (error) {
|
|
43
|
+
throw new Error('Invalid --tokens-json (must be JSON object)');
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (!tokensJson && token) {
|
|
47
|
+
tokensJson = { access_token: token };
|
|
48
|
+
}
|
|
49
|
+
const body = { team_id: teamId };
|
|
50
|
+
if (tokensJson)
|
|
51
|
+
body.tokens_json = tokensJson;
|
|
52
|
+
if (status)
|
|
53
|
+
body.status = status;
|
|
54
|
+
const response = await (0, client_1.requestJson)(context, `/orgs/${orgId}/integrations/slack/connect`, { method: 'POST', body });
|
|
55
|
+
(0, output_1.outputJson)(response, json, `✓ Slack integration connected: ${response.id}`);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
case 'test': {
|
|
59
|
+
const integrationId = positionals[0];
|
|
60
|
+
if (!integrationId) {
|
|
61
|
+
throw new Error('Usage: eve integrations test <integration_id>');
|
|
62
|
+
}
|
|
63
|
+
if (!orgId) {
|
|
64
|
+
throw new Error('Missing org id. Provide --org or set a profile default.');
|
|
65
|
+
}
|
|
66
|
+
const response = await (0, client_1.requestJson)(context, `/orgs/${orgId}/integrations/${integrationId}/test`, { method: 'POST' });
|
|
67
|
+
(0, output_1.outputJson)(response, json, response.ok ? '✓ Integration test ok' : 'Integration test failed');
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
default:
|
|
71
|
+
throw new Error('Usage: eve integrations <list|slack|test>');
|
|
72
|
+
}
|
|
73
|
+
}
|
package/dist/index.js
CHANGED
|
@@ -26,6 +26,8 @@ const init_1 = require("./commands/init");
|
|
|
26
26
|
const release_1 = require("./commands/release");
|
|
27
27
|
const manifest_1 = require("./commands/manifest");
|
|
28
28
|
const build_1 = require("./commands/build");
|
|
29
|
+
const integrations_1 = require("./commands/integrations");
|
|
30
|
+
const chat_1 = require("./commands/chat");
|
|
29
31
|
async function main() {
|
|
30
32
|
const { flags, positionals } = (0, args_1.parseArgs)(process.argv.slice(2));
|
|
31
33
|
const command = positionals[0];
|
|
@@ -114,6 +116,12 @@ async function main() {
|
|
|
114
116
|
case 'build':
|
|
115
117
|
await (0, build_1.handleBuild)(subcommand, rest, flags, context);
|
|
116
118
|
return;
|
|
119
|
+
case 'integrations':
|
|
120
|
+
await (0, integrations_1.handleIntegrations)(subcommand, rest, flags, context);
|
|
121
|
+
return;
|
|
122
|
+
case 'chat':
|
|
123
|
+
await (0, chat_1.handleChat)(subcommand, rest, flags, context);
|
|
124
|
+
return;
|
|
117
125
|
default:
|
|
118
126
|
(0, help_1.showMainHelp)();
|
|
119
127
|
}
|
package/dist/lib/git.js
CHANGED
|
@@ -5,6 +5,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.isGitSha = isGitSha;
|
|
7
7
|
exports.resolveGitRef = resolveGitRef;
|
|
8
|
+
exports.getGitRoot = getGitRoot;
|
|
9
|
+
exports.isGitDirty = isGitDirty;
|
|
10
|
+
exports.getGitBranch = getGitBranch;
|
|
11
|
+
exports.resolveGitBranch = resolveGitBranch;
|
|
8
12
|
const node_child_process_1 = require("node:child_process");
|
|
9
13
|
const node_path_1 = __importDefault(require("node:path"));
|
|
10
14
|
const client_js_1 = require("./client.js");
|
|
@@ -50,12 +54,55 @@ async function resolveGitRef(context, projectId, ref, repoDir) {
|
|
|
50
54
|
'Make sure the ref exists in the repository, or use a 40-character SHA.');
|
|
51
55
|
}
|
|
52
56
|
}
|
|
53
|
-
function getGitRoot() {
|
|
57
|
+
function getGitRoot(repoDir) {
|
|
54
58
|
try {
|
|
55
59
|
return (0, node_child_process_1.execSync)('git rev-parse --show-toplevel', {
|
|
60
|
+
cwd: repoDir,
|
|
61
|
+
encoding: 'utf-8',
|
|
62
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
63
|
+
}).trim();
|
|
64
|
+
}
|
|
65
|
+
catch {
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function isGitDirty(repoDir) {
|
|
70
|
+
try {
|
|
71
|
+
const status = (0, node_child_process_1.execSync)('git status --porcelain', {
|
|
72
|
+
cwd: repoDir,
|
|
73
|
+
encoding: 'utf-8',
|
|
74
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
75
|
+
}).trim();
|
|
76
|
+
return status.length > 0;
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
function getGitBranch(repoDir) {
|
|
83
|
+
try {
|
|
84
|
+
const branch = (0, node_child_process_1.execSync)('git branch --show-current', {
|
|
85
|
+
cwd: repoDir,
|
|
56
86
|
encoding: 'utf-8',
|
|
57
87
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
58
88
|
}).trim();
|
|
89
|
+
return branch || null;
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
function resolveGitBranch(repoDir, ref) {
|
|
96
|
+
if (!ref || isGitSha(ref)) {
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
(0, node_child_process_1.execSync)(`git show-ref --verify --quiet refs/heads/${ref}`, {
|
|
101
|
+
cwd: repoDir,
|
|
102
|
+
encoding: 'utf-8',
|
|
103
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
104
|
+
});
|
|
105
|
+
return ref;
|
|
59
106
|
}
|
|
60
107
|
catch {
|
|
61
108
|
return null;
|
package/dist/lib/help.js
CHANGED
|
@@ -510,13 +510,14 @@ Jobs default to 'ready' phase, making them immediately schedulable.`,
|
|
|
510
510
|
},
|
|
511
511
|
agents: {
|
|
512
512
|
description: 'Inspect agent policy config and harness capabilities for orchestration. Default profile: primary-orchestrator.',
|
|
513
|
-
usage: 'eve agents config
|
|
513
|
+
usage: 'eve agents <config|sync> [options]',
|
|
514
514
|
subcommands: {
|
|
515
515
|
config: {
|
|
516
516
|
description: 'Show agent policy (profiles/councils) and harness availability',
|
|
517
517
|
usage: 'eve agents config [--path <dir>] [--no-harnesses]',
|
|
518
518
|
options: [
|
|
519
519
|
'--path <dir> Repository root to inspect (default: cwd)',
|
|
520
|
+
'--repo-dir <dir> Alias for --path',
|
|
520
521
|
'--no-harnesses Skip harness availability lookup',
|
|
521
522
|
],
|
|
522
523
|
examples: [
|
|
@@ -525,8 +526,25 @@ Jobs default to 'ready' phase, making them immediately schedulable.`,
|
|
|
525
526
|
'eve agents config --path ../my-repo',
|
|
526
527
|
],
|
|
527
528
|
},
|
|
529
|
+
sync: {
|
|
530
|
+
description: 'Sync agents.yaml/teams.yaml/chat.yaml to the API',
|
|
531
|
+
usage: 'eve agents sync --project <id> --ref <sha|branch> [--repo-dir <path>]',
|
|
532
|
+
options: [
|
|
533
|
+
'--project <id> Project ID (uses profile default)',
|
|
534
|
+
'--ref <ref> Git ref to sync (required unless --local)',
|
|
535
|
+
'--local Allow local sync (only for localhost/lvh.me API)',
|
|
536
|
+
'--allow-dirty Allow syncing a dirty working tree',
|
|
537
|
+
'--repo-dir <path> Repository root (default: cwd)',
|
|
538
|
+
'--force-nonlocal Allow --local against non-local API URL',
|
|
539
|
+
],
|
|
540
|
+
examples: [
|
|
541
|
+
'eve agents sync --project proj_xxx --ref main',
|
|
542
|
+
'eve agents sync --project proj_xxx --ref HEAD',
|
|
543
|
+
'eve agents sync --project proj_xxx --local --allow-dirty',
|
|
544
|
+
],
|
|
545
|
+
},
|
|
528
546
|
},
|
|
529
|
-
examples: ['eve agents config --json'],
|
|
547
|
+
examples: ['eve agents config --json', 'eve agents sync --project proj_xxx --ref main'],
|
|
530
548
|
},
|
|
531
549
|
profile: {
|
|
532
550
|
description: `Manage repo-local CLI profiles. Profiles store defaults (API URL, org, project) so you don't
|
|
@@ -1382,6 +1400,58 @@ eve-new-project-setup skill to complete configuration.`,
|
|
|
1382
1400
|
'eve system orchestrator status',
|
|
1383
1401
|
],
|
|
1384
1402
|
},
|
|
1403
|
+
integrations: {
|
|
1404
|
+
description: 'Manage chat integrations (Slack) for an organization.',
|
|
1405
|
+
usage: 'eve integrations <subcommand> [options]',
|
|
1406
|
+
subcommands: {
|
|
1407
|
+
list: {
|
|
1408
|
+
description: 'List integrations for an org',
|
|
1409
|
+
usage: 'eve integrations list --org <org_id>',
|
|
1410
|
+
options: ['--org <id> Organization ID'],
|
|
1411
|
+
},
|
|
1412
|
+
slack: {
|
|
1413
|
+
description: 'Connect a Slack workspace (stub OAuth)',
|
|
1414
|
+
usage: 'eve integrations slack connect --org <org_id> --team-id <team_id> [--token <token>]',
|
|
1415
|
+
options: [
|
|
1416
|
+
'--org <id> Organization ID',
|
|
1417
|
+
'--team-id <id> Slack team ID',
|
|
1418
|
+
'--token <token> Slack access token (stored in tokens_json)',
|
|
1419
|
+
'--tokens-json <json> Raw tokens_json payload',
|
|
1420
|
+
'--status <status> Integration status (default: active)',
|
|
1421
|
+
],
|
|
1422
|
+
},
|
|
1423
|
+
test: {
|
|
1424
|
+
description: 'Test an integration',
|
|
1425
|
+
usage: 'eve integrations test <integration_id>',
|
|
1426
|
+
},
|
|
1427
|
+
},
|
|
1428
|
+
examples: [
|
|
1429
|
+
'eve integrations list --org org_xxx',
|
|
1430
|
+
'eve integrations slack connect --org org_xxx --team-id T123 --token xoxb-...',
|
|
1431
|
+
],
|
|
1432
|
+
},
|
|
1433
|
+
chat: {
|
|
1434
|
+
description: 'Chat tooling for gateway testing.',
|
|
1435
|
+
usage: 'eve chat <subcommand> [options]',
|
|
1436
|
+
subcommands: {
|
|
1437
|
+
simulate: {
|
|
1438
|
+
description: 'Simulate an inbound chat message',
|
|
1439
|
+
usage: 'eve chat simulate --project <id> --team-id <team> --text <message>',
|
|
1440
|
+
options: [
|
|
1441
|
+
'--project <id> Project ID (uses profile default)',
|
|
1442
|
+
'--provider <name> Provider name (default: slack)',
|
|
1443
|
+
'--team-id <id> Slack team ID',
|
|
1444
|
+
'--channel-id <id> Channel ID',
|
|
1445
|
+
'--user-id <id> User ID',
|
|
1446
|
+
'--thread-key <key> Thread key override',
|
|
1447
|
+
'--metadata <json> Extra metadata JSON',
|
|
1448
|
+
],
|
|
1449
|
+
},
|
|
1450
|
+
},
|
|
1451
|
+
examples: [
|
|
1452
|
+
'eve chat simulate --project proj_xxx --team-id T123 --text "hello"',
|
|
1453
|
+
],
|
|
1454
|
+
},
|
|
1385
1455
|
};
|
|
1386
1456
|
function showMainHelp() {
|
|
1387
1457
|
console.log('Eve Horizon CLI');
|
|
@@ -1407,6 +1477,8 @@ function showMainHelp() {
|
|
|
1407
1477
|
console.log(' secrets Manage secrets (project/org/user scope)');
|
|
1408
1478
|
console.log(' harness Inspect harnesses and auth status');
|
|
1409
1479
|
console.log(' agents Inspect agent policy and harness capabilities');
|
|
1480
|
+
console.log(' integrations Manage chat integrations (Slack)');
|
|
1481
|
+
console.log(' chat Simulate chat messages (gateway testing)');
|
|
1410
1482
|
console.log(' profile Manage CLI profiles (API URL, defaults)');
|
|
1411
1483
|
console.log(' auth Authentication (login, logout, status)');
|
|
1412
1484
|
console.log(' admin User and identity management (invite)');
|