@melius-ai/cli 0.8.0 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -265,7 +265,7 @@ Requires the Pro or Enterprise plan.
265
265
  | `mel asset folders` | List the library's folders (`id`, `name`, `path`, `fileCount`) so you can resolve a folder name to an id for `--folder-id` |
266
266
  | `mel asset place <canvasId> <assetIds...>` | Place existing library assets onto a canvas by id — references the **original** asset (no duplicate) |
267
267
 
268
- `mel asset search` searches by meaning (semantic), with exact filename/title matches ranked first, so query with a filename or a description of the content. It returns `{ query, total, results: [{ assetId, filename, fileType, previewUrl, ... }] }`. Filter with `--file-type <image|video|audio|pdf|text>` and `--limit <1-20>`; page deeper with `--offset <n>` (skip the first N matches — page until the running count reaches `total`); scope to one canvas with `--canvas-id` (omit to search the whole team library).
268
+ `mel asset search` searches by meaning (semantic), with exact filename/title matches ranked first, so query with a filename or a description of the content. Pass an exact filename verbatim, including its extension. It returns `{ query, total, results: [{ assetId, filename, fileType, previewUrl, ... }] }`. Filter by origin with `--source <upload|generated>`, by media type with `--file-type <image|video|audio|pdf|text>`, and by page size with `--limit <1-20>`; page deeper with `--offset <n>` (skip the first N matches — page until the running count reaches `total`); scope to one canvas with `--canvas-id` (omit to search the whole team library).
269
269
 
270
270
  Scope to a **folder** with `--folder-id` (from `mel asset folders`): with a query it filters within that folder and its subfolders; **omit the query** to bring in the _whole_ folder (every asset in it). `mel asset folders` returns each folder's root-relative `path` (e.g. `Brand / Logos`) to disambiguate same-named folders.
271
271
 
