@eve-horizon/cli 0.2.41 → 0.2.43

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 +527 -31
  2. package/package.json +8 -8
package/dist/index.js CHANGED
@@ -51269,12 +51269,15 @@ Requires Docker Desktop; k3d and kubectl are auto-managed by the CLI.`,
51269
51269
  usage: "eve ollama targets [--scope-kind <platform|org|project>] [--scope-id <id>] [--json]"
51270
51270
  },
51271
51271
  target: {
51272
- description: "Manage a single target (add, rm, test)",
51273
- usage: "eve ollama target <add|rm|test> [options]",
51272
+ description: "Manage a single target (add, rm, test, wake, pull, models)",
51273
+ usage: "eve ollama target <add|rm|test|wake|pull|models> [options]",
51274
51274
  options: [
51275
51275
  "add: --name <name> --base-url <url> [--scope-kind <kind>] [--scope-id <id>] [--target-type <type>] [--transport-profile <profile>] [--api-key-ref <secret-ref>]",
51276
51276
  "rm: <target-id>",
51277
- "test: <target-id>"
51277
+ "test: <target-id>",
51278
+ "wake: <target-id> [--wait true] [--timeout-ms <ms>] \u2014 Trigger GPU wake via ASG. Without --wait, returns immediately with retry_after_seconds (caller must poll). With --wait, server polls every 2.5s until target is healthy or timeout (default 120s, ~65s typical cold start).",
51279
+ "pull: <target-id> --model-id <id> \u2014 Pull a model onto a remote Ollama target",
51280
+ "models: <target-id> \u2014 List models currently loaded on a remote target"
51278
51281
  ]
51279
51282
  },
51280
51283
  models: {
@@ -51337,6 +51340,11 @@ Requires Docker Desktop; k3d and kubectl are auto-managed by the CLI.`,
51337
51340
  },
