@eve-horizon/cli 0.2.28 → 0.2.30
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 +272 -46
- package/package.json +8 -8
package/dist/index.js
CHANGED
|
@@ -48721,6 +48721,7 @@ function resolveContext(flags, credentials) {
|
|
|
48721
48721
|
const projectId = getStringFlag(flags, ["project"]) || process.env.EVE_PROJECT_ID || profile.project_id;
|
|
48722
48722
|
const authKey = toAuthKey(apiUrl);
|
|
48723
48723
|
const tokenEntry = credentials.tokens[authKey] || credentials.profiles?.[profileName];
|
|
48724
|
+
const jobToken = process.env.EVE_JOB_TOKEN;
|
|
48724
48725
|
return {
|
|
48725
48726
|
apiUrl,
|
|
48726
48727
|
orgId,
|
|
@@ -48728,9 +48729,9 @@ function resolveContext(flags, credentials) {
|
|
|
48728
48729
|
profileName,
|
|
48729
48730
|
profile,
|
|
48730
48731
|
authKey,
|
|
48731
|
-
token: tokenEntry?.access_token,
|
|
48732
|
-
refreshToken: tokenEntry?.refresh_token,
|
|
48733
|
-
expiresAt: tokenEntry?.expires_at,
|
|
48732
|
+
token: jobToken || tokenEntry?.access_token,
|
|
48733
|
+
refreshToken: jobToken ? void 0 : tokenEntry?.refresh_token,
|
|
48734
|
+
expiresAt: jobToken ? void 0 : tokenEntry?.expires_at,
|
|
48734
48735
|
profileSource
|
|
48735
48736
|
};
|
|
48736
48737
|
}
|
|
@@ -50288,7 +50289,7 @@ for cloud deployments. Credentials are stored globally per API URL.`,
|
|
|
50288
50289
|
]
|
|
50289
50290
|
},
|
|
50290
50291
|
admin: {
|
|
50291
|
-
description: "Administrative commands for user and
|
|
50292
|
+
description: "Administrative commands for user, identity, and platform operations.",
|
|
50292
50293
|
usage: "eve admin <subcommand> [options]",
|
|
50293
50294
|
subcommands: {
|
|
50294
50295
|
invite: {
|
|
@@ -50304,11 +50305,24 @@ for cloud deployments. Credentials are stored globally per API URL.`,
|
|
|
50304
50305
|
"eve admin invite --email user@example.com --github octocat",
|
|
50305
50306
|
"eve admin invite --email user@example.com --github octocat --role admin --org org_xxx"
|
|
50306
50307
|
]
|
|
50308
|
+
},
|
|
50309
|
+
"ingress-aliases": {
|
|
50310
|
+
description: "Inspect and reclaim ingress alias claims (system admin)",
|
|
50311
|
+
usage: "eve admin ingress-aliases <list|reclaim> [options]",
|
|
50312
|
+
options: [
|
|
50313
|
+
"list options: --alias <name> --project <id> --environment <id|null> --limit <n> --offset <n>",
|
|
50314
|
+
'reclaim usage: eve admin ingress-aliases reclaim <alias> --reason "<text>"'
|
|
50315
|
+
],
|
|
50316
|
+
examples: [
|
|
50317
|
+
"eve admin ingress-aliases list --project proj_xxx",
|
|
50318
|
+
'eve admin ingress-aliases reclaim eve-pm --reason "Reserved org rename"'
|
|
50319
|
+
]
|
|
50307
50320
|
}
|
|
50308
50321
|
},
|
|
50309
50322
|
examples: [
|
|
50310
50323
|
"eve admin invite --email user@example.com --github octocat",
|
|
50311
|
-
"eve admin invite --email user@example.com --github octocat --org org_xxx"
|
|
50324
|
+
"eve admin invite --email user@example.com --github octocat --org org_xxx",
|
|
50325
|
+
"eve admin ingress-aliases list"
|
|
50312
50326
|
]
|
|
50313
50327
|
},
|
|
50314
50328
|
release: {
|
|
@@ -51321,7 +51335,7 @@ function showMainHelp() {
|
|
|
51321
51335
|
console.log(" analytics Org analytics (jobs, pipelines, env health)");
|
|
51322
51336
|
console.log(" ollama Manage inference targets, aliases, and model routes");
|
|
51323
51337
|
console.log(" access Access control: permissions, roles, bindings, policy-as-code sync");
|
|
51324
|
-
console.log(" admin User and
|
|
51338
|
+
console.log(" admin User and platform admin operations");
|
|
51325
51339
|
console.log(" skills Install skills from skills.txt (skills CLI)");
|
|
51326
51340
|
console.log(" migrate Migration helpers for upgrading config formats");
|
|
51327
51341
|
console.log(" system System health and status checks");
|
|
@@ -51403,6 +51417,7 @@ function showSubcommandHelp(command, subcommand) {
|
|
|
51403
51417
|
// src/lib/client.ts
|
|
51404
51418
|
async function requestJson(context2, path6, options = {}) {
|
|
51405
51419
|
const response = await requestRaw(context2, path6, options);
|
|
51420
|
+
const method = options.method ?? "GET";
|
|
51406
51421
|
if (response.status === 401 && options.tokenOverride === void 0) {
|
|
51407
51422
|
const refreshed = await attemptRefresh(context2);
|
|
51408
51423
|
if (refreshed?.access_token) {
|
|
@@ -51414,14 +51429,16 @@ async function requestJson(context2, path6, options = {}) {
|
|
|
51414
51429
|
tokenOverride: refreshed.access_token
|
|
51415
51430
|
});
|
|
51416
51431
|
if (!retry.ok && !options.allowError) {
|
|
51417
|
-
const message =
|
|
51418
|
-
throw new Error(`HTTP ${retry.status}: ${message}`);
|
|
51432
|
+
const message = formatErrorMessage(retry);
|
|
51433
|
+
throw new Error(`HTTP ${retry.status}: ${method} ${path6}: ${message}`);
|
|
51419
51434
|
}
|
|
51420
51435
|
return retry.data;
|
|
51421
51436
|
}
|
|
51422
51437
|
}
|
|
51423
51438
|
if (!response.ok && !options.allowError) {
|
|
51424
|
-
const message =
|
|
51439
|
+
const message = formatErrorMessage(response);
|
|
51440
|
+
const requestTarget = `${method} ${path6}`;
|
|
51441
|
+
const requestFailedContext = `while calling ${requestTarget}: ${message}`;
|
|
51425
51442
|
if ((response.status === 404 || response.status === 500) && message.includes("Project not found")) {
|
|
51426
51443
|
const projectIdMatch = message.match(/Project not found: (proj_[a-z0-9]+)/);
|
|
51427
51444
|
const projectId = projectIdMatch?.[1] ?? "unknown";
|
|
@@ -51439,7 +51456,7 @@ To fix this, either:
|
|
|
51439
51456
|
To list available projects: eve project list`
|
|
51440
51457
|
);
|
|
51441
51458
|
}
|
|
51442
|
-
throw new Error(`HTTP ${response.status}: ${
|
|
51459
|
+
throw new Error(`HTTP ${response.status}: ${requestFailedContext}`);
|
|
51443
51460
|
}
|
|
51444
51461
|
return response.data;
|
|
51445
51462
|
}
|
|
@@ -51463,11 +51480,19 @@ async function requestRaw(context2, path6, options = {}) {
|
|
|
51463
51480
|
if (token) {
|
|
51464
51481
|
headers.Authorization = `Bearer ${token}`;
|
|
51465
51482
|
}
|
|
51466
|
-
const
|
|
51467
|
-
|
|
51468
|
-
|
|
51469
|
-
|
|
51470
|
-
|
|
51483
|
+
const url = `${context2.apiUrl}${path6}`;
|
|
51484
|
+
const method = options.method ?? "GET";
|
|
51485
|
+
let response;
|
|
51486
|
+
try {
|
|
51487
|
+
response = await fetch(url, {
|
|
51488
|
+
method: options.method ?? "GET",
|
|
51489
|
+
headers,
|
|
51490
|
+
body: options.body ? JSON.stringify(options.body) : void 0
|
|
51491
|
+
});
|
|
51492
|
+
} catch (error) {
|
|
51493
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
51494
|
+
throw new Error(`Request failed for ${method} ${url}: ${message}`);
|
|
51495
|
+
}
|
|
51471
51496
|
const text = await response.text();
|
|
51472
51497
|
let data = null;
|
|
51473
51498
|
if (text) {
|
|
@@ -51479,6 +51504,19 @@ async function requestRaw(context2, path6, options = {}) {
|
|
|
51479
51504
|
}
|
|
51480
51505
|
return { status: response.status, ok: response.ok, data, text };
|
|
51481
51506
|
}
|
|
51507
|
+
function formatErrorMessage(response) {
|
|
51508
|
+
if (typeof response.data === "string") {
|
|
51509
|
+
return response.data;
|
|
51510
|
+
}
|
|
51511
|
+
if (response.data && typeof response.data === "object") {
|
|
51512
|
+
const payload = response.data;
|
|
51513
|
+
return [payload.message, payload.error, payload.detail, response.text].map((entry) => {
|
|
51514
|
+
if (typeof entry === "string" && entry.trim()) return entry;
|
|
51515
|
+
return "";
|
|
51516
|
+
}).find((entry) => entry.length > 0) ?? response.text;
|
|
51517
|
+
}
|
|
51518
|
+
return response.text;
|
|
51519
|
+
}
|
|
51482
51520
|
async function attemptRefresh(context2) {
|
|
51483
51521
|
if (!context2.refreshToken) return void 0;
|
|
51484
51522
|
if (!context2.profile.supabase_url || !context2.profile.supabase_anon_key) return void 0;
|
|
@@ -52116,7 +52154,12 @@ async function fetchProfileStatus(ctx, envFilter) {
|
|
|
52116
52154
|
let services = [];
|
|
52117
52155
|
try {
|
|
52118
52156
|
const diagnose = await requestJson(ctx, `/projects/${ctx.projectId}/envs/${env.name}/diagnose`);
|
|
52119
|
-
services = buildStatusServices(
|
|
52157
|
+
services = buildStatusServices(
|
|
52158
|
+
diagnose.pods,
|
|
52159
|
+
diagnose.namespace ?? env.namespace,
|
|
52160
|
+
domain,
|
|
52161
|
+
env.ingress_aliases ?? []
|
|
52162
|
+
);
|
|
52120
52163
|
} catch {
|
|
52121
52164
|
}
|
|
52122
52165
|
environments.push({
|
|
@@ -52135,7 +52178,7 @@ async function fetchProfileStatus(ctx, envFilter) {
|
|
|
52135
52178
|
environments
|
|
52136
52179
|
};
|
|
52137
52180
|
}
|
|
52138
|
-
function buildStatusServices(pods, namespace, domain) {
|
|
52181
|
+
function buildStatusServices(pods, namespace, domain, ingressAliases) {
|
|
52139
52182
|
const services = /* @__PURE__ */ new Map();
|
|
52140
52183
|
for (const pod of pods) {
|
|
52141
52184
|
const component = pod.labels["eve.component"] || pod.labels["app.kubernetes.io/name"] || pod.labels["app"] || pod.labels["component"] || "unknown";
|
|
@@ -52149,12 +52192,14 @@ function buildStatusServices(pods, namespace, domain) {
|
|
|
52149
52192
|
const allDone = info.phases.size > 0 && [...info.phases].every((p) => p === "Succeeded" || p === "Failed");
|
|
52150
52193
|
const status = allDone ? "completed" : info.ready === info.total ? "ready" : "not-ready";
|
|
52151
52194
|
const url = !allDone && namespace && domain ? buildServiceUrl(name, namespace, domain) : null;
|
|
52195
|
+
const aliasUrls = !allDone && domain ? ingressAliases.filter((entry) => entry.service_name === name).map((entry) => buildAliasUrl(entry.alias, domain)).sort((a, b2) => a.localeCompare(b2)) : [];
|
|
52152
52196
|
return {
|
|
52153
52197
|
name,
|
|
52154
52198
|
pods_ready: info.ready,
|
|
52155
52199
|
pods_total: info.total,
|
|
52156
52200
|
status,
|
|
52157
|
-
url
|
|
52201
|
+
url,
|
|
52202
|
+
alias_urls: aliasUrls
|
|
52158
52203
|
};
|
|
52159
52204
|
});
|
|
52160
52205
|
}
|
|
@@ -52173,6 +52218,10 @@ function buildServiceUrl(component, namespace, domain) {
|
|
|
52173
52218
|
const secure = !domain.includes("lvh.me") && !domain.includes("localhost");
|
|
52174
52219
|
return `${secure ? "https" : "http"}://${component}.${slug}.${domain}`;
|
|
52175
52220
|
}
|
|
52221
|
+
function buildAliasUrl(alias, domain) {
|
|
52222
|
+
const secure = !domain.includes("lvh.me") && !domain.includes("localhost");
|
|
52223
|
+
return `${secure ? "https" : "http"}://${alias}.${domain}`;
|
|
52224
|
+
}
|
|
52176
52225
|
function formatStatusOutput(results) {
|
|
52177
52226
|
for (let i = 0; i < results.length; i++) {
|
|
52178
52227
|
const r = results[i];
|
|
@@ -52211,10 +52260,25 @@ function formatStatusOutput(results) {
|
|
|
52211
52260
|
const podsW = Math.max(...env.services.map((s) => `${s.pods_ready}/${s.pods_total}`.length));
|
|
52212
52261
|
for (const svc of env.services) {
|
|
52213
52262
|
const pods = `${svc.pods_ready}/${svc.pods_total}`;
|
|
52214
|
-
const
|
|
52263
|
+
const urls = [];
|
|
52264
|
+
if (svc.url) {
|
|
52265
|
+
urls.push(svc.url);
|
|
52266
|
+
}
|
|
52267
|
+
for (const aliasUrl of svc.alias_urls ?? []) {
|
|
52268
|
+
if (!urls.includes(aliasUrl)) {
|
|
52269
|
+
urls.push(aliasUrl);
|
|
52270
|
+
}
|
|
52271
|
+
}
|
|
52272
|
+
const urlPart = urls.length > 0 ? ` ${urls[0]}` : "";
|
|
52215
52273
|
console.log(
|
|
52216
52274
|
` ${padRight(svc.name, nameW)} ${padRight(pods, podsW)} ${padRight(svc.status, 9)}${urlPart}`
|
|
52217
52275
|
);
|
|
52276
|
+
if (urls.length > 1) {
|
|
52277
|
+
const prefix = ` ${padRight("", nameW)} ${padRight("", podsW)} ${padRight("", 9)}`;
|
|
52278
|
+
for (const aliasUrl of urls.slice(1)) {
|
|
52279
|
+
console.log(`${prefix} ${aliasUrl}`);
|
|
52280
|
+
}
|
|
52281
|
+
}
|
|
52218
52282
|
}
|
|
52219
52283
|
}
|
|
52220
52284
|
}
|
|
@@ -56731,6 +56795,10 @@ var EnvironmentResponseSchema = external_exports.object({
|
|
|
56731
56795
|
labels: EnvironmentLabelsSchema.nullable(),
|
|
56732
56796
|
current_release_id: external_exports.string().nullable(),
|
|
56733
56797
|
last_failed_release_id: external_exports.string().nullable(),
|
|
56798
|
+
ingress_aliases: external_exports.array(external_exports.object({
|
|
56799
|
+
alias: external_exports.string(),
|
|
56800
|
+
service_name: external_exports.string()
|
|
56801
|
+
})).optional(),
|
|
56734
56802
|
status: EnvironmentStatusSchema,
|
|
56735
56803
|
suspended_at: external_exports.string().nullable(),
|
|
56736
56804
|
suspension_reason: external_exports.string().nullable(),
|
|
@@ -56741,6 +56809,9 @@ var EnvironmentListResponseSchema = external_exports.object({
|
|
|
56741
56809
|
data: external_exports.array(EnvironmentResponseSchema),
|
|
56742
56810
|
pagination: PaginationSchema
|
|
56743
56811
|
});
|
|
56812
|
+
var DeleteEnvironmentRequestSchema = external_exports.object({
|
|
56813
|
+
force: external_exports.boolean().optional()
|
|
56814
|
+
}).optional().default({});
|
|
56744
56815
|
var EnvLogEntrySchema = external_exports.object({
|
|
56745
56816
|
timestamp: external_exports.string(),
|
|
56746
56817
|
line: external_exports.string(),
|
|
@@ -57795,7 +57866,8 @@ var SecretResolveResponseSchema = external_exports.object({
|
|
|
57795
57866
|
});
|
|
57796
57867
|
var SecretMissingItemSchema = external_exports.object({
|
|
57797
57868
|
key: external_exports.string(),
|
|
57798
|
-
hints: external_exports.array(external_exports.string())
|
|
57869
|
+
hints: external_exports.array(external_exports.string()),
|
|
57870
|
+
suggestion: external_exports.string().optional()
|
|
57799
57871
|
});
|
|
57800
57872
|
var SecretValidationResultSchema = external_exports.object({
|
|
57801
57873
|
missing: external_exports.array(SecretMissingItemSchema)
|
|
@@ -58109,9 +58181,15 @@ var ManagedDbConfigSchema = external_exports.object({
|
|
|
58109
58181
|
engine_version: external_exports.string().optional()
|
|
58110
58182
|
// e.g., '16'
|
|
58111
58183
|
});
|
|
58184
|
+
var IngressAliasPattern = /^[a-z][a-z0-9-]*[a-z0-9]$/;
|
|
58185
|
+
var IngressConfigSchema = external_exports.object({
|
|
58186
|
+
public: external_exports.boolean().optional(),
|
|
58187
|
+
port: external_exports.number().optional(),
|
|
58188
|
+
alias: external_exports.string().min(3).max(63).regex(IngressAliasPattern).optional()
|
|
58189
|
+
}).passthrough();
|
|
58112
58190
|
var ServiceXeveSchema = external_exports.object({
|
|
58113
58191
|
role: external_exports.string().optional(),
|
|
58114
|
-
ingress:
|
|
58192
|
+
ingress: IngressConfigSchema.optional(),
|
|
58115
58193
|
api_spec: ApiSpecSchema.optional(),
|
|
58116
58194
|
api_specs: external_exports.array(ApiSpecSchema).optional(),
|
|
58117
58195
|
external: external_exports.boolean().optional(),
|
|
@@ -59529,7 +59607,7 @@ var ManagedModelRegistrySchema = external_exports.record(ManagedModelConfigSchem
|
|
|
59529
59607
|
var InferenceScopeKindSchema = external_exports.enum(["platform", "org", "project"]);
|
|
59530
59608
|
var InferenceTargetTypeSchema = external_exports.enum(["ollama_pool", "external_ollama", "openai_compat"]);
|
|
59531
59609
|
var InferenceTransportProfileSchema = external_exports.enum(["ollama_api", "openai_compat"]);
|
|
59532
|
-
var InferenceTargetStatusSchema = external_exports.enum(["unknown", "healthy", "unhealthy", "draining", "disabled"]);
|
|
59610
|
+
var InferenceTargetStatusSchema = external_exports.enum(["unknown", "healthy", "unhealthy", "waking", "draining", "disabled"]);
|
|
59533
59611
|
var InferenceTargetSchema = external_exports.object({
|
|
59534
59612
|
id: external_exports.string(),
|
|
59535
59613
|
scope_kind: InferenceScopeKindSchema,
|
|
@@ -61682,6 +61760,8 @@ var HARNESS_ENV_MAP = deriveHarnessEnvMap();
|
|
|
61682
61760
|
|
|
61683
61761
|
// ../shared/dist/permissions.js
|
|
61684
61762
|
var ALL_PERMISSIONS = [
|
|
61763
|
+
// Inference
|
|
61764
|
+
"inference:write",
|
|
61685
61765
|
// Jobs
|
|
61686
61766
|
"jobs:read",
|
|
61687
61767
|
"jobs:write",
|
|
@@ -67266,7 +67346,8 @@ async function handleDelete(positionals, flags, context2, json) {
|
|
|
67266
67346
|
context2,
|
|
67267
67347
|
`/projects/${projectId}/envs/${envName}`,
|
|
67268
67348
|
{
|
|
67269
|
-
method: "DELETE"
|
|
67349
|
+
method: "DELETE",
|
|
67350
|
+
...force ? { body: { force: true } } : {}
|
|
67270
67351
|
}
|
|
67271
67352
|
);
|
|
67272
67353
|
if (json) {
|
|
@@ -67479,6 +67560,12 @@ function formatEnvironmentDetails(env, health) {
|
|
|
67479
67560
|
console.log(` Database Ref: ${env.db_ref || "(none)"}`);
|
|
67480
67561
|
console.log(` Current Release: ${env.current_release_id || "(none)"}`);
|
|
67481
67562
|
console.log(` Last Failed: ${env.last_failed_release_id || "(none)"}`);
|
|
67563
|
+
if (env.ingress_aliases && env.ingress_aliases.length > 0) {
|
|
67564
|
+
console.log(" Ingress Aliases:");
|
|
67565
|
+
for (const entry of env.ingress_aliases) {
|
|
67566
|
+
console.log(` ${entry.alias} -> ${entry.service_name}`);
|
|
67567
|
+
}
|
|
67568
|
+
}
|
|
67482
67569
|
if (health) {
|
|
67483
67570
|
console.log("");
|
|
67484
67571
|
console.log(` Deployment Status: ${health.status}`);
|
|
@@ -71404,6 +71491,7 @@ async function applyMigrations(options) {
|
|
|
71404
71491
|
`;
|
|
71405
71492
|
const appliedMap = new Map(appliedRows.map((row) => [row.name, row.checksum]));
|
|
71406
71493
|
const results = [];
|
|
71494
|
+
const isBaseline = appliedMap.size === 0;
|
|
71407
71495
|
for (const migration of migrations) {
|
|
71408
71496
|
const checksum = (0, import_crypto6.createHash)("sha256").update(migration.sql).digest("hex");
|
|
71409
71497
|
const existingChecksum = appliedMap.get(migration.name);
|
|
@@ -71420,10 +71508,25 @@ Current checksum: ${checksum}`);
|
|
|
71420
71508
|
});
|
|
71421
71509
|
continue;
|
|
71422
71510
|
}
|
|
71423
|
-
|
|
71424
|
-
await
|
|
71425
|
-
|
|
71426
|
-
|
|
71511
|
+
try {
|
|
71512
|
+
await db.begin(async (tx) => {
|
|
71513
|
+
await tx.unsafe(migration.sql);
|
|
71514
|
+
await tx.unsafe("INSERT INTO schema_migrations (name, checksum) VALUES ($1, $2)", [migration.name, checksum]);
|
|
71515
|
+
});
|
|
71516
|
+
} catch (error) {
|
|
71517
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
71518
|
+
const isAlreadyExists = /already exists/i.test(msg);
|
|
71519
|
+
if (isBaseline && isAlreadyExists) {
|
|
71520
|
+
console.log(` \u2192 ${migration.name} (baselined \u2014 schema already present)`);
|
|
71521
|
+
await db`
|
|
71522
|
+
INSERT INTO schema_migrations (name, checksum)
|
|
71523
|
+
VALUES (${migration.name}, ${checksum})
|
|
71524
|
+
`;
|
|
71525
|
+
results.push({ filename: migration.name, applied: true, checksum });
|
|
71526
|
+
continue;
|
|
71527
|
+
}
|
|
71528
|
+
throw error;
|
|
71529
|
+
}
|
|
71427
71530
|
results.push({
|
|
71428
71531
|
filename: migration.name,
|
|
71429
71532
|
applied: true,
|
|
@@ -73035,6 +73138,61 @@ ${response.length} record(s)`);
|
|
|
73035
73138
|
throw new Error("Usage: eve admin usage <list|summary> --org <orgId> [--since] [--until] [--limit] [--json]");
|
|
73036
73139
|
}
|
|
73037
73140
|
}
|
|
73141
|
+
case "ingress-aliases": {
|
|
73142
|
+
const action = positionals[0] ?? "list";
|
|
73143
|
+
switch (action) {
|
|
73144
|
+
case "list": {
|
|
73145
|
+
const params = new URLSearchParams();
|
|
73146
|
+
const alias = getStringFlag(flags, ["alias"]);
|
|
73147
|
+
const projectId = getStringFlag(flags, ["project", "project_id"]);
|
|
73148
|
+
const environmentId = getStringFlag(flags, ["environment", "env", "environment_id"]);
|
|
73149
|
+
const limit = getStringFlag(flags, ["limit"]);
|
|
73150
|
+
const offset = getStringFlag(flags, ["offset"]);
|
|
73151
|
+
if (alias) params.set("alias", alias);
|
|
73152
|
+
if (projectId) params.set("project_id", projectId);
|
|
73153
|
+
if (environmentId) params.set("environment_id", environmentId);
|
|
73154
|
+
if (limit) params.set("limit", limit);
|
|
73155
|
+
if (offset) params.set("offset", offset);
|
|
73156
|
+
const query = params.toString();
|
|
73157
|
+
const path6 = `/admin/ingress-aliases${query ? `?${query}` : ""}`;
|
|
73158
|
+
const response = await requestJson(context2, path6);
|
|
73159
|
+
if (json) {
|
|
73160
|
+
outputJson(response, true);
|
|
73161
|
+
return;
|
|
73162
|
+
}
|
|
73163
|
+
const rows = Array.isArray(response.data) ? response.data : [];
|
|
73164
|
+
if (rows.length === 0) {
|
|
73165
|
+
console.log("No ingress aliases found.");
|
|
73166
|
+
return;
|
|
73167
|
+
}
|
|
73168
|
+
for (const row of rows) {
|
|
73169
|
+
console.log(`${row.alias} project=${row.project_id} env=${row.environment_id ?? "(reserved)"} service=${row.service_name}`);
|
|
73170
|
+
}
|
|
73171
|
+
console.log(`
|
|
73172
|
+
${rows.length} alias(es)`);
|
|
73173
|
+
return;
|
|
73174
|
+
}
|
|
73175
|
+
case "reclaim": {
|
|
73176
|
+
const alias = positionals[1] ?? getStringFlag(flags, ["alias"]);
|
|
73177
|
+
const reason = getStringFlag(flags, ["reason"]);
|
|
73178
|
+
if (!alias || !reason) {
|
|
73179
|
+
throw new Error('Usage: eve admin ingress-aliases reclaim <alias> --reason "<text>"');
|
|
73180
|
+
}
|
|
73181
|
+
const response = await requestJson(context2, `/admin/ingress-aliases/${encodeURIComponent(alias)}/reclaim`, {
|
|
73182
|
+
method: "POST",
|
|
73183
|
+
body: { reason }
|
|
73184
|
+
});
|
|
73185
|
+
outputJson(
|
|
73186
|
+
response,
|
|
73187
|
+
json,
|
|
73188
|
+
`+ Reclaimed ${response.alias} (project=${response.project_id}, env=${response.environment_id ?? "(reserved)"})`
|
|
73189
|
+
);
|
|
73190
|
+
return;
|
|
73191
|
+
}
|
|
73192
|
+
default:
|
|
73193
|
+
throw new Error("Usage: eve admin ingress-aliases <list|reclaim> [options]");
|
|
73194
|
+
}
|
|
73195
|
+
}
|
|
73038
73196
|
case "access-requests": {
|
|
73039
73197
|
const action = positionals[0];
|
|
73040
73198
|
switch (action) {
|
|
@@ -73097,7 +73255,7 @@ ${response.length} record(s)`);
|
|
|
73097
73255
|
}
|
|
73098
73256
|
}
|
|
73099
73257
|
default:
|
|
73100
|
-
throw new Error("Usage: eve admin <invite|pricing|receipts|balance|usage|access-requests>");
|
|
73258
|
+
throw new Error("Usage: eve admin <invite|pricing|receipts|balance|usage|ingress-aliases|access-requests>");
|
|
73101
73259
|
}
|
|
73102
73260
|
}
|
|
73103
73261
|
function formatBalanceSummary(data) {
|
|
@@ -78003,7 +78161,36 @@ async function handleOllama(subcommand, positionals, flags, context2) {
|
|
|
78003
78161
|
if (!json) console.log("Target test completed");
|
|
78004
78162
|
return;
|
|
78005
78163
|
}
|
|
78006
|
-
|
|
78164
|
+
if (action === "wake") {
|
|
78165
|
+
const targetId = positionals[1];
|
|
78166
|
+
if (!targetId) throw new Error("Usage: eve ollama target wake <target-id> [--wait=true] [--timeout-ms <ms>]");
|
|
78167
|
+
const query = new URLSearchParams();
|
|
78168
|
+
const wait = asString(flags, "wait");
|
|
78169
|
+
const timeoutMs = asString(flags, "timeout-ms");
|
|
78170
|
+
if (wait === "true" || wait === "1") query.set("wait", "true");
|
|
78171
|
+
if (timeoutMs) query.set("timeout_ms", timeoutMs);
|
|
78172
|
+
const suffix = query.toString() ? `?${query.toString()}` : "";
|
|
78173
|
+
const result = await requestJson(context2, `/inference/targets/${targetId}/wake${suffix}`, {
|
|
78174
|
+
method: "POST"
|
|
78175
|
+
});
|
|
78176
|
+
outputJson(result, json);
|
|
78177
|
+
if (!json) {
|
|
78178
|
+
const nextState = result.ready ? "ready" : result.state;
|
|
78179
|
+
console.log(`Wake request state: ${result.state}`);
|
|
78180
|
+
console.log(`Target: ${result.target_id}`);
|
|
78181
|
+
if (result.waited_ms !== void 0) {
|
|
78182
|
+
console.log(`Waited: ${result.waited_ms}ms`);
|
|
78183
|
+
} else {
|
|
78184
|
+
console.log(`Retry after: ${result.retry_after_seconds}s`);
|
|
78185
|
+
}
|
|
78186
|
+
console.log(`Message: ${result.message}`);
|
|
78187
|
+
if (result.ready) {
|
|
78188
|
+
console.log(`Wake result: ${nextState}`);
|
|
78189
|
+
}
|
|
78190
|
+
}
|
|
78191
|
+
return;
|
|
78192
|
+
}
|
|
78193
|
+
throw new Error("Usage: eve ollama target <add|rm|test|wake> ...");
|
|
78007
78194
|
}
|
|
78008
78195
|
case "models": {
|
|
78009
78196
|
const models = await requestJson(context2, "/inference/models");
|
|
@@ -78552,6 +78739,10 @@ var KUBECTL_STABLE_URL = "https://dl.k8s.io/release/stable.txt";
|
|
|
78552
78739
|
var LOCAL_STACK_ROOT = (0, import_node_path18.resolve)(__dirname, "..", "assets", "local-k8s");
|
|
78553
78740
|
var LOCAL_STACK_OVERLAY = (0, import_node_path18.join)(LOCAL_STACK_ROOT, "overlays", "local");
|
|
78554
78741
|
var LOCAL_STACK_BASE = (0, import_node_path18.join)(LOCAL_STACK_ROOT, "base");
|
|
78742
|
+
var DEFAULT_PLATFORM_NAMESPACE = "eve-horizon";
|
|
78743
|
+
var CONFIGURED_REGISTRY = process.env.ECR_REGISTRY?.trim();
|
|
78744
|
+
var CONFIGURED_NAMESPACE = process.env.ECR_NAMESPACE?.trim() || DEFAULT_PLATFORM_NAMESPACE;
|
|
78745
|
+
var PLATFORM_IMAGE_REGISTRY = buildPlatformImageRegistry();
|
|
78555
78746
|
var SERVICE_DEFINITIONS = [
|
|
78556
78747
|
{ id: "api", workload: "eve-api", kind: "deployment" },
|
|
78557
78748
|
{ id: "orchestrator", workload: "eve-orchestrator", kind: "deployment" },
|
|
@@ -78562,14 +78753,7 @@ var SERVICE_DEFINITIONS = [
|
|
|
78562
78753
|
{ id: "mailpit", workload: "mailpit", kind: "deployment" },
|
|
78563
78754
|
{ id: "sso", workload: "eve-sso", kind: "deployment" }
|
|
78564
78755
|
];
|
|
78565
|
-
var PLATFORM_IMAGES =
|
|
78566
|
-
{ component: "api", remote: "ghcr.io/eve-horizon/api", local: "eve-horizon/api:local" },
|
|
78567
|
-
{ component: "orchestrator", remote: "ghcr.io/eve-horizon/orchestrator", local: "eve-horizon/orchestrator:local" },
|
|
78568
|
-
{ component: "worker", remote: "ghcr.io/eve-horizon/worker", local: "eve-horizon/worker:local" },
|
|
78569
|
-
{ component: "gateway", remote: "ghcr.io/eve-horizon/gateway", local: "eve-horizon/gateway:local" },
|
|
78570
|
-
{ component: "agent-runtime", remote: "ghcr.io/eve-horizon/agent-runtime", local: "eve-horizon/agent-runtime:local" },
|
|
78571
|
-
{ component: "sso", remote: "ghcr.io/eve-horizon/sso", local: "eve-horizon/sso:local" }
|
|
78572
|
-
];
|
|
78756
|
+
var PLATFORM_IMAGES = buildPlatformImages();
|
|
78573
78757
|
var LOG_TARGETS = {
|
|
78574
78758
|
api: { resource: "eve-api", kind: "deployment" },
|
|
78575
78759
|
orchestrator: { resource: "eve-orchestrator", kind: "deployment" },
|
|
@@ -78624,9 +78808,21 @@ async function handleUp(flags, json) {
|
|
|
78624
78808
|
await ensureClusterReady(runtimeOptions);
|
|
78625
78809
|
let deployedVersion = null;
|
|
78626
78810
|
if (!skipDeploy) {
|
|
78811
|
+
const kubectl = requireToolPath("kubectl", "Run 'eve local up' again to auto-install managed tools.");
|
|
78812
|
+
const marker = readManagerMarker(kubectl);
|
|
78813
|
+
if (marker && marker !== "cli") {
|
|
78814
|
+
throw new Error(
|
|
78815
|
+
`This local stack is managed by './bin/eh k8s deploy' (marker: ${marker}).
|
|
78816
|
+
'eve local up' would overwrite source-built images with released registry images.
|
|
78817
|
+
|
|
78818
|
+
To switch to CLI management: eve local reset --force
|
|
78819
|
+
To continue with repo scripts: ./bin/eh k8s deploy`
|
|
78820
|
+
);
|
|
78821
|
+
}
|
|
78627
78822
|
deployedVersion = await resolveRequestedVersion(requestedVersion, runtimeOptions);
|
|
78628
78823
|
await importPlatformImages(deployedVersion, runtimeOptions);
|
|
78629
78824
|
applyLocalManifests(runtimeOptions);
|
|
78825
|
+
writeManagerMarker(kubectl, runtimeOptions);
|
|
78630
78826
|
waitForStatefulSetRollout("postgres", Math.max(timeoutSeconds, 180), runtimeOptions);
|
|
78631
78827
|
runDbMigration(Math.max(timeoutSeconds, 180), runtimeOptions);
|
|
78632
78828
|
generateAuthSecrets(runtimeOptions);
|
|
@@ -79114,22 +79310,21 @@ async function resolveLatestPlatformVersion() {
|
|
|
79114
79310
|
const candidates = Array.from(intersection);
|
|
79115
79311
|
if (candidates.length === 0) {
|
|
79116
79312
|
throw new Error(
|
|
79117
|
-
"Unable to resolve a common platform version from
|
|
79313
|
+
"Unable to resolve a common platform version from configured registry tags. Re-run with --version <x.y.z>."
|
|
79118
79314
|
);
|
|
79119
79315
|
}
|
|
79120
79316
|
candidates.sort(compareSemverDesc);
|
|
79121
79317
|
return candidates[0];
|
|
79122
79318
|
}
|
|
79123
79319
|
async function fetchRegistryTags(imageRef) {
|
|
79124
|
-
const
|
|
79125
|
-
|
|
79126
|
-
|
|
79127
|
-
if (!token) {
|
|
79128
|
-
throw new Error(`Unable to fetch GHCR token for ${imageRef}.`);
|
|
79320
|
+
const slashIndex = imageRef.indexOf("/");
|
|
79321
|
+
if (slashIndex < 0) {
|
|
79322
|
+
throw new Error(`Invalid image reference '${imageRef}'.`);
|
|
79129
79323
|
}
|
|
79324
|
+
const registry = imageRef.slice(0, slashIndex);
|
|
79325
|
+
const repository = imageRef.slice(slashIndex + 1);
|
|
79130
79326
|
const tagsPayload = await fetchText(
|
|
79131
|
-
`https
|
|
79132
|
-
{ Authorization: `Bearer ${token}` }
|
|
79327
|
+
`https://${registry}/v2/${repository}/tags/list?n=200`
|
|
79133
79328
|
);
|
|
79134
79329
|
return JSON.parse(tagsPayload).tags ?? [];
|
|
79135
79330
|
}
|
|
@@ -79165,7 +79360,7 @@ async function importPlatformImages(version2, runtimeOptions) {
|
|
|
79165
79360
|
const pull = pullImageWithRetry(docker, remoteTag, stdio, runtimeOptions);
|
|
79166
79361
|
if (pull.status !== 0) {
|
|
79167
79362
|
throw new Error(
|
|
79168
|
-
`Failed to pull ${remoteTag}. Ensure
|
|
79363
|
+
`Failed to pull ${remoteTag}. Ensure image availability/access at ${image.remote} and the version exists. Try: eve local up --version <x.y.z>`
|
|
79169
79364
|
);
|
|
79170
79365
|
}
|
|
79171
79366
|
run(docker, ["tag", remoteTag, image.local], { stdio });
|
|
@@ -79214,6 +79409,37 @@ function applyLocalManifests(runtimeOptions) {
|
|
|
79214
79409
|
{ stdio: runtimeOptions.verbose && !runtimeOptions.quiet ? "inherit" : "pipe" }
|
|
79215
79410
|
);
|
|
79216
79411
|
}
|
|
79412
|
+
function buildPlatformImageRegistry() {
|
|
79413
|
+
if (CONFIGURED_REGISTRY) {
|
|
79414
|
+
return `${CONFIGURED_REGISTRY}/${CONFIGURED_NAMESPACE}`;
|
|
79415
|
+
}
|
|
79416
|
+
return `public.ecr.aws/w7c4v0w3/${DEFAULT_PLATFORM_NAMESPACE}`;
|
|
79417
|
+
}
|
|
79418
|
+
function buildPlatformImages() {
|
|
79419
|
+
return [
|
|
79420
|
+
{ component: "api", remote: `${PLATFORM_IMAGE_REGISTRY}/api`, local: "eve-horizon/api:local" },
|
|
79421
|
+
{ component: "orchestrator", remote: `${PLATFORM_IMAGE_REGISTRY}/orchestrator`, local: "eve-horizon/orchestrator:local" },
|
|
79422
|
+
{ component: "worker", remote: `${PLATFORM_IMAGE_REGISTRY}/worker`, local: "eve-horizon/worker:local" },
|
|
79423
|
+
{ component: "gateway", remote: `${PLATFORM_IMAGE_REGISTRY}/gateway`, local: "eve-horizon/gateway:local" },
|
|
79424
|
+
{ component: "agent-runtime", remote: `${PLATFORM_IMAGE_REGISTRY}/agent-runtime`, local: "eve-horizon/agent-runtime:local" },
|
|
79425
|
+
{ component: "sso", remote: `${PLATFORM_IMAGE_REGISTRY}/sso`, local: "eve-horizon/sso:local" }
|
|
79426
|
+
];
|
|
79427
|
+
}
|
|
79428
|
+
function readManagerMarker(kubectl) {
|
|
79429
|
+
const result = run(
|
|
79430
|
+
kubectl,
|
|
79431
|
+
["--context", DEFAULT_KUBE_CONTEXT, "get", "namespace", "eve", "-o", "jsonpath={.metadata.annotations.eve-managed-by}"],
|
|
79432
|
+
{ stdio: "pipe", allowFailure: true }
|
|
79433
|
+
);
|
|
79434
|
+
return result.status === 0 ? result.stdout.trim() : "";
|
|
79435
|
+
}
|
|
79436
|
+
function writeManagerMarker(kubectl, runtimeOptions) {
|
|
79437
|
+
run(
|
|
79438
|
+
kubectl,
|
|
79439
|
+
["--context", DEFAULT_KUBE_CONTEXT, "annotate", "namespace", "eve", "eve-managed-by=cli", "--overwrite"],
|
|
79440
|
+
{ stdio: runtimeOptions.verbose && !runtimeOptions.quiet ? "inherit" : "pipe", allowFailure: true }
|
|
79441
|
+
);
|
|
79442
|
+
}
|
|
79217
79443
|
function runDbMigration(timeoutSeconds, runtimeOptions) {
|
|
79218
79444
|
const kubectl = requireToolPath("kubectl", "Run 'eve local up' again to auto-install managed tools.");
|
|
79219
79445
|
const migrateJobPath = (0, import_node_path18.join)(LOCAL_STACK_BASE, "db-migrate-job.yaml");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eve-horizon/cli",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.30",
|
|
4
4
|
"description": "Eve Horizon CLI",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -18,9 +18,6 @@
|
|
|
18
18
|
"assets",
|
|
19
19
|
"README.md"
|
|
20
20
|
],
|
|
21
|
-
"scripts": {
|
|
22
|
-
"build": "rm -rf dist && esbuild src/index.ts --bundle --platform=node --target=node22 --outfile=dist/index.js --format=cjs --external:yaml"
|
|
23
|
-
},
|
|
24
21
|
"publishConfig": {
|
|
25
22
|
"access": "public"
|
|
26
23
|
},
|
|
@@ -31,11 +28,14 @@
|
|
|
31
28
|
"yaml": "^2.5.1"
|
|
32
29
|
},
|
|
33
30
|
"devDependencies": {
|
|
34
|
-
"@eve/migrate": "workspace:*",
|
|
35
|
-
"@eve/shared": "workspace:*",
|
|
36
31
|
"@types/node": "^22.0.0",
|
|
37
32
|
"esbuild": "^0.27.3",
|
|
38
33
|
"postgres": "^3.4.0",
|
|
39
|
-
"typescript": "^5.7.0"
|
|
34
|
+
"typescript": "^5.7.0",
|
|
35
|
+
"@eve/shared": "0.0.1",
|
|
36
|
+
"@eve/migrate": "0.0.1"
|
|
37
|
+
},
|
|
38
|
+
"scripts": {
|
|
39
|
+
"build": "rm -rf dist && esbuild src/index.ts --bundle --platform=node --target=node22 --outfile=dist/index.js --format=cjs --external:yaml"
|
|
40
40
|
}
|
|
41
|
-
}
|
|
41
|
+
}
|