@melius-ai/cli 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin/mel.js CHANGED
@@ -7,7 +7,7 @@ import {
7
7
  printUpgradeNoticeIfNeeded,
8
8
  withDefaultHelp,
9
9
  writeError
10
- } from "../chunk-5APS3BGT.js";
10
+ } from "../chunk-VOIPEX54.js";
11
11
 
12
12
  // bin/mel.ts
13
13
  var program = createProgram();
@@ -7740,6 +7740,13 @@ var MAX_VARIATIONS = 10;
7740
7740
 
7741
7741
  // ../api-contract/src/common.ts
7742
7742
  var MessageResponseSchema = external_exports.object({ message: external_exports.string() });
7743
+ var ApiErrorResponseSchema = external_exports.object({
7744
+ statusCode: external_exports.number().int(),
7745
+ message: external_exports.string(),
7746
+ error: external_exports.string(),
7747
+ code: external_exports.string().optional(),
7748
+ retryAfterSeconds: external_exports.number().int().optional()
7749
+ });
7743
7750
  var ShareVisibilitySchema = external_exports.enum(["team", "anyone"]);
7744
7751
  var CompletedPartSchema = external_exports.object({
7745
7752
  partNumber: external_exports.number().int().positive(),
@@ -7903,6 +7910,13 @@ var customContextContract = c.router({
7903
7910
  }
7904
7911
  });
7905
7912
 
7913
+ // ../api-contract/src/rgb-color.ts
7914
+ var RgbColorSchema = external_exports.object({
7915
+ r: external_exports.number().int().min(0).max(255),
7916
+ g: external_exports.number().int().min(0).max(255),
7917
+ b: external_exports.number().int().min(0).max(255)
7918
+ });
7919
+
7906
7920
  // ../api-contract/src/files.ts
7907
7921
  var c2 = initContract();
7908
7922
  var FileSourceSchema = external_exports.enum(["upload", "generated"]);
@@ -7929,12 +7943,25 @@ var MAX_ASSET_TAG_NAME_LENGTH = 100;
7929
7943
  var FileTagSchema = external_exports.object({
7930
7944
  id: external_exports.string().uuid(),
7931
7945
  name: external_exports.string(),
7932
- color: external_exports.string()
7946
+ color: external_exports.string(),
7947
+ /**
7948
+ * Which subsystem-written tag this is, or null for a team-authored one.
7949
+ * Same open string as {@link AssetTagResponseSchema}: a chip only ever
7950
+ * needs the *fact* for the shared rules (rename freely, never delete, never
7951
+ * apply by hand), and a second system tag must not need a contract change.
7952
+ * {@link AssetSystemTag} names the one case that reads the value — the
7953
+ * sign-off projection, which a node-scoped surface has to be able to tell
7954
+ * apart from an ordinary tag.
7955
+ */
7956
+ systemTag: external_exports.string().nullable()
7933
7957
  });
7934
7958
  var FileCanvasBacklinkSchema = external_exports.object({
7935
7959
  canvasId: external_exports.string().uuid(),
7936
7960
  projectId: external_exports.string().uuid(),
7937
7961
  canvasTitle: external_exports.string(),
7962
+ // The owning project, so the picker can qualify canvases that share a
7963
+ // title. Optional: responses from a core build that predates it omit it.
7964
+ projectTitle: external_exports.string().optional(),
7938
7965
  // A node on this canvas whose active version holds the asset, so opening
7939
7966
  // the canvas can center on it. Null when no such node survives (e.g. it was
7940
7967
  // deleted but the asset is still referenced elsewhere on the canvas).
@@ -7987,7 +8014,11 @@ var FileGenerationSchema = external_exports.object({
7987
8014
  *
7988
8015
  * Optional so a client that ships ahead of the server keeps validating —
7989
8016
  * absent reads the same as "not a tool run". */
7990
- sourceToolName: external_exports.string().nullable().optional()
8017
+ sourceToolName: external_exports.string().nullable().optional(),
8018
+ /** Recraft palette persisted with the version that created this asset. */
8019
+ colors: external_exports.array(RgbColorSchema).optional(),
8020
+ /** Recraft background color persisted with the version that created this asset. */
8021
+ backgroundColor: RgbColorSchema.optional()
7991
8022
  });
7992
8023
  var FileDetailSchema = FileCardSchema.extend({
7993
8024
  width: external_exports.number().int().nullable(),
@@ -8098,6 +8129,12 @@ var ListFilesQuerySchema = external_exports.object({
8098
8129
  // active one — so a generation a member starred survives later regens and
8099
8130
  // stays findable here. Same query-string coercion as `hidden`.
8100
8131
  favorited: external_exports.union([external_exports.boolean(), external_exports.literal("true"), external_exports.literal("false")]).optional().transform((value) => value === true || value === "true"),
8132
+ // The "Archived" view: generations whose every canvas home is archived (a
8133
+ // deleted project) or trashed (a deleted canvas), so they are exactly the
8134
+ // assets the normal grid drops. Uploads never appear here — they survive
8135
+ // archiving and stay in the main listing. Same query-string coercion as
8136
+ // `hidden`.
8137
+ archived: external_exports.union([external_exports.boolean(), external_exports.literal("true"), external_exports.literal("false")]).optional().transform((value) => value === true || value === "true"),
8101
8138
  // Whether to compute the exact `total`. Defaults to `true`. The Files
8102
8139
  // visibility predicate is an EXISTS over the team's whole node graph, so an
8103
8140
  // exact `count(*)` scans every asset (seconds on large teams) and runs in
@@ -8132,7 +8169,11 @@ var FileTabCountsResponseSchema = external_exports.object({
8132
8169
  all: external_exports.number().int(),
8133
8170
  uploads: external_exports.number().int(),
8134
8171
  generations: external_exports.number().int(),
8135
- favorites: external_exports.number().int()
8172
+ favorites: external_exports.number().int(),
8173
+ // Optional so a web bundle that ships before core still parses the older
8174
+ // response; callers treat a missing count as 0. Can be made required once
8175
+ // this has fully rolled out.
8176
+ archived: external_exports.number().int().optional()
8136
8177
  });
8137
8178
  var AGENT_ASSET_SEARCH_PAGE_SIZE = 20;
8138
8179
  var AgentAssetSearchQuerySchema = external_exports.object({
@@ -8249,6 +8290,14 @@ var AssetTagResponseSchema = external_exports.object({
8249
8290
  createdByName: external_exports.string().nullable(),
8250
8291
  createdAt: external_exports.string().datetime(),
8251
8292
  updatedAt: external_exports.string().datetime(),
8293
+ /**
8294
+ * Names which subsystem-written tag this is, or null for a tag a person
8295
+ * authored. Opaque to the client on purpose: it needs the *fact*, not the
8296
+ * value, because the rule is the same for every one of them — a non-null
8297
+ * tag may be renamed but never deleted, applied or removed by hand — and a
8298
+ * second system tag should not need a contract change to be handled right.
8299
+ */
8300
+ systemTag: external_exports.string().nullable(),
8252
8301
  // How many of the team's assets carry this tag. Present in listAssetTags;
8253
8302
  // omitted on single-tag create/update responses (which don't recount).
8254
8303
  assetCount: external_exports.number().int().nonnegative().optional()
@@ -9294,6 +9343,84 @@ var ListAudioVoicesResponseSchema = external_exports.object({
9294
9343
  hasMore: external_exports.boolean(),
9295
9344
  totalCount: external_exports.number()
9296
9345
  });
9346
+ var FISH_AUDIO_VOICE_LIBRARY_STYLES = [
9347
+ { value: "narration", label: "Narration" },
9348
+ { value: "conversational", label: "Conversational" },
9349
+ { value: "character-voice", label: "Characters" },
9350
+ { value: "social-media", label: "Social media" },
9351
+ { value: "educational", label: "Educational" },
9352
+ { value: "advertisement", label: "Advertisement" },
9353
+ { value: "entertainment", label: "Entertainment" },
9354
+ { value: "storytelling", label: "Storytelling" },
9355
+ { value: "announcer", label: "Announcer" },
9356
+ { value: "cinematic", label: "Cinematic" }
9357
+ ];
9358
+ var FISH_AUDIO_VOICE_LIBRARY_TONES = [
9359
+ { value: "calm", label: "Calm" },
9360
+ { value: "energetic", label: "Energetic" },
9361
+ { value: "deep", label: "Deep" },
9362
+ { value: "soft", label: "Soft" },
9363
+ { value: "clear", label: "Clear" },
9364
+ { value: "confident", label: "Confident" },
9365
+ { value: "authoritative", label: "Authoritative" },
9366
+ { value: "dramatic", label: "Dramatic" },
9367
+ { value: "expressive", label: "Expressive" },
9368
+ { value: "friendly", label: "Friendly" },
9369
+ { value: "professional", label: "Professional" }
9370
+ ];
9371
+ var FISH_AUDIO_VOICE_LIBRARY_FILTER_OPTIONS = {
9372
+ gender: ["male", "female", "neutral"],
9373
+ age: ["young", "middle-aged", "old"],
9374
+ style: FISH_AUDIO_VOICE_LIBRARY_STYLES.map((entry) => entry.value),
9375
+ tone: FISH_AUDIO_VOICE_LIBRARY_TONES.map((entry) => entry.value),
9376
+ language: [
9377
+ "en",
9378
+ "es",
9379
+ "zh",
9380
+ "ar",
9381
+ "pt",
9382
+ "ru",
9383
+ "ja",
9384
+ "fr",
9385
+ "de",
9386
+ "ko",
9387
+ "it",
9388
+ "hi",
9389
+ "el",
9390
+ "ro",
9391
+ "sv",
9392
+ "tl"
9393
+ ]
9394
+ };
9395
+ var FishAudioVoiceResponseSchema = external_exports.object({
9396
+ voiceId: external_exports.string(),
9397
+ name: external_exports.string(),
9398
+ description: external_exports.string(),
9399
+ previewUrl: external_exports.string().url().nullable(),
9400
+ tags: external_exports.array(external_exports.string()),
9401
+ languages: external_exports.array(external_exports.string()),
9402
+ /**
9403
+ * Titles are not unique in Fish's user-uploaded catalog, so popularity is
9404
+ * what tells two same-named clones apart. Optional so an older core can
9405
+ * still satisfy a newer client mid-rollout.
9406
+ */
9407
+ likeCount: external_exports.number().optional()
9408
+ });
9409
+ var ListFishAudioVoicesQuerySchema = external_exports.object({
9410
+ page: external_exports.coerce.number().int().min(0).default(0),
9411
+ /** Matched by Fish as a case-insensitive substring of the voice title. */
9412
+ search: external_exports.string().optional(),
9413
+ gender: external_exports.enum(asZodEnum(FISH_AUDIO_VOICE_LIBRARY_FILTER_OPTIONS.gender)).optional(),
9414
+ age: external_exports.enum(asZodEnum(FISH_AUDIO_VOICE_LIBRARY_FILTER_OPTIONS.age)).optional(),
9415
+ style: external_exports.enum(asZodEnum(FISH_AUDIO_VOICE_LIBRARY_FILTER_OPTIONS.style)).optional(),
9416
+ tone: external_exports.enum(asZodEnum(FISH_AUDIO_VOICE_LIBRARY_FILTER_OPTIONS.tone)).optional(),
9417
+ language: external_exports.enum(asZodEnum(FISH_AUDIO_VOICE_LIBRARY_FILTER_OPTIONS.language)).optional()
9418
+ });
9419
+ var ListFishAudioVoicesResponseSchema = external_exports.object({
9420
+ voices: external_exports.array(FishAudioVoiceResponseSchema),
9421
+ page: external_exports.number(),
9422
+ hasMore: external_exports.boolean()
9423
+ });
9297
9424
  var AudioForbiddenResponseSchema = external_exports.object({
9298
9425
  message: external_exports.string()
9299
9426
  });
@@ -9320,6 +9447,29 @@ var ListFavoriteVoicesResponseSchema = external_exports.object({
9320
9447
  voices: external_exports.array(AudioVoiceResponseSchema)
9321
9448
  });
9322
9449
  var audioContract = c5.router({
9450
+ listFishAudioVoices: {
9451
+ method: "GET",
9452
+ path: "/audio/fish-audio/voices",
9453
+ query: ListFishAudioVoicesQuerySchema,
9454
+ responses: {
9455
+ 200: ListFishAudioVoicesResponseSchema,
9456
+ 403: AudioForbiddenResponseSchema
9457
+ }
9458
+ },
9459
+ // A picked voice can be off every page the picker has loaded, so the
9460
+ // trigger resolves its name by id rather than scanning the catalog.
9461
+ getFishAudioVoice: {
9462
+ method: "GET",
9463
+ path: "/audio/fish-audio/voices/:voiceId",
9464
+ pathParams: external_exports.object({
9465
+ voiceId: external_exports.string().trim().min(1)
9466
+ }),
9467
+ responses: {
9468
+ 200: FishAudioVoiceResponseSchema,
9469
+ 403: AudioForbiddenResponseSchema,
9470
+ 404: AudioVoiceNotFoundResponseSchema
9471
+ }
9472
+ },
9323
9473
  listVoices: {
9324
9474
  method: "GET",
9325
9475
  path: "/audio/voices",
@@ -9361,12 +9511,29 @@ var audioContract = c5.router({
9361
9511
  }
9362
9512
  });
9363
9513
 
9514
+ // ../canvas-yjs/src/group-color.ts
9515
+ var GROUP_COLOR_KEYS = [
9516
+ "default",
9517
+ "amber",
9518
+ "blue",
9519
+ "purple",
9520
+ "olive"
9521
+ ];
9522
+
9364
9523
  // ../api-contract/src/heygen.ts
9365
9524
  var HeygenAvatarSettingsSchema = external_exports.object({
9366
9525
  backgroundColor: external_exports.string().regex(/^#[0-9a-f]{6}$/i, "Background color must be a hex color").optional(),
9367
9526
  removeBackground: external_exports.boolean().optional(),
9368
9527
  fit: external_exports.enum(["cover", "contain"]).optional(),
9369
- caption: external_exports.boolean().optional()
9528
+ caption: external_exports.boolean().optional(),
9529
+ /**
9530
+ * Runware TTS voice id for the text-driven path (e.g.
9531
+ * "chill_brian_male_english"), chosen from the provider's voice catalog.
9532
+ * Only used when a script is typed with no connected audio; the
9533
+ * audio-driven (mirror-voice) path ignores it. When absent the backend
9534
+ * falls back to its default voice.
9535
+ */
9536
+ voice: external_exports.string().trim().min(1).optional()
9370
9537
  });
9371
9538
  var HeygenAvatarVariantSchema = external_exports.object({
9372
9539
  avatar: external_exports.string().describe(
@@ -10054,6 +10221,7 @@ var ELEVENLABS_OUTPUT_FORMATS = [
10054
10221
  var ElevenLabsOutputFormatSchema = external_exports.enum(
10055
10222
  ELEVENLABS_OUTPUT_FORMATS.map((f) => f.value)
10056
10223
  );
10224
+ var ELEVENLABS_V3_MODEL_ID = "eleven_v3";
10057
10225
  var slider01 = (defaultValue) => ({
10058
10226
  min: 0,
10059
10227
  max: 1,
@@ -10144,6 +10312,8 @@ var ElevenLabsVoiceSettingsSchema = external_exports.object({
10144
10312
  removeBackgroundNoise: external_exports.boolean().optional(),
10145
10313
  outputFormat: ElevenLabsOutputFormatSchema.optional()
10146
10314
  });
10315
+ var AUDIO_TAG_BODY = /\[[^\]\n]*[A-Za-z][^\]\n]*\]/;
10316
+ var AUDIO_TAG_BODY_GLOBAL = new RegExp(AUDIO_TAG_BODY.source, "g");
10147
10317
 
10148
10318
  // ../api-contract/src/generation-failure-reason.ts
10149
10319
  var GENERATION_FAILURE_REASONS = [
@@ -10395,6 +10565,10 @@ var TemplatePortTargetSchema = external_exports.object({
10395
10565
  nodeKey: external_exports.string(),
10396
10566
  internalHandle: external_exports.string().nullable()
10397
10567
  });
10568
+ var TemplatePortSourcePositionSchema = external_exports.object({
10569
+ x: external_exports.number(),
10570
+ y: external_exports.number()
10571
+ });
10398
10572
  var TemplatePortSchema = external_exports.discriminatedUnion("direction", [
10399
10573
  external_exports.object({
10400
10574
  direction: external_exports.literal("input"),
@@ -10424,6 +10598,8 @@ var TemplatePortSchema = external_exports.discriminatedUnion("direction", [
10424
10598
  * single `nodeKey`/`internalHandle` binding (pre-fan-out templates).
10425
10599
  */
10426
10600
  internalTargets: external_exports.array(TemplatePortTargetSchema).optional(),
10601
+ /** Authored position of this input's source. See the schema's doc. */
10602
+ sourcePosition: TemplatePortSourcePositionSchema.optional(),
10427
10603
  ...TemplatePortBaseFields
10428
10604
  }),
10429
10605
  external_exports.object({
@@ -10479,6 +10655,12 @@ var InstancePortBindingSchema = external_exports.discriminatedUnion("direction",
10479
10655
  * the next connect, so a stale id never strands a slot.
10480
10656
  */
10481
10657
  connectedSourceIds: external_exports.array(external_exports.string()).optional(),
10658
+ /**
10659
+ * `TemplatePort.sourcePosition` baked onto this canvas — apply adds the
10660
+ * same offset it gives the hidden children, so this is absolute here and
10661
+ * expand can treat it exactly like a child position.
10662
+ */
10663
+ sourcePosition: TemplatePortSourcePositionSchema.optional(),
10482
10664
  ...InstancePortBindingBaseFields
10483
10665
  }),
10484
10666
  external_exports.object({
@@ -10503,6 +10685,14 @@ var CanvasResponseSchema = external_exports.object({
10503
10685
  createdAt: external_exports.string().datetime(),
10504
10686
  updatedAt: external_exports.string().datetime()
10505
10687
  });
10688
+ var CanvasVersionFavoriteSchema = external_exports.object({
10689
+ nodeId: external_exports.string().uuid(),
10690
+ versionId: external_exports.string().uuid(),
10691
+ favoritedByUserId: external_exports.string().uuid()
10692
+ });
10693
+ var CanvasVersionFavoritesResponseSchema = external_exports.object({
10694
+ favorites: external_exports.array(CanvasVersionFavoriteSchema)
10695
+ });
10506
10696
  var GeometrySchema = external_exports.object({
10507
10697
  x: external_exports.number(),
10508
10698
  y: external_exports.number(),
@@ -10531,6 +10721,7 @@ var EdgeTypeSchema = external_exports.enum([
10531
10721
  "file"
10532
10722
  ]);
10533
10723
  var GroupTypeSchema = external_exports.enum(["default", "unified", "template"]);
10724
+ var GroupColorSchema = external_exports.enum(GROUP_COLOR_KEYS);
10534
10725
  var ModelConfigSchema = external_exports.object({
10535
10726
  model: external_exports.string(),
10536
10727
  variant: external_exports.string(),
@@ -10543,10 +10734,12 @@ var ModelConfigSchema = external_exports.object({
10543
10734
  // ratios + resolution that produced it.
10544
10735
  ratios: external_exports.array(external_exports.string()).optional(),
10545
10736
  resolution: external_exports.string().optional(),
10546
- /** Audio-only: stock ElevenLabs voice id used for this version's generation. */
10737
+ /** Audio-only: voice used for generation. */
10547
10738
  voiceId: external_exports.string().optional(),
10548
10739
  /** Audio-only: team custom voice id; takes precedence over voiceId on version switch. */
10549
10740
  customVoiceId: external_exports.string().uuid().optional(),
10741
+ /** Audio-only: the run intentionally used the provider's default voice. */
10742
+ usesProviderDefaultVoice: external_exports.literal(true).optional(),
10550
10743
  /** better-font-32b only: the font the model renders the requested text in (supplied to the model as a rendered reference image). */
10551
10744
  font: external_exports.object({
10552
10745
  source: external_exports.enum(["custom", "google"]),
@@ -10557,7 +10750,11 @@ var ModelConfigSchema = external_exports.object({
10557
10750
  /** SDXL only: sampler steps used for this version. */
10558
10751
  steps: external_exports.number().optional(),
10559
10752
  /** SDXL only: classifier-free guidance scale used for this version. */
10560
- guidanceScale: external_exports.number().optional()
10753
+ guidanceScale: external_exports.number().optional(),
10754
+ /** Recraft only: RGB palette used for this version's generation. */
10755
+ colors: external_exports.array(RgbColorSchema).optional(),
10756
+ /** Recraft only: RGB background used for this version's generation. */
10757
+ backgroundColor: RgbColorSchema.optional()
10561
10758
  });
10562
10759
  var ModelConfigInputSchema = external_exports.object({
10563
10760
  model: external_exports.string(),
@@ -10580,6 +10777,8 @@ var OutputResolutionPresetSchema = external_exports.enum([
10580
10777
  "540p",
10581
10778
  "580p",
10582
10779
  "720p",
10780
+ // Fal's MiniMax H3 resolution enum spells its low tier `768P`.
10781
+ "768P",
10583
10782
  "1080p",
10584
10783
  "1440p",
10585
10784
  "2160p",
@@ -10788,6 +10987,7 @@ var NodeResponseSchema = external_exports.object({
10788
10987
  /** Per-clip trim windows for stitch nodes (keyed by source node id, from CRDT). */
10789
10988
  stitchClipTrims: StitchClipTrimsSchema.nullable().optional(),
10790
10989
  groupType: GroupTypeSchema.nullable().optional(),
10990
+ groupColor: GroupColorSchema.nullable().optional(),
10791
10991
  /** Resolved input/output port bindings on a template-instance group (from CRDT). */
10792
10992
  templatePorts: external_exports.array(InstancePortBindingSchema).nullable().optional(),
10793
10993
  /** The source template id on a template-instance group (from CRDT). */
@@ -10918,7 +11118,7 @@ var NodeRunStatusSchema = external_exports.enum([
10918
11118
  var CreateNodeRunResponseSchema = external_exports.object({
10919
11119
  id: external_exports.string().uuid()
10920
11120
  });
10921
- var RunOriginSchema = external_exports.enum(["canvas", "playground"]);
11121
+ var RunOriginSchema = external_exports.enum(["canvas", "playground", "cast"]);
10922
11122
  var RunNodeBodySchema = external_exports.object({
10923
11123
  canvasId: external_exports.string().uuid().optional(),
10924
11124
  /** Product surface this run originated on. Defaults to `canvas` server-side. */
@@ -10965,17 +11165,24 @@ var RunNodeBodySchema = external_exports.object({
10965
11165
  * own default still applies.
10966
11166
  */
10967
11167
  negativePrompt: external_exports.string().optional(),
11168
+ /** Recraft's preferred RGB palette. Ignored by other models. */
11169
+ colors: external_exports.array(RgbColorSchema).optional(),
11170
+ /** Recraft's RGB background colour. Ignored by other models. */
11171
+ backgroundColor: RgbColorSchema.optional(),
10968
11172
  /** Explicit image URLs to include as inputs (merged with edge-resolved images). */
10969
11173
  imageUrls: external_exports.array(external_exports.string().url()).max(MAX_INPUT_IMAGES).optional(),
10970
11174
  /**
10971
- * Provider-specific voice id for audio TTS. Today only ElevenLabs is
10972
- * wired up when other providers ship their own voice catalogues the
10973
- * field set will grow (e.g. `openaiVoiceId`). Required when running an
10974
- * audio node in `text-to-speech` mode; ignored otherwise. Mode-specific
10975
- * validation lives in the run service because the schema can't see the
10976
- * resolved model→mode mapping.
11175
+ * ElevenLabs voice id for audio TTS. Superseded by `voiceId`, which works
11176
+ * for every provider; kept so already-deployed clients keep running.
11177
+ * Mode-specific validation lives in the run service because the schema
11178
+ * can't see the resolved model→mode mapping.
10977
11179
  */
10978
11180
  elevenLabsVoiceId: external_exports.string().trim().min(1).optional(),
11181
+ /**
11182
+ * Provider-agnostic voice selection, validated against the resolved
11183
+ * variant's voice capability. Takes precedence over `elevenLabsVoiceId`.
11184
+ */
11185
+ voiceId: external_exports.string().trim().min(1).optional(),
10979
11186
  /**
10980
11187
  * Team-owned custom voice. When set the backend resolves the underlying
10981
11188
  * provider voice id from the database and uses it in place of
@@ -11071,6 +11278,11 @@ var RunVideoToolBodySchema = external_exports.object({
11071
11278
  toolName: external_exports.string().trim().min(1),
11072
11279
  toolConfig: external_exports.record(external_exports.unknown()).optional()
11073
11280
  });
11281
+ var ExtractVideoFrameBodySchema = external_exports.object({
11282
+ canvasId: external_exports.string().uuid(),
11283
+ targetNodeId: external_exports.string().uuid(),
11284
+ timeMs: external_exports.number().int().min(0)
11285
+ });
11074
11286
  var NodeRunResponseSchema = external_exports.object({
11075
11287
  id: external_exports.string().uuid(),
11076
11288
  nodeId: external_exports.string().uuid(),
@@ -11518,6 +11730,15 @@ var canvasContract = c7.router({
11518
11730
  pathParams: external_exports.object({ canvasId: external_exports.string().uuid() }),
11519
11731
  responses: { 200: CanvasResponseSchema }
11520
11732
  },
11733
+ getCanvasVersionFavorites: {
11734
+ method: "GET",
11735
+ path: "/canvases/:canvasId/version-favorites",
11736
+ pathParams: external_exports.object({ canvasId: external_exports.string().uuid() }),
11737
+ responses: {
11738
+ 200: CanvasVersionFavoritesResponseSchema,
11739
+ 404: MessageResponseSchema
11740
+ }
11741
+ },
11521
11742
  updateCanvas: {
11522
11743
  method: "PATCH",
11523
11744
  path: "/canvases/:canvasId",
@@ -12005,6 +12226,17 @@ var canvasContract = c7.router({
12005
12226
  404: NodeRunErrorResponseSchema
12006
12227
  }
12007
12228
  },
12229
+ extractVideoFrame: {
12230
+ method: "POST",
12231
+ path: "/nodes/:nodeId/frame-extractions",
12232
+ pathParams: external_exports.object({ nodeId: external_exports.string().uuid() }),
12233
+ body: ExtractVideoFrameBodySchema,
12234
+ responses: {
12235
+ 201: CreateNodeRunResponseSchema,
12236
+ 400: NodeRunErrorResponseSchema,
12237
+ 404: NodeRunErrorResponseSchema
12238
+ }
12239
+ },
12008
12240
  getNodeRun: {
12009
12241
  method: "GET",
12010
12242
  path: "/node-runs/:nodeRunId",
@@ -12077,6 +12309,17 @@ var canvasContract = c7.router({
12077
12309
  method: "GET",
12078
12310
  path: "/canvases/:canvasId/node-runs/latest",
12079
12311
  pathParams: external_exports.object({ canvasId: external_exports.string().uuid() }),
12312
+ query: external_exports.object({
12313
+ /**
12314
+ * Return every pending/running run per node instead of only the
12315
+ * single latest run. A node can have several runs in flight at
12316
+ * once, and the default one-per-node shape drops all but the
12317
+ * newest — so a reload loses the others. Opt-in: clients that
12318
+ * key run state by node id must not receive multiple rows for
12319
+ * one node.
12320
+ */
12321
+ includeAllActiveRuns: external_exports.coerce.boolean().optional()
12322
+ }),
12080
12323
  responses: {
12081
12324
  200: external_exports.object({
12082
12325
  data: external_exports.array(LatestNodeRunResponseSchema)
@@ -12590,6 +12833,24 @@ var customFontContract = c8.router({
12590
12833
  }
12591
12834
  });
12592
12835
 
12836
+ // ../api-contract/src/audio-voices.ts
12837
+ var VoiceCatalogIdSchema = external_exports.enum(["elevenlabs", "fish-audio"]);
12838
+ var VoiceCapabilitySchema = external_exports.discriminatedUnion("source", [
12839
+ external_exports.object({
12840
+ source: external_exports.literal("static"),
12841
+ /** The provider's complete voice enum. */
12842
+ values: external_exports.array(external_exports.string()).readonly(),
12843
+ defaultVoice: external_exports.string()
12844
+ }),
12845
+ external_exports.object({
12846
+ source: external_exports.literal("catalog"),
12847
+ catalog: VoiceCatalogIdSchema,
12848
+ defaultVoice: external_exports.string().optional(),
12849
+ /** Team-owned cloned voices may be selected alongside the catalog. */
12850
+ supportsCustomVoices: external_exports.boolean().optional()
12851
+ })
12852
+ ]);
12853
+
12593
12854
  // ../api-contract/src/generation.ts
12594
12855
  var c9 = initContract();
12595
12856
  var GenerationJobStatusSchema = external_exports.enum([
@@ -12598,6 +12859,7 @@ var GenerationJobStatusSchema = external_exports.enum([
12598
12859
  "failed",
12599
12860
  "cancelled"
12600
12861
  ]);
12862
+ var FISH_AUDIO_MODEL = "fish-audio-s2.1-pro";
12601
12863
  var BetterFontSourceSchema = external_exports.enum(["custom", "google"]);
12602
12864
  var BetterFontSelectionSchema = external_exports.object({
12603
12865
  source: BetterFontSourceSchema,
@@ -12647,6 +12909,10 @@ var GenerationRunBodySchema = external_exports.object({
12647
12909
  * "blur, distort, and low quality") still applies.
12648
12910
  */
12649
12911
  negativePrompt: external_exports.string().optional(),
12912
+ /** Recraft's preferred RGB palette. Ignored by models without `falColorsField`. */
12913
+ colors: external_exports.array(RgbColorSchema).optional(),
12914
+ /** Recraft's RGB background colour. Ignored by models without `falBackgroundColorField`. */
12915
+ backgroundColor: RgbColorSchema.optional(),
12650
12916
  /**
12651
12917
  * The font the better-font-32b model should use as its typography
12652
12918
  * reference. Only honored when `model === "better-font-32b"`; ignored
@@ -12698,6 +12964,9 @@ var AutoModelDefaultCapabilitiesSchema = external_exports.object({
12698
12964
  supportedDurationsByResolution: external_exports.record(external_exports.string(), external_exports.array(external_exports.number())).nullable().optional(),
12699
12965
  supportedResolutions: external_exports.array(OutputResolutionSchema).nullable().optional(),
12700
12966
  supportsCustomResolution: external_exports.boolean().optional(),
12967
+ maxCustomResolutionArea: external_exports.number().nullable().optional(),
12968
+ minCustomResolutionArea: external_exports.number().nullable().optional(),
12969
+ maxCustomResolutionAspectRatio: external_exports.number().nullable().optional(),
12701
12970
  resolutionPricingMultipliers: external_exports.record(external_exports.string(), external_exports.number()).nullable().optional(),
12702
12971
  audioOffCreditMultiplier: external_exports.number().nullable().optional(),
12703
12972
  audioOffCreditMultipliersByResolution: external_exports.record(external_exports.string(), external_exports.number()).nullable().optional(),
@@ -12706,6 +12975,8 @@ var AutoModelDefaultCapabilitiesSchema = external_exports.object({
12706
12975
  maxReferenceImagesWithEndImage: external_exports.number().nullable().optional(),
12707
12976
  maxVideoInputs: external_exports.number().nullable().optional(),
12708
12977
  maxAudioInputs: external_exports.number().nullable().optional(),
12978
+ /** Maximum combined reference image, video, and audio inputs. */
12979
+ maxCombinedReferenceInputs: external_exports.number().nullable().optional(),
12709
12980
  maxNativeOutputs: external_exports.number().nullable().optional(),
12710
12981
  maxInputArea: external_exports.number().nullable().optional(),
12711
12982
  minInputVideoArea: external_exports.number().nullable().optional(),
@@ -12746,6 +13017,27 @@ var AutoModelDefaultsCategorySchema = external_exports.object({
12746
13017
  var AutoModelDefaultsResponseSchema = AutoModelDefaultsCategorySchema.extend({
12747
13018
  fast: AutoModelDefaultsCategorySchema
12748
13019
  });
13020
+ function sanitizeAgentAutoModelDefaultsCategory(category) {
13021
+ if (category.audio?.textToSpeech.model !== FISH_AUDIO_MODEL) {
13022
+ return category;
13023
+ }
13024
+ return {
13025
+ ...category,
13026
+ audio: {
13027
+ ...category.audio,
13028
+ textToSpeech: {
13029
+ model: ELEVENLABS_V3_MODEL_ID,
13030
+ variant: "text-to-speech"
13031
+ }
13032
+ }
13033
+ };
13034
+ }
13035
+ function sanitizeAgentAutoModelDefaults(defaults) {
13036
+ const standard = sanitizeAgentAutoModelDefaultsCategory(defaults);
13037
+ const fast = sanitizeAgentAutoModelDefaultsCategory(defaults.fast);
13038
+ if (standard === defaults && fast === defaults.fast) return defaults;
13039
+ return { ...standard, fast };
13040
+ }
12749
13041
  var ModelCostSchema = external_exports.discriminatedUnion("type", [
12750
13042
  external_exports.object({
12751
13043
  type: external_exports.literal("fixed"),
@@ -12818,6 +13110,8 @@ var ModelVariantResponseSchema = external_exports.object({
12818
13110
  supportsNegativePrompt: external_exports.boolean().optional(),
12819
13111
  supportedAspectRatios: external_exports.array(OutputAspectRatioSchema),
12820
13112
  supportedDurations: external_exports.array(external_exports.number()).nullable(),
13113
+ /** Provider default used when a duration is not selected. */
13114
+ defaultDuration: external_exports.number().nullable().optional(),
12821
13115
  /**
12822
13116
  * For a per-second model whose output length is NOT user-selected: how the
12823
13117
  * billed length is derived. `"input-media"` → longest connected input
@@ -12828,6 +13122,9 @@ var ModelVariantResponseSchema = external_exports.object({
12828
13122
  supportedDurationsByResolution: external_exports.record(external_exports.string(), external_exports.array(external_exports.number())).nullable().optional(),
12829
13123
  supportedResolutions: external_exports.array(OutputResolutionSchema).nullable(),
12830
13124
  supportsCustomResolution: external_exports.boolean().optional(),
13125
+ maxCustomResolutionArea: external_exports.number().nullable().optional(),
13126
+ minCustomResolutionArea: external_exports.number().nullable().optional(),
13127
+ maxCustomResolutionAspectRatio: external_exports.number().nullable().optional(),
12831
13128
  resolutionPricingMultipliers: external_exports.record(external_exports.string(), external_exports.number()).nullable(),
12832
13129
  /** Multiplier applied to creditCost when audio is toggled off. */
12833
13130
  audioOffCreditMultiplier: external_exports.number().nullable().optional(),
@@ -12838,6 +13135,7 @@ var ModelVariantResponseSchema = external_exports.object({
12838
13135
  maxReferenceImagesWithEndImage: external_exports.number().nullable().optional(),
12839
13136
  maxVideoInputs: external_exports.number().nullable().optional(),
12840
13137
  maxAudioInputs: external_exports.number().nullable().optional(),
13138
+ maxCombinedReferenceInputs: external_exports.number().nullable().optional(),
12841
13139
  /**
12842
13140
  * For variants accepting both video and audio: whether the connected
12843
13141
  * durations must line up. `false` for lipsync models (e.g. Kling Lipsync)
@@ -12869,6 +13167,8 @@ var ModelVariantResponseSchema = external_exports.object({
12869
13167
  defaultResolution: OutputResolutionSchema.nullable().optional(),
12870
13168
  featuredDescription: external_exports.string().nullable(),
12871
13169
  cost: ModelCostSchema.optional(),
13170
+ /** Selectable voices for audio variants, or null when none apply. */
13171
+ voices: VoiceCapabilitySchema.nullable().optional(),
12872
13172
  /**
12873
13173
  * Per-second credit multiplier applied to connected input video duration,
12874
13174
  * using the resolution-adjusted output per-second price as the base. Lets
@@ -12988,10 +13288,21 @@ var generationContract = c9.router({
12988
13288
  listHeygenAvatarVAvatars: {
12989
13289
  method: "GET",
12990
13290
  path: "/generation/heygen-avatar-v-avatars",
13291
+ // Each HeyGen avatar model has its own provider roster, so the caller
13292
+ // names the model it is picking for. Omitted means Avatar V, which is
13293
+ // what every client sent before Avatar IV existed.
13294
+ query: external_exports.object({ model: external_exports.string().optional() }).optional(),
12991
13295
  responses: {
12992
13296
  200: external_exports.object({ avatars: external_exports.array(external_exports.string()) })
12993
13297
  }
12994
13298
  },
13299
+ listHeygenAvatarVVoices: {
13300
+ method: "GET",
13301
+ path: "/generation/heygen-avatar-v-voices",
13302
+ responses: {
13303
+ 200: external_exports.object({ voices: external_exports.array(external_exports.string()) })
13304
+ }
13305
+ },
12995
13306
  getAutoModelDefaults: {
12996
13307
  method: "GET",
12997
13308
  path: "/generation/auto-model-defaults",
@@ -13081,42 +13392,56 @@ var c10 = initContract();
13081
13392
  var TextNodeDataSchema = external_exports.object({
13082
13393
  title: external_exports.string(),
13083
13394
  mode: external_exports.string(),
13084
- prompt: external_exports.string()
13085
- }).passthrough();
13395
+ prompt: external_exports.string(),
13396
+ /** `getValidHandles` builds a text node's targets as `["text", ...this]`. */
13397
+ supportedInputs: external_exports.array(external_exports.string()).optional()
13398
+ });
13086
13399
  var ImageNodeDataSchema = external_exports.object({
13087
13400
  title: external_exports.string(),
13088
13401
  src: external_exports.string().optional(),
13089
13402
  mode: external_exports.string(),
13090
13403
  aspectRatio: external_exports.string().optional(),
13091
13404
  prompt: external_exports.string()
13092
- }).passthrough();
13405
+ });
13093
13406
  var VideoNodeDataSchema = external_exports.object({
13094
13407
  title: external_exports.string(),
13095
13408
  src: external_exports.string().optional(),
13096
13409
  mode: external_exports.string(),
13097
13410
  aspectRatio: external_exports.string().optional(),
13098
13411
  duration: external_exports.string().optional(),
13099
- prompt: external_exports.string()
13100
- }).passthrough();
13412
+ prompt: external_exports.string(),
13413
+ /**
13414
+ * Handle validation tests these by key PRESENCE (`hasModelCapabilityFlags`
13415
+ * in `canvas-handles.ts`) and treats them as one family, so dropping any one
13416
+ * key disables the whole model-flag branch rather than just that flag.
13417
+ * Declared together for that reason, not because every preset sets all four.
13418
+ */
13419
+ modelSupportsEndImage: external_exports.boolean().optional(),
13420
+ modelSupportsReferenceImage: external_exports.boolean().optional(),
13421
+ modelSupportsOptionalStartImage: external_exports.boolean().optional(),
13422
+ modelSupportsAudioInput: external_exports.boolean().optional()
13423
+ });
13101
13424
  var AudioNodeDataSchema = external_exports.object({
13102
13425
  title: external_exports.string(),
13103
13426
  src: external_exports.string().optional(),
13104
13427
  mode: external_exports.string().optional(),
13105
13428
  prompt: external_exports.string().optional(),
13106
13429
  voiceId: external_exports.string().optional()
13107
- }).passthrough();
13430
+ });
13108
13431
  var FileNodeDataSchema = external_exports.object({
13109
13432
  title: external_exports.string(),
13110
13433
  src: external_exports.string().optional(),
13111
- mediaType: external_exports.enum(["image", "video"])
13112
- }).passthrough();
13434
+ mediaType: external_exports.enum(["image", "video"]),
13435
+ /** Opts the preset viewer's file node into rendering an audio output. */
13436
+ showAudioOutput: external_exports.boolean().optional()
13437
+ });
13113
13438
  var CustomTextNodeDataSchema = external_exports.object({
13114
13439
  title: external_exports.string(),
13115
13440
  generatedText: external_exports.string().optional()
13116
- }).passthrough();
13441
+ });
13117
13442
  var GroupNodeDataSchema = external_exports.object({
13118
13443
  label: external_exports.string()
13119
- }).passthrough();
13444
+ });
13120
13445
  var SharedNodeFields = {
13121
13446
  key: external_exports.string(),
13122
13447
  width: external_exports.number().optional(),
@@ -13835,6 +14160,12 @@ var teamContract = c13.router({
13835
14160
  body: null,
13836
14161
  responses: { 204: c13.noBody() }
13837
14162
  },
14163
+ leaveTeam: {
14164
+ method: "POST",
14165
+ path: "/teams/current/leave",
14166
+ body: null,
14167
+ responses: { 204: c13.noBody() }
14168
+ },
13838
14169
  listMembers: {
13839
14170
  method: "GET",
13840
14171
  path: "/teams/current/members",
@@ -14734,7 +15065,7 @@ function isMajorUpgrade(current, latest) {
14734
15065
  return l[0] > c17[0];
14735
15066
  }
14736
15067
  function shouldShowUpgradeNotice(ctx = {}) {
14737
- const current = ctx.current ?? "0.13.0";
15068
+ const current = ctx.current ?? "0.15.0";
14738
15069
  const latest = ctx.latest ?? serverLatestVersion;
14739
15070
  const env = ctx.env ?? process.env;
14740
15071
  const isTty = ctx.isTty ?? Boolean(process.stderr.isTTY);
@@ -14755,7 +15086,7 @@ Upgrade: npm install -g @melius-ai/cli@latest (or: brew update && brew upgrade
14755
15086
  function printUpgradeNoticeIfNeeded(ctx = {}) {
14756
15087
  try {
14757
15088
  if (!shouldShowUpgradeNotice(ctx)) return;
14758
- const current = ctx.current ?? "0.13.0";
15089
+ const current = ctx.current ?? "0.15.0";
14759
15090
  const latest = ctx.latest ?? serverLatestVersion;
14760
15091
  process.stderr.write(formatUpgradeNotice(current, latest));
14761
15092
  } catch {
@@ -16235,34 +16566,35 @@ function mapPresetLayoutNodeToDirectBody(layoutNode, nodeId, parentId, resolvedP
16235
16566
  title: getLayoutNodeTitle(layoutNode)
16236
16567
  };
16237
16568
  if (parentId !== void 0) body.groupId = parentId;
16238
- const prompt = resolvedPrompts?.get(layoutNode.key) ?? layoutNode.data.prompt;
16569
+ const data = layoutNode.data;
16570
+ const prompt = resolvedPrompts?.get(layoutNode.key) ?? ("prompt" in data ? data.prompt : void 0);
16239
16571
  if (typeof prompt === "string") {
16240
16572
  body.textPrompt = prompt;
16241
16573
  }
16242
- if (typeof layoutNode.data.generatedText === "string") {
16243
- body.text = layoutNode.data.generatedText;
16574
+ if ("generatedText" in data && typeof data.generatedText === "string") {
16575
+ body.text = data.generatedText;
16244
16576
  }
16245
- if (typeof layoutNode.data.aspectRatio === "string") {
16246
- body.outputAspectRatio = layoutNode.data.aspectRatio;
16577
+ if ("aspectRatio" in data && typeof data.aspectRatio === "string") {
16578
+ body.outputAspectRatio = data.aspectRatio;
16247
16579
  }
16248
- if (layoutNode.data.duration !== void 0) {
16249
- body.outputDuration = Number(layoutNode.data.duration);
16580
+ if ("duration" in data && data.duration !== void 0) {
16581
+ body.outputDuration = Number(data.duration);
16250
16582
  }
16251
16583
  if (layoutNode.autoModel) {
16252
16584
  body.modelConfig = layoutNode.autoModel;
16253
16585
  }
16254
- if (layoutNode.data.mediaType === "image" || layoutNode.data.mediaType === "video") {
16255
- body.mediaType = layoutNode.data.mediaType;
16586
+ if ("mediaType" in data && (data.mediaType === "image" || data.mediaType === "video")) {
16587
+ body.mediaType = data.mediaType;
16256
16588
  }
16257
- if (typeof layoutNode.data.voiceId === "string") {
16258
- body.voiceId = layoutNode.data.voiceId;
16589
+ if ("voiceId" in data && typeof data.voiceId === "string") {
16590
+ body.voiceId = data.voiceId;
16259
16591
  }
16260
16592
  return body;
16261
16593
  }
16262
16594
  function resolvePresetMentions(layout, keyToId) {
16263
16595
  const titleToId = /* @__PURE__ */ new Map();
16264
16596
  for (const node of layout.nodes) {
16265
- const title = node.data.title ?? node.data.label;
16597
+ const title = readLayoutNodeName(node);
16266
16598
  const nodeId = keyToId.get(node.key);
16267
16599
  if (title && nodeId) {
16268
16600
  titleToId.set(title.toLowerCase(), nodeId);
@@ -16270,7 +16602,7 @@ function resolvePresetMentions(layout, keyToId) {
16270
16602
  }
16271
16603
  const resolved = /* @__PURE__ */ new Map();
16272
16604
  for (const node of layout.nodes) {
16273
- const prompt = node.data.prompt;
16605
+ const prompt = "prompt" in node.data ? node.data.prompt : void 0;
16274
16606
  if (!prompt) continue;
16275
16607
  const rewritten = prompt.replace(
16276
16608
  MENTION_RE,
@@ -16293,8 +16625,12 @@ function getNodeWidth(nodeCfg) {
16293
16625
  function getNodeHeight(nodeCfg) {
16294
16626
  return nodeCfg.height ?? getEstimatedHeight(nodeCfg.type);
16295
16627
  }
16628
+ function readLayoutNodeName(layoutNode) {
16629
+ if ("title" in layoutNode.data) return layoutNode.data.title;
16630
+ return layoutNode.data.label;
16631
+ }
16296
16632
  function getLayoutNodeTitle(layoutNode) {
16297
- return layoutNode.data.title ?? layoutNode.data.label ?? layoutNode.type.charAt(0).toUpperCase() + layoutNode.type.slice(1);
16633
+ return readLayoutNodeName(layoutNode) ?? layoutNode.type.charAt(0).toUpperCase() + layoutNode.type.slice(1);
16298
16634
  }
16299
16635
  function groupByColumn(nodes) {
16300
16636
  const hasColumns = nodes.some((n) => n.column !== void 0);
@@ -16841,6 +17177,18 @@ function resolveNodeIds2(canvasId, nodeIds) {
16841
17177
 
16842
17178
  // src/lib/validation.ts
16843
17179
  function validateModelConfig(model, variant) {
17180
+ if (model === FISH_AUDIO_MODEL) {
17181
+ writeError(
17182
+ formatError(
17183
+ "USAGE_ERROR",
17184
+ `${FISH_AUDIO_MODEL} is not available in the CLI`,
17185
+ {
17186
+ suggestion: "Choose a model returned by: mel model list --category audio"
17187
+ }
17188
+ ),
17189
+ EXIT_USAGE_ERROR
17190
+ );
17191
+ }
16844
17192
  if (model && variant) return { model, variant };
16845
17193
  if (!model && !variant) return void 0;
16846
17194
  writeError(
@@ -18683,7 +19031,10 @@ Examples:
18683
19031
  handleApiError(result.status, result.body);
18684
19032
  }
18685
19033
  const body = result.body;
18686
- writeJson(body.models, getOutputOpts());
19034
+ writeJson(
19035
+ body.models.filter((entry) => entry.name !== FISH_AUDIO_MODEL),
19036
+ getOutputOpts()
19037
+ );
18687
19038
  });
18688
19039
  model.command("defaults").description("Show which model is used when no --model is specified").addHelpText(
18689
19040
  "after",
@@ -18700,7 +19051,10 @@ Examples:
18700
19051
  if (result.status !== 200) {
18701
19052
  handleApiError(result.status, result.body);
18702
19053
  }
18703
- writeJson(result.body, getOutputOpts());
19054
+ writeJson(
19055
+ sanitizeAgentAutoModelDefaults(result.body),
19056
+ getOutputOpts()
19057
+ );
18704
19058
  });
18705
19059
  }
18706
19060
 
@@ -19951,7 +20305,7 @@ function withDefaultHelp(args) {
19951
20305
  }
19952
20306
  function createProgram() {
19953
20307
  const program2 = new Command();
19954
- program2.name("mel").description("Mel \u2014 Melius agent CLI").version("0.13.0").showSuggestionAfterError(true).option("--json", "Force JSON output (default)").option("--text", "Human-readable output").option(
20308
+ program2.name("mel").description("Mel \u2014 Melius agent CLI").version("0.15.0").showSuggestionAfterError(true).option("--json", "Force JSON output (default)").option("--text", "Human-readable output").option(
19955
20309
  "--fields <fields>",
19956
20310
  "Select specific output fields (comma-separated)"
19957
20311
  ).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-5APS3BGT.js";
5
+ } from "../chunk-VOIPEX54.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.13.0",
3
+ "version": "0.15.0",
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",