@@ -276,6 +276,8 @@ Filter by **tag** with `--tags <names>` (comma-separated, case-insensitive): ass
276
276
  ```bash
277
277
  # Find an asset, then bring it onto a canvas and wire it
278
278
  mel asset search "black jacket shot" --file-type image
279
+ mel asset search "Product_Shot_05.PNG" --source upload
280
+ mel asset search "shark close-up" --source generated
279
281
  mel asset place <canvasId> <assetId1> <assetId2>
280
282
 
281
283
  # Bring in a whole folder: resolve the folder, then search it with no query
package/dist/bin/mel.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  printUpgradeNoticeIfNeeded,
8
8
  withDefaultHelp,
9
9
  writeError
10
- } from "../chunk-3PBGQVUH.js";
10
+ } from "../chunk-WRLYKNYI.js";
11
11
 
12
12
  // bin/mel.ts
13
13
  var program = createProgram();
@@ -7736,6 +7736,7 @@ var MAX_INPUT_VIDEOS = 3;
7736
7736
  var MAX_INPUT_DOCUMENTS = 5;
7737
7737
  var MAX_AGENT_MESSAGE_CONTENT_LENGTH = 5e4;
7738
7738
  var MAX_SEED = 2147483647;
7739
+ var MAX_VARIATIONS = 10;
7739
7740
 
7740
7741
  // ../api-contract/src/common.ts
7741
7742
  var MessageResponseSchema = external_exports.object({ message: external_exports.string() });
@@ -8041,6 +8042,9 @@ var BulkDownloadFilesResponseSchema = external_exports.object({
8041
8042
  var BulkHideFilesBodySchema = external_exports.object({
8042
8043
  assetIds: BulkFileAssetIdsSchema
8043
8044
  });
8045
+ var BulkDeleteFilesBodySchema = external_exports.object({
8046
+ assetIds: BulkFileAssetIdsSchema
8047
+ });
8044
8048
  var BulkUnhideFilesBodySchema = external_exports.object({
8045
8049
  assetIds: BulkFileAssetIdsSchema
8046
8050
  });
@@ -8125,16 +8129,18 @@ var FileTabCountsResponseSchema = external_exports.object({
8125
8129
  var AGENT_ASSET_SEARCH_PAGE_SIZE = 20;
8126
8130
  var AgentAssetSearchQuerySchema = external_exports.object({
8127
8131
  query: external_exports.string().trim().min(1).max(500).optional().describe(
8128
- 'The semantic search query \u2014 a filename or a description of the asset (e.g. "red logo", "the shark photo"). Provide it to FIND specific assets. OMIT it entirely to bring in EVERY asset from a folder: when the member says "bring in all my assets from the X folder" / "add everything in X to the canvas", resolve the folder with list_asset_folders and call asset_search with just that `folderId` and NO query. Never invent a query when the member asked for everything in a folder \u2014 a query filters and will drop assets they wanted. Omitting the query requires a `folderId`.'
8132
+ 'The semantic search query \u2014 an exact filename or a description of the asset (e.g. "Product_Shot_05.png", "red logo", "the shark photo"). When the member gives an exact filename, pass it verbatim, including its extension; exact matches rank first. Provide a query to FIND specific assets. OMIT it entirely to bring in EVERY asset from a folder: when the member says "bring in all my assets from the X folder" / "add everything in X to the canvas", resolve the folder with list_asset_folders and call asset_search with just that `folderId` and NO query. Never invent a query when the member asked for everything in a folder \u2014 a query filters and will drop assets they wanted. Omitting the query requires a `folderId`.'
8129
8133
  ),
8130
8134
  limit: external_exports.coerce.number().int().min(1).max(AGENT_ASSET_SEARCH_PAGE_SIZE).default(AGENT_ASSET_SEARCH_PAGE_SIZE),
8131
- source: FileSourceSchema.optional(),
8135
+ source: FileSourceSchema.optional().describe(
8136
+ "Optional. Filter by where the asset came from: `upload` for files uploaded by a member, or `generated` for media created in Melius. Set this only when the member explicitly asks for uploads or generations; omit it to search both."
8137
+ ),
8132
8138
  fileType: FileTypeSchema.optional(),
8133
8139
  canvasId: external_exports.string().uuid().optional().describe(
8134
8140
  'Optional. Omit to search the whole team library \u2014 this is the default and what nearly every request wants (e.g. "use the asset I have"). Only set this to scope to a DIFFERENT canvas the member explicitly names ("search my other canvas"), resolving the id from canvas_list. Do NOT pass the canvas the chat is currently on (its assets are already visible via canvas_content, and scoping there hides whole-library matches), and never guess an id.'
8135
8141
  ),
8136
8142
  folderId: external_exports.string().uuid().optional().describe(
8137
- 'Optional. Scope to one Files folder AND its subfolders. Omit to search the whole team library \u2014 the default, and what nearly every request wants. Set it when the member names a specific folder \u2014 either to FILTER within it (pass `folderId` + `query`, e.g. "find the shark shot in my ocean folder") or to bring in EVERYTHING in it (pass `folderId` and OMIT `query`, e.g. "add all my assets from the ocean folder"). Resolve the id with list_asset_folders (match by name; if several plausibly match, ask which one); never guess a folder id.'
8143
+ 'Optional. Scope to one Files folder AND its subfolders. Omit to search the whole team library \u2014 the default, and what nearly every request wants. Set it when the member names a specific folder \u2014 either to FILTER within it (pass `folderId` + `query`, e.g. "find the shark shot in my ocean folder") or to bring in EVERYTHING in it (pass `folderId` and OMIT `query`, e.g. "add all my assets from the ocean folder"). Resolve the id with list_asset_folders: prefer a case-insensitive exact name or path before considering partial matches; if several exact or partial matches remain, ask which one. Never guess a folder id.'
8138
8144
  ),
8139
8145
  tags: external_exports.string().trim().optional().describe(
8140
8146
  'Optional. Filter to assets carrying ALL of these tags (AND). Pass a tag name ONLY when the member explicitly asks to filter by a tag (e.g. "find my assets tagged brand", "my hero tag") \u2014 never infer one from ordinary words in their request. Comma-separated (e.g. "brand" or "brand,hero"), case-insensitive. Combine with `query` to search within tagged assets, or omit `query` (with tags and/or a folderId) to bring in every asset carrying them. An unknown or misspelled tag name matches nothing, so pass only tags the member actually named.'
@@ -8436,6 +8442,17 @@ var filesContract = c2.router({
8436
8442
  },
8437
8443
  summary: "Hide files from Files"
8438
8444
  },
8445
+ bulkDeleteFiles: {
8446
+ method: "POST",
8447
+ path: "/files/bulk/delete",
8448
+ body: BulkDeleteFilesBodySchema,
8449
+ responses: {
8450
+ 200: BulkFileActionResponseSchema,
8451
+ 403: ErrorBodySchema,
8452
+ 404: ErrorBodySchema
8453
+ },
8454
+ summary: "Delete files from Files"
8455
+ },
8439
8456
  hideFile: {
8440
8457
  method: "POST",
8441
8458
  path: "/files/:assetId/hide",
@@ -8448,6 +8465,18 @@ var filesContract = c2.router({
8448
8465
  },
8449
8466
  summary: "Hide a file from Files"
8450
8467
  },
8468
+ deleteFile: {
8469
+ method: "DELETE",
8470
+ path: "/files/:assetId",
8471
+ pathParams: FileAssetIdParamsSchema,
8472
+ body: null,
8473
+ responses: {
8474
+ 204: c2.noBody(),
8475
+ 403: ErrorBodySchema,
8476
+ 404: ErrorBodySchema
8477
+ },
8478
+ summary: "Delete a file from Files"
8479
+ },
8451
8480
  bulkUnhideFiles: {
8452
8481
  method: "POST",
8453
8482
  path: "/files/bulk/unhide",
@@ -9390,10 +9419,7 @@ var AutoModelProxy = class {
9390
9419
  resolve(input) {
9391
9420
  switch (input.nodeType) {
9392
9421
  case "video":
9393
- return this.resolveVideo(
9394
- input.connectedInputs,
9395
- input.canvasVideoInputRoutingEnabled === true
9396
- );
9422
+ return this.resolveVideo(input.connectedInputs);
9397
9423
  case "image":
9398
9424
  return this.resolveImage(input.connectedInputs);
9399
9425
  case "text":
@@ -9412,7 +9438,7 @@ var AutoModelProxy = class {
9412
9438
  return this.registry;
9413
9439
  }
9414
9440
  // ── Private resolvers ───────────────────────────────────────────────
9415
- resolveVideo(ci, canvasVideoInputRoutingEnabled) {
9441
+ resolveVideo(ci) {
9416
9442
  const hasAnyImage = ci.hasImage || ci.hasStartingImage || ci.hasEndImage || ci.hasReferenceImage;
9417
9443
  if (ci.hasVideo && hasAnyImage) {
9418
9444
  if (ci.hasEndImage) {
@@ -9445,11 +9471,7 @@ var AutoModelProxy = class {
9445
9471
  return this.lookupRoute("video", "video-with-audio");
9446
9472
  }
9447
9473
  if (ci.hasAudio && (ci.hasStartingImage || ci.hasImage) && ci.hasEndImage) {
9448
- return canvasVideoInputRoutingEnabled ? this.lookupRoute("video", "frames-with-audio") : {
9449
- valid: true,
9450
- model: "ltx-2.3-audio",
9451
- variant: "image-to-video"
9452
- };
9474
+ return this.lookupRoute("video", "frames-with-audio");
9453
9475
  }
9454
9476
  if (ci.hasAudio && hasAnyImage) {
9455
9477
  return this.lookupRoute("video", "image-with-audio");
@@ -9775,6 +9797,20 @@ function parseCustomResolution(resolution) {
9775
9797
  return { width, height };
9776
9798
  }
9777
9799
  var MENTION_RE = /@\[([^\]]+)\](?:\{([^}]+)\})?/g;
9800
+ var MENTION_WITH_ID_RE = /@\[[^\]]+\]\{([^}]+)\}/g;
9801
+ function extractMentionedNodeIds(text) {
9802
+ if (!text) return [];
9803
+ const ids = [];
9804
+ const seen = /* @__PURE__ */ new Set();
9805
+ for (const match of text.matchAll(MENTION_WITH_ID_RE)) {
9806
+ const id = match[1];
9807
+ if (!seen.has(id)) {
9808
+ seen.add(id);
9809
+ ids.push(id);
9810
+ }
9811
+ }
9812
+ return ids;
9813
+ }
9778
9814
  var MAGIC_RESIZE_NODE_WIDTH = 500;
9779
9815
  var MAGIC_RESIZE_PREGEN_HEIGHT = 550;
9780
9816
 
@@ -9990,6 +10026,19 @@ var ElevenLabsVoiceSettingsSchema = external_exports.object({
9990
10026
  outputFormat: ElevenLabsOutputFormatSchema.optional()
9991
10027
  });
9992
10028
 
10029
+ // ../api-contract/src/generation-failure-reason.ts
10030
+ var GENERATION_FAILURE_REASONS = [
10031
+ "insufficient_credits",
10032
+ "content_policy",
10033
+ "no_media_generated",
10034
+ "provider_error",
10035
+ "validation_error",
10036
+ "timeout",
10037
+ "system",
10038
+ "unknown"
10039
+ ];
10040
+ var GenerationFailureReasonSchema = external_exports.enum(GENERATION_FAILURE_REASONS);
10041
+
9993
10042
  // ../api-contract/src/lora.ts
9994
10043
  var c6 = initContract();
9995
10044
  var LORA_UPLOAD_PART_SIZE_BYTES = 16 * 1024 * 1024;
@@ -10502,6 +10551,16 @@ var NodeVersionResponseSchema = external_exports.object({
10502
10551
  */
10503
10552
  modelDisplayName: external_exports.string().nullable().optional(),
10504
10553
  asset: AssetResponseSchema.nullable(),
10554
+ /**
10555
+ * For a version produced by a node tool (background removal, subtitles,
10556
+ * GIF, upscale — i.e. `sourceToolName` is set), the source asset the tool
10557
+ * transformed. A tool runs in place on a file node, so the input lives on
10558
+ * an earlier version that the bulk content response does not ship; this
10559
+ * surfaces it so consumers (e.g. Playground history) can show what the tool
10560
+ * ran on without re-fetching the node's full version list. Populated only
10561
+ * when the caller opts in via `includeToolInputReferences`.
10562
+ */
10563
+ toolInputAsset: AssetResponseSchema.nullable().optional(),
10505
10564
  pdfExtraction: PdfExtractionSchema.nullable().optional(),
10506
10565
  /** Present when an active node run exists for this version (e.g. PDF extraction in progress). */
10507
10566
  nodeRunId: external_exports.string().uuid().nullable().optional(),
@@ -10524,7 +10583,12 @@ var MagicResizeOutputSchema = external_exports.object({
10524
10583
  assetId: external_exports.string().nullable(),
10525
10584
  assetUrl: external_exports.string().nullable(),
10526
10585
  previewUrl: external_exports.string().nullable(),
10527
- failed: external_exports.boolean().optional()
10586
+ failed: external_exports.boolean().optional(),
10587
+ // User-facing failure reason for a `failed` layer, mirroring the error
10588
+ // message + severity a regular media node shows (e.g. a provider error vs.
10589
+ // a content-moderation warning). Absent on successful layers.
10590
+ errorMessage: external_exports.string().nullish(),
10591
+ errorSeverity: external_exports.enum(["error", "warning"]).nullish()
10528
10592
  });
10529
10593
  var NodeResponseSchema = external_exports.object({
10530
10594
  id: external_exports.string().uuid(),
@@ -10586,6 +10650,8 @@ var NodeResponseSchema = external_exports.object({
10586
10650
  childNodeIds: external_exports.array(external_exports.string().uuid()).optional(),
10587
10651
  /** Per-ratio outputs for magic-resize nodes (from CRDT); one per variant. */
10588
10652
  magicResizeOutputs: external_exports.array(MagicResizeOutputSchema).nullable().optional(),
10653
+ /** User id of the team member who created the node, or null when unknown. */
10654
+ createdByUserId: external_exports.string().uuid().nullable().optional(),
10589
10655
  versions: external_exports.array(NodeVersionResponseSchema),
10590
10656
  createdAt: external_exports.string().datetime(),
10591
10657
  updatedAt: external_exports.string().datetime()
@@ -10606,7 +10672,7 @@ var CanvasMediaPresetSchema = external_exports.object({
10606
10672
  aspectRatio: OutputAspectRatioSchema.optional(),
10607
10673
  resolution: OutputResolutionSchema.optional(),
10608
10674
  fast: external_exports.boolean().optional(),
10609
- numVariations: external_exports.number().int().min(1).max(10).optional()
10675
+ numVariations: external_exports.number().int().min(1).max(MAX_VARIATIONS).optional()
10610
10676
  }).optional(),
10611
10677
  video: external_exports.object({
10612
10678
  model: external_exports.string().optional(),
@@ -10615,13 +10681,13 @@ var CanvasMediaPresetSchema = external_exports.object({
10615
10681
  resolution: OutputResolutionSchema.optional(),
10616
10682
  duration: external_exports.number().int().positive().optional(),
10617
10683
  fast: external_exports.boolean().optional(),
10618
- numVariations: external_exports.number().int().min(1).max(10).optional()
10684
+ numVariations: external_exports.number().int().min(1).max(MAX_VARIATIONS).optional()
10619
10685
  }).optional(),
10620
10686
  text: external_exports.object({
10621
10687
  model: external_exports.string().optional(),
10622
10688
  mode: external_exports.string().optional(),
10623
10689
  fast: external_exports.boolean().optional(),
10624
- numVariations: external_exports.number().int().min(1).max(10).optional()
10690
+ numVariations: external_exports.number().int().min(1).max(MAX_VARIATIONS).optional()
10625
10691
  }).optional(),
10626
10692
  audio: external_exports.object({
10627
10693
  model: external_exports.string().optional(),
@@ -10663,7 +10729,24 @@ var CanvasContentQuerySchema = external_exports.object({
10663
10729
  * so the model reads the summary instead of a URL. The web app does
10664
10730
  * not set this, so it always receives URLs.
10665
10731
  */
10666
- mediaSummaries: QueryBooleanSchema.optional()
10732
+ mediaSummaries: QueryBooleanSchema.optional(),
10733
+ /**
10734
+ * Opt-in: resolve the source asset each node-tool version transformed
10735
+ * onto `version.toolInputAsset` (see that field). Off by default so the
10736
+ * common canvas/agent/MCP reads never pay the extra version lookup; the
10737
+ * Playground history loader sets it to restore tool-run input previews.
10738
+ */
10739
+ includeToolInputReferences: QueryBooleanSchema.optional(),
10740
+ /**
10741
+ * Opt-in: ship EVERY asset-bearing version for generation nodes
10742
+ * (image/video/audio) with more than one output, so a
10743
+ * native-variations node (one node, N output versions) can rebuild
10744
+ * its full output set from a bulk read. Resolved in a bounded batched
10745
+ * pass like `includeToolInputReferences`; off by default so common
10746
+ * reads pay nothing. Unlike `includeAllVersions` it needs no nodeId
10747
+ * scoping.
10748
+ */
10749
+ includeVariationVersions: QueryBooleanSchema.optional()
10667
10750
  }).refine(
10668
10751
  (query) => query.includeAllVersions !== true || query.nodeId !== void 0,
10669
10752
  {
@@ -10698,7 +10781,7 @@ var RunNodeBodySchema = external_exports.object({
10698
10781
  outputDuration: external_exports.number().int().positive().optional(),
10699
10782
  outputResolution: OutputResolutionSchema.optional(),
10700
10783
  seed: external_exports.number().int().nonnegative().max(MAX_SEED).optional(),
10701
- numVariations: external_exports.number().int().min(1).max(10).optional(),
10784
+ numVariations: external_exports.number().int().min(1).max(MAX_VARIATIONS).optional(),
10702
10785
  /**
10703
10786
  * Dev-only: force a specific generation provider for the run. When set,
10704
10787
  * `prepareGenerationRequest` restricts variant selection to the named
@@ -10772,7 +10855,7 @@ var RunImageToolBodySchema = external_exports.object({
10772
10855
  canvasId: external_exports.string().uuid().optional(),
10773
10856
  toolName: external_exports.string().trim().min(1),
10774
10857
  toolConfig: external_exports.record(external_exports.unknown()).optional(),
10775
- numVariations: external_exports.number().int().min(1).max(10).optional(),
10858
+ numVariations: external_exports.number().int().min(1).max(MAX_VARIATIONS).optional(),
10776
10859
  /** Base64-encoded PNG mask image for inpainting (white = areas to regenerate). */
10777
10860
  maskImageBase64: external_exports.string().optional()
10778
10861
  });
@@ -10841,6 +10924,7 @@ var NodeRunResponseSchema = external_exports.object({
10841
10924
  errorMessage: external_exports.string().nullable(),
10842
10925
  errorSeverity: ErrorSeveritySchema.nullable().default(null),
10843
10926
  errorRetryable: external_exports.boolean().nullable().optional(),
10927
+ errorReason: GenerationFailureReasonSchema.nullable().optional(),
10844
10928
  numVariationsRequested: external_exports.number().int().nullable(),
10845
10929
  numVariationsCompleted: external_exports.number().int().nullable().optional(),
10846
10930
  numVariationsFailed: external_exports.number().int().nullable().optional(),
@@ -10895,6 +10979,7 @@ var LatestNodeRunResponseSchema = external_exports.object({
10895
10979
  errorMessage: external_exports.string().nullable(),
10896
10980
  errorSeverity: ErrorSeveritySchema.nullable().default(null),
10897
10981
  errorRetryable: external_exports.boolean().nullable().optional(),
10982
+ errorReason: GenerationFailureReasonSchema.nullable().optional(),
10898
10983
  numVariationsRequested: external_exports.number().int().nullable(),
10899
10984
  numVariationsCompleted: external_exports.number().int().nullable().optional(),
10900
10985
  numVariationsFailed: external_exports.number().int().nullable().optional(),
@@ -11446,7 +11531,12 @@ var canvasContract = c7.router({
11446
11531
  failedLayers: external_exports.array(
11447
11532
  external_exports.object({
11448
11533
  layerIndex: external_exports.number().int(),
11449
- ratio: external_exports.string()
11534
+ ratio: external_exports.string(),
11535
+ // User-facing failure reason + severity (mirrors a
11536
+ // regular media node's error/warning). Optional so
11537
+ // a new client tolerates an older backend.
11538
+ errorMessage: external_exports.string().nullish(),
11539
+ errorSeverity: external_exports.enum(["error", "warning"]).nullish()
11450
11540
  })
11451
11541
  ).nullish()
11452
11542
  }),
@@ -11775,7 +11865,7 @@ var canvasContract = c7.router({
11775
11865
  * every intermediate node — see `BulkNodeRunService`. Used by the
11776
11866
  * template box's variation stepper. Defaults to 1 when omitted.
11777
11867
  */
11778
- numVariations: external_exports.number().int().min(1).max(10).optional(),
11868
+ numVariations: external_exports.number().int().min(1).max(MAX_VARIATIONS).optional(),
11779
11869
  /**
11780
11870
  * Node ids whose audio-to-video duration should be matched to
11781
11871
  * connected generated audio after upstream audio nodes finish.
@@ -12306,7 +12396,7 @@ var GenerationRunBodySchema = external_exports.object({
12306
12396
  duration: external_exports.number().int().positive().optional(),
12307
12397
  resolution: OutputResolutionSchema.optional(),
12308
12398
  seed: external_exports.number().int().nonnegative().max(MAX_SEED).optional(),
12309
- numVariations: external_exports.number().int().min(1).max(10).optional(),
12399
+ numVariations: external_exports.number().int().min(1).max(MAX_VARIATIONS).optional(),
12310
12400
  /**
12311
12401
  * Whether the variant should generate audio. Only honored on variants
12312
12402
  * whose registry entry declares `falAudioField`. Defaults to `true`.
@@ -12573,6 +12663,10 @@ var GenerationHistoryItemSchema = external_exports.object({
12573
12663
  id: external_exports.string(),
12574
12664
  type: external_exports.enum(["media", "text"]),
12575
12665
  model: external_exports.string(),
12666
+ // Speed tier (e.g. "fast") the job ran at, when it ran at a non-standard
12667
+ // one. Optional so older clients ignore it and the field is absent for
12668
+ // standard-tier and text generations.
12669
+ tier: external_exports.string().nullable().optional(),
12576
12670
  status: GenerationJobStatusSchema,
12577
12671
  creditCost: external_exports.number().nullable(),
12578
12672
  createdAt: external_exports.string(),
@@ -12631,6 +12725,15 @@ var generationContract = c9.router({
12631
12725
  200: ListGenerativeModelsResponseSchema
12632
12726
  }
12633
12727
  },
12728
+ listPublicGenerativeModels: {
12729
+ method: "GET",
12730
+ path: "/generation/models/public",
12731
+ query: external_exports.object({ category: ModelCategorySchema }),
12732
+ responses: {
12733
+ 200: ListGenerativeModelsResponseSchema
12734
+ },
12735
+ summary: "List generally-available models without authentication (logged-out home)"
12736
+ },
12634
12737
  listHeygenAvatarVAvatars: {
12635
12738
  method: "GET",
12636
12739
  path: "/generation/heygen-avatar-v-avatars",
@@ -12645,6 +12748,14 @@ var generationContract = c9.router({
12645
12748
  200: AutoModelDefaultsResponseSchema
12646
12749
  }
12647
12750
  },
12751
+ getPublicAutoModelDefaults: {
12752
+ method: "GET",
12753
+ path: "/generation/auto-model-defaults/public",
12754
+ responses: {
12755
+ 200: AutoModelDefaultsResponseSchema
12756
+ },
12757
+ summary: "Auto-model defaults without authentication (logged-out home)"
12758
+ },
12648
12759
  listGenerationHistory: {
12649
12760
  method: "GET",
12650
12761
  path: "/generation/history",
@@ -14138,7 +14249,7 @@ function isMajorUpgrade(current, latest) {
14138
14249
  return l[0] > c17[0];
14139
14250
  }
14140
14251
  function shouldShowUpgradeNotice(ctx = {}) {
14141
- const current = ctx.current ?? "0.8.0";
14252
+ const current = ctx.current ?? "0.9.1";
14142
14253
  const latest = ctx.latest ?? serverLatestVersion;
14143
14254
  const env = ctx.env ?? process.env;
14144
14255
  const isTty = ctx.isTty ?? Boolean(process.stderr.isTTY);
@@ -14159,7 +14270,7 @@ Upgrade: npm install -g @melius-ai/cli@latest (or: brew update && brew upgrade
14159
14270
  function printUpgradeNoticeIfNeeded(ctx = {}) {
14160
14271
  try {
14161
14272
  if (!shouldShowUpgradeNotice(ctx)) return;
14162
- const current = ctx.current ?? "0.8.0";
14273
+ const current = ctx.current ?? "0.9.1";
14163
14274
  const latest = ctx.latest ?? serverLatestVersion;
14164
14275
  process.stderr.write(formatUpgradeNotice(current, latest));
14165
14276
  } catch {
@@ -15416,11 +15527,36 @@ function planLayout(content, planned, edges, anchorNodeIds) {
15416
15527
  srcNodeId: e.srcNodeId,
15417
15528
  dstNodeId: e.dstNodeId
15418
15529
  }));
15530
+ const canvasNodeIds = new Set(content.nodes.map((n) => n.id));
15531
+ const mentionEdges = [];
15532
+ let mentionEdgeIndex = 0;
15533
+ for (const p of planned) {
15534
+ const mentionIds = /* @__PURE__ */ new Set([
15535
+ ...extractMentionedNodeIds(p.prompt),
15536
+ ...extractMentionedNodeIds(p.text)
15537
+ ]);
15538
+ for (const mentionedId of mentionIds) {
15539
+ let srcId;
15540
+ if (virtualIds.has(mentionedId)) {
15541
+ srcId = mentionedId;
15542
+ } else if (canvasNodeIds.has(mentionedId)) {
15543
+ const node = nodeById.get(mentionedId);
15544
+ srcId = node?.groupId ?? mentionedId;
15545
+ }
15546
+ if (!srcId || srcId === p.id) continue;
15547
+ mentionEdges.push({
15548
+ id: `mention-${mentionEdgeIndex++}`,
15549
+ srcNodeId: srcId,
15550
+ dstNodeId: p.id
15551
+ });
15552
+ }
15553
+ }
15419
15554
  const anchorEdges = [];
15420
15555
  if (anchorNodes && anchorNodes.length > 0) {
15421
15556
  const hasExplicitAnchorEdge = [
15422
15557
  ...plannedEdges,
15423
- ...relevantExisting
15558
+ ...relevantExisting,
15559
+ ...mentionEdges
15424
15560
  ].some(
15425
15561
  (e) => anchorNodeIds.includes(e.srcNodeId) && virtualIds.has(e.dstNodeId)
15426
15562
  );
@@ -15436,7 +15572,17 @@ function planLayout(content, planned, edges, anchorNodeIds) {
15436
15572
  }
15437
15573
  }
15438
15574
  }
15439
- const allEdges = [...plannedEdges, ...relevantExisting, ...anchorEdges];
15575
+ const baseEdges = [...plannedEdges, ...relevantExisting, ...anchorEdges];
15576
+ const baseEdgeKeys = new Set(
15577
+ baseEdges.map((e) => `${e.srcNodeId}->${e.dstNodeId}`)
15578
+ );
15579
+ const uniqueMentionEdges = mentionEdges.filter((e) => {
15580
+ const key = `${e.srcNodeId}->${e.dstNodeId}`;
15581
+ if (baseEdgeKeys.has(key)) return false;
15582
+ baseEdgeKeys.add(key);
15583
+ return true;
15584
+ });
15585
+ const allEdges = [...baseEdges, ...uniqueMentionEdges];
15440
15586
  const allNodes = [...existingNodes, ...virtualNodes];
15441
15587
  const virtualIdsArr = [...virtualIds];
15442
15588
  const rawResult = computeAutoformat(allNodes, allEdges, virtualIdsArr);
@@ -16651,7 +16797,9 @@ Valid node types: text, image, video, audio, file, group, custom_text, stitch.
16651
16797
  const planned = itemsWithoutGeometry.map((item) => ({
16652
16798
  id: item.id ?? item.type,
16653
16799
  nodeType: item.type,
16654
- aspectRatio: item.aspectRatio
16800
+ aspectRatio: item.aspectRatio,
16801
+ prompt: item.prompt,
16802
+ text: item.text
16655
16803
  }));
16656
16804
  const plannedIds = new Set(planned.map((p) => p.id));
16657
16805
  const edges = (edgeItems ?? []).filter(
@@ -18843,10 +18991,10 @@ function registerAssetCommands(program2, getOutputOpts) {
18843
18991
  "Search and place the team's Files (DAM) library assets. Requires a Pro or Enterprise plan"
18844
18992
  );
18845
18993
  asset.command("search").description(
18846
- "Search the team's Files/DAM library (uploads + past generations) by meaning (semantic), with exact filename/title matches ranked first. Returns up to 20 relevant matches per page. Scope to a folder with --folder-id; filter by tag with --tags; omit the query and pass --folder-id or --tags to bring in the whole folder / all tagged assets"
18994
+ "Search the team's Files/DAM library (uploads + past generations) by meaning (semantic), with exact filename/title matches ranked first. Returns up to 20 relevant matches per page. Filter by asset source with --source, scope to a folder with --folder-id, or filter by tag with --tags; omit the query and pass --folder-id or --tags to bring in the whole folder / all tagged assets"
18847
18995
  ).argument(
18848
18996
  "[query]",
18849
- 'Search terms \u2014 a filename or a description of the content, e.g. "Product_Shot_05" or "black jacket shot". Optional: OMIT it and pass --folder-id to list EVERY asset in that folder'
18997
+ 'Search terms \u2014 an exact filename (including its extension) or a description of the content, e.g. "Product_Shot_05.png" or "black jacket shot". Optional: OMIT it and pass --folder-id to list EVERY asset in that folder'
18850
18998
  ).option("--limit <n>", "Max results per page (1-20, default 20)", "20").option(
18851
18999
  "--offset <n>",
18852
19000
  "Skip the first N matches to page deeper (default 0). Page with --limit until the running count reaches the response's total",
@@ -18854,6 +19002,9 @@ function registerAssetCommands(program2, getOutputOpts) {
18854
19002
  ).option(
18855
19003
  "--file-type <type>",
18856
19004
  "Filter by media type: image, video, audio, pdf, or text"
19005
+ ).option(
19006
+ "--source <source>",
19007
+ "Filter by asset source: upload (member-uploaded files) or generated (media created in Melius)"
18857
19008
  ).option(
18858
19009
  "--canvas-id <canvasId>",
18859
19010
  "Scope to one canvas's assets (a filename match within that canvas). Omit to search the whole team library by meaning, exact matches first (the default)"
@@ -18873,6 +19024,8 @@ Resolve a folder name to an id with mel asset folders first.
18873
19024
 
18874
19025
  Examples:
18875
19026
  $ mel asset search "black jacket shot"
19027
+ $ mel asset search "Product_Shot_05.PNG" --source upload
19028
+ $ mel asset search "shark close-up" --source generated
18876
19029
  $ mel asset search "logo" --file-type image --limit 10
18877
19030
  $ mel asset search "logo" --limit 20 --offset 20
18878
19031
  $ mel asset search "shark" --folder-id <folderId> # find within a folder
@@ -18902,6 +19055,9 @@ Examples:
18902
19055
  ...opts.fileType !== void 0 && {
18903
19056
  fileType: opts.fileType
18904
19057
  },
19058
+ ...opts.source !== void 0 && {
19059
+ source: opts.source
19060
+ },
18905
19061
  ...opts.canvasId !== void 0 && {
18906
19062
  canvasId: opts.canvasId
18907
19063
  },
@@ -19115,7 +19271,7 @@ function withDefaultHelp(args) {
19115
19271
  }
19116
19272
  function createProgram() {
19117
19273
  const program2 = new Command();
19118
- program2.name("mel").description("Mel \u2014 Melius agent CLI").version("0.8.0").showSuggestionAfterError(true).option("--json", "Force JSON output (default)").option("--text", "Human-readable output").option(
19274
+ program2.name("mel").description("Mel \u2014 Melius agent CLI").version("0.9.1").showSuggestionAfterError(true).option("--json", "Force JSON output (default)").option("--text", "Human-readable output").option(
19119
19275
  "--fields <fields>",
19120
19276
  "Select specific output fields (comma-separated)"
19121
19277
  ).option("--quiet", "Suppress output, exit code only").option("--verbose", "Log request/response metadata to stderr").addHelpText(
package/dist/src/index.js CHANGED
@@ -2,7 +2,7 @@ import { createRequire } from 'node:module'; const require = createRequire(impor
2
2
  import {
3
3
  createProgram,
4
4
  withDefaultHelp
5
- } from "../chunk-3PBGQVUH.js";
5
+ } from "../chunk-WRLYKNYI.js";
6
6
  export {
7
7
  createProgram,
8
8
  withDefaultHelp
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@melius-ai/cli",
3
- "version": "0.8.0",
3
+ "version": "0.9.1",
4
4
  "description": "The Melius command-line interface — create canvases and run AI image/video generations from your terminal",
5
5
  "keywords": [
6
6
  "ai",