@eve-horizon/cli 0.2.40 → 0.2.42

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 +542 -49
  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
  },
@@ -67380,32 +67572,46 @@ async function resolveGitRef(context2, projectId, ref, repoDir) {
67380
67572
  return ref;
67381
67573
  }
67382
67574
  const resolvedRepoDir = repoDir ?? getGitRoot();
67383
- if (!resolvedRepoDir) {
67384
- throw new Error(
67385
- `Failed to resolve git ref '${ref}': not in a git repository.
67386
- Run the command from the project repository, pass --repo-dir <path>, or use a 40-character SHA.`
67387
- );
67388
- }
67575
+ let useLocal = !!resolvedRepoDir;
67576
+ let projectRepoUrl;
67389
67577
  if (projectId) {
67390
67578
  const project = await requestJson(context2, `/projects/${projectId}`);
67579
+ projectRepoUrl = project.repo_url;
67391
67580
  const expected = normalizeRepoIdentity(project.repo_url);
67392
- const actual = normalizeRepoIdentity(getGitOriginUrl(resolvedRepoDir));
67393
- const repoDirIdentity = normalizeRepoIdentity(resolvedRepoDir);
67581
+ const actual = resolvedRepoDir ? normalizeRepoIdentity(getGitOriginUrl(resolvedRepoDir)) : null;
67582
+ const repoDirIdentity = resolvedRepoDir ? normalizeRepoIdentity(resolvedRepoDir) : null;
67394
67583
  if (expected && actual && expected !== actual) {
67395
- throw new Error(
67396
- `Failed to resolve git ref '${ref}': current repo does not match project repo.
67397
- Project repo: ${project.repo_url}
67398
- Current repo: ${getGitOriginUrl(resolvedRepoDir)}
67399
- Run the command from the project repository, pass --repo-dir <path>, or use a 40-character SHA.`
67400
- );
67584
+ useLocal = false;
67401
67585
  }
67402
67586
  if (expected && !actual && (!repoDirIdentity || repoDirIdentity !== expected)) {
67403
- throw new Error(
67404
- `Failed to resolve git ref '${ref}': current repo has no origin remote to validate against project repo.
67405
- Project repo: ${project.repo_url}
67406
- Run the command from the project repository, pass --repo-dir <path>, or use a 40-character SHA.`
67407
- );
67587
+ useLocal = false;
67588
+ }
67589
+ }
67590
+ if (useLocal && resolvedRepoDir) {
67591
+ try {
67592
+ return (0, import_node_child_process5.execSync)(`git rev-parse ${ref}`, {
67593
+ cwd: resolvedRepoDir,
67594
+ encoding: "utf-8",
67595
+ stdio: ["pipe", "pipe", "pipe"]
67596
+ }).trim();
67597
+ } catch {
67598
+ }
67599
+ }
67600
+ if (projectRepoUrl) {
67601
+ const sha = resolveRefRemote(projectRepoUrl, ref);
67602
+ if (sha) {
67603
+ return sha;
67408
67604
  }
67605
+ throw new Error(
67606
+ `Failed to resolve git ref '${ref}' against remote '${projectRepoUrl}'.
67607
+ Make sure the ref (branch or tag) exists in the remote repository, or use a 40-character SHA.`
67608
+ );
67609
+ }
67610
+ if (!resolvedRepoDir) {
67611
+ throw new Error(
67612
+ `Failed to resolve git ref '${ref}': not in a git repository.
67613
+ Run the command from the project repository, pass --repo-dir <path>, or use a 40-character SHA.`
67614
+ );
67409
67615
  }