51338
51341
  examples: [
51339
51342
  "eve ollama target add --name local --base-url http://localhost:11434 --scope-kind platform --target-type external_ollama",
51343
+ "eve ollama target wake itgt_xxx --wait true # Block until GPU target is healthy (~65s)",
51344
+ "eve ollama target wake itgt_xxx --wait true --timeout-ms 180000 # Wait up to 3 minutes",
51345
+ "eve ollama target wake itgt_xxx # Fire-and-forget (returns retry_after_seconds)",
51346
+ "eve ollama target pull itgt_xxx --model-id imod_xxx # Pull model onto remote target",
51347
+ "eve ollama target models itgt_xxx # List models on remote target",
51340
51348
  "eve ollama model add --canonical gpt-oss:120b --provider ollama --slug gpt-oss:120b",
51341
51349
  "eve ollama install add --target-id itgt_xxx --model-id imod_xxx --min-target-capacity 1",
51342
51350
  "eve ollama assignments --scope-kind platform",
@@ -51361,6 +51369,55 @@ Requires Docker Desktop; k3d and kubectl are auto-managed by the CLI.`,
51361
51369
  examples: [
51362
51370
  "eve migrate skills-to-packs"
51363
51371
  ]
51372
+ },
51373
+ github: {
51374
+ description: "Set up GitHub webhook integration.\nOne command to connect GitHub push/PR events to Eve pipelines.",
51375
+ usage: "eve github <subcommand> [options]",
51376
+ subcommands: {
51377
+ setup: {
51378
+ description: "Configure GitHub webhook (auto-creates via gh CLI if available)",
51379
+ usage: "eve github setup [--project <id>] [--regenerate]",
51380
+ options: [
51381
+ "--project <id> Project ID (uses profile default)",
51382
+ "--regenerate Generate a new webhook secret (replaces existing)",
51383
+ "--json Output as JSON"
51384
+ ],
51385
+ examples: [
51386
+ "eve github setup",
51387
+ "eve github setup --project proj_xxx",
51388
+ "eve github setup --regenerate"
51389
+ ]
51390
+ },
51391
+ status: {
51392
+ description: "Check if GitHub webhook is configured",
51393
+ usage: "eve github status [--project <id>]",
51394
+ options: [
51395
+ "--project <id> Project ID (uses profile default)",
51396
+ "--json Output as JSON"
51397
+ ],
51398
+ examples: [
51399
+ "eve github status"
51400
+ ]
51401
+ },
51402
+ test: {
51403
+ description: "Send a test github.push event to verify pipeline triggers",
51404
+ usage: "eve github test [--project <id>]",
51405
+ options: [
51406
+ "--project <id> Project ID (uses profile default)",
51407
+ "--json Output as JSON"
51408
+ ],
51409
+ examples: [
51410
+ "eve github test",
51411
+ "eve github test --project proj_xxx"
51412
+ ]
51413
+ }
51414
+ },
51415
+ examples: [
51416
+ "eve github setup # Auto-create webhook via gh CLI",
51417
+ "eve github setup --regenerate # Rotate webhook secret",
51418
+ "eve github status # Check if configured",
51419
+ "eve github test # Fire test event"
51420
+ ]
51364
51421
  }
51365
51422
  };
51366
51423
  function showMainHelp() {
@@ -51392,6 +51449,7 @@ function showMainHelp() {
51392
51449
  console.log(" harness Inspect harnesses and auth status");
51393
51450
  console.log(" agents Inspect agent policy and harness capabilities");
51394
51451
  console.log(" packs Manage AgentPack lockfile and resolution");
51452
+ console.log(" github Set up GitHub webhook integration");
51395
51453
  console.log(" integrations Manage chat integrations (Slack)");
51396
51454
  console.log(" chat Simulate chat messages (gateway testing)");
51397
51455
  console.log(" supervise Long-poll child events (lead agent coordination)");
@@ -56563,7 +56621,15 @@ var configSchema = external_exports.object({
56563
56621
  EVE_CORS_ORIGIN: external_exports.string().default("*"),
56564
56622
  // CORS origin: '*' (any), 'true' (reflect), or specific URL
56565
56623
  Z_AI_API_KEY: external_exports.string().optional(),
56566
- ZAI_MODEL: external_exports.string().optional()
56624
+ ZAI_MODEL: external_exports.string().optional(),
56625
+ EVE_STORAGE_BACKEND: external_exports.string().optional(),
56626
+ EVE_STORAGE_ENDPOINT: external_exports.string().optional(),
56627
+ EVE_STORAGE_PUBLIC_ENDPOINT: external_exports.string().optional(),
56628
+ EVE_STORAGE_REGION: external_exports.string().optional(),
56629
+ EVE_STORAGE_ACCESS_KEY_ID: external_exports.string().optional(),
56630
+ EVE_STORAGE_SECRET_ACCESS_KEY: external_exports.string().optional(),
56631
+ EVE_STORAGE_ORG_BUCKET_PREFIX: external_exports.string().optional(),
56632
+ EVE_STORAGE_INTERNAL_BUCKET: external_exports.string().optional()
56567
56633
  });
56568
56634
 
56569
56635
  // ../shared/dist/harnesses/config.js
@@ -56766,7 +56832,7 @@ var HARNESS_CAPABILITIES = {
56766
56832
  mclaude: {
56767
56833
  supports_model: true,
56768
56834
  model_notes: "Model override supported via CLAUDE_MODEL or --model.",
56769
- model_examples: ["opus-4.5", "sonnet-4", "haiku-4.5"],
56835
+ model_examples: ["opus-4-6", "sonnet-4-6", "opus-4.5", "sonnet-4.5", "haiku-4.5"],
56770
56836
  reasoning: {
56771
56837
  supported: true,
56772
56838
  levels: ["low", "medium", "high", "x-high"],
@@ -56777,7 +56843,7 @@ var HARNESS_CAPABILITIES = {
56777
56843
  claude: {
56778
56844
  supports_model: true,
56779
56845
  model_notes: "Model override supported via CLAUDE_MODEL or --model.",
56780
- model_examples: ["opus-4.5", "sonnet-4", "haiku-4.5"],
56846
+ model_examples: ["opus-4-6", "sonnet-4-6", "opus-4.5", "sonnet-4.5", "haiku-4.5"],
56781
56847
  reasoning: {
56782
56848
  supported: true,
56783
56849
  levels: ["low", "medium", "high", "x-high"],
@@ -58549,6 +58615,18 @@ var IngressConfigSchema = external_exports.object({
58549
58615
  port: external_exports.number().optional(),
58550
58616
  alias: external_exports.string().min(3).max(63).regex(IngressAliasPattern).optional()
58551
58617
  }).passthrough();
58618
+ var ObjectStoreBucketSchema = external_exports.object({
58619
+ name: external_exports.string().min(1).regex(/^[a-z][a-z0-9-]*[a-z0-9]$/, "Bucket name must be lowercase alphanumeric with hyphens"),
58620
+ visibility: external_exports.enum(["private", "public"]).default("private"),
58621
+ cors: external_exports.object({
58622
+ origins: external_exports.array(external_exports.string()).optional(),
58623
+ methods: external_exports.array(external_exports.string()).optional(),
58624
+ max_age_seconds: external_exports.number().optional()
58625
+ }).optional()
58626
+ }).passthrough();
58627
+ var ObjectStoreConfigSchema = external_exports.object({
58628
+ buckets: external_exports.array(ObjectStoreBucketSchema).optional()
58629
+ }).passthrough();
58552
58630
  var ServiceXeveSchema = external_exports.object({
58553
58631
  role: external_exports.string().optional(),
58554
58632
  ingress: IngressConfigSchema.optional(),
@@ -58559,7 +58637,8 @@ var ServiceXeveSchema = external_exports.object({
58559
58637
  worker_type: external_exports.string().optional(),
58560
58638
  files: external_exports.array(ServiceFilesEntrySchema).optional(),
58561
58639
  storage: ServiceStorageSchema.optional(),
58562
- managed: ManagedDbConfigSchema.optional()
58640
+ managed: ManagedDbConfigSchema.optional(),
58641
+ object_store: ObjectStoreConfigSchema.optional()
58563
58642
  }).passthrough();
58564
58643
  var ServiceSchema = external_exports.object({
58565
58644
  image: external_exports.string().optional(),
@@ -59685,7 +59764,11 @@ var OrgFsEventSchema = external_exports.object({
59685
59764
  size_bytes: external_exports.number().int().nonnegative().nullable().optional(),
59686
59765
  source_side: OrgFsEventSourceSideSchema,
59687
59766
  metadata: external_exports.record(external_exports.unknown()).optional(),
59688
- created_at: external_exports.string()
59767
+ created_at: external_exports.string(),
59768
+ download_url: external_exports.string().nullable().optional(),
59769
+ // presigned GET URL, included for file.created/file.updated
59770
+ storage_key: external_exports.string().nullable().optional()
59771
+ // S3 object key, for reference
59689
59772
  });
59690
59773
  var OrgFsEventListResponseSchema = external_exports.object({
59691
59774
  data: external_exports.array(OrgFsEventSchema),
@@ -59726,7 +59809,11 @@ var OrgFsInternalIngestEventRequestSchema = external_exports.object({
59726
59809
  content_hash: external_exports.string().optional(),
59727
59810
  size_bytes: external_exports.number().int().nonnegative().optional(),
59728
59811
  source_side: OrgFsEventSourceSideSchema,
59729
- metadata: external_exports.record(external_exports.unknown()).optional()
59812
+ metadata: external_exports.record(external_exports.unknown()).optional(),
59813
+ storage_key: external_exports.string().optional(),
59814
+ // S3 key; if provided, upserts org_fs_objects
59815
+ mime_type: external_exports.string().optional()
59816
+ // MIME type; used for org_fs_objects upsert
59730
59817
  });
59731
59818
  var OrgFsInternalHeartbeatRequestSchema = external_exports.object({
59732
59819
  cursor: external_exports.number().int().nonnegative().optional(),
@@ -59736,6 +59823,76 @@ var OrgFsInternalHeartbeatRequestSchema = external_exports.object({
59736
59823
  var OrgFsInternalMetricsRequestSchema = external_exports.object({
59737
59824
  metrics: external_exports.record(external_exports.unknown())
59738
59825
  });
59826
+ var OrgFsUploadUrlResponseSchema = external_exports.object({
59827
+ upload_url: external_exports.string(),
59828
+ storage_key: external_exports.string(),
59829
+ method: external_exports.literal("PUT"),
59830
+ expires_at: external_exports.string(),
59831
+ max_bytes: external_exports.number().int().positive()
59832
+ });
59833
+ var OrgFsDownloadUrlResponseSchema = external_exports.object({
59834
+ download_url: external_exports.string(),
59835
+ storage_key: external_exports.string(),
59836
+ content_hash: external_exports.string(),
59837
+ size_bytes: external_exports.number().int().nonnegative(),
59838
+ mime_type: external_exports.string(),
59839
+ expires_at: external_exports.string()
59840
+ });
59841
+ var OrgFsObjectSchema = external_exports.object({
59842
+ id: external_exports.string(),
59843
+ path: external_exports.string(),
59844
+ storage_key: external_exports.string(),
59845
+ content_hash: external_exports.string(),
59846
+ size_bytes: external_exports.number().int().nonnegative(),
59847
+ mime_type: external_exports.string(),
59848
+ deleted_at: external_exports.string().nullable().optional(),
59849
+ updated_at: external_exports.string(),
59850
+ created_at: external_exports.string()
59851
+ });
59852
+ var OrgFsObjectListResponseSchema = external_exports.object({
59853
+ data: external_exports.array(OrgFsObjectSchema),
59854
+ pagination: external_exports.object({
59855
+ limit: external_exports.number().int().positive(),
59856
+ next_after: external_exports.string().nullable()
59857
+ })
59858
+ });
59859
+ var OrgFsCreateShareRequestSchema = external_exports.object({
59860
+ path: external_exports.string().min(1),
59861
+ expires_in: external_exports.string().optional(),
59862
+ // e.g. '7d', '24h', '30m'; null = never expires
59863
+ label: external_exports.string().optional()
59864
+ });
59865
+ var OrgFsShareSchema = external_exports.object({
59866
+ id: external_exports.string(),
59867
+ org_id: external_exports.string(),
59868
+ path: external_exports.string(),
59869
+ label: external_exports.string().nullable(),
59870
+ url: external_exports.string(),
59871
+ created_by: external_exports.string(),
59872
+ expires_at: external_exports.string().nullable(),
59873
+ accessed_at: external_exports.string().nullable(),
59874
+ access_count: external_exports.number().int().nonnegative(),
59875
+ revoked_at: external_exports.string().nullable(),
59876
+ created_at: external_exports.string()
59877
+ });
59878
+ var OrgFsShareListResponseSchema = external_exports.object({
59879
+ data: external_exports.array(OrgFsShareSchema)
59880
+ });
59881
+ var OrgFsCreatePublicPathRequestSchema = external_exports.object({
59882
+ path_prefix: external_exports.string().min(1),
59883
+ label: external_exports.string().optional()
59884
+ });
59885
+ var OrgFsPublicPathSchema = external_exports.object({
59886
+ id: external_exports.string(),
59887
+ org_id: external_exports.string(),
59888
+ path_prefix: external_exports.string(),
59889
+ label: external_exports.string().nullable(),
59890
+ created_by: external_exports.string(),
59891
+ created_at: external_exports.string()
59892
+ });
59893
+ var OrgFsPublicPathListResponseSchema = external_exports.object({
59894
+ data: external_exports.array(OrgFsPublicPathSchema)
59895
+ });
59739
59896
 
59740
59897
  // ../shared/dist/schemas/resource.js
59741
59898
  var ResolveResourcesRequestSchema = external_exports.object({
@@ -60607,11 +60764,46 @@ var DEFAULT_RATE_CARD_V1 = {
60607
60764
  llm: {
60608
60765
  byok: {
60609
60766
  anthropic: {
60767
+ "claude-opus-4-6": {
60768
+ input_per_million_usd: "5.00",
60769
+ output_per_million_usd: "25.00",
60770
+ cache_read_per_million_usd: "0.50",
60771
+ cache_write_per_million_usd: "6.25",
60772
+ reasoning_per_million_usd: null
60773
+ },
60774
+ "claude-sonnet-4-6": {
60775
+ input_per_million_usd: "3.00",
60776
+ output_per_million_usd: "15.00",
60777
+ cache_read_per_million_usd: "0.30",
60778
+ cache_write_per_million_usd: "3.75",
60779
+ reasoning_per_million_usd: null
60780
+ },
60610
60781
  "claude-opus-4-5": {
60611
- input_per_million_usd: "15.00",
60612
- output_per_million_usd: "75.00",
60613
- cache_read_per_million_usd: "1.50",
60614
- cache_write_per_million_usd: "18.75",
60782
+ input_per_million_usd: "5.00",
60783
+ output_per_million_usd: "25.00",
60784
+ cache_read_per_million_usd: "0.50",
60785
+ cache_write_per_million_usd: "6.25",
60786
+ reasoning_per_million_usd: null
60787
+ },
60788
+ "claude-sonnet-4-5": {
60789
+ input_per_million_usd: "3.00",
60790
+ output_per_million_usd: "15.00",
60791
+ cache_read_per_million_usd: "0.30",
60792
+ cache_write_per_million_usd: "3.75",
60793
+ reasoning_per_million_usd: null
60794
+ },
60795
+ "claude-haiku-4-5": {
60796
+ input_per_million_usd: "1.00",
60797
+ output_per_million_usd: "5.00",
60798
+ cache_read_per_million_usd: "0.10",
60799
+ cache_write_per_million_usd: "1.25",
60800
+ reasoning_per_million_usd: null
60801
+ },
60802
+ "claude-sonnet-4": {
60803
+ input_per_million_usd: "3.00",
60804
+ output_per_million_usd: "15.00",
60805
+ cache_read_per_million_usd: "0.30",
60806
+ cache_write_per_million_usd: "3.75",
60615
60807
  reasoning_per_million_usd: null
60616
60808
  }
60617
60809
  },
@@ -73145,28 +73337,31 @@ async function handleInstall(positionals, flags) {
73145
73337
  function installSkill(skillsBin, skill, projectRoot) {
73146
73338
  console.log(` Installing: ${skill.source} (${skill.type})`);
73147
73339
  const localDir = resolveLocalDirIfExists(skill, projectRoot);
73148
- const wantsExcludePrivate = localDir !== null && fs4.existsSync(path6.join(localDir, PRIVATE_SKILLS_DIRNAME)) && !sourcePathExplicitlyTargetsPrivate(skill.source);
73340
+ const excludePrivate = localDir !== null && !sourcePathExplicitlyTargetsPrivate(skill.source);
73149
73341
  try {
73150
73342
  const agents = ["claude-code", "codex", "gemini-cli"];
73151
- if (wantsExcludePrivate && localDir) {
73152
- const skillDirs = findSkillDirs(localDir, { fullDepth: true, excludePrivate: true });
73343
+ if (localDir) {
73344
+ const skillDirs = findSkillDirs(localDir, { fullDepth: true, excludePrivate });
73153
73345
  if (skillDirs.length === 0) {
73154
- console.log(` No skills found under ${skill.source} (after excluding ${PRIVATE_SKILLS_DIRNAME}/)`);
73346
+ console.log(` No skills found under ${skill.source}`);
73155
73347
  return;
73156
73348
  }
73157
- console.log(` Installing ${skillDirs.length} public skill(s) (excluding ${PRIVATE_SKILLS_DIRNAME}/)...`);
73158
- for (const dir of skillDirs) {
73159
- const rel = path6.relative(projectRoot, dir);
73160
- const installSource = rel.startsWith(".") ? rel : `./${rel}`;
73161
- for (const agent of agents) {
73162
- (0, import_node_child_process7.execSync)(`${skillsBin} add ${JSON.stringify(installSource)} -a ${agent} -s '*' -y --full-depth`, {
73163
- cwd: projectRoot,
73164
- stdio: "inherit",
73165
- timeout: 12e4
73166
- });
73349
+ if (skillDirs.length > 1 || skillDirs[0] !== localDir) {
73350
+ const label = excludePrivate ? ` (excluding ${PRIVATE_SKILLS_DIRNAME}/)` : "";
73351
+ console.log(` Installing ${skillDirs.length} skill(s)${label}...`);
73352
+ for (const dir of skillDirs) {
73353
+ const rel = path6.relative(projectRoot, dir);
73354
+ const installSource = rel.startsWith(".") ? rel : `./${rel}`;
73355
+ for (const agent of agents) {
73356
+ (0, import_node_child_process7.execSync)(`${skillsBin} add ${JSON.stringify(installSource)} -a ${agent} -s '*' -y --full-depth`, {
73357
+ cwd: projectRoot,
73358
+ stdio: "inherit",
73359
+ timeout: 12e4
73360
+ });
73361
+ }
73167
73362
  }
73363
+ return;
73168
73364
  }
73169
- return;
73170
73365
  }
73171
73366
  for (const agent of agents) {
73172
73367
  (0, import_node_child_process7.execSync)(`${skillsBin} add ${JSON.stringify(skill.source)} -a ${agent} -s '*' -y --full-depth`, {
@@ -73280,6 +73475,7 @@ function parseSkillsManifest(manifestPath) {
73280
73475
  }
73281
73476
  const content = fs4.readFileSync(manifestPath, "utf-8");
73282
73477
  const sources = [];
73478
+ const manifestDir = path6.dirname(manifestPath);
73283
73479
  for (const rawLine of content.split("\n")) {
73284
73480
  const line = rawLine.split("#")[0].trim();
73285
73481
  if (!line) continue;
@@ -73288,11 +73484,46 @@ function parseSkillsManifest(manifestPath) {
73288
73484
  const expanded = expandGlobPattern(line, manifestPath, explicitPrivateTarget);
73289
73485
  sources.push(...expanded);
73290
73486
  } else {
73291
- sources.push(parseSkillSource(line));
73487
+ const parsed = parseSkillSource(line);
73488
+ if (parsed.type === "local") {
73489
+ const expanded = tryExpandLocalDirectory(parsed, manifestDir);
73490
+ if (expanded) {
73491
+ sources.push(...expanded);
73492
+ continue;
73493
+ }
73494
+ }
73495
+ sources.push(parsed);
73292
73496
  }
73293
73497
  }
73294
73498
  return sources;
73295
73499
  }
73500
+ function tryExpandLocalDirectory(skill, manifestDir) {
73501
+ let source = skill.source;
73502
+ if (source.startsWith("~")) {
73503
+ source = source.replace(/^~/, process.env.HOME || "~");
73504
+ }
73505
+ const abs = path6.isAbsolute(source) ? source : path6.resolve(manifestDir, source);
73506
+ try {
73507
+ if (!fs4.existsSync(abs) || !fs4.statSync(abs).isDirectory()) return null;
73508
+ } catch {
73509
+ return null;
73510
+ }
73511
+ if (fs4.existsSync(path6.join(abs, "SKILL.md"))) return null;
73512
+ const explicitPrivate = sourcePathExplicitlyTargetsPrivate(skill.source);
73513
+ const skillDirs = findSkillDirs(abs, { fullDepth: true, excludePrivate: !explicitPrivate });
73514
+ if (skillDirs.length === 0) return null;
73515
+ return skillDirs.map((dir) => {
73516
+ const name = path6.basename(dir);
73517
+ const relativePath = path6.relative(manifestDir, dir);
73518
+ const resolvedSource = relativePath.startsWith(".") ? relativePath : `./${relativePath}`;
73519
+ return {
73520
+ raw: skill.raw,
73521
+ source: resolvedSource,
73522
+ type: "local",
73523
+ name
73524
+ };
73525
+ });
73526
+ }
73296
73527
  function parseSkillSource(line) {
73297
73528
  if (line.startsWith("https://") || line.startsWith("http://")) {
73298
73529
  const name2 = extractNameFromUrl(line);
@@ -78943,7 +79174,57 @@ async function handleOllama(subcommand, positionals, flags, context2) {
78943
79174
  }
78944
79175
  return;
78945
79176
  }
78946
- throw new Error("Usage: eve ollama target <add|rm|test|wake> ...");
79177
+ if (action === "pull") {
79178
+ const targetId = positionals[1];
79179
+ if (!targetId) throw new Error("Usage: eve ollama target pull <target-id> --model-id <id>");
79180
+ const modelId = requireString(flags, "model-id");
79181
+ const query = new URLSearchParams();
79182
+ query.set("model_id", modelId);
79183
+ const result = await requestJson(
79184
+ context2,
79185
+ `/inference/targets/${targetId}/pull?${query.toString()}`,
79186
+ { method: "POST" }
79187
+ );
79188
+ outputJson(result, json);
79189
+ if (!json) {
79190
+ if (result.ok) {
79191
+ console.log(`Pull complete: ${result.model} on ${result.target}`);
79192
+ } else {
79193
+ console.error(`Pull failed: ${result.message}`);
79194
+ process.exitCode = 1;
79195
+ }
79196
+ }
79197
+ return;
79198
+ }
79199
+ if (action === "models") {
79200
+ const targetId = positionals[1];
79201
+ if (!targetId) throw new Error("Usage: eve ollama target models <target-id>");
79202
+ const result = await requestJson(
79203
+ context2,
79204
+ `/inference/targets/${targetId}/remote-models`
79205
+ );
79206
+ if (json) {
79207
+ outputJson(result, json);
79208
+ return;
79209
+ }
79210
+ console.log(`Models on target "${result.target}":`);
79211
+ if (result.models.length === 0) {
79212
+ console.log(" (none)");
79213
+ return;
79214
+ }
79215
+ printTable(
79216
+ ["Name", "Size (GB)", "Modified"],
79217
+ result.models.map((m) => [
79218
+ m.name,
79219
+ (m.size / 1e9).toFixed(1),
79220
+ m.modified_at
79221
+ ])
79222
+ );
79223
+ return;
79224
+ }
79225
+ throw new Error(
79226
+ "Usage: eve ollama target <add|rm|test|wake|pull|models> ...\n wake: <target-id> [--wait true] [--timeout-ms <ms>] Trigger GPU wake (default timeout 120s with --wait)"
79227
+ );
78947
79228
  }
78948
79229
  case "models": {
78949
79230
  const models = await requestJson(context2, "/inference/models");
@@ -79545,8 +79826,65 @@ async function handleFs(subcommand, positionals, flags, context2) {
79545
79826
  await handleSync2(action, positionals.slice(1), flags, context2);
79546
79827
  return;
79547
79828
  }
79829
+ case "share": {
79830
+ const orgId = getOrgOrThrow(flags, context2);
79831
+ const path8 = positionals[0];
79832
+ if (!path8) throw new Error("Usage: eve fs share <path> --org <org> [--expires <duration>] [--label <text>]");
79833
+ const body = {
79834
+ path: path8,
79835
+ expires_in: getStringFlag(flags, ["expires", "expires-in", "ttl"]) ?? void 0,
79836
+ label: getStringFlag(flags, ["label"]) ?? void 0
79837
+ };
79838
+ const json = Boolean(flags["json"]);
79839
+ const share = await requestJson(context2, `/orgs/${orgId}/fs/share`, { method: "POST", body });
79840
+ if (json) {
79841
+ outputJson(share, true);
79842
+ } else {
79843
+ console.log(`Share URL: ${share.url}`);
79844
+ if (share.expires_at) console.log(`Expires: ${share.expires_at}`);
79845
+ if (share.label) console.log(`Label: ${share.label}`);
79846
+ console.log(`Token: ${share.id}`);
79847
+ }
79848
+ return;
79849
+ }
79850
+ case "shares": {
79851
+ const orgId = getOrgOrThrow(flags, context2);
79852
+ const json = Boolean(flags["json"]);
79853
+ const result = await requestJson(context2, `/orgs/${orgId}/fs/shares`);
79854
+ outputJson(result, json, `${result.data.length} active share(s)`);
79855
+ return;
79856
+ }
79857
+ case "revoke": {
79858
+ const orgId = getOrgOrThrow(flags, context2);
79859
+ const token = positionals[0];
79860
+ if (!token) throw new Error("Usage: eve fs revoke <token> --org <org>");
79861
+ const json = Boolean(flags["json"]);
79862
+ const share = await requestJson(context2, `/orgs/${orgId}/fs/shares/${token}`, { method: "DELETE" });
79863
+ outputJson(share, json, `Share token ${token} revoked`);
79864
+ return;
79865
+ }
79866
+ case "publish": {
79867
+ const orgId = getOrgOrThrow(flags, context2);
79868
+ const pathPrefix = positionals[0];
79869
+ if (!pathPrefix) throw new Error("Usage: eve fs publish <path-prefix> --org <org> [--label <text>]");
79870
+ const body = {
79871
+ path_prefix: pathPrefix,
79872
+ label: getStringFlag(flags, ["label"]) ?? void 0
79873
+ };
79874
+ const json = Boolean(flags["json"]);
79875
+ const result = await requestJson(context2, `/orgs/${orgId}/fs/public-paths`, { method: "POST", body });
79876
+ outputJson(result, json, `Published path prefix: ${pathPrefix}`);
79877
+ return;
79878
+ }
79879
+ case "public-paths": {
79880
+ const orgId = getOrgOrThrow(flags, context2);
79881
+ const json = Boolean(flags["json"]);
79882
+ const result = await requestJson(context2, `/orgs/${orgId}/fs/public-paths`);
79883
+ outputJson(result, json, `${result.data.length} public path(s)`);
79884
+ return;
79885
+ }
79548
79886
  default:
79549
- throw new Error("Usage: eve fs sync <init|status|logs|pause|resume|disconnect|mode|conflicts|resolve|doctor>");
79887
+ throw new Error("Usage: eve fs <sync|share|shares|revoke|publish|public-paths> ...");
79550
79888
  }
79551
79889
  }
79552
79890
 
@@ -80662,6 +81000,161 @@ function sleep(ms) {
80662
81000
  });
80663
81001
  }
80664
81002
 
81003
+ // src/commands/github.ts
81004
+ var import_node_child_process11 = require("node:child_process");
81005
+ async function handleGithub(subcommand, positionals, flags, context2) {
81006
+ const json = Boolean(flags.json);
81007
+ const projectId = getStringFlag(flags, ["project"]) ?? context2.projectId;
81008
+ if (!projectId) {
81009
+ throw new Error("Missing --project flag or profile default project.");
81010
+ }
81011
+ switch (subcommand) {
81012
+ case "setup":
81013
+ await setupGithub(projectId, flags, json, context2);
81014
+ return;
81015
+ case "status":
81016
+ await statusGithub(projectId, json, context2);
81017
+ return;
81018
+ case "test":
81019
+ await testGithub(projectId, json, context2);
81020
+ return;
81021
+ default:
81022
+ throw new Error("Usage: eve github <setup|status|test> [--project <id>]");
81023
+ }
81024
+ }
81025
+ async function setupGithub(projectId, flags, json, context2) {
81026
+ const regenerate = getBooleanFlag(flags, ["regenerate"]) ?? false;
81027
+ const result = await requestJson(context2, `/projects/${projectId}/github/setup`, {
81028
+ method: "POST",
81029
+ body: { regenerate }
81030
+ });
81031
+ if (json) {
81032
+ outputJson(result, true);
81033
+ return;
81034
+ }
81035
+ const ownerRepo = extractOwnerRepo(result.repo_url);
81036
+ if (!ownerRepo) {
81037
+ printManualInstructions(result);
81038
+ return;
81039
+ }
81040
+ if (tryGhWebhook(ownerRepo, result.webhook_url, result.secret, result.events)) {
81041
+ console.log(`Webhook created on ${ownerRepo}!`);
81042
+ console.log("");
81043
+ console.log(` Events: ${result.events.join(", ")}`);
81044
+ console.log(` URL: ${result.webhook_url}`);
81045
+ console.log("");
81046
+ console.log("GitHub will now send push and pull_request events to Eve.");
81047
+ console.log('Run "eve github test" to verify the pipeline trigger fires.');
81048
+ } else {
81049
+ printManualInstructions(result);
81050
+ }
81051
+ }
81052
+ async function statusGithub(projectId, json, context2) {
81053
+ const result = await requestJson(context2, `/projects/${projectId}/github/status`);
81054
+ if (json) {
81055
+ outputJson(result, true);
81056
+ return;
81057
+ }
81058
+ if (result.configured) {
81059
+ console.log("GitHub webhook: configured");
81060
+ } else {
81061
+ console.log("GitHub webhook: not configured");
81062
+ console.log('Run "eve github setup" to configure.');
81063
+ }
81064
+ console.log(` Webhook URL: ${result.webhook_url}`);
81065
+ }
81066
+ async function testGithub(projectId, json, context2) {
81067
+ const result = await requestJson(context2, `/projects/${projectId}/github/test`, {
81068
+ method: "POST"
81069
+ });
81070
+ if (json) {
81071
+ outputJson(result, true);
81072
+ return;
81073
+ }
81074
+ console.log(`Test event created: ${result.event_id}`);
81075
+ console.log("");
81076
+ console.log("If you have a pipeline with a github.push trigger, it should fire now.");
81077
+ console.log("Check with: eve event list --project " + projectId);
81078
+ }
81079
+ function extractOwnerRepo(repoUrl) {
81080
+ const httpsMatch = repoUrl.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?$/);
81081
+ if (httpsMatch) return httpsMatch[1];
81082
+ const sshMatch = repoUrl.match(/github\.com:([^/]+\/[^/]+?)(?:\.git)?$/);
81083
+ if (sshMatch) return sshMatch[1];
81084
+ return null;
81085
+ }
81086
+ function tryGhWebhook(ownerRepo, webhookUrl, secret, events) {
81087
+ try {
81088
+ (0, import_node_child_process11.execSync)("gh auth status", { stdio: "pipe", timeout: 1e4 });
81089
+ } catch {
81090
+ return false;
81091
+ }
81092
+ try {
81093
+ const existing = (0, import_node_child_process11.execSync)(
81094
+ `gh api repos/${ownerRepo}/hooks --jq '[.[] | select(.config.url == "${webhookUrl}")] | length'`,
81095
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 15e3 }
81096
+ ).trim();
81097
+ if (existing !== "0") {
81098
+ const hookId = (0, import_node_child_process11.execSync)(
81099
+ `gh api repos/${ownerRepo}/hooks --jq '[.[] | select(.config.url == "${webhookUrl}")][0].id'`,
81100
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 15e3 }
81101
+ ).trim();
81102
+ if (hookId) {
81103
+ (0, import_node_child_process11.execSync)(
81104
+ `gh api repos/${ownerRepo}/hooks/${hookId} -X PATCH -f config[url]="${webhookUrl}" -f config[content_type]=json -f config[secret]="${secret}" -f config[insecure_ssl]=0 ` + events.map((e) => `-f events[]=${e}`).join(" ") + ` -f active=true`,
81105
+ { stdio: "pipe", timeout: 15e3 }
81106
+ );
81107
+ return true;
81108
+ }
81109
+ }
81110
+ } catch {
81111
+ }
81112
+ try {
81113
+ (0, import_node_child_process11.execSync)(
81114
+ `gh api repos/${ownerRepo}/hooks -X POST -f name=web -f config[url]="${webhookUrl}" -f config[content_type]=json -f config[secret]="${secret}" -f config[insecure_ssl]=0 ` + events.map((e) => `-f events[]=${e}`).join(" ") + ` -f active=true`,
81115
+ { stdio: "pipe", timeout: 15e3 }
81116
+ );
81117
+ return true;
81118
+ } catch {
81119
+ return false;
81120
+ }
81121
+ }
81122
+ function printManualInstructions(result) {
81123
+ const ownerRepo = extractOwnerRepo(result.repo_url);
81124
+ console.log("GitHub webhook setup");
81125
+ console.log("");
81126
+ console.log(` Webhook URL: ${result.webhook_url}`);
81127
+ console.log(` Secret: ${result.secret}`);
81128
+ console.log(` Content type: application/json`);
81129
+ console.log(` Events: ${result.events.join(", ")}`);
81130
+ console.log("");
81131
+ if (ownerRepo) {
81132
+ console.log("Auto-setup with gh CLI (install from https://cli.github.com):");
81133
+ console.log("");
81134
+ console.log(` gh api repos/${ownerRepo}/hooks -X POST \\`);
81135
+ console.log(` -f name=web \\`);
81136
+ console.log(` -f config[url]="${result.webhook_url}" \\`);
81137
+ console.log(` -f config[content_type]=json \\`);
81138
+ console.log(` -f config[secret]="${result.secret}" \\`);
81139
+ result.events.forEach((e) => {
81140
+ console.log(` -f events[]=${e} \\`);
81141
+ });
81142
+ console.log(` -f active=true`);
81143
+ console.log("");
81144
+ }
81145
+ console.log("Or configure manually:");
81146
+ if (ownerRepo) {
81147
+ console.log(` 1. Go to https://github.com/${ownerRepo}/settings/hooks/new`);
81148
+ } else {
81149
+ console.log(" 1. Go to your repo Settings > Webhooks > Add webhook");
81150
+ }
81151
+ console.log(" 2. Payload URL: " + result.webhook_url);
81152
+ console.log(" 3. Content type: application/json");
81153
+ console.log(" 4. Secret: " + result.secret);
81154
+ console.log(' 5. Events: "push" and "pull_request"');
81155
+ console.log(' 6. Click "Add webhook"');
81156
+ }
81157
+
80665
81158
  // src/index.ts
