@eve-horizon/cli 0.2.48 → 0.2.51

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.
Files changed (2) hide show
  1. package/dist/index.js +360 -23
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -58620,7 +58620,8 @@ var PackYamlSchema = external_exports.object({
58620
58620
  id: external_exports.string().min(1).regex(/^[a-z0-9-]+$/, "Pack ID must be lowercase alphanumeric with hyphens"),
58621
58621
  imports: external_exports.object({
58622
58622
  agents: external_exports.string().min(1),
58623
- teams: external_exports.string().min(1),
58623
+ teams: external_exports.string().min(1).optional(),
58624
+ workflows: external_exports.string().min(1).optional(),
58624
58625
  chat: external_exports.string().min(1).optional(),
58625
58626
  x_eve: external_exports.string().min(1).optional()
58626
58627
  }),
@@ -58757,12 +58758,21 @@ var ServiceStorageSchema = external_exports.object({
58757
58758
  storage_class: external_exports.string().optional(),
58758
58759
  name: external_exports.string().optional()
58759
58760
  }).passthrough();
58761
+ var ManagedDbBackupConfigSchema = external_exports.object({
58762
+ schedule: external_exports.union([external_exports.string(), external_exports.literal(false)]).optional(),
58763
+ // cron expression or false to disable
58764
+ retention: external_exports.string().regex(/^\s*\d+\s*d\s*$/, 'Retention must be in days, e.g. "30d"').optional(),
58765
+ // e.g., '30d', '90d'
58766
+ snapshot_on_delete: external_exports.boolean().optional(),
58767
+ snapshot_on_reset: external_exports.boolean().optional()
58768
+ });
58760
58769
  var ManagedDbConfigSchema = external_exports.object({
58761
58770
  class: external_exports.string().min(1),
58762
58771
  // e.g., 'db.p1'
58763
58772
  engine: external_exports.literal("postgres").default("postgres"),
58764
- engine_version: external_exports.string().optional()
58773
+ engine_version: external_exports.string().optional(),
58765
58774
  // e.g., '16'
58775
+ backup: ManagedDbBackupConfigSchema.optional()
58766
58776
  });
58767
58777
  var IngressAliasPattern = /^[a-z][a-z0-9-]*[a-z0-9]$/;
58768
58778
  var IngressConfigSchema = external_exports.object({
@@ -58974,7 +58984,8 @@ var DbResetRequestSchema = external_exports.object({
58974
58984
  migrations: external_exports.array(DbMigrationInputSchema).optional(),
58975
58985
  no_migrate: external_exports.boolean().optional(),
58976
58986
  force: external_exports.boolean().optional(),
58977
- danger_reset_production: external_exports.boolean().optional()
58987
+ danger_reset_production: external_exports.boolean().optional(),
58988
+ skip_snapshot: external_exports.boolean().optional()
58978
58989
  });
58979
58990
  var DbResetResponseSchema = external_exports.object({
58980
58991
  reset: external_exports.boolean(),
@@ -59102,6 +59113,7 @@ var AgentContextSchema = external_exports.object({
59102
59113
  parent_attachments: AgentContextParentAttachmentsSchema.optional(),
59103
59114
  threads: AgentContextThreadsSchema.optional()
59104
59115
  }).passthrough();
59116
+ var VALID_TOOLCHAINS = ["python", "media", "rust", "java", "kotlin"];
59105
59117
  var AgentEntrySchema = external_exports.object({
59106
59118
  name: external_exports.string().optional(),
59107
59119
  slug: AgentSlugSchema.optional(),
@@ -59110,6 +59122,7 @@ var AgentEntrySchema = external_exports.object({
59110
59122
  skill: external_exports.string().min(1),
59111
59123
  workflow: external_exports.string().optional(),
59112
59124
  harness_profile: external_exports.string().optional(),
59125
+ toolchains: external_exports.array(external_exports.enum(VALID_TOOLCHAINS)).optional(),
59113
59126
  context: AgentContextSchema.optional(),
59114
59127
  access: AgentAccessSchema.optional(),
59115
59128
  policies: AgentPolicySchema.optional(),
@@ -59624,6 +59637,47 @@ var RegisterManagedDbInstanceRequestSchema = external_exports.object({
59624
59637
  var ScaleManagedDbRequestSchema = external_exports.object({
59625
59638
  class: external_exports.string().min(1)
59626
59639
  });
59640
+ var ManagedDbSnapshotTriggerSchema = external_exports.enum([
59641
+ "manual",
59642
+ "scheduled",
59643
+ "pre_delete",
59644
+ "pre_reset"
59645
+ ]);
59646
+ var ManagedDbSnapshotStatusSchema = external_exports.enum([
59647
+ "in_progress",
59648
+ "completed",
59649
+ "failed"
59650
+ ]);
59651
+ var ManagedDbSnapshotResponseSchema = external_exports.object({
59652
+ id: external_exports.string(),
59653
+ tenant_id: external_exports.string(),
59654
+ org_id: external_exports.string(),
59655
+ project_id: external_exports.string(),
59656
+ env_id: external_exports.string(),
59657
+ instance_id: external_exports.string(),
59658
+ created_by: external_exports.string().nullable(),
59659
+ trigger: ManagedDbSnapshotTriggerSchema,
59660
+ status: ManagedDbSnapshotStatusSchema,
59661
+ s3_bucket: external_exports.string().nullable(),
59662
+ s3_key: external_exports.string().nullable(),
59663
+ size_bytes: external_exports.number().nullable(),
59664
+ db_size_bytes: external_exports.number().nullable(),
59665
+ pg_version: external_exports.string().nullable(),
59666
+ error_message: external_exports.string().nullable(),
59667
+ retention: external_exports.string(),
59668
+ expires_at: external_exports.string().nullable(),
59669
+ created_at: external_exports.string(),
59670
+ completed_at: external_exports.string().nullable()
59671
+ });
59672
+ var CreateSnapshotRequestSchema = external_exports.object({
59673
+ retention: external_exports.string().regex(/^\s*\d+\s*d\s*$/, 'Retention must be in days, e.g. "30d"').optional()
59674
+ });
59675
+ var RestoreSnapshotRequestSchema = external_exports.object({
59676
+ snapshot_id: external_exports.string().min(1),
59677
+ source_env: external_exports.string().optional(),
59678
+ source_project: external_exports.string().optional(),
59679
+ skip_safety_snapshot: external_exports.boolean().optional()
59680
+ });
59627
59681
 
59628
59682
  // ../shared/dist/schemas/job-attachment.js
59629
59683
  var CreateJobAttachmentRequestSchema = external_exports.object({
@@ -60503,7 +60557,8 @@ async function resolvePack(entry, projectSlug, repoRoot) {
60503
60557
  const raw = fs2.readFileSync(packYamlPath, "utf-8");
60504
60558
  const parsed = PackYamlSchema.parse((0, import_yaml2.parse)(raw));
60505
60559
  const agents = loadYamlMap(path3.join(packDir, parsed.imports.agents));
60506
- const teams = loadYamlMap(path3.join(packDir, parsed.imports.teams));
60560
+ const teams = parsed.imports.teams ? loadYamlMap(path3.join(packDir, parsed.imports.teams)) : { version: 1, teams: {} };
60561
+ const workflows = parsed.imports.workflows ? loadYamlMap(path3.join(packDir, parsed.imports.workflows)) : null;
60507
60562
  const chat = parsed.imports.chat ? loadYamlMap(path3.join(packDir, parsed.imports.chat)) : null;
60508
60563
  const xEve = parsed.imports.x_eve ? loadYamlMap(path3.join(packDir, parsed.imports.x_eve)) : null;
60509
60564
  const prefixedAgents = prefixAgentSlugs(agents, projectSlug);
@@ -60516,6 +60571,7 @@ async function resolvePack(entry, projectSlug, repoRoot) {
60516
60571
  ref: entry.ref ?? resolveLocalRef(packDir),
60517
60572
  agents: gatewayResolvedAgents,
60518
60573
  teams,
60574
+ workflows,
60519
60575
  chat,
60520
60576
  xEve,
60521
60577
  skillPaths: skillPaths2
@@ -60531,6 +60587,7 @@ async function resolvePack(entry, projectSlug, repoRoot) {
60531
60587
  ref: entry.ref ?? resolveLocalRef(packDir),
60532
60588
  agents: {},
60533
60589
  teams: {},
60590
+ workflows: null,
60534
60591
  chat: null,
60535
60592
  xEve: null,
60536
60593
  skillPaths
@@ -72667,9 +72724,17 @@ async function handleDb(subcommand, positionals, flags, context2) {
72667
72724
  return handleScale(positionals, flags, context2, jsonOutput);
72668
72725
  case "destroy":
72669
72726
  return handleDestroy(positionals, flags, context2, jsonOutput);
72727
+ case "snapshot":
72728
+ return handleSnapshot(positionals, flags, context2, jsonOutput);
72729
+ case "snapshots":
72730
+ return handleSnapshots(positionals, flags, context2, jsonOutput);
72731
+ case "restore":
72732
+ return handleRestore(positionals, flags, context2, jsonOutput);
72733
+ case "backup-status":
72734
+ return handleBackupStatus(positionals, flags, context2, jsonOutput);
72670
72735
  default:
72671
72736
  throw new Error(
72672
- "Usage: eve db <command> [options]\n\nCommands:\n schema --env <name>|--url <url> Show DB schema info\n rls --env <name> Show RLS policies and tables\n rls init --with-groups Scaffold group-aware RLS helper SQL\n sql --env <name>|--url <url> --sql <stmt> Run parameterized SQL\n migrate --env <name>|--url <url> [--path <dir>] Apply pending migrations\n migrations --env <name>|--url <url> List applied migrations\n reset --env <name>|--url <url> --force [--no-migrate] Reset DB schema\n wipe --env <name>|--url <url> --force Reset schema without migrations\n new <description> Create new migration file\n status --env <name> Show managed DB status\n rotate-credentials --env <name> Rotate managed DB credentials\n scale --env <name> --class <cls> Scale managed DB class\n destroy --env <name> --force Destroy managed DB"
72737
+ "Usage: eve db <command> [options]\n\nCommands:\n schema --env <name>|--url <url> Show DB schema info\n rls --env <name> Show RLS policies and tables\n rls init --with-groups Scaffold group-aware RLS helper SQL\n sql --env <name>|--url <url> --sql <stmt> Run parameterized SQL\n migrate --env <name>|--url <url> [--path <dir>] Apply pending migrations\n migrations --env <name>|--url <url> List applied migrations\n reset --env <name>|--url <url> --force [--no-migrate] [--skip-snapshot] Reset DB schema\n wipe --env <name>|--url <url> --force Reset schema without migrations\n new <description> Create new migration file\n status --env <name> Show managed DB status\n rotate-credentials --env <name> Rotate managed DB credentials\n scale --env <name> --class <cls> Scale managed DB class\n destroy --env <name> --force [--skip-snapshot] Destroy managed DB\n snapshot --env <name> Create a DB snapshot\n snapshot show <snapshot_id> Show snapshot details\n snapshot delete <snapshot_id> [--force] Delete a snapshot\n snapshots --env <name> List DB snapshots\n restore --env <name> --snapshot <id> Restore from snapshot\n backup-status --env <name> Show backup schedule/status"
72673
72738
  );
72674
72739
  }
72675
72740
  }
@@ -73086,6 +73151,7 @@ async function handleReset2(positionals, flags, context2, jsonOutput) {
73086
73151
  const noMigrate = toBoolean(flags["no-migrate"]) ?? toBoolean(flags.no_migrate) ?? false;
73087
73152
  const force = toBoolean(flags.force) ?? false;
73088
73153
  const dangerResetProduction = toBoolean(flags["danger-reset-production"]) ?? toBoolean(flags.danger_reset_production) ?? false;
73154
+ const skipSnapshot = toBoolean(flags["skip-snapshot"]) ?? false;
73089
73155
  const migrations = noMigrate ? [] : loadMigrationsFromPath(getStringFlag(flags, ["path"]) ?? "db/migrations");
73090
73156
  if (target.mode === "url") {
73091
73157
  if (!force) {
@@ -73128,6 +73194,7 @@ async function handleReset2(positionals, flags, context2, jsonOutput) {
73128
73194
  no_migrate: noMigrate,
73129
73195
  force,
73130
73196
  danger_reset_production: dangerResetProduction,
73197
+ skip_snapshot: skipSnapshot,
73131
73198
  ...noMigrate ? {} : { migrations }
73132
73199
  }
73133
73200
  }
@@ -73255,9 +73322,13 @@ async function handleDestroy(positionals, flags, context2, jsonOutput) {
73255
73322
  "This will destroy the managed database permanently.\nAdd --force to confirm: eve db destroy --env <name> --force"
73256
73323
  );
73257
73324
  }
73325
+ const skipSnapshot = toBoolean(flags["skip-snapshot"]);
73326
+ const params = new URLSearchParams();
73327
+ if (skipSnapshot) params.set("skip_snapshot", "true");
73328
+ const qs = params.toString();
73258
73329
  const response = await requestJson(
73259
73330
  context2,
73260
- `/projects/${projectId}/envs/${envName}/db/managed`,
73331
+ `/projects/${projectId}/envs/${envName}/db/managed${qs ? "?" + qs : ""}`,
73261
73332
  { method: "DELETE" }
73262
73333
  );
73263
73334
  if (jsonOutput) {
@@ -73267,6 +73338,173 @@ async function handleDestroy(positionals, flags, context2, jsonOutput) {
73267
73338
  console.log(`${result.message}`);
73268
73339
  }
73269
73340
  }
73341
+ async function handleSnapshot(positionals, flags, context2, jsonOutput) {
73342
+ const sub = positionals[0];
73343
+ if (sub === "show") {
73344
+ const snapshotId = positionals[1] ?? getStringFlag(flags, ["id"]);
73345
+ if (!snapshotId) {
73346
+ throw new Error("Usage: eve db snapshot show <snapshot_id> [--env <name>] [--project <id>]");
73347
+ }
73348
+ const { projectId: projectId2, envName: envName2 } = resolveProjectEnv(positionals.slice(2), flags, context2);
73349
+ const response2 = await requestJson(context2, `/projects/${projectId2}/envs/${envName2}/db/snapshots/${snapshotId}`);
73350
+ if (jsonOutput) {
73351
+ outputJson(response2, true);
73352
+ } else {
73353
+ printSnapshotDetail(response2);
73354
+ }
73355
+ return;
73356
+ }
73357
+ if (sub === "delete") {
73358
+ const snapshotId = positionals[1] ?? getStringFlag(flags, ["id"]);
73359
+ if (!snapshotId) {
73360
+ throw new Error("Usage: eve db snapshot delete <snapshot_id> [--env <name>] [--force]");
73361
+ }
73362
+ if (!toBoolean(flags.force)) {
73363
+ throw new Error("Add --force to confirm snapshot deletion");
73364
+ }
73365
+ const { projectId: projectId2, envName: envName2 } = resolveProjectEnv(positionals.slice(2), flags, context2);
73366
+ const response2 = await requestJson(context2, `/projects/${projectId2}/envs/${envName2}/db/snapshots/${snapshotId}`, {
73367
+ method: "DELETE"
73368
+ });
73369
+ outputJson(response2, jsonOutput, "Snapshot deleted");
73370
+ return;
73371
+ }
73372
+ if (sub === "download") {
73373
+ const snapshotId = positionals[1] ?? getStringFlag(flags, ["id"]);
73374
+ if (!snapshotId) {
73375
+ throw new Error("Usage: eve db snapshot download <snapshot_id> --output <path> [--env <name>]");
73376
+ }
73377
+ const outputPath = getStringFlag(flags, ["output", "o"]);
73378
+ if (!outputPath) {
73379
+ throw new Error("--output <path> is required");
73380
+ }
73381
+ const { projectId: projectId2, envName: envName2 } = resolveProjectEnv(positionals.slice(2), flags, context2);
73382
+ const response2 = await requestJson(context2, `/projects/${projectId2}/envs/${envName2}/db/snapshots/${snapshotId}/download`);
73383
+ console.log(`Download URL: ${response2.url}`);
73384
+ console.log('Use: curl -o <file> "<url>" or wget -O <file> "<url>"');
73385
+ return;
73386
+ }
73387
+ const { projectId, envName } = resolveProjectEnv(positionals, flags, context2);
73388
+ const retention = getStringFlag(flags, ["retention"]);
73389
+ const body = {};
73390
+ if (retention) body.retention = retention;
73391
+ const response = await requestJson(context2, `/projects/${projectId}/envs/${envName}/db/snapshots`, {
73392
+ method: "POST",
73393
+ body
73394
+ });
73395
+ if (jsonOutput) {
73396
+ outputJson(response, true);
73397
+ } else {
73398
+ const snap = response;
73399
+ console.log(`Snapshot: ${snap.id} (${snap.status})`);
73400
+ if (snap.s3_key) {
73401
+ console.log(`S3 Key: ${snap.s3_key}`);
73402
+ }
73403
+ console.log(`Trigger: ${snap.trigger}`);
73404
+ console.log(`Retention: ${snap.retention}`);
73405
+ }
73406
+ }
73407
+ async function handleSnapshots(positionals, flags, context2, jsonOutput) {
73408
+ const { projectId, envName } = resolveProjectEnv(positionals, flags, context2);
73409
+ const status = getStringFlag(flags, ["status"]);
73410
+ const limit = getStringFlag(flags, ["limit"]);
73411
+ const params = new URLSearchParams();
73412
+ if (status) params.set("status", status);
73413
+ if (limit) params.set("limit", limit);
73414
+ const qs = params.toString();
73415
+ const response = await requestJson(
73416
+ context2,
73417
+ `/projects/${projectId}/envs/${envName}/db/snapshots${qs ? "?" + qs : ""}`
73418
+ );
73419
+ if (jsonOutput) {
73420
+ outputJson(response, true);
73421
+ } else {
73422
+ const snapshots = response;
73423
+ if (snapshots.length === 0) {
73424
+ console.log("No snapshots found.");
73425
+ return;
73426
+ }
73427
+ console.log("ID Trigger Status Size DB Size Created");
73428
+ console.log("-".repeat(85));
73429
+ for (const snap of snapshots) {
73430
+ const size2 = snap.size_bytes ? formatBytes(snap.size_bytes) : "-";
73431
+ const dbSize = snap.db_size_bytes ? formatBytes(snap.db_size_bytes) : "-";
73432
+ const id = String(snap.id).padEnd(20);
73433
+ const trigger = String(snap.trigger).padEnd(12);
73434
+ const st = String(snap.status).padEnd(12);
73435
+ const created = snap.created_at ? new Date(snap.created_at).toLocaleString() : "-";
73436
+ console.log(`${id}${trigger}${st}${size2.padEnd(11)}${dbSize.padEnd(11)}${created}`);
73437
+ }
73438
+ }
73439
+ }
73440
+ async function handleRestore(positionals, flags, context2, jsonOutput) {
73441
+ const { projectId, envName } = resolveProjectEnv(positionals, flags, context2);
73442
+ const snapshotId = getStringFlag(flags, ["snapshot"]);
73443
+ if (!snapshotId) {
73444
+ throw new Error("Usage: eve db restore --env <name> --snapshot <snapshot_id> [--force] [--skip-safety-snapshot]");
73445
+ }
73446
+ if (!toBoolean(flags.force)) {
73447
+ throw new Error(
73448
+ "This will overwrite the current database with snapshot data.\nAdd --force to confirm: eve db restore --env <name> --snapshot <id> --force"
73449
+ );
73450
+ }
73451
+ const body = {
73452
+ snapshot_id: snapshotId
73453
+ };
73454
+ const sourceEnv = getStringFlag(flags, ["source-env"]);
73455
+ const sourceProject = getStringFlag(flags, ["source-project"]);
73456
+ if (sourceEnv) body.source_env = sourceEnv;
73457
+ if (sourceProject) body.source_project = sourceProject;
73458
+ if (toBoolean(flags["skip-safety-snapshot"])) body.skip_safety_snapshot = true;
73459
+ const response = await requestJson(context2, `/projects/${projectId}/envs/${envName}/db/restore`, {
73460
+ method: "POST",
73461
+ body
73462
+ });
73463
+ outputJson(response, jsonOutput, "Restore initiated successfully");
73464
+ }
73465
+ async function handleBackupStatus(positionals, flags, context2, jsonOutput) {
73466
+ const { projectId, envName } = resolveProjectEnv(positionals, flags, context2);
73467
+ const response = await requestJson(context2, `/projects/${projectId}/envs/${envName}/db/backup-status`);
73468
+ if (jsonOutput) {
73469
+ outputJson(response, true);
73470
+ } else {
73471
+ const status = response;
73472
+ console.log(`Environment: ${envName} (${status.class})`);
73473
+ console.log(`Schedule: ${status.schedule ?? "none"}`);
73474
+ console.log(`Retention: ${status.retention ?? "default"}`);
73475
+ if (status.last_snapshot_at) {
73476
+ console.log(`Last: ${new Date(status.last_snapshot_at).toLocaleString()}`);
73477
+ }
73478
+ if (status.next_snapshot_at) {
73479
+ console.log(`Next: ${new Date(status.next_snapshot_at).toLocaleString()}`);
73480
+ }
73481
+ console.log(`Snapshots: ${status.snapshot_count ?? 0} stored`);
73482
+ console.log(`Snapshot-on-delete: ${status.snapshot_on_delete ? "enabled" : "disabled"}`);
73483
+ console.log(`Snapshot-on-reset: ${status.snapshot_on_reset ? "enabled" : "disabled"}`);
73484
+ }
73485
+ }
73486
+ function printSnapshotDetail(snap) {
73487
+ console.log(`Snapshot: ${snap.id}
73488
+ `);
73489
+ console.log(` Status: ${snap.status}`);
73490
+ console.log(` Trigger: ${snap.trigger}`);
73491
+ if (snap.size_bytes) console.log(` Size: ${formatBytes(snap.size_bytes)}`);
73492
+ if (snap.db_size_bytes) console.log(` DB Size: ${formatBytes(snap.db_size_bytes)}`);
73493
+ if (snap.pg_version) console.log(` PG Version: ${snap.pg_version}`);
73494
+ console.log(` Retention: ${snap.retention}`);
73495
+ if (snap.expires_at) console.log(` Expires: ${new Date(snap.expires_at).toLocaleString()}`);
73496
+ if (snap.error_message) console.log(` Error: ${snap.error_message}`);
73497
+ console.log(` Created: ${snap.created_at ? new Date(snap.created_at).toLocaleString() : "-"}`);
73498
+ if (snap.completed_at) console.log(` Completed: ${new Date(snap.completed_at).toLocaleString()}`);
73499
+ if (snap.created_by) console.log(` Created By: ${snap.created_by}`);
73500
+ }
73501
+ function formatBytes(bytes) {
73502
+ if (bytes === 0) return "0 B";
73503
+ const units = ["B", "KB", "MB", "GB", "TB"];
73504
+ const i = Math.floor(Math.log(bytes) / Math.log(1024));
73505
+ const value = bytes / Math.pow(1024, i);
73506
+ return `${value.toFixed(i > 0 ? 1 : 0)} ${units[i]}`;
73507
+ }
73270
73508
 
73271
73509
  // src/commands/event.ts
73272
73510
  async function handleEvent(subcommand, positionals, flags, context2) {
@@ -74663,12 +74901,20 @@ async function resolvePacksAndMerge(repoRoot, manifest, projectSlug) {
74663
74901
  }
74664
74902
  }
74665
74903
  let mergedAgents = {};
74666
- let mergedTeams = {};
74667
- let mergedChat = { routes: [] };
74904
+ let mergedTeams = { version: 1, teams: {} };
74905
+ let mergedWorkflows = null;
74906
+ let mergedChat = { version: 1, routes: [] };
74668
74907
  const xEveFragments = [];
74669
74908
  for (const pack of resolvedPacks) {
74670
74909
  mergedAgents = mergeMapConfig(mergedAgents, pack.agents);
74671
74910
  mergedTeams = mergeMapConfig(mergedTeams, pack.teams);
74911
+ if (pack.workflows) {
74912
+ const packWorkflows = extractInnerMap(pack.workflows, "workflows");
74913
+ if (Object.keys(packWorkflows).length > 0) {
74914
+ mergedWorkflows = mergedWorkflows ?? {};
74915
+ Object.assign(mergedWorkflows, packWorkflows);
74916
+ }
74917
+ }
74672
74918
  if (pack.chat) {
74673
74919
  mergedChat = mergeChatConfig(
74674
74920
  mergedChat,
@@ -74697,7 +74943,7 @@ async function resolvePacksAndMerge(repoRoot, manifest, projectSlug) {
74697
74943
  }
74698
74944
  const projectXEve = xEve ?? {};
74699
74945
  const { packs: _p, install_agents: _ia, ...projectXEveRest } = projectXEve;
74700
- mergeXEve(xEveFragments, projectXEveRest);
74946
+ const mergedXEve = mergeXEve(xEveFragments, projectXEveRest);
74701
74947
  validateEffectiveConfig(mergedAgents, mergedTeams, mergedChat);
74702
74948
  const lockfile = {
74703
74949
  resolved_at: (/* @__PURE__ */ new Date()).toISOString(),
@@ -74712,7 +74958,7 @@ async function resolvePacksAndMerge(repoRoot, manifest, projectSlug) {
74712
74958
  agents_count: Object.keys(extractInnerMap(mergedAgents, "agents")).length,
74713
74959
  teams_count: Object.keys(extractInnerMap(mergedTeams, "teams")).length,
74714
74960
  routes_count: (mergedChat.routes ?? []).length,
74715
- profiles_count: 0,
74961
+ profiles_count: Object.keys(mergedXEve?.profiles ?? {}).length,
74716
74962
  agents_hash: simpleHash(JSON.stringify(mergedAgents)),
74717
74963
  teams_hash: simpleHash(JSON.stringify(mergedTeams)),
74718
74964
  chat_hash: simpleHash(JSON.stringify(mergedChat))
@@ -74728,6 +74974,10 @@ async function resolvePacksAndMerge(repoRoot, manifest, projectSlug) {
74728
74974
  agentsYaml: (0, import_yaml3.stringify)(mergedAgents),
74729
74975
  teamsYaml: (0, import_yaml3.stringify)(mergedTeams),
74730
74976
  chatYaml: (0, import_yaml3.stringify)(mergedChat),
74977
+ workflowsYaml: mergedWorkflows ? (0, import_yaml3.stringify)({
74978
+ workflows: mergedWorkflows,
74979
+ ...Object.keys(mergedXEve).length > 0 ? { x_eve: mergedXEve } : {}
74980
+ }) : null,
74731
74981
  packRefs
74732
74982
  };
74733
74983
  }
@@ -74891,6 +75141,17 @@ async function handleAgents(subcommand, positionals, flags, context2) {
74891
75141
  teamsYaml = packResult.teamsYaml;
74892
75142
  chatYaml = packResult.chatYaml;
74893
75143
  packRefs = packResult.packRefs;
75144
+ if (packResult.workflowsYaml) {
75145
+ await requestJson(
75146
+ context2,
75147
+ `/projects/${projectId}/manifest`,
75148
+ {
75149
+ method: "POST",
75150
+ body: { yaml: packResult.workflowsYaml }
75151
+ }
75152
+ );
75153
+ console.log(` \u2713 Workflows synced to manifest`);
75154
+ }
74894
75155
  } else {
74895
75156
  const configPaths = resolveAgentsConfigPaths(repoRoot, manifest);
74896
75157
  agentsYaml = (0, import_node_fs11.readFileSync)(ensureFileExists(configPaths.agentsPath, "agents config"), "utf-8");
@@ -75920,7 +76181,7 @@ function formatArtifactList(artifacts) {
75920
76181
  for (const artifact of artifacts) {
75921
76182
  const service = artifact.service_name.padEnd(25);
75922
76183
  const image = artifact.image_ref.padEnd(50);
75923
- const size2 = artifact.size_bytes ? formatBytes(artifact.size_bytes) : "-";
76184
+ const size2 = artifact.size_bytes ? formatBytes2(artifact.size_bytes) : "-";
75924
76185
  console.log(`${service}${image}${size2}`);
75925
76186
  if (artifact.digest) {
75926
76187
  console.log(` Digest: ${artifact.digest}`);
@@ -75932,7 +76193,7 @@ function formatArtifactList(artifacts) {
75932
76193
  console.log("");
75933
76194
  console.log(`Total: ${artifacts.length} artifacts`);
75934
76195
  }
75935
- function formatBytes(bytes) {
76196
+ function formatBytes2(bytes) {
75936
76197
  if (bytes < 1024) return `${bytes} B`;
75937
76198
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`;
75938
76199
  if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
@@ -75967,15 +76228,25 @@ async function handleIntegrations(subcommand, positionals, flags, context2) {
75967
76228
  if (!orgId) {
75968
76229
  throw new Error("Missing org id. Provide --org or set a profile default.");
75969
76230
  }
75970
- const url = `${context2.apiUrl}/orgs/${orgId}/integrations/slack/authorize`;
76231
+ const ttlFlag = getStringFlag(flags, ["ttl"]);
76232
+ const ttlSeconds = ttlFlag ? parseTtl(ttlFlag) : void 0;
76233
+ const body2 = {};
76234
+ if (ttlSeconds !== void 0) body2.ttl_seconds = ttlSeconds;
76235
+ const response2 = await requestJson(
76236
+ context2,
76237
+ `/orgs/${orgId}/integrations/slack/install-token`,
76238
+ { method: "POST", body: body2 }
76239
+ );
76240
+ const url = `${context2.apiUrl}/integrations/slack/install?token=${encodeURIComponent(response2.token)}`;
75971
76241
  if (json) {
75972
- outputJson({ url, org_id: orgId }, json);
76242
+ outputJson({ url, expires_at: response2.expires_at }, json);
75973
76243
  } else {
75974
- console.log(`Slack install URL:
76244
+ console.log(`Slack install link (expires ${response2.expires_at}):
75975
76245
 
75976
76246
  ${url}
75977
76247
 
75978
- Share this URL with your Slack workspace admin.`);
76248
+ Share this link with your Slack workspace admin.
76249
+ No Eve login required \u2014 they just click and approve.`);
75979
76250
  }
75980
76251
  return;
75981
76252
  }
@@ -76064,6 +76335,14 @@ Share this URL with your Slack workspace admin.`);
76064
76335
  throw new Error("Usage: eve integrations <list|slack|test|update>");
76065
76336
  }
76066
76337
  }
76338
+ function parseTtl(value) {
76339
+ const match = value.match(/^(\d+)(s|m|h|d)?$/);
76340
+ if (!match) throw new Error("Invalid --ttl format. Use e.g. 24h, 7d, 3600");
76341
+ const num = parseInt(match[1], 10);
76342
+ const unit = match[2] ?? "s";
76343
+ const multiplier = { s: 1, m: 60, h: 3600, d: 86400 };
76344
+ return num * multiplier[unit];
76345
+ }
76067
76346
 
76068
76347
  // src/commands/chat.ts
76069
76348
  async function handleChat(subcommand, _positionals, flags, context2) {
@@ -80096,39 +80375,97 @@ async function handleIngest(subcommand, positionals, flags, context2) {
80096
80375
  function inferMimeType(fileName) {
80097
80376
  const ext = fileName.split(".").pop()?.toLowerCase();
80098
80377
  switch (ext) {
80378
+ // Text
80099
80379
  case "md":
80100
80380
  return "text/markdown";
80101
80381
  case "txt":
80102
80382
  return "text/plain";
80103
- case "pdf":
80104
- return "application/pdf";
80383
+ case "csv":
80384
+ return "text/csv";
80385
+ case "html":
80386
+ case "htm":
80387
+ return "text/html";
80388
+ // Structured data
80105
80389
  case "json":
80106
80390
  return "application/json";
80107
80391
  case "yaml":
80108
80392
  case "yml":
80109
80393
  return "application/yaml";
80110
- case "html":
80111
- case "htm":
80112
- return "text/html";
80113
- case "csv":
80114
- return "text/csv";
80115
80394
  case "xml":
80116
80395
  return "application/xml";
80396
+ // Documents
80397
+ case "pdf":
80398
+ return "application/pdf";
80117
80399
  case "doc":
80118
80400
  return "application/msword";
80119
80401
  case "docx":
80120
80402
  return "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
80403
+ case "rtf":
80404
+ return "application/rtf";
80405
+ // Images
80121
80406
  case "png":
80122
80407
  return "image/png";
80123
80408
  case "jpg":
80124
80409
  case "jpeg":
80125
80410
  return "image/jpeg";
80411
+ case "gif":
80412
+ return "image/gif";
80413
+ case "webp":
80414
+ return "image/webp";
80415
+ case "svg":
80416
+ return "image/svg+xml";
80417
+ case "tiff":
80418
+ case "tif":
80419
+ return "image/tiff";
80420
+ // Audio
80126
80421
  case "mp3":
80127
80422
  return "audio/mpeg";
80128
80423
  case "wav":
80129
80424
  return "audio/wav";
80425
+ case "m4a":
80426
+ return "audio/mp4";
80427
+ case "aac":
80428
+ return "audio/aac";
80429
+ case "ogg":
80430
+ return "audio/ogg";
80431
+ case "opus":
80432
+ return "audio/opus";
80433
+ case "flac":
80434
+ return "audio/flac";
80435
+ case "wma":
80436
+ return "audio/x-ms-wma";
80437
+ case "amr":
80438
+ return "audio/amr";
80439
+ case "m4b":
80440
+ return "audio/mp4";
80441
+ case "m4r":
80442
+ return "audio/mp4";
80443
+ case "oga":
80444
+ return "audio/ogg";
80445
+ // Video
80130
80446
  case "mp4":
80131
80447
  return "video/mp4";
80448
+ case "mkv":
80449
+ return "video/x-matroska";
80450
+ case "mov":
80451
+ return "video/quicktime";
80452
+ case "avi":
80453
+ return "video/x-msvideo";
80454
+ case "wmv":
80455
+ return "video/x-ms-wmv";
80456
+ case "webm":
80457
+ return "video/webm";
80458
+ case "flv":
80459
+ return "video/x-flv";
80460
+ case "m4v":
80461
+ return "video/x-m4v";
80462
+ case "mpeg":
80463
+ case "mpg":
80464
+ return "video/mpeg";
80465
+ case "3gp":
80466
+ return "video/3gpp";
80467
+ case "ogv":
80468
+ return "video/ogg";
80132
80469
  default:
80133
80470
  return "application/octet-stream";
80134
80471
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eve-horizon/cli",
3
- "version": "0.2.48",
3
+ "version": "0.2.51",
4
4
  "description": "Eve Horizon CLI",
5
5
  "license": "MIT",
6
6
  "repository": {