67410
67616
  try {
67411
67617
  return (0, import_node_child_process5.execSync)(`git rev-parse ${ref}`, {
@@ -67470,6 +67676,25 @@ function resolveGitBranch(repoDir, ref) {
67470
67676
  return null;
67471
67677
  }
67472
67678
  }
67679
+ function resolveRefRemote(repoUrl, ref) {
67680
+ try {
67681
+ const output = (0, import_node_child_process5.execSync)(`git ls-remote ${repoUrl} ${ref}`, {
67682
+ encoding: "utf-8",
67683
+ stdio: ["pipe", "pipe", "pipe"],
67684
+ timeout: 15e3
67685
+ }).trim();
67686
+ for (const line of output.split("\n")) {
67687
+ const [sha, refName] = line.split(" ");
67688
+ if (!sha || !refName) continue;
67689
+ if (refName === `refs/heads/${ref}` || refName === `refs/tags/${ref}` || refName === ref) {
67690
+ return sha;
67691
+ }
67692
+ }
67693
+ return null;
67694
+ } catch {
67695
+ return null;
67696
+ }
67697
+ }
67473
67698
  function getGitOriginUrl(repoDir) {
67474
67699
  try {
67475
67700
  const url = (0, import_node_child_process5.execSync)("git config --get remote.origin.url", {
@@ -73112,28 +73337,31 @@ async function handleInstall(positionals, flags) {
73112
73337
  function installSkill(skillsBin, skill, projectRoot) {
73113
73338
  console.log(` Installing: ${skill.source} (${skill.type})`);
73114
73339
  const localDir = resolveLocalDirIfExists(skill, projectRoot);
73115
- const wantsExcludePrivate = localDir !== null && fs4.existsSync(path6.join(localDir, PRIVATE_SKILLS_DIRNAME)) && !sourcePathExplicitlyTargetsPrivate(skill.source);
73340
+ const excludePrivate = localDir !== null && !sourcePathExplicitlyTargetsPrivate(skill.source);
73116
73341
  try {
73117
73342
  const agents = ["claude-code", "codex", "gemini-cli"];
73118
- if (wantsExcludePrivate && localDir) {
73119
- const skillDirs = findSkillDirs(localDir, { fullDepth: true, excludePrivate: true });
73343
+ if (localDir) {
73344
+ const skillDirs = findSkillDirs(localDir, { fullDepth: true, excludePrivate });
73120
73345
  if (skillDirs.length === 0) {
73121
- console.log(` No skills found under ${skill.source} (after excluding ${PRIVATE_SKILLS_DIRNAME}/)`);
73346
+ console.log(` No skills found under ${skill.source}`);
73122
73347
  return;
73123
73348
  }
73124
- console.log(` Installing ${skillDirs.length} public skill(s) (excluding ${PRIVATE_SKILLS_DIRNAME}/)...`);
73125
- for (const dir of skillDirs) {
73126
- const rel = path6.relative(projectRoot, dir);
73127
- const installSource = rel.startsWith(".") ? rel : `./${rel}`;
73128
- for (const agent of agents) {
73129
- (0, import_node_child_process7.execSync)(`${skillsBin} add ${JSON.stringify(installSource)} -a ${agent} -s '*' -y --full-depth`, {
73130
- cwd: projectRoot,
73131
- stdio: "inherit",
73132
- timeout: 12e4
73133
- });
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
+ }
73134
73362
  }
73363
+ return;
73135
73364
  }
73136
- return;
73137
73365
  }
73138
73366
  for (const agent of agents) {
73139
73367
  (0, import_node_child_process7.execSync)(`${skillsBin} add ${JSON.stringify(skill.source)} -a ${agent} -s '*' -y --full-depth`, {
@@ -78910,7 +79138,57 @@ async function handleOllama(subcommand, positionals, flags, context2) {
78910
79138
  }
78911
79139
  return;
78912
79140
  }
78913
- throw new Error("Usage: eve ollama target <add|rm|test|wake> ...");
79141
+ if (action === "pull") {
79142
+ const targetId = positionals[1];
79143
+ if (!targetId) throw new Error("Usage: eve ollama target pull <target-id> --model-id <id>");
79144
+ const modelId = requireString(flags, "model-id");
79145
+ const query = new URLSearchParams();
79146
+ query.set("model_id", modelId);
79147
+ const result = await requestJson(
79148
+ context2,
79149
+ `/inference/targets/${targetId}/pull?${query.toString()}`,
79150
+ { method: "POST" }
79151
+ );
79152
+ outputJson(result, json);
79153
+ if (!json) {
79154
+ if (result.ok) {
79155
+ console.log(`Pull complete: ${result.model} on ${result.target}`);
79156
+ } else {
79157
+ console.error(`Pull failed: ${result.message}`);
79158
+ process.exitCode = 1;
79159
+ }
79160
+ }
79161
+ return;
79162
+ }
79163
+ if (action === "models") {
79164
+ const targetId = positionals[1];
79165
+ if (!targetId) throw new Error("Usage: eve ollama target models <target-id>");
79166
+ const result = await requestJson(
79167
+ context2,
79168
+ `/inference/targets/${targetId}/remote-models`
79169
+ );
79170
+ if (json) {
79171
+ outputJson(result, json);
79172
+ return;
79173
+ }
79174
+ console.log(`Models on target "${result.target}":`);
79175
+ if (result.models.length === 0) {
79176
+ console.log(" (none)");
79177
+ return;
79178
+ }
79179
+ printTable(
79180
+ ["Name", "Size (GB)", "Modified"],
79181
+ result.models.map((m) => [
79182
+ m.name,
79183
+ (m.size / 1e9).toFixed(1),
79184
+ m.modified_at
79185
+ ])
79186
+ );
79187
+ return;
79188
+ }
79189
+ throw new Error(
79190
+ "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)"
79191
+ );
78914
79192
  }
78915
79193
  case "models": {
78916
79194
  const models = await requestJson(context2, "/inference/models");
@@ -79512,8 +79790,65 @@ async function handleFs(subcommand, positionals, flags, context2) {
79512
79790
  await handleSync2(action, positionals.slice(1), flags, context2);
79513
79791
  return;
79514
79792
  }
79793
+ case "share": {
79794
+ const orgId = getOrgOrThrow(flags, context2);
79795
+ const path8 = positionals[0];
79796
+ if (!path8) throw new Error("Usage: eve fs share <path> --org <org> [--expires <duration>] [--label <text>]");
79797
+ const body = {
79798
+ path: path8,
79799
+ expires_in: getStringFlag(flags, ["expires", "expires-in", "ttl"]) ?? void 0,
79800
+ label: getStringFlag(flags, ["label"]) ?? void 0
79801
+ };
79802
+ const json = Boolean(flags["json"]);
79803
+ const share = await requestJson(context2, `/orgs/${orgId}/fs/share`, { method: "POST", body });
79804
+ if (json) {
79805
+ outputJson(share, true);
79806
+ } else {
79807
+ console.log(`Share URL: ${share.url}`);
79808
+ if (share.expires_at) console.log(`Expires: ${share.expires_at}`);
79809
+ if (share.label) console.log(`Label: ${share.label}`);
79810
+ console.log(`Token: ${share.id}`);
79811
+ }
79812
+ return;
79813
+ }
79814
+ case "shares": {
79815
+ const orgId = getOrgOrThrow(flags, context2);
79816
+ const json = Boolean(flags["json"]);
79817
+ const result = await requestJson(context2, `/orgs/${orgId}/fs/shares`);
79818
+ outputJson(result, json, `${result.data.length} active share(s)`);
79819
+ return;
79820
+ }
79821
+ case "revoke": {
79822
+ const orgId = getOrgOrThrow(flags, context2);
79823
+ const token = positionals[0];
79824
+ if (!token) throw new Error("Usage: eve fs revoke <token> --org <org>");
79825
+ const json = Boolean(flags["json"]);
79826
+ const share = await requestJson(context2, `/orgs/${orgId}/fs/shares/${token}`, { method: "DELETE" });
79827
+ outputJson(share, json, `Share token ${token} revoked`);
79828
+ return;
79829
+ }
79830
+ case "publish": {
79831
+ const orgId = getOrgOrThrow(flags, context2);
79832
+ const pathPrefix = positionals[0];
79833
+ if (!pathPrefix) throw new Error("Usage: eve fs publish <path-prefix> --org <org> [--label <text>]");
79834
+ const body = {
79835
+ path_prefix: pathPrefix,
79836
+ label: getStringFlag(flags, ["label"]) ?? void 0
79837
+ };
79838
+ const json = Boolean(flags["json"]);
79839
+ const result = await requestJson(context2, `/orgs/${orgId}/fs/public-paths`, { method: "POST", body });
79840
+ outputJson(result, json, `Published path prefix: ${pathPrefix}`);
79841
+ return;
79842
+ }
79843
+ case "public-paths": {
79844
+ const orgId = getOrgOrThrow(flags, context2);
79845
+ const json = Boolean(flags["json"]);
79846
+ const result = await requestJson(context2, `/orgs/${orgId}/fs/public-paths`);
79847
+ outputJson(result, json, `${result.data.length} public path(s)`);
79848
+ return;
79849
+ }
79515
79850
  default:
79516
- throw new Error("Usage: eve fs sync <init|status|logs|pause|resume|disconnect|mode|conflicts|resolve|doctor>");
79851
+ throw new Error("Usage: eve fs <sync|share|shares|revoke|publish|public-paths> ...");
79517
79852
  }
79518
79853
  }
79519
79854
 
@@ -80629,6 +80964,161 @@ function sleep(ms) {
80629
80964
  });
80630
80965
  }
80631
80966
 
80967
+ // src/commands/github.ts
80968
+ var import_node_child_process11 = require("node:child_process");
80969
+ async function handleGithub(subcommand, positionals, flags, context2) {
80970
+ const json = Boolean(flags.json);
80971
+ const projectId = getStringFlag(flags, ["project"]) ?? context2.projectId;
80972
+ if (!projectId) {
80973
+ throw new Error("Missing --project flag or profile default project.");
80974
+ }
80975
+ switch (subcommand) {
80976
+ case "setup":
80977
+ await setupGithub(projectId, flags, json, context2);
80978
+ return;
80979
+ case "status":
80980
+ await statusGithub(projectId, json, context2);
80981
+ return;
80982
+ case "test":
80983
+ await testGithub(projectId, json, context2);
80984
+ return;
80985
+ default:
80986
+ throw new Error("Usage: eve github <setup|status|test> [--project <id>]");
80987
+ }
80988
+ }
80989
+ async function setupGithub(projectId, flags, json, context2) {
80990
+ const regenerate = getBooleanFlag(flags, ["regenerate"]) ?? false;
80991
+ const result = await requestJson(context2, `/projects/${projectId}/github/setup`, {
80992
+ method: "POST",
80993
+ body: { regenerate }
80994
+ });
80995
+ if (json) {
80996
+ outputJson(result, true);
80997
+ return;
80998
+ }
80999
+ const ownerRepo = extractOwnerRepo(result.repo_url);
81000
+ if (!ownerRepo) {
81001
+ printManualInstructions(result);
81002
+ return;
81003
+ }
81004
+ if (tryGhWebhook(ownerRepo, result.webhook_url, result.secret, result.events)) {
81005
+ console.log(`Webhook created on ${ownerRepo}!`);
81006
+ console.log("");
81007
+ console.log(` Events: ${result.events.join(", ")}`);
81008
+ console.log(` URL: ${result.webhook_url}`);
81009
+ console.log("");
81010
+ console.log("GitHub will now send push and pull_request events to Eve.");
81011
+ console.log('Run "eve github test" to verify the pipeline trigger fires.');
81012
+ } else {
81013
+ printManualInstructions(result);
81014
+ }
81015
+ }
81016
+ async function statusGithub(projectId, json, context2) {
81017
+ const result = await requestJson(context2, `/projects/${projectId}/github/status`);
81018
+ if (json) {
81019
+ outputJson(result, true);
81020
+ return;
81021
+ }
81022
+ if (result.configured) {
81023
+ console.log("GitHub webhook: configured");
81024
+ } else {
81025
+ console.log("GitHub webhook: not configured");
81026
+ console.log('Run "eve github setup" to configure.');
81027
+ }
81028
+ console.log(` Webhook URL: ${result.webhook_url}`);
81029
+ }
81030
+ async function testGithub(projectId, json, context2) {
81031
+ const result = await requestJson(context2, `/projects/${projectId}/github/test`, {
81032
+ method: "POST"
81033
+ });
81034
+ if (json) {
81035
+ outputJson(result, true);
81036
+ return;
81037
+ }
81038
+ console.log(`Test event created: ${result.event_id}`);
81039
+ console.log("");
81040
+ console.log("If you have a pipeline with a github.push trigger, it should fire now.");
81041
+ console.log("Check with: eve event list --project " + projectId);
81042
+ }
81043
+ function extractOwnerRepo(repoUrl) {
81044
+ const httpsMatch = repoUrl.match(/github\.com\/([^/]+\/[^/]+?)(?:\.git)?$/);
81045
+ if (httpsMatch) return httpsMatch[1];
81046
+ const sshMatch = repoUrl.match(/github\.com:([^/]+\/[^/]+?)(?:\.git)?$/);
81047
+ if (sshMatch) return sshMatch[1];
81048
+ return null;
81049
+ }
81050
+ function tryGhWebhook(ownerRepo, webhookUrl, secret, events) {
81051
+ try {
81052
+ (0, import_node_child_process11.execSync)("gh auth status", { stdio: "pipe", timeout: 1e4 });
81053
+ } catch {
81054
+ return false;
81055
+ }
81056
+ try {
81057
+ const existing = (0, import_node_child_process11.execSync)(
81058
+ `gh api repos/${ownerRepo}/hooks --jq '[.[] | select(.config.url == "${webhookUrl}")] | length'`,
81059
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 15e3 }
81060
+ ).trim();
81061
+ if (existing !== "0") {
81062
+ const hookId = (0, import_node_child_process11.execSync)(
81063
+ `gh api repos/${ownerRepo}/hooks --jq '[.[] | select(.config.url == "${webhookUrl}")][0].id'`,
81064
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"], timeout: 15e3 }
81065
+ ).trim();
81066
+ if (hookId) {
81067
+ (0, import_node_child_process11.execSync)(
81068
+ `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`,
81069
+ { stdio: "pipe", timeout: 15e3 }
81070
+ );
81071
+ return true;
81072
+ }
81073
+ }
81074
+ } catch {
81075
+ }
81076
+ try {
81077
+ (0, import_node_child_process11.execSync)(
81078
+ `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`,
81079
+ { stdio: "pipe", timeout: 15e3 }
81080
+ );
81081
+ return true;
81082
+ } catch {
81083
+ return false;
81084
+ }
81085
+ }
81086
+ function printManualInstructions(result) {
81087
+ const ownerRepo = extractOwnerRepo(result.repo_url);
81088
+ console.log("GitHub webhook setup");
81089
+ console.log("");
81090
+ console.log(` Webhook URL: ${result.webhook_url}`);
81091
+ console.log(` Secret: ${result.secret}`);
81092
+ console.log(` Content type: application/json`);
81093
+ console.log(` Events: ${result.events.join(", ")}`);
81094
+ console.log("");
81095
+ if (ownerRepo) {
81096
+ console.log("Auto-setup with gh CLI (install from https://cli.github.com):");
81097
+ console.log("");
81098
+ console.log(` gh api repos/${ownerRepo}/hooks -X POST \\`);
81099
+ console.log(` -f name=web \\`);
81100
+ console.log(` -f config[url]="${result.webhook_url}" \\`);
81101
+ console.log(` -f config[content_type]=json \\`);
81102
+ console.log(` -f config[secret]="${result.secret}" \\`);
81103
+ result.events.forEach((e) => {
81104
+ console.log(` -f events[]=${e} \\`);
81105
+ });
81106
+ console.log(` -f active=true`);
81107
+ console.log("");
81108
+ }
81109
+ console.log("Or configure manually:");
81110
+ if (ownerRepo) {
81111
+ console.log(` 1. Go to https://github.com/${ownerRepo}/settings/hooks/new`);
81112
+ } else {
81113
+ console.log(" 1. Go to your repo Settings > Webhooks > Add webhook");
81114
+ }
81115
+ console.log(" 2. Payload URL: " + result.webhook_url);
81116
+ console.log(" 3. Content type: application/json");
81117
+ console.log(" 4. Secret: " + result.secret);
81118
+ console.log(' 5. Events: "push" and "pull_request"');
81119
+ console.log(' 6. Click "Add webhook"');
81120
+ }
81121
+
80632
81122
  // src/index.ts
80633
81123
  function getCliVersion() {
80634
81124
  try {
@@ -80821,6 +81311,9 @@ async function main2() {
80821
81311
  case "local":
80822
81312
  await handleLocal(subcommand, rest, flags, context2);
80823
81313
  return;
81314
+ case "github":
81315
+ await handleGithub(subcommand, rest, flags, context2);
81316
+ return;
80824
81317
  default:
80825
81318
  showMainHelp();
80826
81319
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@eve-horizon/cli",
3
- "version": "0.2.40",
3
+ "version": "0.2.42",
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
+ }