80666
81159
  function getCliVersion() {
80667
81160
  try {
@@ -80854,6 +81347,9 @@ async function main2() {
80854
81347
  case "local":
80855
81348
  await handleLocal(subcommand, rest, flags, context2);
80856
81349
  return;
81350
+ case "github":
81351
+ await handleGithub(subcommand, rest, flags, context2);
81352
+ return;
80857
81353
  default:
80858
81354
  showMainHelp();
80859
81355
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eve-horizon/cli",
3
- "version": "0.2.41",
3
+ "version": "0.2.43",
4
4
  "description": "Eve Horizon CLI",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -18,6 +18,9 @@
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
+ },
21
24
  "publishConfig": {
22
25
  "access": "public"
23
26
  },
@@ -28,14 +31,11 @@
28
31
  "yaml": "^2.5.1"
29
32
  },
30
33
  "devDependencies": {
34
+ "@eve/migrate": "workspace:*",
35
+ "@eve/shared": "workspace:*",
31
36
  "@types/node": "^22.0.0",
32
37
  "esbuild": "^0.27.3",
33
38
  "postgres": "^3.4.0",
34
- "typescript": "^5.7.0",
35
- "@eve/migrate": "0.0.1",
36
- "@eve/shared": "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"
39
+ "typescript": "^5.7.0"
40
40
  }
41
- }
41
+ }