@melius-ai/cli 0.9.0 → 0.10.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/README.md +25 -0
- package/dist/bin/mel.js +1 -1
- package/dist/{chunk-24FW76XZ.js → chunk-GEI5UAWV.js} +371 -21
- package/dist/src/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -203,6 +203,31 @@ mel preset apply <canvasId> <presetId>
|
|
|
203
203
|
mel bulk-run start <canvasId> --wait
|
|
204
204
|
```
|
|
205
205
|
|
|
206
|
+
### Templates
|
|
207
|
+
|
|
208
|
+
Templates are reusable workflows applied server-side as collapsed boxes. Listing includes global templates and templates scoped to the current team. The CLI exposes only template metadata, declared ports, and the applied box IDs; internal workflow nodes and configuration stay private.
|
|
209
|
+
|
|
210
|
+
| Command | Description |
|
|
211
|
+
| -------------------------------------------- | ------------------------------------------------------------------------ |
|
|
212
|
+
| `mel template list` | List available templates and their declared input/output ports |
|
|
213
|
+
| `mel template apply <canvasId> <templateId>` | Apply a template as one collapsed box and return `instanceId`, `groupId` |
|
|
214
|
+
|
|
215
|
+
```bash
|
|
216
|
+
# Discover templates and ports
|
|
217
|
+
mel template list
|
|
218
|
+
mel template list --fields id,title,inputPorts,outputPorts
|
|
219
|
+
|
|
220
|
+
# Apply with automatic placement
|
|
221
|
+
mel template apply <canvasId> <templateId>
|
|
222
|
+
|
|
223
|
+
# Materialize a text input while applying
|
|
224
|
+
mel template apply <canvasId> <templateId> \
|
|
225
|
+
--inputs '[{"kind":"text","portId":"<portId>","text":"A red shoe"}]'
|
|
226
|
+
|
|
227
|
+
# Run only the opaque template box
|
|
228
|
+
mel bulk-run start <canvasId> --node-ids <groupId> --wait
|
|
229
|
+
```
|
|
230
|
+
|
|
206
231
|
### Models
|
|
207
232
|
|
|
208
233
|
| Command | Description |
|
package/dist/bin/mel.js
CHANGED
|
@@ -8647,12 +8647,17 @@ var AgentMessageFeedbackResponseSchema = external_exports.object({
|
|
|
8647
8647
|
createdAt: external_exports.string().datetime()
|
|
8648
8648
|
});
|
|
8649
8649
|
var AgentSessionStatusSchema = external_exports.enum(["active", "ended", "error"]);
|
|
8650
|
+
var AgentSessionSourceSchema = external_exports.enum(["web", "slack"]);
|
|
8650
8651
|
var AgentSessionResponseSchema = external_exports.object({
|
|
8651
8652
|
id: external_exports.string().uuid(),
|
|
8652
8653
|
userId: external_exports.string().uuid(),
|
|
8653
8654
|
teamId: external_exports.string().uuid(),
|
|
8654
8655
|
title: external_exports.string(),
|
|
8655
8656
|
status: AgentSessionStatusSchema,
|
|
8657
|
+
/** Optional so web clients remain compatible with servers that predate session sources. */
|
|
8658
|
+
source: AgentSessionSourceSchema.optional(),
|
|
8659
|
+
/** True when this transcript is view-only on the current surface. */
|
|
8660
|
+
readOnly: external_exports.boolean().optional(),
|
|
8656
8661
|
/** True when the agent is actively generating a response. */
|
|
8657
8662
|
isGenerating: external_exports.boolean(),
|
|
8658
8663
|
/** Present when the session is waiting for the user to approve a tool call. */
|
|
@@ -8781,6 +8786,28 @@ var agentContract = c3.router({
|
|
|
8781
8786
|
},
|
|
8782
8787
|
summary: "Get an agent session with recent messages"
|
|
8783
8788
|
},
|
|
8789
|
+
getInternalDemoCanvasSession: {
|
|
8790
|
+
method: "GET",
|
|
8791
|
+
path: "/agent/internal-demo-canvas-sessions/:sessionId",
|
|
8792
|
+
pathParams: external_exports.object({ sessionId: external_exports.string().uuid() }),
|
|
8793
|
+
query: external_exports.object({
|
|
8794
|
+
messageLimit: external_exports.coerce.number().int().min(0).max(100).default(50)
|
|
8795
|
+
}),
|
|
8796
|
+
responses: {
|
|
8797
|
+
200: AgentSessionResponseSchema
|
|
8798
|
+
},
|
|
8799
|
+
summary: "Get an internal demo canvas Slack transcript"
|
|
8800
|
+
},
|
|
8801
|
+
forkInternalDemoCanvasSession: {
|
|
8802
|
+
method: "POST",
|
|
8803
|
+
path: "/agent/internal-demo-canvas-sessions/:sessionId/fork",
|
|
8804
|
+
pathParams: external_exports.object({ sessionId: external_exports.string().uuid() }),
|
|
8805
|
+
body: null,
|
|
8806
|
+
responses: {
|
|
8807
|
+
201: AgentSessionResponseSchema
|
|
8808
|
+
},
|
|
8809
|
+
summary: "Fork an internal demo canvas Slack transcript into a private agent session"
|
|
8810
|
+
},
|
|
8784
8811
|
renameSession: {
|
|
8785
8812
|
method: "PATCH",
|
|
8786
8813
|
path: "/agent/sessions/:sessionId",
|
|
@@ -9797,6 +9824,20 @@ function parseCustomResolution(resolution) {
|
|
|
9797
9824
|
return { width, height };
|
|
9798
9825
|
}
|
|
9799
9826
|
var MENTION_RE = /@\[([^\]]+)\](?:\{([^}]+)\})?/g;
|
|
9827
|
+
var MENTION_WITH_ID_RE = /@\[[^\]]+\]\{([^}]+)\}/g;
|
|
9828
|
+
function extractMentionedNodeIds(text) {
|
|
9829
|
+
if (!text) return [];
|
|
9830
|
+
const ids = [];
|
|
9831
|
+
const seen = /* @__PURE__ */ new Set();
|
|
9832
|
+
for (const match of text.matchAll(MENTION_WITH_ID_RE)) {
|
|
9833
|
+
const id = match[1];
|
|
9834
|
+
if (!seen.has(id)) {
|
|
9835
|
+
seen.add(id);
|
|
9836
|
+
ids.push(id);
|
|
9837
|
+
}
|
|
9838
|
+
}
|
|
9839
|
+
return ids;
|
|
9840
|
+
}
|
|
9800
9841
|
var MAGIC_RESIZE_NODE_WIDTH = 500;
|
|
9801
9842
|
var MAGIC_RESIZE_PREGEN_HEIGHT = 550;
|
|
9802
9843
|
|
|
@@ -10012,6 +10053,19 @@ var ElevenLabsVoiceSettingsSchema = external_exports.object({
|
|
|
10012
10053
|
outputFormat: ElevenLabsOutputFormatSchema.optional()
|
|
10013
10054
|
});
|
|
10014
10055
|
|
|
10056
|
+
// ../api-contract/src/generation-failure-reason.ts
|
|
10057
|
+
var GENERATION_FAILURE_REASONS = [
|
|
10058
|
+
"insufficient_credits",
|
|
10059
|
+
"content_policy",
|
|
10060
|
+
"no_media_generated",
|
|
10061
|
+
"provider_error",
|
|
10062
|
+
"validation_error",
|
|
10063
|
+
"timeout",
|
|
10064
|
+
"system",
|
|
10065
|
+
"unknown"
|
|
10066
|
+
];
|
|
10067
|
+
var GenerationFailureReasonSchema = external_exports.enum(GENERATION_FAILURE_REASONS);
|
|
10068
|
+
|
|
10015
10069
|
// ../api-contract/src/lora.ts
|
|
10016
10070
|
var c6 = initContract();
|
|
10017
10071
|
var LORA_UPLOAD_PART_SIZE_BYTES = 16 * 1024 * 1024;
|
|
@@ -10194,7 +10248,21 @@ var PreviewAssetSchema = external_exports.object({
|
|
|
10194
10248
|
thumbnailUrl: external_exports.string().nullable()
|
|
10195
10249
|
});
|
|
10196
10250
|
|
|
10251
|
+
// ../api-contract/src/template-port-summary.ts
|
|
10252
|
+
var TemplatePortSummarySchema = external_exports.object({
|
|
10253
|
+
id: external_exports.string(),
|
|
10254
|
+
direction: external_exports.enum(["input", "output"]),
|
|
10255
|
+
label: external_exports.string(),
|
|
10256
|
+
handleType: external_exports.string(),
|
|
10257
|
+
required: external_exports.boolean().optional(),
|
|
10258
|
+
maxConnections: external_exports.number().int().positive().optional(),
|
|
10259
|
+
outputAspectRatio: external_exports.enum(ASPECT_RATIOS).nullable().optional(),
|
|
10260
|
+
exampleAssetUrl: external_exports.string().nullable().optional(),
|
|
10261
|
+
exampleText: external_exports.string().nullable().optional()
|
|
10262
|
+
});
|
|
10263
|
+
|
|
10197
10264
|
// ../api-contract/src/templates-ports.ts
|
|
10265
|
+
var TEMPLATE_EXAMPLE_TEXT_MAX_LENGTH = 2e3;
|
|
10198
10266
|
var TemplatePortBaseFields = {
|
|
10199
10267
|
/** Stable handle id on the box, e.g. "in_character", "out_angle_1". */
|
|
10200
10268
|
id: external_exports.string(),
|
|
@@ -10211,7 +10279,25 @@ var TemplatePortBaseFields = {
|
|
|
10211
10279
|
*/
|
|
10212
10280
|
internalHandle: external_exports.string().nullable(),
|
|
10213
10281
|
/** Optional vertical position override on the box (e.g. "35%"). */
|
|
10214
|
-
top: external_exports.string().optional()
|
|
10282
|
+
top: external_exports.string().optional(),
|
|
10283
|
+
/**
|
|
10284
|
+
* Example media for a MEDIA port (image/video/audio input source or output
|
|
10285
|
+
* result), shown in the template details panel and the build/edit authoring
|
|
10286
|
+
* UIs. `exampleAssetKey` is the persisted ref: an S3 object key under
|
|
10287
|
+
* `template-examples/`, copied at capture so the example outlives the source
|
|
10288
|
+
* canvas — exactly like `previewImageUrl`. `exampleAssetUrl` is the
|
|
10289
|
+
* freshly-signed display URL, populated on read only and ignored on write.
|
|
10290
|
+
* Both absent when the port has no media example (unset, or a text port).
|
|
10291
|
+
*/
|
|
10292
|
+
exampleAssetKey: external_exports.string().nullable().optional(),
|
|
10293
|
+
exampleAssetUrl: external_exports.string().nullable().optional(),
|
|
10294
|
+
/**
|
|
10295
|
+
* Example prompt for a TEXT port — the text parallel of `exampleAssetKey`.
|
|
10296
|
+
* Stored inline (no S3, no signing) since it's just a string; the details
|
|
10297
|
+
* panel shows it truncated, and "use example as input" drops a text node
|
|
10298
|
+
* pre-filled with it. Absent for media ports and text ports with no example.
|
|
10299
|
+
*/
|
|
10300
|
+
exampleText: external_exports.string().max(TEMPLATE_EXAMPLE_TEXT_MAX_LENGTH).nullable().optional()
|
|
10215
10301
|
};
|
|
10216
10302
|
var TemplatePortTargetSchema = external_exports.object({
|
|
10217
10303
|
nodeKey: external_exports.string(),
|
|
@@ -10309,15 +10395,6 @@ var InstancePortBindingSchema = external_exports.discriminatedUnion("direction",
|
|
|
10309
10395
|
...InstancePortBindingBaseFields
|
|
10310
10396
|
})
|
|
10311
10397
|
]);
|
|
10312
|
-
var TemplatePortSummarySchema = external_exports.object({
|
|
10313
|
-
id: external_exports.string(),
|
|
10314
|
-
direction: external_exports.enum(["input", "output"]),
|
|
10315
|
-
label: external_exports.string(),
|
|
10316
|
-
handleType: external_exports.string(),
|
|
10317
|
-
required: external_exports.boolean().optional(),
|
|
10318
|
-
maxConnections: external_exports.number().int().positive().optional(),
|
|
10319
|
-
outputAspectRatio: external_exports.enum(ASPECT_RATIOS).nullable().optional()
|
|
10320
|
-
});
|
|
10321
10398
|
|
|
10322
10399
|
// ../api-contract/src/canvas.ts
|
|
10323
10400
|
var c7 = initContract();
|
|
@@ -10897,6 +10974,7 @@ var NodeRunResponseSchema = external_exports.object({
|
|
|
10897
10974
|
errorMessage: external_exports.string().nullable(),
|
|
10898
10975
|
errorSeverity: ErrorSeveritySchema.nullable().default(null),
|
|
10899
10976
|
errorRetryable: external_exports.boolean().nullable().optional(),
|
|
10977
|
+
errorReason: GenerationFailureReasonSchema.nullable().optional(),
|
|
10900
10978
|
numVariationsRequested: external_exports.number().int().nullable(),
|
|
10901
10979
|
numVariationsCompleted: external_exports.number().int().nullable().optional(),
|
|
10902
10980
|
numVariationsFailed: external_exports.number().int().nullable().optional(),
|
|
@@ -10951,6 +11029,7 @@ var LatestNodeRunResponseSchema = external_exports.object({
|
|
|
10951
11029
|
errorMessage: external_exports.string().nullable(),
|
|
10952
11030
|
errorSeverity: ErrorSeveritySchema.nullable().default(null),
|
|
10953
11031
|
errorRetryable: external_exports.boolean().nullable().optional(),
|
|
11032
|
+
errorReason: GenerationFailureReasonSchema.nullable().optional(),
|
|
10954
11033
|
numVariationsRequested: external_exports.number().int().nullable(),
|
|
10955
11034
|
numVariationsCompleted: external_exports.number().int().nullable().optional(),
|
|
10956
11035
|
numVariationsFailed: external_exports.number().int().nullable().optional(),
|
|
@@ -11257,7 +11336,33 @@ var CanvasSettingsResponseSchema = external_exports.object({
|
|
|
11257
11336
|
createdAt: external_exports.string().datetime(),
|
|
11258
11337
|
updatedAt: external_exports.string().datetime()
|
|
11259
11338
|
});
|
|
11339
|
+
var PlaygroundCanvasReferenceSchema = external_exports.object({
|
|
11340
|
+
projectId: external_exports.string().uuid(),
|
|
11341
|
+
canvasId: external_exports.string().uuid()
|
|
11342
|
+
});
|
|
11343
|
+
var PlaygroundCanvasPageSchema = external_exports.object({
|
|
11344
|
+
projectId: external_exports.string().uuid().nullable(),
|
|
11345
|
+
data: external_exports.array(external_exports.object({ id: external_exports.string().uuid() })),
|
|
11346
|
+
total: external_exports.number().int().nonnegative()
|
|
11347
|
+
});
|
|
11260
11348
|
var canvasContract = c7.router({
|
|
11349
|
+
createPlaygroundCanvas: {
|
|
11350
|
+
method: "POST",
|
|
11351
|
+
path: "/playground/canvases",
|
|
11352
|
+
body: null,
|
|
11353
|
+
responses: {
|
|
11354
|
+
201: PlaygroundCanvasReferenceSchema,
|
|
11355
|
+
409: MessageResponseSchema
|
|
11356
|
+
}
|
|
11357
|
+
},
|
|
11358
|
+
listPlaygroundCanvases: {
|
|
11359
|
+
method: "GET",
|
|
11360
|
+
path: "/playground/canvases",
|
|
11361
|
+
query: external_exports.object({
|
|
11362
|
+
...paginationQuery({ maxLimit: 100, defaultLimit: 25 })
|
|
11363
|
+
}),
|
|
11364
|
+
responses: { 200: PlaygroundCanvasPageSchema }
|
|
11365
|
+
},
|
|
11261
11366
|
createCanvas: {
|
|
11262
11367
|
method: "POST",
|
|
11263
11368
|
path: "/projects/:projectId/canvases",
|
|
@@ -13787,8 +13892,81 @@ var projectContract = c14.router({
|
|
|
13787
13892
|
}
|
|
13788
13893
|
});
|
|
13789
13894
|
|
|
13895
|
+
// ../api-contract/src/template-apply-input.ts
|
|
13896
|
+
var TemplateApplyInputSchema = external_exports.discriminatedUnion("kind", [
|
|
13897
|
+
external_exports.object({
|
|
13898
|
+
kind: external_exports.literal("asset"),
|
|
13899
|
+
portId: external_exports.string(),
|
|
13900
|
+
assetId: external_exports.string().uuid(),
|
|
13901
|
+
mediaType: external_exports.enum(["image", "video", "audio", "pdf"])
|
|
13902
|
+
}),
|
|
13903
|
+
external_exports.object({
|
|
13904
|
+
kind: external_exports.literal("text"),
|
|
13905
|
+
portId: external_exports.string(),
|
|
13906
|
+
text: external_exports.string().min(1)
|
|
13907
|
+
})
|
|
13908
|
+
]);
|
|
13909
|
+
|
|
13910
|
+
// ../api-contract/src/template-public-api.ts
|
|
13911
|
+
var TemplateResponseSchema = external_exports.object({
|
|
13912
|
+
id: external_exports.string(),
|
|
13913
|
+
title: external_exports.string(),
|
|
13914
|
+
groupLabel: external_exports.string(),
|
|
13915
|
+
icon: external_exports.string(),
|
|
13916
|
+
description: external_exports.string(),
|
|
13917
|
+
previewImageUrl: external_exports.string().nullable(),
|
|
13918
|
+
previewVideoUrl: external_exports.string().nullable().optional(),
|
|
13919
|
+
inputPorts: external_exports.array(TemplatePortSummarySchema),
|
|
13920
|
+
outputPorts: external_exports.array(TemplatePortSummarySchema),
|
|
13921
|
+
canEdit: external_exports.boolean(),
|
|
13922
|
+
isGlobal: external_exports.boolean().optional(),
|
|
13923
|
+
authorName: external_exports.string().nullable().optional(),
|
|
13924
|
+
estimatedCreditCost: external_exports.number().optional(),
|
|
13925
|
+
tags: external_exports.array(external_exports.string()).optional()
|
|
13926
|
+
});
|
|
13927
|
+
var PublicApplyTemplateResponseSchema = external_exports.object({
|
|
13928
|
+
/** The created template instance id. */
|
|
13929
|
+
instanceId: external_exports.string(),
|
|
13930
|
+
/** The collapsed group id shown on the canvas. */
|
|
13931
|
+
groupId: external_exports.string()
|
|
13932
|
+
});
|
|
13933
|
+
var ApplyTemplateBodySchema = external_exports.object({
|
|
13934
|
+
canvasId: external_exports.string().uuid(),
|
|
13935
|
+
templateId: external_exports.string().uuid(),
|
|
13936
|
+
/** Box center X. Auto-positioned to avoid existing nodes if omitted. */
|
|
13937
|
+
centerX: external_exports.number().optional(),
|
|
13938
|
+
/** Box center Y. Auto-positioned to avoid existing nodes if omitted. */
|
|
13939
|
+
centerY: external_exports.number().optional(),
|
|
13940
|
+
/** Optional input values materialized with the template instance. */
|
|
13941
|
+
inputs: external_exports.array(TemplateApplyInputSchema).optional()
|
|
13942
|
+
});
|
|
13943
|
+
var templateListRoute = {
|
|
13944
|
+
method: "GET",
|
|
13945
|
+
path: "/templates",
|
|
13946
|
+
responses: {
|
|
13947
|
+
200: external_exports.object({
|
|
13948
|
+
data: external_exports.array(TemplateResponseSchema)
|
|
13949
|
+
})
|
|
13950
|
+
},
|
|
13951
|
+
summary: "List available templates (active)"
|
|
13952
|
+
};
|
|
13953
|
+
var templateApplyRouteBase = {
|
|
13954
|
+
method: "POST",
|
|
13955
|
+
path: "/templates/apply",
|
|
13956
|
+
body: ApplyTemplateBodySchema,
|
|
13957
|
+
summary: "Apply a template as a collapsed canvas box"
|
|
13958
|
+
};
|
|
13959
|
+
var publicTemplateApplyRoute = {
|
|
13960
|
+
...templateApplyRouteBase,
|
|
13961
|
+
responses: {
|
|
13962
|
+
200: PublicApplyTemplateResponseSchema,
|
|
13963
|
+
404: MessageResponseSchema
|
|
13964
|
+
}
|
|
13965
|
+
};
|
|
13966
|
+
|
|
13790
13967
|
// ../api-contract/src/upload.ts
|
|
13791
13968
|
var c15 = initContract();
|
|
13969
|
+
var PdfExtractionModeSchema = external_exports.enum(["summary", "pages"]);
|
|
13792
13970
|
var InitUploadBodySchema = external_exports.object({
|
|
13793
13971
|
nodeId: external_exports.string().uuid().optional(),
|
|
13794
13972
|
filename: external_exports.string(),
|
|
@@ -13848,7 +14026,10 @@ var CompleteUploadBodySchema = external_exports.object({
|
|
|
13848
14026
|
// edit/upstream change to keep `src` fresh for downstream nodes; those
|
|
13849
14027
|
// background refreshes set this so they don't mint a new version each time.
|
|
13850
14028
|
// Explicit user saves omit it and fork a new version as usual.
|
|
13851
|
-
replaceActiveVersion: external_exports.boolean().optional()
|
|
14029
|
+
replaceActiveVersion: external_exports.boolean().optional(),
|
|
14030
|
+
// PDF-only: how to process the upload once complete. Omitted ⇒ "summary"
|
|
14031
|
+
// (the server default and every non-PDF upload). See PdfExtractionModeSchema.
|
|
14032
|
+
pdfExtractionMode: PdfExtractionModeSchema.optional()
|
|
13852
14033
|
});
|
|
13853
14034
|
var CompleteUploadResponseSchema = external_exports.object({
|
|
13854
14035
|
success: external_exports.boolean(),
|
|
@@ -13969,6 +14150,10 @@ var publicContract = c16.router(
|
|
|
13969
14150
|
preset: {
|
|
13970
14151
|
list: presetsContract.listPresets
|
|
13971
14152
|
},
|
|
14153
|
+
template: {
|
|
14154
|
+
list: templateListRoute,
|
|
14155
|
+
apply: publicTemplateApplyRoute
|
|
14156
|
+
},
|
|
13972
14157
|
team: {
|
|
13973
14158
|
list: teamContract.listMyTeams
|
|
13974
14159
|
},
|
|
@@ -14220,7 +14405,7 @@ function isMajorUpgrade(current, latest) {
|
|
|
14220
14405
|
return l[0] > c17[0];
|
|
14221
14406
|
}
|
|
14222
14407
|
function shouldShowUpgradeNotice(ctx = {}) {
|
|
14223
|
-
const current = ctx.current ?? "0.
|
|
14408
|
+
const current = ctx.current ?? "0.10.0";
|
|
14224
14409
|
const latest = ctx.latest ?? serverLatestVersion;
|
|
14225
14410
|
const env = ctx.env ?? process.env;
|
|
14226
14411
|
const isTty = ctx.isTty ?? Boolean(process.stderr.isTTY);
|
|
@@ -14241,7 +14426,7 @@ Upgrade: npm install -g @melius-ai/cli@latest (or: brew update && brew upgrade
|
|
|
14241
14426
|
function printUpgradeNoticeIfNeeded(ctx = {}) {
|
|
14242
14427
|
try {
|
|
14243
14428
|
if (!shouldShowUpgradeNotice(ctx)) return;
|
|
14244
|
-
const current = ctx.current ?? "0.
|
|
14429
|
+
const current = ctx.current ?? "0.10.0";
|
|
14245
14430
|
const latest = ctx.latest ?? serverLatestVersion;
|
|
14246
14431
|
process.stderr.write(formatUpgradeNotice(current, latest));
|
|
14247
14432
|
} catch {
|
|
@@ -15273,14 +15458,27 @@ function shiftToAvoidExisting(result, allNodes, targetIds, allEdges = []) {
|
|
|
15273
15458
|
}));
|
|
15274
15459
|
const existingIds = new Set(otherNodes.map((n) => n.id));
|
|
15275
15460
|
const nodeById = new Map(allNodes.map((n) => [n.id, n]));
|
|
15461
|
+
function resolveTopLevelNodeId(id) {
|
|
15462
|
+
let resolvedId = id;
|
|
15463
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15464
|
+
while (!seen.has(resolvedId)) {
|
|
15465
|
+
seen.add(resolvedId);
|
|
15466
|
+
const parentId2 = nodeById.get(resolvedId)?.groupId;
|
|
15467
|
+
if (!parentId2) break;
|
|
15468
|
+
resolvedId = parentId2;
|
|
15469
|
+
}
|
|
15470
|
+
return resolvedId;
|
|
15471
|
+
}
|
|
15276
15472
|
const incomingSourceIds = /* @__PURE__ */ new Set();
|
|
15277
15473
|
const outgoingTargetIds = /* @__PURE__ */ new Set();
|
|
15278
15474
|
for (const edge of allEdges) {
|
|
15279
|
-
|
|
15280
|
-
|
|
15475
|
+
const srcNodeId = resolveTopLevelNodeId(edge.srcNodeId);
|
|
15476
|
+
const dstNodeId = resolveTopLevelNodeId(edge.dstNodeId);
|
|
15477
|
+
if (existingIds.has(srcNodeId) && targetIds.has(dstNodeId)) {
|
|
15478
|
+
incomingSourceIds.add(srcNodeId);
|
|
15281
15479
|
}
|
|
15282
|
-
if (targetIds.has(
|
|
15283
|
-
outgoingTargetIds.add(
|
|
15480
|
+
if (targetIds.has(srcNodeId) && existingIds.has(dstNodeId)) {
|
|
15481
|
+
outgoingTargetIds.add(dstNodeId);
|
|
15284
15482
|
}
|
|
15285
15483
|
}
|
|
15286
15484
|
const SCATTER_THRESHOLD = 3;
|
|
@@ -15498,11 +15696,36 @@ function planLayout(content, planned, edges, anchorNodeIds) {
|
|
|
15498
15696
|
srcNodeId: e.srcNodeId,
|
|
15499
15697
|
dstNodeId: e.dstNodeId
|
|
15500
15698
|
}));
|
|
15699
|
+
const canvasNodeIds = new Set(content.nodes.map((n) => n.id));
|
|
15700
|
+
const mentionEdges = [];
|
|
15701
|
+
let mentionEdgeIndex = 0;
|
|
15702
|
+
for (const p of planned) {
|
|
15703
|
+
const mentionIds = /* @__PURE__ */ new Set([
|
|
15704
|
+
...extractMentionedNodeIds(p.prompt),
|
|
15705
|
+
...extractMentionedNodeIds(p.text)
|
|
15706
|
+
]);
|
|
15707
|
+
for (const mentionedId of mentionIds) {
|
|
15708
|
+
let srcId;
|
|
15709
|
+
if (virtualIds.has(mentionedId)) {
|
|
15710
|
+
srcId = mentionedId;
|
|
15711
|
+
} else if (canvasNodeIds.has(mentionedId)) {
|
|
15712
|
+
const node = nodeById.get(mentionedId);
|
|
15713
|
+
srcId = node?.groupId ?? mentionedId;
|
|
15714
|
+
}
|
|
15715
|
+
if (!srcId || srcId === p.id) continue;
|
|
15716
|
+
mentionEdges.push({
|
|
15717
|
+
id: `mention-${mentionEdgeIndex++}`,
|
|
15718
|
+
srcNodeId: srcId,
|
|
15719
|
+
dstNodeId: p.id
|
|
15720
|
+
});
|
|
15721
|
+
}
|
|
15722
|
+
}
|
|
15501
15723
|
const anchorEdges = [];
|
|
15502
15724
|
if (anchorNodes && anchorNodes.length > 0) {
|
|
15503
15725
|
const hasExplicitAnchorEdge = [
|
|
15504
15726
|
...plannedEdges,
|
|
15505
|
-
...relevantExisting
|
|
15727
|
+
...relevantExisting,
|
|
15728
|
+
...mentionEdges
|
|
15506
15729
|
].some(
|
|
15507
15730
|
(e) => anchorNodeIds.includes(e.srcNodeId) && virtualIds.has(e.dstNodeId)
|
|
15508
15731
|
);
|
|
@@ -15518,7 +15741,17 @@ function planLayout(content, planned, edges, anchorNodeIds) {
|
|
|
15518
15741
|
}
|
|
15519
15742
|
}
|
|
15520
15743
|
}
|
|
15521
|
-
const
|
|
15744
|
+
const baseEdges = [...plannedEdges, ...relevantExisting, ...anchorEdges];
|
|
15745
|
+
const baseEdgeKeys = new Set(
|
|
15746
|
+
baseEdges.map((e) => `${e.srcNodeId}->${e.dstNodeId}`)
|
|
15747
|
+
);
|
|
15748
|
+
const uniqueMentionEdges = mentionEdges.filter((e) => {
|
|
15749
|
+
const key = `${e.srcNodeId}->${e.dstNodeId}`;
|
|
15750
|
+
if (baseEdgeKeys.has(key)) return false;
|
|
15751
|
+
baseEdgeKeys.add(key);
|
|
15752
|
+
return true;
|
|
15753
|
+
});
|
|
15754
|
+
const allEdges = [...baseEdges, ...uniqueMentionEdges];
|
|
15522
15755
|
const allNodes = [...existingNodes, ...virtualNodes];
|
|
15523
15756
|
const virtualIdsArr = [...virtualIds];
|
|
15524
15757
|
const rawResult = computeAutoformat(allNodes, allEdges, virtualIdsArr);
|
|
@@ -16733,7 +16966,9 @@ Valid node types: text, image, video, audio, file, group, custom_text, stitch.
|
|
|
16733
16966
|
const planned = itemsWithoutGeometry.map((item) => ({
|
|
16734
16967
|
id: item.id ?? item.type,
|
|
16735
16968
|
nodeType: item.type,
|
|
16736
|
-
aspectRatio: item.aspectRatio
|
|
16969
|
+
aspectRatio: item.aspectRatio,
|
|
16970
|
+
prompt: item.prompt,
|
|
16971
|
+
text: item.text
|
|
16737
16972
|
}));
|
|
16738
16973
|
const plannedIds = new Set(planned.map((p) => p.id));
|
|
16739
16974
|
const edges = (edgeItems ?? []).filter(
|
|
@@ -18750,6 +18985,120 @@ Examples:
|
|
|
18750
18985
|
);
|
|
18751
18986
|
}
|
|
18752
18987
|
|
|
18988
|
+
// src/commands/template.ts
|
|
18989
|
+
function parseCoordinate(value, option) {
|
|
18990
|
+
if (value === void 0) return void 0;
|
|
18991
|
+
const parsed = Number(value);
|
|
18992
|
+
if (Number.isFinite(parsed)) return parsed;
|
|
18993
|
+
writeError(
|
|
18994
|
+
formatError("USAGE_ERROR", `${option} must be a finite number`, {
|
|
18995
|
+
suggestion: `Provide ${option} <number> or omit it for automatic placement`
|
|
18996
|
+
}),
|
|
18997
|
+
EXIT_USAGE_ERROR
|
|
18998
|
+
);
|
|
18999
|
+
}
|
|
19000
|
+
function parseInputs(value) {
|
|
19001
|
+
if (value === void 0) return void 0;
|
|
19002
|
+
let parsed;
|
|
19003
|
+
try {
|
|
19004
|
+
parsed = JSON.parse(value);
|
|
19005
|
+
} catch {
|
|
19006
|
+
writeError(
|
|
19007
|
+
formatError("USAGE_ERROR", "Invalid JSON in --inputs", {
|
|
19008
|
+
suggestion: `--inputs must be a JSON array, for example '[{"kind":"text","portId":"prompt","text":"A red shoe"}]'`
|
|
19009
|
+
}),
|
|
19010
|
+
EXIT_USAGE_ERROR
|
|
19011
|
+
);
|
|
19012
|
+
}
|
|
19013
|
+
const result = TemplateApplyInputSchema.array().safeParse(parsed);
|
|
19014
|
+
if (result.success) return result.data;
|
|
19015
|
+
writeError(
|
|
19016
|
+
formatError(
|
|
19017
|
+
"USAGE_ERROR",
|
|
19018
|
+
result.error.issues.map((issue) => issue.message).join("; "),
|
|
19019
|
+
{
|
|
19020
|
+
suggestion: 'Use text inputs {"kind":"text","portId":"<portId>","text":"<text>"} or asset inputs {"kind":"asset","portId":"<portId>","assetId":"<assetId>","mediaType":"image|video|audio|pdf"}'
|
|
19021
|
+
}
|
|
19022
|
+
),
|
|
19023
|
+
EXIT_USAGE_ERROR
|
|
19024
|
+
);
|
|
19025
|
+
}
|
|
19026
|
+
function registerTemplateCommands(program2, getOutputOpts) {
|
|
19027
|
+
const template = program2.command("template").description("List and apply opaque canvas workflow templates");
|
|
19028
|
+
template.command("list").description(
|
|
19029
|
+
"List available templates with display metadata and declared input/output ports"
|
|
19030
|
+
).addHelpText(
|
|
19031
|
+
"after",
|
|
19032
|
+
`
|
|
19033
|
+
Returns: Array of templates with id, title, description, previewImageUrl, inputPorts, outputPorts, and estimatedCreditCost.
|
|
19034
|
+
Includes global templates and templates scoped to the current team.
|
|
19035
|
+
The template's internal workflow stays private. Use a returned id with mel template apply.
|
|
19036
|
+
|
|
19037
|
+
Examples:
|
|
19038
|
+
$ mel template list
|
|
19039
|
+
$ mel template list --fields id,title,inputPorts,outputPorts`
|
|
19040
|
+
).action(async () => {
|
|
19041
|
+
const client = getClient();
|
|
19042
|
+
const result = await client.template.list();
|
|
19043
|
+
if (result.status !== 200) {
|
|
19044
|
+
handleApiError(result.status, result.body);
|
|
19045
|
+
}
|
|
19046
|
+
writeJson(result.body.data, getOutputOpts());
|
|
19047
|
+
});
|
|
19048
|
+
template.command("apply").description(
|
|
19049
|
+
"Apply a template to a canvas as one collapsed box and return its instanceId and groupId"
|
|
19050
|
+
).argument(
|
|
19051
|
+
"<canvasId>",
|
|
19052
|
+
"Canvas ID (from mel canvas create or mel canvas list output)"
|
|
19053
|
+
).argument("<templateId>", "Template ID (from mel template list output)").option(
|
|
19054
|
+
"--center-x <number>",
|
|
19055
|
+
"X center for the template box. Omit for automatic non-overlapping placement"
|
|
19056
|
+
).option(
|
|
19057
|
+
"--center-y <number>",
|
|
19058
|
+
"Y center for the template box. Omit for automatic non-overlapping placement"
|
|
19059
|
+
).option(
|
|
19060
|
+
"--inputs <json>",
|
|
19061
|
+
"JSON array of text or library-asset inputs targeting port IDs from mel template list"
|
|
19062
|
+
).addHelpText(
|
|
19063
|
+
"after",
|
|
19064
|
+
`
|
|
19065
|
+
Returns: { instanceId, groupId }. Internal workflow node IDs are never returned.
|
|
19066
|
+
Input kinds: text {kind,portId,text}; asset {kind,portId,assetId,mediaType} where mediaType is image, video, audio, or pdf.
|
|
19067
|
+
Omit --center-x/--center-y to place the box automatically. Use mel canvas content <canvasId> afterward to inspect its public ports.
|
|
19068
|
+
Run the applied template with mel bulk-run start <canvasId> --node-ids <groupId> --wait.
|
|
19069
|
+
|
|
19070
|
+
Examples:
|
|
19071
|
+
$ mel template apply <canvasId> <templateId>
|
|
19072
|
+
$ mel template apply <canvasId> <templateId> --inputs '[{"kind":"text","portId":"<portId>","text":"A red shoe"}]'
|
|
19073
|
+
$ mel bulk-run start <canvasId> --node-ids <groupId> --wait`
|
|
19074
|
+
).action(
|
|
19075
|
+
async (canvasId, templateId, opts) => {
|
|
19076
|
+
const client = getClient();
|
|
19077
|
+
const centerX = parseCoordinate(opts.centerX, "--center-x");
|
|
19078
|
+
const centerY = parseCoordinate(opts.centerY, "--center-y");
|
|
19079
|
+
const inputs = parseInputs(opts.inputs);
|
|
19080
|
+
const result = await client.template.apply({
|
|
19081
|
+
body: {
|
|
19082
|
+
canvasId,
|
|
19083
|
+
templateId,
|
|
19084
|
+
...centerX !== void 0 && { centerX },
|
|
19085
|
+
...centerY !== void 0 && { centerY },
|
|
19086
|
+
...inputs !== void 0 && { inputs }
|
|
19087
|
+
}
|
|
19088
|
+
});
|
|
19089
|
+
if (result.status !== 200) {
|
|
19090
|
+
handleApiError(
|
|
19091
|
+
result.status,
|
|
19092
|
+
result.body,
|
|
19093
|
+
"Run: mel template list"
|
|
19094
|
+
);
|
|
19095
|
+
}
|
|
19096
|
+
const { instanceId, groupId } = result.body;
|
|
19097
|
+
writeJson({ instanceId, groupId }, getOutputOpts());
|
|
19098
|
+
}
|
|
19099
|
+
);
|
|
19100
|
+
}
|
|
19101
|
+
|
|
18753
19102
|
// src/lib/upload.ts
|
|
18754
19103
|
import * as fs3 from "fs";
|
|
18755
19104
|
import * as path3 from "path";
|
|
@@ -19205,7 +19554,7 @@ function withDefaultHelp(args) {
|
|
|
19205
19554
|
}
|
|
19206
19555
|
function createProgram() {
|
|
19207
19556
|
const program2 = new Command();
|
|
19208
|
-
program2.name("mel").description("Mel \u2014 Melius agent CLI").version("0.
|
|
19557
|
+
program2.name("mel").description("Mel \u2014 Melius agent CLI").version("0.10.0").showSuggestionAfterError(true).option("--json", "Force JSON output (default)").option("--text", "Human-readable output").option(
|
|
19209
19558
|
"--fields <fields>",
|
|
19210
19559
|
"Select specific output fields (comma-separated)"
|
|
19211
19560
|
).option("--quiet", "Suppress output, exit code only").option("--verbose", "Log request/response metadata to stderr").addHelpText(
|
|
@@ -19244,6 +19593,7 @@ Learn more: https://docs.melius.com`
|
|
|
19244
19593
|
registerAudioCommands(program2, getOutputOpts);
|
|
19245
19594
|
registerFontCommands(program2, getOutputOpts);
|
|
19246
19595
|
registerPresetCommands(program2, getOutputOpts);
|
|
19596
|
+
registerTemplateCommands(program2, getOutputOpts);
|
|
19247
19597
|
registerConfigCommands(program2, getOutputOpts);
|
|
19248
19598
|
if (false) {
|
|
19249
19599
|
registerSkillCommands(program2, getOutputOpts);
|
package/dist/src/index.js
CHANGED