@marlinjai/studio-mcp 0.1.0 → 0.1.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 +2 -2
- package/dist/cli.js +69 -24
- package/dist/index.d.ts +210 -5
- package/dist/index.js +69 -24
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -101,7 +101,7 @@ The token is held in memory only. It is never logged, never serialized into a re
|
|
|
101
101
|
| `studio_workflow_screenshot` | Render a saved workflow's document as a diagram (labelled boxes and wires, positioned by the document's own layout), the Figma `get_screenshot` equivalent for a workflow graph. Not a pixel-exact canvas preview, a diagnostic diagram for checking topology. Returns `{ url, width, height }` (a 24h signed link). Free, read-only. |
|
|
102
102
|
| `studio_list_published` | List every published recipe: `{ recipes: [{ slug, label, publishedRevision, updatedAt, hasEffects }] }`. `hasEffects` tells you whether running it creates/attaches an entity record (a character, a brand reference) on success, versus a pure generation recipe. Free, read-only. |
|
|
103
103
|
| `studio_describe_published` | Describe one published recipe by slug: `{ slug, definition, hasEffects }`. `definition` is the FROZEN workflow (params, node shapes) exactly as it was at publish time, never the live authoring document. Read this before `studio_run_published` to know what params it needs. Free, read-only. |
|
|
104
|
-
| `studio_run_published` | Run a published recipe by slug against its frozen definition; `params` fill the definition's own param bindings. On success, the recipe's declared post-run effects fire automatically (e.g. minting creates the character and attaches its reference views); effects never fire on a failed or
|
|
104
|
+
| `studio_run_published` | Run a published recipe by slug against its frozen definition; `params` fill the definition's own param bindings. On success, the recipe's declared post-run effects fire automatically (e.g. minting creates the character and attaches its reference views); effects never fire on a failed, partial or cancelled run. Each node is a paid job. |
|
|
105
105
|
|
|
106
106
|
All waiting tools accept `waitSeconds` (default 600) and back off between polls (2s doubling up to 15s). A timeout never cancels anything server-side: the tool error carries the id so the agent can poll again.
|
|
107
107
|
|
|
@@ -159,7 +159,7 @@ Two workflows behave differently from a document built through this contract:
|
|
|
159
159
|
|
|
160
160
|
A **recipe** is a workflow that has been *published* under a stable public slug: its document and an optional declared list of post-run effects (create a character, attach a reference image, create a brand) are frozen together at publish time. `studio_list_published` / `studio_describe_published` / `studio_run_published` are the derived, read-only-until-you-run surface over every recipe that exists: the same three tools serve every recipe ever published, so the surface never grows as recipes are added.
|
|
161
161
|
|
|
162
|
-
Running a recipe (`studio_run_published`) always executes the FROZEN definition, never the live authoring document (which may have moved on since publish). If every node in the run succeeds, the recipe's declared effects fire automatically and exactly once; a failed or
|
|
162
|
+
Running a recipe (`studio_run_published`) always executes the FROZEN definition, never the live authoring document (which may have moved on since publish). If every node in the run succeeds, the recipe's declared effects fire automatically and exactly once; a failed, partial or cancelled run (one somebody stopped) never triggers them, so a broken run can never leave a half-created character or a reference attached to nothing. Publishing a workflow (setting the slug and the effect list) is not yet exposed as an MCP tool: it is done through the HTTP API (`POST /api/v1/workflows/:savedId/publish`) or on the canvas.
|
|
163
163
|
|
|
164
164
|
`studio_mint_character` and `studio_replace_character_in_video` (above) are today still hand-written tools, not recipes; migrating them onto published recipe twins is planned but not yet done, so both surfaces currently coexist.
|
|
165
165
|
|
package/dist/cli.js
CHANGED
|
@@ -213,8 +213,8 @@ var StudioClient = class {
|
|
|
213
213
|
}
|
|
214
214
|
/** S9: a rendered diagram of a saved workflow's document, so an agent can
|
|
215
215
|
* see the graph it just built. */
|
|
216
|
-
getWorkflowScreenshot(savedId2) {
|
|
217
|
-
return this.json("GET", `/api/v1/workflows/${encodeURIComponent(savedId2)}/screenshot`);
|
|
216
|
+
getWorkflowScreenshot(savedId2, opts = {}) {
|
|
217
|
+
return this.json("GET", `/api/v1/workflows/${encodeURIComponent(savedId2)}/screenshot${projectQuery(opts.projectId)}`);
|
|
218
218
|
}
|
|
219
219
|
// ── Recipes (S10): published workflow + closed post-run effect list ──
|
|
220
220
|
publishWorkflow(savedId2, body) {
|
|
@@ -239,9 +239,10 @@ var StudioClient = class {
|
|
|
239
239
|
describeNodeTypes() {
|
|
240
240
|
return this.json("GET", "/api/v1/node-types");
|
|
241
241
|
}
|
|
242
|
-
/** `savedId` carries a `saved:` prefix; the colon is URL-encoded.
|
|
243
|
-
|
|
244
|
-
|
|
242
|
+
/** `savedId` carries a `saved:` prefix; the colon is URL-encoded. `projectId`
|
|
243
|
+
* names the project the workflow lives in; absent, the Studio's default. */
|
|
244
|
+
getWorkflowDocument(savedId2, opts = {}) {
|
|
245
|
+
return this.json("GET", `/api/v1/workflows/${encodeURIComponent(savedId2)}${projectQuery(opts.projectId)}`);
|
|
245
246
|
}
|
|
246
247
|
/** Create a document by applying `ops` to an empty one (the same code path as apply). */
|
|
247
248
|
createWorkflow(body) {
|
|
@@ -412,6 +413,9 @@ function mimeForFilename(name) {
|
|
|
412
413
|
return "application/octet-stream";
|
|
413
414
|
}
|
|
414
415
|
}
|
|
416
|
+
function projectQuery(projectId) {
|
|
417
|
+
return projectId === void 0 ? "" : `?projectId=${encodeURIComponent(projectId)}`;
|
|
418
|
+
}
|
|
415
419
|
|
|
416
420
|
// src/tools.ts
|
|
417
421
|
import { z as z8 } from "zod";
|
|
@@ -634,6 +638,7 @@ var AssetIdSchema = z3.string().max(128);
|
|
|
634
638
|
var PortTypeSchema = z3.enum(PORT_TYPES);
|
|
635
639
|
var InputTypeSchema = z3.enum(INPUT_PORT_TYPES);
|
|
636
640
|
var PositionSchema = z3.object({ x: z3.number().finite(), y: z3.number().finite() });
|
|
641
|
+
var CollapsedSchema = z3.boolean();
|
|
637
642
|
var TaskNodeSchema = z3.object({
|
|
638
643
|
id: IdSchema,
|
|
639
644
|
kind: z3.literal("task"),
|
|
@@ -654,13 +659,15 @@ var TaskNodeSchema = z3.object({
|
|
|
654
659
|
bakedInputs: z3.record(KeySchema, LiteralBindingSchema).default({}),
|
|
655
660
|
/** The generation id that feeds downstream. Absent = latest (D4). */
|
|
656
661
|
activeGeneration: IdSchema.optional(),
|
|
657
|
-
label: LabelSchema.optional()
|
|
662
|
+
label: LabelSchema.optional(),
|
|
663
|
+
collapsed: CollapsedSchema.optional()
|
|
658
664
|
});
|
|
659
665
|
var PromptSourceNodeSchema = z3.object({
|
|
660
666
|
id: IdSchema,
|
|
661
667
|
kind: z3.literal("prompt-source"),
|
|
662
668
|
text: PromptTextSchema.default(""),
|
|
663
|
-
label: LabelSchema.optional()
|
|
669
|
+
label: LabelSchema.optional(),
|
|
670
|
+
collapsed: CollapsedSchema.optional()
|
|
664
671
|
});
|
|
665
672
|
var ImageSourceNodeSchema = z3.object({
|
|
666
673
|
id: IdSchema,
|
|
@@ -671,7 +678,8 @@ var ImageSourceNodeSchema = z3.object({
|
|
|
671
678
|
/** The Storage Brain asset id, when known (E18: every image input resolves to
|
|
672
679
|
* an asset id). */
|
|
673
680
|
assetId: AssetIdSchema.optional(),
|
|
674
|
-
label: LabelSchema.optional()
|
|
681
|
+
label: LabelSchema.optional(),
|
|
682
|
+
collapsed: CollapsedSchema.optional()
|
|
675
683
|
});
|
|
676
684
|
var InputNodeSchema = z3.object({
|
|
677
685
|
id: IdSchema,
|
|
@@ -686,7 +694,8 @@ var InputNodeSchema = z3.object({
|
|
|
686
694
|
/** Used when a run omits the input. Never null: absent means no default. */
|
|
687
695
|
default: JsonNonNullValueSchema.optional(),
|
|
688
696
|
label: LabelSchema.optional(),
|
|
689
|
-
description: DescriptionSchema.optional()
|
|
697
|
+
description: DescriptionSchema.optional(),
|
|
698
|
+
collapsed: CollapsedSchema.optional()
|
|
690
699
|
});
|
|
691
700
|
var DocNodeSchema = z3.discriminatedUnion("kind", [
|
|
692
701
|
TaskNodeSchema,
|
|
@@ -704,6 +713,18 @@ var DocGroupSchema = z3.object({
|
|
|
704
713
|
label: LabelSchema.optional(),
|
|
705
714
|
nodeIds: z3.array(IdSchema).min(1)
|
|
706
715
|
});
|
|
716
|
+
var EDGE_ROUTINGS = ["curved", "orthogonal"];
|
|
717
|
+
var EdgeRoutingSchema = z3.enum(EDGE_ROUTINGS);
|
|
718
|
+
var WireRouteSchema = z3.object({
|
|
719
|
+
from: PositionSchema,
|
|
720
|
+
to: PositionSchema,
|
|
721
|
+
points: z3.array(PositionSchema).max(64)
|
|
722
|
+
});
|
|
723
|
+
var DocumentViewSchema = z3.object({
|
|
724
|
+
edgeRouting: EdgeRoutingSchema.optional(),
|
|
725
|
+
/** Routed wires from the last Arrange, keyed by `edgeKey`. */
|
|
726
|
+
wires: z3.record(z3.string().max(512), WireRouteSchema).optional()
|
|
727
|
+
});
|
|
707
728
|
var WorkflowDocumentSchema = z3.object({
|
|
708
729
|
schema: z3.number().int().positive(),
|
|
709
730
|
id: IdSchema,
|
|
@@ -711,7 +732,10 @@ var WorkflowDocumentSchema = z3.object({
|
|
|
711
732
|
nodes: z3.array(DocNodeSchema).max(2e3),
|
|
712
733
|
edges: z3.array(DocEdgeSchema).max(8e3),
|
|
713
734
|
layout: z3.record(IdSchema, PositionSchema).default({}),
|
|
714
|
-
groups: z3.array(DocGroupSchema).max(500).default([])
|
|
735
|
+
groups: z3.array(DocGroupSchema).max(500).default([]),
|
|
736
|
+
/** Display preferences; absent on every document written before they
|
|
737
|
+
* existed (additive, so `DOCUMENT_SCHEMA_VERSION` is unchanged). */
|
|
738
|
+
view: DocumentViewSchema.optional()
|
|
715
739
|
});
|
|
716
740
|
function edgeKey(e) {
|
|
717
741
|
return JSON.stringify([e.source, e.target, e.port]);
|
|
@@ -1480,16 +1504,19 @@ var TaskNodePropsSchema = z4.object({
|
|
|
1480
1504
|
task: z4.enum(MODEL_TASKS),
|
|
1481
1505
|
model: ModelIdSchema,
|
|
1482
1506
|
prompt: PromptTextSchema,
|
|
1483
|
-
label: LabelSchema.nullable()
|
|
1507
|
+
label: LabelSchema.nullable(),
|
|
1508
|
+
collapsed: CollapsedSchema.nullable()
|
|
1484
1509
|
}).partial().strict();
|
|
1485
1510
|
var PromptSourcePropsSchema = z4.object({
|
|
1486
1511
|
text: PromptTextSchema,
|
|
1487
|
-
label: LabelSchema.nullable()
|
|
1512
|
+
label: LabelSchema.nullable(),
|
|
1513
|
+
collapsed: CollapsedSchema.nullable()
|
|
1488
1514
|
}).partial().strict();
|
|
1489
1515
|
var ImageSourcePropsSchema = z4.object({
|
|
1490
1516
|
imageUrl: UrlSchema,
|
|
1491
1517
|
assetId: AssetIdSchema.nullable(),
|
|
1492
|
-
label: LabelSchema.nullable()
|
|
1518
|
+
label: LabelSchema.nullable(),
|
|
1519
|
+
collapsed: CollapsedSchema.nullable()
|
|
1493
1520
|
}).partial().strict();
|
|
1494
1521
|
var InputNodePropsSchema = z4.object({
|
|
1495
1522
|
name: InputNameSchema,
|
|
@@ -1498,14 +1525,19 @@ var InputNodePropsSchema = z4.object({
|
|
|
1498
1525
|
cardinality: z4.enum(["one", "many"]).nullable(),
|
|
1499
1526
|
default: JsonNonNullValueSchema.nullable(),
|
|
1500
1527
|
label: LabelSchema.nullable(),
|
|
1501
|
-
description: DescriptionSchema.nullable()
|
|
1528
|
+
description: DescriptionSchema.nullable(),
|
|
1529
|
+
collapsed: CollapsedSchema.nullable()
|
|
1502
1530
|
}).partial().strict();
|
|
1503
1531
|
var GroupPropsSchema = z4.object({
|
|
1504
1532
|
label: LabelSchema.nullable(),
|
|
1505
1533
|
nodeIds: z4.array(IdSchema).min(1)
|
|
1506
1534
|
}).partial().strict();
|
|
1507
1535
|
var DocumentPropsSchema = z4.object({
|
|
1508
|
-
label: LabelSchema
|
|
1536
|
+
label: LabelSchema,
|
|
1537
|
+
/** Display preferences (`view.edgeRouting`); null clears the whole
|
|
1538
|
+
* object. The object is replaced, not merged: pass every field you want
|
|
1539
|
+
* kept. */
|
|
1540
|
+
view: DocumentViewSchema.strict().nullable()
|
|
1509
1541
|
}).partial().strict();
|
|
1510
1542
|
var AddNodeOpSchema = z4.object({
|
|
1511
1543
|
type: z4.literal("addNode"),
|
|
@@ -2076,7 +2108,7 @@ async function pollUntil(what, fetchState, isDone, opts = {}) {
|
|
|
2076
2108
|
}
|
|
2077
2109
|
}
|
|
2078
2110
|
var TERMINAL_JOB_STATUSES = /* @__PURE__ */ new Set(["succeeded", "failed", "canceled"]);
|
|
2079
|
-
var TERMINAL_RUN_STATUSES = /* @__PURE__ */ new Set(["succeeded", "failed", "partial"]);
|
|
2111
|
+
var TERMINAL_RUN_STATUSES = /* @__PURE__ */ new Set(["succeeded", "failed", "partial", "cancelled"]);
|
|
2080
2112
|
function isJobTerminal(res) {
|
|
2081
2113
|
return TERMINAL_JOB_STATUSES.has(res.job.status);
|
|
2082
2114
|
}
|
|
@@ -2409,11 +2441,12 @@ var studioWorkflowGet = defineTool({
|
|
|
2409
2441
|
description: "Read a saved workflow. By default returns a summary: { savedId, revision, label, readOnly, nodes: [{ id, kind, label?, task?, model?, prompt? (first 80 chars, plus promptLength), imageUrl?, name?, type?, required?, wires: { in, out } }], edgeCount, groupCount, projection: { ok, issues } } where revision is the baseRevision for studio_workflow_apply and projection says whether the workflow can run and why not. A workflow the canvas cannot represent comes back as { readOnly: true, definitionNodeCount, projection, hint } with no nodes: it is readable and runnable (studio_run_workflow with its savedId) but not patchable. needsLossyAcknowledgement: true means its first patch must carry acknowledgeLossy: true. full: true returns the whole response instead; use it only when you need every field.",
|
|
2410
2442
|
inputSchema: {
|
|
2411
2443
|
savedId,
|
|
2444
|
+
projectId: z7.string().min(1).optional().describe("Project id from studio_list_projects the workflow lives in; omit for the default project."),
|
|
2412
2445
|
full: z7.boolean().default(false).describe("Return the whole response (the full document, or the stored definition of a read-only workflow) instead of the summary.")
|
|
2413
2446
|
},
|
|
2414
2447
|
annotations: { readOnlyHint: true },
|
|
2415
2448
|
handler: async (args, ctx) => {
|
|
2416
|
-
const res = await ctx.client.getWorkflowDocument(args.savedId);
|
|
2449
|
+
const res = await ctx.client.getWorkflowDocument(args.savedId, args.projectId !== void 0 ? { projectId: args.projectId } : {});
|
|
2417
2450
|
if (args.full) return res;
|
|
2418
2451
|
if (res.readOnly === true || res.document === null) {
|
|
2419
2452
|
const definition = isRecord(res.definition) ? res.definition : null;
|
|
@@ -2486,6 +2519,7 @@ var studioWorkflowApply = defineTool({
|
|
|
2486
2519
|
description: 'Change a saved workflow atomically: the ops are applied all-or-nothing on top of baseRevision (the revision from studio_workflow_get, studio_workflow_create or your last apply). Success returns { ok: true, savedId, revision, appliedCount, inverseCount, affectedNodes (summaries of the nodes the patch touched, removed ones as { id, removed: true }), projection: { ok, issues }, idempotencyKey, replayed }. Every refusal comes back as { ok: false, code, hint } you can act on rather than an error: "stale_revision" (re-read, rebase your ops, apply again on the revision returned), "invalid_patch" (error.opIndex names the offending op), "forbidden" (opIndex plus the missingScope your credential needs), "not_editable" (this workflow is readable and runnable but cannot be patched), "lossy_import" (read notes, then resend with acknowledgeLossy: true and a NEW idempotencyKey), "idempotency_mismatch" (that key belongs to a different patch: use a fresh one), and "network_error" / "server_error" which you retry with the SAME idempotencyKey so the patch can never apply twice.',
|
|
2487
2520
|
inputSchema: {
|
|
2488
2521
|
savedId,
|
|
2522
|
+
projectId: z7.string().min(1).optional().describe("Project id from studio_list_projects the workflow lives in; omit for the default project."),
|
|
2489
2523
|
baseRevision: PatchSchema.shape.baseRevision.describe("The revision the ops were written against. The Studio refuses a stale one with stale_revision."),
|
|
2490
2524
|
ops: opsSchema,
|
|
2491
2525
|
idempotencyKey: PatchSchema.shape.idempotencyKey.describe(
|
|
@@ -2500,6 +2534,7 @@ var studioWorkflowApply = defineTool({
|
|
|
2500
2534
|
let res;
|
|
2501
2535
|
try {
|
|
2502
2536
|
res = await ctx.client.applyWorkflowPatch(args.savedId, {
|
|
2537
|
+
...args.projectId !== void 0 ? { projectId: args.projectId } : {},
|
|
2503
2538
|
baseRevision: args.baseRevision,
|
|
2504
2539
|
ops: args.ops,
|
|
2505
2540
|
idempotencyKey,
|
|
@@ -2534,16 +2569,18 @@ var studioWorkflowValidate = defineTool({
|
|
|
2534
2569
|
inputSchema: {
|
|
2535
2570
|
document: WorkflowDocumentSchema.optional().describe("The document to validate. Either this or savedId."),
|
|
2536
2571
|
savedId: savedId.optional().describe("Fetch this saved workflow first and validate against its current document. Either this or document, not both."),
|
|
2572
|
+
projectId: z7.string().min(1).optional().describe("Project id from studio_list_projects the saved workflow lives in (only with savedId); omit for the default project."),
|
|
2537
2573
|
ops: PatchSchema.shape.ops.optional().describe("Ops to apply to the document before projecting it (the same vocabulary and limits as studio_workflow_apply)."),
|
|
2538
2574
|
params: paramsSchema.optional()
|
|
2539
2575
|
},
|
|
2540
2576
|
annotations: { readOnlyHint: true },
|
|
2541
2577
|
handler: async (args, ctx) => {
|
|
2542
2578
|
if (args.document && args.savedId) throw new ToolInputError("pass either `document` or `savedId`, not both");
|
|
2579
|
+
if (args.projectId !== void 0 && !args.savedId) throw new ToolInputError("`projectId` only applies when fetching by `savedId`");
|
|
2543
2580
|
let document = args.document;
|
|
2544
2581
|
if (!document) {
|
|
2545
2582
|
if (!args.savedId) throw new ToolInputError("provide a `document` or a `savedId` to validate");
|
|
2546
|
-
const saved = await ctx.client.getWorkflowDocument(args.savedId);
|
|
2583
|
+
const saved = await ctx.client.getWorkflowDocument(args.savedId, args.projectId !== void 0 ? { projectId: args.projectId } : {});
|
|
2547
2584
|
if (saved.readOnly === true || saved.document === null) {
|
|
2548
2585
|
throw new ToolInputError(
|
|
2549
2586
|
`workflow ${args.savedId} has no document to validate: the canvas cannot represent its stored definition (studio_workflow_get shows readOnly: true and why). It is still runnable with studio_run_workflow.`
|
|
@@ -2562,11 +2599,12 @@ var studioWorkflowScreenshot = defineTool({
|
|
|
2562
2599
|
name: "studio_workflow_screenshot",
|
|
2563
2600
|
description: "Render a saved workflow's document as a diagram (labelled boxes and wires, positioned by the document's own layout) so you can see the graph you just built, the Figma get_screenshot equivalent. NOT a pixel-exact preview of the real canvas: a plain diagnostic diagram for checking topology (is everything wired the way I meant, did that addNode land where I expected). Returns { url, width, height }; the url is a signed Storage Brain link, valid for 24h. Free, read-only.",
|
|
2564
2601
|
inputSchema: {
|
|
2565
|
-
savedId
|
|
2602
|
+
savedId,
|
|
2603
|
+
projectId: z7.string().min(1).optional().describe("Project id from studio_list_projects the workflow lives in; omit for the default project.")
|
|
2566
2604
|
},
|
|
2567
2605
|
annotations: { readOnlyHint: true },
|
|
2568
2606
|
handler: async (args, ctx) => {
|
|
2569
|
-
return ctx.client.getWorkflowScreenshot(args.savedId);
|
|
2607
|
+
return ctx.client.getWorkflowScreenshot(args.savedId, args.projectId !== void 0 ? { projectId: args.projectId } : {});
|
|
2570
2608
|
}
|
|
2571
2609
|
});
|
|
2572
2610
|
var WORKFLOW_TOOLS = [
|
|
@@ -2599,6 +2637,8 @@ function projectJob(res) {
|
|
|
2599
2637
|
function projectNodeRun(nr) {
|
|
2600
2638
|
return {
|
|
2601
2639
|
nodeId: nr.nodeId,
|
|
2640
|
+
// The node-run (generation) id: what `upstreamGenerations` pins.
|
|
2641
|
+
id: nr.id ?? null,
|
|
2602
2642
|
status: nr.status,
|
|
2603
2643
|
url: nr.resultUrl ?? nr.results?.[0]?.url ?? null,
|
|
2604
2644
|
kind: nr.results?.[0]?.kind ?? null,
|
|
@@ -2856,13 +2896,16 @@ var workflowDefinitionSchema = WorkflowDefinitionSchema.describe(
|
|
|
2856
2896
|
);
|
|
2857
2897
|
var studioRunWorkflow = defineTool({
|
|
2858
2898
|
name: "studio_run_workflow",
|
|
2859
|
-
description: `Run a generation workflow DAG. Pass an inline definition (nodes of provider calls wired by ref bindings; this is what the hosted Studio accepts) or the savedId of a workflow saved in the Studio (the Studio runs that workflow's current document, exactly what the canvas would run). Params fill {kind:"param"} bindings. Returns the runId plus per-node status, URLs and cost; with wait=true (default) it blocks until the run is terminal (succeeded, failed, partial). Each node becomes a paid job.`,
|
|
2899
|
+
description: `Run a generation workflow DAG. Pass an inline definition (nodes of provider calls wired by ref bindings; this is what the hosted Studio accepts) or the savedId of a workflow saved in the Studio (the Studio runs that workflow's current document, exactly what the canvas would run). Params fill {kind:"param"} bindings. Returns the runId plus per-node status, URLs and cost; with wait=true (default) it blocks until the run is terminal (succeeded, failed, partial, cancelled). Each node becomes a paid job. Use an inline definition ONLY for the first batch of a new deliverable (one workflow, a node per item, a stable label); a follow-up on an existing item belongs in that saved workflow as a new node (studio_workflow_apply: addNode plus connect from the node it refines) run here with savedId and nodeIds, because every listed inline run is saved as its own workflow.`,
|
|
2860
2900
|
inputSchema: {
|
|
2861
2901
|
projectId: z8.string().min(1).describe("Project id from studio_list_projects."),
|
|
2862
2902
|
definition: workflowDefinitionSchema.optional(),
|
|
2863
2903
|
savedId: z8.string().optional().describe("Id of a saved workflow (from studio_workflow_create, studio_workflow_get or a listed run) to run instead of an inline definition. An unknown id is a 404 naming it; a workflow that is not runnable yet comes back as not_runnable with per-node issues."),
|
|
2864
2904
|
params: z8.record(z8.string(), z8.unknown()).optional().describe("Values for the definition's params."),
|
|
2865
2905
|
nodeIds: z8.array(z8.string()).optional().describe("Run only this subset of nodes (requires an inline `definition` or a `savedId`)."),
|
|
2906
|
+
upstreamGenerations: z8.record(z8.string(), z8.string()).optional().describe(
|
|
2907
|
+
'Pin WHICH generation of an upstream node feeds this subset run: { "<upstream node id>": "<node-run id>" } (the per-node `id` that studio_get_run returns). A verified pin is reused even when the planner has no matching cache key for it (an inline first batch, or a node edited and reverted), so a follow-up node wired from an earlier generation runs against exactly that image. An unknown id is refused naming the node, never silently replaced by the latest.'
|
|
2908
|
+
),
|
|
2866
2909
|
runs: z8.number().int().min(1).max(8).optional().describe("Repeat a node subset N times (1 to 8)."),
|
|
2867
2910
|
visibility: z8.enum(["listed", "unlisted"]).optional().describe("Whether the run shows in the Studio workflow list."),
|
|
2868
2911
|
budgetUsd: z8.number().nonnegative().optional().describe(
|
|
@@ -2886,6 +2929,7 @@ var studioRunWorkflow = defineTool({
|
|
|
2886
2929
|
...args.definition ? { definition: args.definition } : {},
|
|
2887
2930
|
...args.params ? { params: args.params } : {},
|
|
2888
2931
|
...args.nodeIds && args.nodeIds.length > 0 ? { nodeIds: args.nodeIds } : {},
|
|
2932
|
+
...args.upstreamGenerations ? { upstreamGenerations: args.upstreamGenerations } : {},
|
|
2889
2933
|
...args.runs !== void 0 ? { runs: args.runs } : {},
|
|
2890
2934
|
...args.savedId ? { savedId: args.savedId } : {},
|
|
2891
2935
|
...args.visibility ? { visibility: args.visibility } : {},
|
|
@@ -2899,7 +2943,7 @@ var studioRunWorkflow = defineTool({
|
|
|
2899
2943
|
});
|
|
2900
2944
|
var studioGetRun = defineTool({
|
|
2901
2945
|
name: "studio_get_run",
|
|
2902
|
-
description: "Fetch a workflow run by runId: overall status (pending, running, succeeded, failed, partial, awaiting_decision), total cost, and per-node status, result URL, cost and error message. Set wait=true to block until the run settles. A run at awaiting_decision is parked on a person at a judge node: waiting returns immediately with a `waiting` block naming the node and its candidates, because polling can never clear it; ask the user to choose and submit their answer with studio_decide_judge.",
|
|
2946
|
+
description: "Fetch a workflow run by runId: overall status (pending, running, succeeded, failed, partial, awaiting_decision, cancelled; cancelled means somebody stopped it), total cost, and per-node status, result URL, cost and error message. Set wait=true to block until the run settles. A run at awaiting_decision is parked on a person at a judge node: waiting returns immediately with a `waiting` block naming the node and its candidates, because polling can never clear it; ask the user to choose and submit their answer with studio_decide_judge.",
|
|
2903
2947
|
inputSchema: {
|
|
2904
2948
|
runId: z8.string().min(1),
|
|
2905
2949
|
wait: z8.boolean().default(false),
|
|
@@ -3146,7 +3190,7 @@ function registerTools(server, ctx) {
|
|
|
3146
3190
|
|
|
3147
3191
|
// src/server.ts
|
|
3148
3192
|
var SERVER_NAME = "lumitra-studio";
|
|
3149
|
-
var SERVER_VERSION = "0.1.
|
|
3193
|
+
var SERVER_VERSION = "0.1.1";
|
|
3150
3194
|
function createStudioMcpServer(opts = {}) {
|
|
3151
3195
|
const config = opts.config ?? resolveConfig(opts.env ?? process.env);
|
|
3152
3196
|
const client = new StudioClient(config, {
|
|
@@ -3160,7 +3204,8 @@ function createStudioMcpServer(opts = {}) {
|
|
|
3160
3204
|
"Lumitra Studio: brand-consistent image generation, character minting, workflow runs and the still-swap video recipe over the hosted Studio API.",
|
|
3161
3205
|
"Start with studio_list_projects to get a projectId. Every generation costs real money (roughly $0.04 per image, $0.30 per character mint, $0.70 per video take); check studio_get_spend when in doubt.",
|
|
3162
3206
|
"Long jobs: tools wait by default (up to timeoutSeconds, 600 by default) and return ids you can poll with studio_get_job / studio_get_run if they time out.",
|
|
3163
|
-
"Authoring a workflow is free and revisioned: studio_workflow_describe for the vocabulary, studio_workflow_create to build one from ops, studio_workflow_apply to change it on top of a baseRevision (a stale_revision result means re-read, rebase, retry), studio_workflow_validate to dry-run before spending, then studio_run_workflow with its savedId."
|
|
3207
|
+
"Authoring a workflow is free and revisioned: studio_workflow_describe for the vocabulary, studio_workflow_create to build one from ops, studio_workflow_apply to change it on top of a baseRevision (a stale_revision result means re-read, rebase, retry), studio_workflow_validate to dry-run before spending, then studio_run_workflow with its savedId.",
|
|
3208
|
+
"Workflow hygiene: one deliverable is ONE saved workflow with a node per item, and a refinement of an item (edit, upscale, variation) is a NEW NODE appended to that workflow with studio_workflow_apply (addNode plus a connect from the node it refines, so the earlier generation is its input), then studio_run_workflow with savedId and nodeIds limited to the new node. Never send a fresh inline definition for a follow-up: every listed inline run is saved as its own workflow, which scatters one deliverable across duplicates."
|
|
3164
3209
|
].join(" ")
|
|
3165
3210
|
}
|
|
3166
3211
|
);
|
package/dist/index.d.ts
CHANGED
|
@@ -54,17 +54,20 @@ declare const DocNodeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
54
54
|
}, z.core.$strip>>>;
|
|
55
55
|
activeGeneration: z.ZodOptional<z.ZodString>;
|
|
56
56
|
label: z.ZodOptional<z.ZodString>;
|
|
57
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
57
58
|
}, z.core.$strip>, z.ZodObject<{
|
|
58
59
|
id: z.ZodString;
|
|
59
60
|
kind: z.ZodLiteral<"prompt-source">;
|
|
60
61
|
text: z.ZodDefault<z.ZodString>;
|
|
61
62
|
label: z.ZodOptional<z.ZodString>;
|
|
63
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
62
64
|
}, z.core.$strip>, z.ZodObject<{
|
|
63
65
|
id: z.ZodString;
|
|
64
66
|
kind: z.ZodLiteral<"image-source">;
|
|
65
67
|
imageUrl: z.ZodDefault<z.ZodString>;
|
|
66
68
|
assetId: z.ZodOptional<z.ZodString>;
|
|
67
69
|
label: z.ZodOptional<z.ZodString>;
|
|
70
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
68
71
|
}, z.core.$strip>, z.ZodObject<{
|
|
69
72
|
id: z.ZodString;
|
|
70
73
|
kind: z.ZodLiteral<"input">;
|
|
@@ -85,6 +88,7 @@ declare const DocNodeSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
85
88
|
default: z.ZodOptional<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>;
|
|
86
89
|
label: z.ZodOptional<z.ZodString>;
|
|
87
90
|
description: z.ZodOptional<z.ZodString>;
|
|
91
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
88
92
|
}, z.core.$strip>], "kind">;
|
|
89
93
|
type DocNode = z.infer<typeof DocNodeSchema>;
|
|
90
94
|
type DocNodeKind = DocNode["kind"];
|
|
@@ -130,17 +134,20 @@ declare const WorkflowDocumentSchema: z.ZodObject<{
|
|
|
130
134
|
}, z.core.$strip>>>;
|
|
131
135
|
activeGeneration: z.ZodOptional<z.ZodString>;
|
|
132
136
|
label: z.ZodOptional<z.ZodString>;
|
|
137
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
133
138
|
}, z.core.$strip>, z.ZodObject<{
|
|
134
139
|
id: z.ZodString;
|
|
135
140
|
kind: z.ZodLiteral<"prompt-source">;
|
|
136
141
|
text: z.ZodDefault<z.ZodString>;
|
|
137
142
|
label: z.ZodOptional<z.ZodString>;
|
|
143
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
138
144
|
}, z.core.$strip>, z.ZodObject<{
|
|
139
145
|
id: z.ZodString;
|
|
140
146
|
kind: z.ZodLiteral<"image-source">;
|
|
141
147
|
imageUrl: z.ZodDefault<z.ZodString>;
|
|
142
148
|
assetId: z.ZodOptional<z.ZodString>;
|
|
143
149
|
label: z.ZodOptional<z.ZodString>;
|
|
150
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
144
151
|
}, z.core.$strip>, z.ZodObject<{
|
|
145
152
|
id: z.ZodString;
|
|
146
153
|
kind: z.ZodLiteral<"input">;
|
|
@@ -161,6 +168,7 @@ declare const WorkflowDocumentSchema: z.ZodObject<{
|
|
|
161
168
|
default: z.ZodOptional<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>;
|
|
162
169
|
label: z.ZodOptional<z.ZodString>;
|
|
163
170
|
description: z.ZodOptional<z.ZodString>;
|
|
171
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
164
172
|
}, z.core.$strip>], "kind">>;
|
|
165
173
|
edges: z.ZodArray<z.ZodObject<{
|
|
166
174
|
source: z.ZodString;
|
|
@@ -184,6 +192,26 @@ declare const WorkflowDocumentSchema: z.ZodObject<{
|
|
|
184
192
|
label: z.ZodOptional<z.ZodString>;
|
|
185
193
|
nodeIds: z.ZodArray<z.ZodString>;
|
|
186
194
|
}, z.core.$strip>>>;
|
|
195
|
+
view: z.ZodOptional<z.ZodObject<{
|
|
196
|
+
edgeRouting: z.ZodOptional<z.ZodEnum<{
|
|
197
|
+
curved: "curved";
|
|
198
|
+
orthogonal: "orthogonal";
|
|
199
|
+
}>>;
|
|
200
|
+
wires: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
201
|
+
from: z.ZodObject<{
|
|
202
|
+
x: z.ZodNumber;
|
|
203
|
+
y: z.ZodNumber;
|
|
204
|
+
}, z.core.$strip>;
|
|
205
|
+
to: z.ZodObject<{
|
|
206
|
+
x: z.ZodNumber;
|
|
207
|
+
y: z.ZodNumber;
|
|
208
|
+
}, z.core.$strip>;
|
|
209
|
+
points: z.ZodArray<z.ZodObject<{
|
|
210
|
+
x: z.ZodNumber;
|
|
211
|
+
y: z.ZodNumber;
|
|
212
|
+
}, z.core.$strip>>;
|
|
213
|
+
}, z.core.$strip>>>;
|
|
214
|
+
}, z.core.$strip>>;
|
|
187
215
|
}, z.core.$strip>;
|
|
188
216
|
type WorkflowDocument = z.infer<typeof WorkflowDocumentSchema>;
|
|
189
217
|
declare const OpSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -226,17 +254,20 @@ declare const OpSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
226
254
|
}, z.core.$strip>>>;
|
|
227
255
|
activeGeneration: z.ZodOptional<z.ZodString>;
|
|
228
256
|
label: z.ZodOptional<z.ZodString>;
|
|
257
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
229
258
|
}, z.core.$strip>, z.ZodObject<{
|
|
230
259
|
id: z.ZodString;
|
|
231
260
|
kind: z.ZodLiteral<"prompt-source">;
|
|
232
261
|
text: z.ZodDefault<z.ZodString>;
|
|
233
262
|
label: z.ZodOptional<z.ZodString>;
|
|
263
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
234
264
|
}, z.core.$strip>, z.ZodObject<{
|
|
235
265
|
id: z.ZodString;
|
|
236
266
|
kind: z.ZodLiteral<"image-source">;
|
|
237
267
|
imageUrl: z.ZodDefault<z.ZodString>;
|
|
238
268
|
assetId: z.ZodOptional<z.ZodString>;
|
|
239
269
|
label: z.ZodOptional<z.ZodString>;
|
|
270
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
240
271
|
}, z.core.$strip>, z.ZodObject<{
|
|
241
272
|
id: z.ZodString;
|
|
242
273
|
kind: z.ZodLiteral<"input">;
|
|
@@ -257,6 +288,7 @@ declare const OpSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
257
288
|
default: z.ZodOptional<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>;
|
|
258
289
|
label: z.ZodOptional<z.ZodString>;
|
|
259
290
|
description: z.ZodOptional<z.ZodString>;
|
|
291
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
260
292
|
}, z.core.$strip>], "kind">;
|
|
261
293
|
position: z.ZodOptional<z.ZodObject<{
|
|
262
294
|
x: z.ZodNumber;
|
|
@@ -300,6 +332,7 @@ declare const OpSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
300
332
|
model: z.ZodOptional<z.ZodString>;
|
|
301
333
|
prompt: z.ZodOptional<z.ZodString>;
|
|
302
334
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
335
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
303
336
|
}, z.core.$strict>;
|
|
304
337
|
}, z.core.$strip>, z.ZodObject<{
|
|
305
338
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -308,6 +341,7 @@ declare const OpSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
308
341
|
props: z.ZodObject<{
|
|
309
342
|
text: z.ZodOptional<z.ZodString>;
|
|
310
343
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
344
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
311
345
|
}, z.core.$strict>;
|
|
312
346
|
}, z.core.$strip>, z.ZodObject<{
|
|
313
347
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -317,6 +351,7 @@ declare const OpSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
317
351
|
imageUrl: z.ZodOptional<z.ZodString>;
|
|
318
352
|
assetId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
319
353
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
354
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
320
355
|
}, z.core.$strict>;
|
|
321
356
|
}, z.core.$strip>, z.ZodObject<{
|
|
322
357
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -340,6 +375,7 @@ declare const OpSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
340
375
|
default: z.ZodOptional<z.ZodNullable<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>>;
|
|
341
376
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
342
377
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
378
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
343
379
|
}, z.core.$strict>;
|
|
344
380
|
}, z.core.$strip>], "kind">, z.ZodObject<{
|
|
345
381
|
type: z.ZodLiteral<"setNodeSetting">;
|
|
@@ -426,6 +462,26 @@ declare const OpSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
|
426
462
|
type: z.ZodLiteral<"setDocumentProps">;
|
|
427
463
|
props: z.ZodObject<{
|
|
428
464
|
label: z.ZodOptional<z.ZodString>;
|
|
465
|
+
view: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
466
|
+
edgeRouting: z.ZodOptional<z.ZodEnum<{
|
|
467
|
+
curved: "curved";
|
|
468
|
+
orthogonal: "orthogonal";
|
|
469
|
+
}>>;
|
|
470
|
+
wires: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
471
|
+
from: z.ZodObject<{
|
|
472
|
+
x: z.ZodNumber;
|
|
473
|
+
y: z.ZodNumber;
|
|
474
|
+
}, z.core.$strip>;
|
|
475
|
+
to: z.ZodObject<{
|
|
476
|
+
x: z.ZodNumber;
|
|
477
|
+
y: z.ZodNumber;
|
|
478
|
+
}, z.core.$strip>;
|
|
479
|
+
points: z.ZodArray<z.ZodObject<{
|
|
480
|
+
x: z.ZodNumber;
|
|
481
|
+
y: z.ZodNumber;
|
|
482
|
+
}, z.core.$strip>>;
|
|
483
|
+
}, z.core.$strip>>>;
|
|
484
|
+
}, z.core.$strict>>>;
|
|
429
485
|
}, z.core.$strict>;
|
|
430
486
|
}, z.core.$strip>], "type">;
|
|
431
487
|
type Op = z.infer<typeof OpSchema>;
|
|
@@ -473,17 +529,20 @@ declare const PatchSchema: z.ZodObject<{
|
|
|
473
529
|
}, z.core.$strip>>>;
|
|
474
530
|
activeGeneration: z.ZodOptional<z.ZodString>;
|
|
475
531
|
label: z.ZodOptional<z.ZodString>;
|
|
532
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
476
533
|
}, z.core.$strip>, z.ZodObject<{
|
|
477
534
|
id: z.ZodString;
|
|
478
535
|
kind: z.ZodLiteral<"prompt-source">;
|
|
479
536
|
text: z.ZodDefault<z.ZodString>;
|
|
480
537
|
label: z.ZodOptional<z.ZodString>;
|
|
538
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
481
539
|
}, z.core.$strip>, z.ZodObject<{
|
|
482
540
|
id: z.ZodString;
|
|
483
541
|
kind: z.ZodLiteral<"image-source">;
|
|
484
542
|
imageUrl: z.ZodDefault<z.ZodString>;
|
|
485
543
|
assetId: z.ZodOptional<z.ZodString>;
|
|
486
544
|
label: z.ZodOptional<z.ZodString>;
|
|
545
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
487
546
|
}, z.core.$strip>, z.ZodObject<{
|
|
488
547
|
id: z.ZodString;
|
|
489
548
|
kind: z.ZodLiteral<"input">;
|
|
@@ -504,6 +563,7 @@ declare const PatchSchema: z.ZodObject<{
|
|
|
504
563
|
default: z.ZodOptional<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>;
|
|
505
564
|
label: z.ZodOptional<z.ZodString>;
|
|
506
565
|
description: z.ZodOptional<z.ZodString>;
|
|
566
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
507
567
|
}, z.core.$strip>], "kind">;
|
|
508
568
|
position: z.ZodOptional<z.ZodObject<{
|
|
509
569
|
x: z.ZodNumber;
|
|
@@ -547,6 +607,7 @@ declare const PatchSchema: z.ZodObject<{
|
|
|
547
607
|
model: z.ZodOptional<z.ZodString>;
|
|
548
608
|
prompt: z.ZodOptional<z.ZodString>;
|
|
549
609
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
610
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
550
611
|
}, z.core.$strict>;
|
|
551
612
|
}, z.core.$strip>, z.ZodObject<{
|
|
552
613
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -555,6 +616,7 @@ declare const PatchSchema: z.ZodObject<{
|
|
|
555
616
|
props: z.ZodObject<{
|
|
556
617
|
text: z.ZodOptional<z.ZodString>;
|
|
557
618
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
619
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
558
620
|
}, z.core.$strict>;
|
|
559
621
|
}, z.core.$strip>, z.ZodObject<{
|
|
560
622
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -564,6 +626,7 @@ declare const PatchSchema: z.ZodObject<{
|
|
|
564
626
|
imageUrl: z.ZodOptional<z.ZodString>;
|
|
565
627
|
assetId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
566
628
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
629
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
567
630
|
}, z.core.$strict>;
|
|
568
631
|
}, z.core.$strip>, z.ZodObject<{
|
|
569
632
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -587,6 +650,7 @@ declare const PatchSchema: z.ZodObject<{
|
|
|
587
650
|
default: z.ZodOptional<z.ZodNullable<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>>;
|
|
588
651
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
589
652
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
653
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
590
654
|
}, z.core.$strict>;
|
|
591
655
|
}, z.core.$strip>], "kind">, z.ZodObject<{
|
|
592
656
|
type: z.ZodLiteral<"setNodeSetting">;
|
|
@@ -673,6 +737,26 @@ declare const PatchSchema: z.ZodObject<{
|
|
|
673
737
|
type: z.ZodLiteral<"setDocumentProps">;
|
|
674
738
|
props: z.ZodObject<{
|
|
675
739
|
label: z.ZodOptional<z.ZodString>;
|
|
740
|
+
view: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
741
|
+
edgeRouting: z.ZodOptional<z.ZodEnum<{
|
|
742
|
+
curved: "curved";
|
|
743
|
+
orthogonal: "orthogonal";
|
|
744
|
+
}>>;
|
|
745
|
+
wires: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
746
|
+
from: z.ZodObject<{
|
|
747
|
+
x: z.ZodNumber;
|
|
748
|
+
y: z.ZodNumber;
|
|
749
|
+
}, z.core.$strip>;
|
|
750
|
+
to: z.ZodObject<{
|
|
751
|
+
x: z.ZodNumber;
|
|
752
|
+
y: z.ZodNumber;
|
|
753
|
+
}, z.core.$strip>;
|
|
754
|
+
points: z.ZodArray<z.ZodObject<{
|
|
755
|
+
x: z.ZodNumber;
|
|
756
|
+
y: z.ZodNumber;
|
|
757
|
+
}, z.core.$strip>>;
|
|
758
|
+
}, z.core.$strip>>>;
|
|
759
|
+
}, z.core.$strict>>>;
|
|
676
760
|
}, z.core.$strict>;
|
|
677
761
|
}, z.core.$strip>], "type">>;
|
|
678
762
|
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
@@ -801,7 +885,7 @@ interface CharacterReference {
|
|
|
801
885
|
}
|
|
802
886
|
/** `awaiting_decision` (P3 J2) is a run PARKED on a human decision at a judge
|
|
803
887
|
* node: not terminal, not a failure, and polling will never clear it. */
|
|
804
|
-
type RunStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'partial' | 'awaiting_decision' | (string & {});
|
|
888
|
+
type RunStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'partial' | 'awaiting_decision' | 'cancelled' | (string & {});
|
|
805
889
|
type NodeStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'awaiting_decision' | (string & {});
|
|
806
890
|
/** One candidate a parked judge node is waiting on a decision about. The url
|
|
807
891
|
* is signed per response; `generationId` is what a decision names. */
|
|
@@ -816,6 +900,8 @@ interface JudgeCandidate {
|
|
|
816
900
|
}
|
|
817
901
|
interface NodeRun {
|
|
818
902
|
nodeId: string;
|
|
903
|
+
/** The node-run (generation) id; pinnable via `upstreamGenerations`. */
|
|
904
|
+
id?: string;
|
|
819
905
|
status: NodeStatus;
|
|
820
906
|
jobId?: string | null;
|
|
821
907
|
resultUrl?: string | null;
|
|
@@ -1109,6 +1195,7 @@ declare class StudioClient {
|
|
|
1109
1195
|
definitionId?: string;
|
|
1110
1196
|
params?: Record<string, unknown>;
|
|
1111
1197
|
nodeIds?: string[];
|
|
1198
|
+
upstreamGenerations?: Record<string, string>;
|
|
1112
1199
|
runs?: number;
|
|
1113
1200
|
savedId?: string;
|
|
1114
1201
|
visibility?: 'listed' | 'unlisted';
|
|
@@ -1136,7 +1223,9 @@ declare class StudioClient {
|
|
|
1136
1223
|
getRunNodeUrl(runId: string, nodeId: string): Promise<NodeResultResponse>;
|
|
1137
1224
|
/** S9: a rendered diagram of a saved workflow's document, so an agent can
|
|
1138
1225
|
* see the graph it just built. */
|
|
1139
|
-
getWorkflowScreenshot(savedId: string
|
|
1226
|
+
getWorkflowScreenshot(savedId: string, opts?: {
|
|
1227
|
+
projectId?: string;
|
|
1228
|
+
}): Promise<{
|
|
1140
1229
|
url: string;
|
|
1141
1230
|
width: number;
|
|
1142
1231
|
height: number;
|
|
@@ -1185,8 +1274,11 @@ declare class StudioClient {
|
|
|
1185
1274
|
savedId?: string;
|
|
1186
1275
|
}): Promise<Record<string, unknown>>;
|
|
1187
1276
|
describeNodeTypes(): Promise<NodeTypesResponse>;
|
|
1188
|
-
/** `savedId` carries a `saved:` prefix; the colon is URL-encoded.
|
|
1189
|
-
|
|
1277
|
+
/** `savedId` carries a `saved:` prefix; the colon is URL-encoded. `projectId`
|
|
1278
|
+
* names the project the workflow lives in; absent, the Studio's default. */
|
|
1279
|
+
getWorkflowDocument(savedId: string, opts?: {
|
|
1280
|
+
projectId?: string;
|
|
1281
|
+
}): Promise<WorkflowDocumentResponse>;
|
|
1190
1282
|
/** Create a document by applying `ops` to an empty one (the same code path as apply). */
|
|
1191
1283
|
createWorkflow(body: {
|
|
1192
1284
|
ops: Op[];
|
|
@@ -1200,6 +1292,7 @@ declare class StudioClient {
|
|
|
1200
1292
|
*/
|
|
1201
1293
|
applyWorkflowPatch(savedId: string, patch: Patch & {
|
|
1202
1294
|
acknowledgeLossy?: boolean;
|
|
1295
|
+
projectId?: string;
|
|
1203
1296
|
}): Promise<WorkflowApplyResponse>;
|
|
1204
1297
|
/** Stateless dry-run of ops and run params against a document. No side effects. */
|
|
1205
1298
|
validateWorkflow(body: {
|
|
@@ -1311,7 +1404,7 @@ declare function registerTools(server: McpServer, ctx: ToolContext): void;
|
|
|
1311
1404
|
*/
|
|
1312
1405
|
|
|
1313
1406
|
declare const SERVER_NAME = "lumitra-studio";
|
|
1314
|
-
declare const SERVER_VERSION = "0.1.
|
|
1407
|
+
declare const SERVER_VERSION = "0.1.1";
|
|
1315
1408
|
interface CreateServerOptions {
|
|
1316
1409
|
config?: StudioConfig;
|
|
1317
1410
|
env?: NodeJS.ProcessEnv;
|
|
@@ -1360,6 +1453,7 @@ declare const studioWorkflowDescribe: ToolDef<{
|
|
|
1360
1453
|
}>;
|
|
1361
1454
|
declare const studioWorkflowGet: ToolDef<{
|
|
1362
1455
|
savedId: z.ZodString;
|
|
1456
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
1363
1457
|
full: z.ZodDefault<z.ZodBoolean>;
|
|
1364
1458
|
}>;
|
|
1365
1459
|
declare const studioWorkflowCreate: ToolDef<{
|
|
@@ -1403,17 +1497,20 @@ declare const studioWorkflowCreate: ToolDef<{
|
|
|
1403
1497
|
}, z.core.$strip>>>;
|
|
1404
1498
|
activeGeneration: z.ZodOptional<z.ZodString>;
|
|
1405
1499
|
label: z.ZodOptional<z.ZodString>;
|
|
1500
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1406
1501
|
}, z.core.$strip>, z.ZodObject<{
|
|
1407
1502
|
id: z.ZodString;
|
|
1408
1503
|
kind: z.ZodLiteral<"prompt-source">;
|
|
1409
1504
|
text: z.ZodDefault<z.ZodString>;
|
|
1410
1505
|
label: z.ZodOptional<z.ZodString>;
|
|
1506
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1411
1507
|
}, z.core.$strip>, z.ZodObject<{
|
|
1412
1508
|
id: z.ZodString;
|
|
1413
1509
|
kind: z.ZodLiteral<"image-source">;
|
|
1414
1510
|
imageUrl: z.ZodDefault<z.ZodString>;
|
|
1415
1511
|
assetId: z.ZodOptional<z.ZodString>;
|
|
1416
1512
|
label: z.ZodOptional<z.ZodString>;
|
|
1513
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1417
1514
|
}, z.core.$strip>, z.ZodObject<{
|
|
1418
1515
|
id: z.ZodString;
|
|
1419
1516
|
kind: z.ZodLiteral<"input">;
|
|
@@ -1434,6 +1531,7 @@ declare const studioWorkflowCreate: ToolDef<{
|
|
|
1434
1531
|
default: z.ZodOptional<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>;
|
|
1435
1532
|
label: z.ZodOptional<z.ZodString>;
|
|
1436
1533
|
description: z.ZodOptional<z.ZodString>;
|
|
1534
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1437
1535
|
}, z.core.$strip>], "kind">;
|
|
1438
1536
|
position: z.ZodOptional<z.ZodObject<{
|
|
1439
1537
|
x: z.ZodNumber;
|
|
@@ -1477,6 +1575,7 @@ declare const studioWorkflowCreate: ToolDef<{
|
|
|
1477
1575
|
model: z.ZodOptional<z.ZodString>;
|
|
1478
1576
|
prompt: z.ZodOptional<z.ZodString>;
|
|
1479
1577
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1578
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
1480
1579
|
}, z.core.$strict>;
|
|
1481
1580
|
}, z.core.$strip>, z.ZodObject<{
|
|
1482
1581
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -1485,6 +1584,7 @@ declare const studioWorkflowCreate: ToolDef<{
|
|
|
1485
1584
|
props: z.ZodObject<{
|
|
1486
1585
|
text: z.ZodOptional<z.ZodString>;
|
|
1487
1586
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1587
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
1488
1588
|
}, z.core.$strict>;
|
|
1489
1589
|
}, z.core.$strip>, z.ZodObject<{
|
|
1490
1590
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -1494,6 +1594,7 @@ declare const studioWorkflowCreate: ToolDef<{
|
|
|
1494
1594
|
imageUrl: z.ZodOptional<z.ZodString>;
|
|
1495
1595
|
assetId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1496
1596
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1597
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
1497
1598
|
}, z.core.$strict>;
|
|
1498
1599
|
}, z.core.$strip>, z.ZodObject<{
|
|
1499
1600
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -1517,6 +1618,7 @@ declare const studioWorkflowCreate: ToolDef<{
|
|
|
1517
1618
|
default: z.ZodOptional<z.ZodNullable<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>>;
|
|
1518
1619
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1519
1620
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1621
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
1520
1622
|
}, z.core.$strict>;
|
|
1521
1623
|
}, z.core.$strip>], "kind">, z.ZodObject<{
|
|
1522
1624
|
type: z.ZodLiteral<"setNodeSetting">;
|
|
@@ -1603,6 +1705,26 @@ declare const studioWorkflowCreate: ToolDef<{
|
|
|
1603
1705
|
type: z.ZodLiteral<"setDocumentProps">;
|
|
1604
1706
|
props: z.ZodObject<{
|
|
1605
1707
|
label: z.ZodOptional<z.ZodString>;
|
|
1708
|
+
view: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
1709
|
+
edgeRouting: z.ZodOptional<z.ZodEnum<{
|
|
1710
|
+
curved: "curved";
|
|
1711
|
+
orthogonal: "orthogonal";
|
|
1712
|
+
}>>;
|
|
1713
|
+
wires: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
1714
|
+
from: z.ZodObject<{
|
|
1715
|
+
x: z.ZodNumber;
|
|
1716
|
+
y: z.ZodNumber;
|
|
1717
|
+
}, z.core.$strip>;
|
|
1718
|
+
to: z.ZodObject<{
|
|
1719
|
+
x: z.ZodNumber;
|
|
1720
|
+
y: z.ZodNumber;
|
|
1721
|
+
}, z.core.$strip>;
|
|
1722
|
+
points: z.ZodArray<z.ZodObject<{
|
|
1723
|
+
x: z.ZodNumber;
|
|
1724
|
+
y: z.ZodNumber;
|
|
1725
|
+
}, z.core.$strip>>;
|
|
1726
|
+
}, z.core.$strip>>>;
|
|
1727
|
+
}, z.core.$strict>>>;
|
|
1606
1728
|
}, z.core.$strict>;
|
|
1607
1729
|
}, z.core.$strip>], "type">>;
|
|
1608
1730
|
label: z.ZodOptional<z.ZodString>;
|
|
@@ -1610,6 +1732,7 @@ declare const studioWorkflowCreate: ToolDef<{
|
|
|
1610
1732
|
}>;
|
|
1611
1733
|
declare const studioWorkflowApply: ToolDef<{
|
|
1612
1734
|
savedId: z.ZodString;
|
|
1735
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
1613
1736
|
baseRevision: z.ZodNumber;
|
|
1614
1737
|
ops: z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1615
1738
|
type: z.ZodLiteral<"addNode">;
|
|
@@ -1651,17 +1774,20 @@ declare const studioWorkflowApply: ToolDef<{
|
|
|
1651
1774
|
}, z.core.$strip>>>;
|
|
1652
1775
|
activeGeneration: z.ZodOptional<z.ZodString>;
|
|
1653
1776
|
label: z.ZodOptional<z.ZodString>;
|
|
1777
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1654
1778
|
}, z.core.$strip>, z.ZodObject<{
|
|
1655
1779
|
id: z.ZodString;
|
|
1656
1780
|
kind: z.ZodLiteral<"prompt-source">;
|
|
1657
1781
|
text: z.ZodDefault<z.ZodString>;
|
|
1658
1782
|
label: z.ZodOptional<z.ZodString>;
|
|
1783
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1659
1784
|
}, z.core.$strip>, z.ZodObject<{
|
|
1660
1785
|
id: z.ZodString;
|
|
1661
1786
|
kind: z.ZodLiteral<"image-source">;
|
|
1662
1787
|
imageUrl: z.ZodDefault<z.ZodString>;
|
|
1663
1788
|
assetId: z.ZodOptional<z.ZodString>;
|
|
1664
1789
|
label: z.ZodOptional<z.ZodString>;
|
|
1790
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1665
1791
|
}, z.core.$strip>, z.ZodObject<{
|
|
1666
1792
|
id: z.ZodString;
|
|
1667
1793
|
kind: z.ZodLiteral<"input">;
|
|
@@ -1682,6 +1808,7 @@ declare const studioWorkflowApply: ToolDef<{
|
|
|
1682
1808
|
default: z.ZodOptional<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>;
|
|
1683
1809
|
label: z.ZodOptional<z.ZodString>;
|
|
1684
1810
|
description: z.ZodOptional<z.ZodString>;
|
|
1811
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1685
1812
|
}, z.core.$strip>], "kind">;
|
|
1686
1813
|
position: z.ZodOptional<z.ZodObject<{
|
|
1687
1814
|
x: z.ZodNumber;
|
|
@@ -1725,6 +1852,7 @@ declare const studioWorkflowApply: ToolDef<{
|
|
|
1725
1852
|
model: z.ZodOptional<z.ZodString>;
|
|
1726
1853
|
prompt: z.ZodOptional<z.ZodString>;
|
|
1727
1854
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1855
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
1728
1856
|
}, z.core.$strict>;
|
|
1729
1857
|
}, z.core.$strip>, z.ZodObject<{
|
|
1730
1858
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -1733,6 +1861,7 @@ declare const studioWorkflowApply: ToolDef<{
|
|
|
1733
1861
|
props: z.ZodObject<{
|
|
1734
1862
|
text: z.ZodOptional<z.ZodString>;
|
|
1735
1863
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1864
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
1736
1865
|
}, z.core.$strict>;
|
|
1737
1866
|
}, z.core.$strip>, z.ZodObject<{
|
|
1738
1867
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -1742,6 +1871,7 @@ declare const studioWorkflowApply: ToolDef<{
|
|
|
1742
1871
|
imageUrl: z.ZodOptional<z.ZodString>;
|
|
1743
1872
|
assetId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1744
1873
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1874
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
1745
1875
|
}, z.core.$strict>;
|
|
1746
1876
|
}, z.core.$strip>, z.ZodObject<{
|
|
1747
1877
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -1765,6 +1895,7 @@ declare const studioWorkflowApply: ToolDef<{
|
|
|
1765
1895
|
default: z.ZodOptional<z.ZodNullable<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>>;
|
|
1766
1896
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1767
1897
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
1898
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
1768
1899
|
}, z.core.$strict>;
|
|
1769
1900
|
}, z.core.$strip>], "kind">, z.ZodObject<{
|
|
1770
1901
|
type: z.ZodLiteral<"setNodeSetting">;
|
|
@@ -1851,6 +1982,26 @@ declare const studioWorkflowApply: ToolDef<{
|
|
|
1851
1982
|
type: z.ZodLiteral<"setDocumentProps">;
|
|
1852
1983
|
props: z.ZodObject<{
|
|
1853
1984
|
label: z.ZodOptional<z.ZodString>;
|
|
1985
|
+
view: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
1986
|
+
edgeRouting: z.ZodOptional<z.ZodEnum<{
|
|
1987
|
+
curved: "curved";
|
|
1988
|
+
orthogonal: "orthogonal";
|
|
1989
|
+
}>>;
|
|
1990
|
+
wires: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
1991
|
+
from: z.ZodObject<{
|
|
1992
|
+
x: z.ZodNumber;
|
|
1993
|
+
y: z.ZodNumber;
|
|
1994
|
+
}, z.core.$strip>;
|
|
1995
|
+
to: z.ZodObject<{
|
|
1996
|
+
x: z.ZodNumber;
|
|
1997
|
+
y: z.ZodNumber;
|
|
1998
|
+
}, z.core.$strip>;
|
|
1999
|
+
points: z.ZodArray<z.ZodObject<{
|
|
2000
|
+
x: z.ZodNumber;
|
|
2001
|
+
y: z.ZodNumber;
|
|
2002
|
+
}, z.core.$strip>>;
|
|
2003
|
+
}, z.core.$strip>>>;
|
|
2004
|
+
}, z.core.$strict>>>;
|
|
1854
2005
|
}, z.core.$strict>;
|
|
1855
2006
|
}, z.core.$strip>], "type">>;
|
|
1856
2007
|
idempotencyKey: z.ZodOptional<z.ZodString>;
|
|
@@ -1899,17 +2050,20 @@ declare const studioWorkflowValidate: ToolDef<{
|
|
|
1899
2050
|
}, z.core.$strip>>>;
|
|
1900
2051
|
activeGeneration: z.ZodOptional<z.ZodString>;
|
|
1901
2052
|
label: z.ZodOptional<z.ZodString>;
|
|
2053
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1902
2054
|
}, z.core.$strip>, z.ZodObject<{
|
|
1903
2055
|
id: z.ZodString;
|
|
1904
2056
|
kind: z.ZodLiteral<"prompt-source">;
|
|
1905
2057
|
text: z.ZodDefault<z.ZodString>;
|
|
1906
2058
|
label: z.ZodOptional<z.ZodString>;
|
|
2059
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1907
2060
|
}, z.core.$strip>, z.ZodObject<{
|
|
1908
2061
|
id: z.ZodString;
|
|
1909
2062
|
kind: z.ZodLiteral<"image-source">;
|
|
1910
2063
|
imageUrl: z.ZodDefault<z.ZodString>;
|
|
1911
2064
|
assetId: z.ZodOptional<z.ZodString>;
|
|
1912
2065
|
label: z.ZodOptional<z.ZodString>;
|
|
2066
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1913
2067
|
}, z.core.$strip>, z.ZodObject<{
|
|
1914
2068
|
id: z.ZodString;
|
|
1915
2069
|
kind: z.ZodLiteral<"input">;
|
|
@@ -1930,6 +2084,7 @@ declare const studioWorkflowValidate: ToolDef<{
|
|
|
1930
2084
|
default: z.ZodOptional<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>;
|
|
1931
2085
|
label: z.ZodOptional<z.ZodString>;
|
|
1932
2086
|
description: z.ZodOptional<z.ZodString>;
|
|
2087
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1933
2088
|
}, z.core.$strip>], "kind">>;
|
|
1934
2089
|
edges: z.ZodArray<z.ZodObject<{
|
|
1935
2090
|
source: z.ZodString;
|
|
@@ -1953,8 +2108,29 @@ declare const studioWorkflowValidate: ToolDef<{
|
|
|
1953
2108
|
label: z.ZodOptional<z.ZodString>;
|
|
1954
2109
|
nodeIds: z.ZodArray<z.ZodString>;
|
|
1955
2110
|
}, z.core.$strip>>>;
|
|
2111
|
+
view: z.ZodOptional<z.ZodObject<{
|
|
2112
|
+
edgeRouting: z.ZodOptional<z.ZodEnum<{
|
|
2113
|
+
curved: "curved";
|
|
2114
|
+
orthogonal: "orthogonal";
|
|
2115
|
+
}>>;
|
|
2116
|
+
wires: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
2117
|
+
from: z.ZodObject<{
|
|
2118
|
+
x: z.ZodNumber;
|
|
2119
|
+
y: z.ZodNumber;
|
|
2120
|
+
}, z.core.$strip>;
|
|
2121
|
+
to: z.ZodObject<{
|
|
2122
|
+
x: z.ZodNumber;
|
|
2123
|
+
y: z.ZodNumber;
|
|
2124
|
+
}, z.core.$strip>;
|
|
2125
|
+
points: z.ZodArray<z.ZodObject<{
|
|
2126
|
+
x: z.ZodNumber;
|
|
2127
|
+
y: z.ZodNumber;
|
|
2128
|
+
}, z.core.$strip>>;
|
|
2129
|
+
}, z.core.$strip>>>;
|
|
2130
|
+
}, z.core.$strip>>;
|
|
1956
2131
|
}, z.core.$strip>>;
|
|
1957
2132
|
savedId: z.ZodOptional<z.ZodString>;
|
|
2133
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
1958
2134
|
ops: z.ZodOptional<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
1959
2135
|
type: z.ZodLiteral<"addNode">;
|
|
1960
2136
|
node: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
@@ -1995,17 +2171,20 @@ declare const studioWorkflowValidate: ToolDef<{
|
|
|
1995
2171
|
}, z.core.$strip>>>;
|
|
1996
2172
|
activeGeneration: z.ZodOptional<z.ZodString>;
|
|
1997
2173
|
label: z.ZodOptional<z.ZodString>;
|
|
2174
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
1998
2175
|
}, z.core.$strip>, z.ZodObject<{
|
|
1999
2176
|
id: z.ZodString;
|
|
2000
2177
|
kind: z.ZodLiteral<"prompt-source">;
|
|
2001
2178
|
text: z.ZodDefault<z.ZodString>;
|
|
2002
2179
|
label: z.ZodOptional<z.ZodString>;
|
|
2180
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
2003
2181
|
}, z.core.$strip>, z.ZodObject<{
|
|
2004
2182
|
id: z.ZodString;
|
|
2005
2183
|
kind: z.ZodLiteral<"image-source">;
|
|
2006
2184
|
imageUrl: z.ZodDefault<z.ZodString>;
|
|
2007
2185
|
assetId: z.ZodOptional<z.ZodString>;
|
|
2008
2186
|
label: z.ZodOptional<z.ZodString>;
|
|
2187
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
2009
2188
|
}, z.core.$strip>, z.ZodObject<{
|
|
2010
2189
|
id: z.ZodString;
|
|
2011
2190
|
kind: z.ZodLiteral<"input">;
|
|
@@ -2026,6 +2205,7 @@ declare const studioWorkflowValidate: ToolDef<{
|
|
|
2026
2205
|
default: z.ZodOptional<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>;
|
|
2027
2206
|
label: z.ZodOptional<z.ZodString>;
|
|
2028
2207
|
description: z.ZodOptional<z.ZodString>;
|
|
2208
|
+
collapsed: z.ZodOptional<z.ZodBoolean>;
|
|
2029
2209
|
}, z.core.$strip>], "kind">;
|
|
2030
2210
|
position: z.ZodOptional<z.ZodObject<{
|
|
2031
2211
|
x: z.ZodNumber;
|
|
@@ -2069,6 +2249,7 @@ declare const studioWorkflowValidate: ToolDef<{
|
|
|
2069
2249
|
model: z.ZodOptional<z.ZodString>;
|
|
2070
2250
|
prompt: z.ZodOptional<z.ZodString>;
|
|
2071
2251
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2252
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
2072
2253
|
}, z.core.$strict>;
|
|
2073
2254
|
}, z.core.$strip>, z.ZodObject<{
|
|
2074
2255
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -2077,6 +2258,7 @@ declare const studioWorkflowValidate: ToolDef<{
|
|
|
2077
2258
|
props: z.ZodObject<{
|
|
2078
2259
|
text: z.ZodOptional<z.ZodString>;
|
|
2079
2260
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2261
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
2080
2262
|
}, z.core.$strict>;
|
|
2081
2263
|
}, z.core.$strip>, z.ZodObject<{
|
|
2082
2264
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -2086,6 +2268,7 @@ declare const studioWorkflowValidate: ToolDef<{
|
|
|
2086
2268
|
imageUrl: z.ZodOptional<z.ZodString>;
|
|
2087
2269
|
assetId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2088
2270
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2271
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
2089
2272
|
}, z.core.$strict>;
|
|
2090
2273
|
}, z.core.$strip>, z.ZodObject<{
|
|
2091
2274
|
type: z.ZodLiteral<"setNodeProps">;
|
|
@@ -2109,6 +2292,7 @@ declare const studioWorkflowValidate: ToolDef<{
|
|
|
2109
2292
|
default: z.ZodOptional<z.ZodNullable<z.ZodType<JsonNonNullValue, unknown, z.core.$ZodTypeInternals<JsonNonNullValue, unknown>>>>;
|
|
2110
2293
|
label: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2111
2294
|
description: z.ZodOptional<z.ZodNullable<z.ZodString>>;
|
|
2295
|
+
collapsed: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
|
|
2112
2296
|
}, z.core.$strict>;
|
|
2113
2297
|
}, z.core.$strip>], "kind">, z.ZodObject<{
|
|
2114
2298
|
type: z.ZodLiteral<"setNodeSetting">;
|
|
@@ -2195,12 +2379,33 @@ declare const studioWorkflowValidate: ToolDef<{
|
|
|
2195
2379
|
type: z.ZodLiteral<"setDocumentProps">;
|
|
2196
2380
|
props: z.ZodObject<{
|
|
2197
2381
|
label: z.ZodOptional<z.ZodString>;
|
|
2382
|
+
view: z.ZodOptional<z.ZodNullable<z.ZodObject<{
|
|
2383
|
+
edgeRouting: z.ZodOptional<z.ZodEnum<{
|
|
2384
|
+
curved: "curved";
|
|
2385
|
+
orthogonal: "orthogonal";
|
|
2386
|
+
}>>;
|
|
2387
|
+
wires: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
2388
|
+
from: z.ZodObject<{
|
|
2389
|
+
x: z.ZodNumber;
|
|
2390
|
+
y: z.ZodNumber;
|
|
2391
|
+
}, z.core.$strip>;
|
|
2392
|
+
to: z.ZodObject<{
|
|
2393
|
+
x: z.ZodNumber;
|
|
2394
|
+
y: z.ZodNumber;
|
|
2395
|
+
}, z.core.$strip>;
|
|
2396
|
+
points: z.ZodArray<z.ZodObject<{
|
|
2397
|
+
x: z.ZodNumber;
|
|
2398
|
+
y: z.ZodNumber;
|
|
2399
|
+
}, z.core.$strip>>;
|
|
2400
|
+
}, z.core.$strip>>>;
|
|
2401
|
+
}, z.core.$strict>>>;
|
|
2198
2402
|
}, z.core.$strict>;
|
|
2199
2403
|
}, z.core.$strip>], "type">>>;
|
|
2200
2404
|
params: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
2201
2405
|
}>;
|
|
2202
2406
|
declare const studioWorkflowScreenshot: ToolDef<{
|
|
2203
2407
|
savedId: z.ZodString;
|
|
2408
|
+
projectId: z.ZodOptional<z.ZodString>;
|
|
2204
2409
|
}>;
|
|
2205
2410
|
/** The six primitives, in registration order. */
|
|
2206
2411
|
declare const WORKFLOW_TOOLS: readonly ToolDef<z.ZodRawShape>[];
|
package/dist/index.js
CHANGED
|
@@ -162,8 +162,8 @@ var StudioClient = class {
|
|
|
162
162
|
}
|
|
163
163
|
/** S9: a rendered diagram of a saved workflow's document, so an agent can
|
|
164
164
|
* see the graph it just built. */
|
|
165
|
-
getWorkflowScreenshot(savedId2) {
|
|
166
|
-
return this.json("GET", `/api/v1/workflows/${encodeURIComponent(savedId2)}/screenshot`);
|
|
165
|
+
getWorkflowScreenshot(savedId2, opts = {}) {
|
|
166
|
+
return this.json("GET", `/api/v1/workflows/${encodeURIComponent(savedId2)}/screenshot${projectQuery(opts.projectId)}`);
|
|
167
167
|
}
|
|
168
168
|
// ── Recipes (S10): published workflow + closed post-run effect list ──
|
|
169
169
|
publishWorkflow(savedId2, body) {
|
|
@@ -188,9 +188,10 @@ var StudioClient = class {
|
|
|
188
188
|
describeNodeTypes() {
|
|
189
189
|
return this.json("GET", "/api/v1/node-types");
|
|
190
190
|
}
|
|
191
|
-
/** `savedId` carries a `saved:` prefix; the colon is URL-encoded.
|
|
192
|
-
|
|
193
|
-
|
|
191
|
+
/** `savedId` carries a `saved:` prefix; the colon is URL-encoded. `projectId`
|
|
192
|
+
* names the project the workflow lives in; absent, the Studio's default. */
|
|
193
|
+
getWorkflowDocument(savedId2, opts = {}) {
|
|
194
|
+
return this.json("GET", `/api/v1/workflows/${encodeURIComponent(savedId2)}${projectQuery(opts.projectId)}`);
|
|
194
195
|
}
|
|
195
196
|
/** Create a document by applying `ops` to an empty one (the same code path as apply). */
|
|
196
197
|
createWorkflow(body) {
|
|
@@ -361,6 +362,9 @@ function mimeForFilename(name) {
|
|
|
361
362
|
return "application/octet-stream";
|
|
362
363
|
}
|
|
363
364
|
}
|
|
365
|
+
function projectQuery(projectId) {
|
|
366
|
+
return projectId === void 0 ? "" : `?projectId=${encodeURIComponent(projectId)}`;
|
|
367
|
+
}
|
|
364
368
|
|
|
365
369
|
// src/config.ts
|
|
366
370
|
var DEFAULT_BASE_URL = "https://studio.lumitra.co";
|
|
@@ -626,6 +630,7 @@ var AssetIdSchema = z3.string().max(128);
|
|
|
626
630
|
var PortTypeSchema = z3.enum(PORT_TYPES);
|
|
627
631
|
var InputTypeSchema = z3.enum(INPUT_PORT_TYPES);
|
|
628
632
|
var PositionSchema = z3.object({ x: z3.number().finite(), y: z3.number().finite() });
|
|
633
|
+
var CollapsedSchema = z3.boolean();
|
|
629
634
|
var TaskNodeSchema = z3.object({
|
|
630
635
|
id: IdSchema,
|
|
631
636
|
kind: z3.literal("task"),
|
|
@@ -646,13 +651,15 @@ var TaskNodeSchema = z3.object({
|
|
|
646
651
|
bakedInputs: z3.record(KeySchema, LiteralBindingSchema).default({}),
|
|
647
652
|
/** The generation id that feeds downstream. Absent = latest (D4). */
|
|
648
653
|
activeGeneration: IdSchema.optional(),
|
|
649
|
-
label: LabelSchema.optional()
|
|
654
|
+
label: LabelSchema.optional(),
|
|
655
|
+
collapsed: CollapsedSchema.optional()
|
|
650
656
|
});
|
|
651
657
|
var PromptSourceNodeSchema = z3.object({
|
|
652
658
|
id: IdSchema,
|
|
653
659
|
kind: z3.literal("prompt-source"),
|
|
654
660
|
text: PromptTextSchema.default(""),
|
|
655
|
-
label: LabelSchema.optional()
|
|
661
|
+
label: LabelSchema.optional(),
|
|
662
|
+
collapsed: CollapsedSchema.optional()
|
|
656
663
|
});
|
|
657
664
|
var ImageSourceNodeSchema = z3.object({
|
|
658
665
|
id: IdSchema,
|
|
@@ -663,7 +670,8 @@ var ImageSourceNodeSchema = z3.object({
|
|
|
663
670
|
/** The Storage Brain asset id, when known (E18: every image input resolves to
|
|
664
671
|
* an asset id). */
|
|
665
672
|
assetId: AssetIdSchema.optional(),
|
|
666
|
-
label: LabelSchema.optional()
|
|
673
|
+
label: LabelSchema.optional(),
|
|
674
|
+
collapsed: CollapsedSchema.optional()
|
|
667
675
|
});
|
|
668
676
|
var InputNodeSchema = z3.object({
|
|
669
677
|
id: IdSchema,
|
|
@@ -678,7 +686,8 @@ var InputNodeSchema = z3.object({
|
|
|
678
686
|
/** Used when a run omits the input. Never null: absent means no default. */
|
|
679
687
|
default: JsonNonNullValueSchema.optional(),
|
|
680
688
|
label: LabelSchema.optional(),
|
|
681
|
-
description: DescriptionSchema.optional()
|
|
689
|
+
description: DescriptionSchema.optional(),
|
|
690
|
+
collapsed: CollapsedSchema.optional()
|
|
682
691
|
});
|
|
683
692
|
var DocNodeSchema = z3.discriminatedUnion("kind", [
|
|
684
693
|
TaskNodeSchema,
|
|
@@ -696,6 +705,18 @@ var DocGroupSchema = z3.object({
|
|
|
696
705
|
label: LabelSchema.optional(),
|
|
697
706
|
nodeIds: z3.array(IdSchema).min(1)
|
|
698
707
|
});
|
|
708
|
+
var EDGE_ROUTINGS = ["curved", "orthogonal"];
|
|
709
|
+
var EdgeRoutingSchema = z3.enum(EDGE_ROUTINGS);
|
|
710
|
+
var WireRouteSchema = z3.object({
|
|
711
|
+
from: PositionSchema,
|
|
712
|
+
to: PositionSchema,
|
|
713
|
+
points: z3.array(PositionSchema).max(64)
|
|
714
|
+
});
|
|
715
|
+
var DocumentViewSchema = z3.object({
|
|
716
|
+
edgeRouting: EdgeRoutingSchema.optional(),
|
|
717
|
+
/** Routed wires from the last Arrange, keyed by `edgeKey`. */
|
|
718
|
+
wires: z3.record(z3.string().max(512), WireRouteSchema).optional()
|
|
719
|
+
});
|
|
699
720
|
var WorkflowDocumentSchema = z3.object({
|
|
700
721
|
schema: z3.number().int().positive(),
|
|
701
722
|
id: IdSchema,
|
|
@@ -703,7 +724,10 @@ var WorkflowDocumentSchema = z3.object({
|
|
|
703
724
|
nodes: z3.array(DocNodeSchema).max(2e3),
|
|
704
725
|
edges: z3.array(DocEdgeSchema).max(8e3),
|
|
705
726
|
layout: z3.record(IdSchema, PositionSchema).default({}),
|
|
706
|
-
groups: z3.array(DocGroupSchema).max(500).default([])
|
|
727
|
+
groups: z3.array(DocGroupSchema).max(500).default([]),
|
|
728
|
+
/** Display preferences; absent on every document written before they
|
|
729
|
+
* existed (additive, so `DOCUMENT_SCHEMA_VERSION` is unchanged). */
|
|
730
|
+
view: DocumentViewSchema.optional()
|
|
707
731
|
});
|
|
708
732
|
function edgeKey(e) {
|
|
709
733
|
return JSON.stringify([e.source, e.target, e.port]);
|
|
@@ -1472,16 +1496,19 @@ var TaskNodePropsSchema = z4.object({
|
|
|
1472
1496
|
task: z4.enum(MODEL_TASKS),
|
|
1473
1497
|
model: ModelIdSchema,
|
|
1474
1498
|
prompt: PromptTextSchema,
|
|
1475
|
-
label: LabelSchema.nullable()
|
|
1499
|
+
label: LabelSchema.nullable(),
|
|
1500
|
+
collapsed: CollapsedSchema.nullable()
|
|
1476
1501
|
}).partial().strict();
|
|
1477
1502
|
var PromptSourcePropsSchema = z4.object({
|
|
1478
1503
|
text: PromptTextSchema,
|
|
1479
|
-
label: LabelSchema.nullable()
|
|
1504
|
+
label: LabelSchema.nullable(),
|
|
1505
|
+
collapsed: CollapsedSchema.nullable()
|
|
1480
1506
|
}).partial().strict();
|
|
1481
1507
|
var ImageSourcePropsSchema = z4.object({
|
|
1482
1508
|
imageUrl: UrlSchema,
|
|
1483
1509
|
assetId: AssetIdSchema.nullable(),
|
|
1484
|
-
label: LabelSchema.nullable()
|
|
1510
|
+
label: LabelSchema.nullable(),
|
|
1511
|
+
collapsed: CollapsedSchema.nullable()
|
|
1485
1512
|
}).partial().strict();
|
|
1486
1513
|
var InputNodePropsSchema = z4.object({
|
|
1487
1514
|
name: InputNameSchema,
|
|
@@ -1490,14 +1517,19 @@ var InputNodePropsSchema = z4.object({
|
|
|
1490
1517
|
cardinality: z4.enum(["one", "many"]).nullable(),
|
|
1491
1518
|
default: JsonNonNullValueSchema.nullable(),
|
|
1492
1519
|
label: LabelSchema.nullable(),
|
|
1493
|
-
description: DescriptionSchema.nullable()
|
|
1520
|
+
description: DescriptionSchema.nullable(),
|
|
1521
|
+
collapsed: CollapsedSchema.nullable()
|
|
1494
1522
|
}).partial().strict();
|
|
1495
1523
|
var GroupPropsSchema = z4.object({
|
|
1496
1524
|
label: LabelSchema.nullable(),
|
|
1497
1525
|
nodeIds: z4.array(IdSchema).min(1)
|
|
1498
1526
|
}).partial().strict();
|
|
1499
1527
|
var DocumentPropsSchema = z4.object({
|
|
1500
|
-
label: LabelSchema
|
|
1528
|
+
label: LabelSchema,
|
|
1529
|
+
/** Display preferences (`view.edgeRouting`); null clears the whole
|
|
1530
|
+
* object. The object is replaced, not merged: pass every field you want
|
|
1531
|
+
* kept. */
|
|
1532
|
+
view: DocumentViewSchema.strict().nullable()
|
|
1501
1533
|
}).partial().strict();
|
|
1502
1534
|
var AddNodeOpSchema = z4.object({
|
|
1503
1535
|
type: z4.literal("addNode"),
|
|
@@ -2071,7 +2103,7 @@ async function pollUntil(what, fetchState, isDone, opts = {}) {
|
|
|
2071
2103
|
}
|
|
2072
2104
|
}
|
|
2073
2105
|
var TERMINAL_JOB_STATUSES = /* @__PURE__ */ new Set(["succeeded", "failed", "canceled"]);
|
|
2074
|
-
var TERMINAL_RUN_STATUSES = /* @__PURE__ */ new Set(["succeeded", "failed", "partial"]);
|
|
2106
|
+
var TERMINAL_RUN_STATUSES = /* @__PURE__ */ new Set(["succeeded", "failed", "partial", "cancelled"]);
|
|
2075
2107
|
function isJobTerminal(res) {
|
|
2076
2108
|
return TERMINAL_JOB_STATUSES.has(res.job.status);
|
|
2077
2109
|
}
|
|
@@ -2404,11 +2436,12 @@ var studioWorkflowGet = defineTool({
|
|
|
2404
2436
|
description: "Read a saved workflow. By default returns a summary: { savedId, revision, label, readOnly, nodes: [{ id, kind, label?, task?, model?, prompt? (first 80 chars, plus promptLength), imageUrl?, name?, type?, required?, wires: { in, out } }], edgeCount, groupCount, projection: { ok, issues } } where revision is the baseRevision for studio_workflow_apply and projection says whether the workflow can run and why not. A workflow the canvas cannot represent comes back as { readOnly: true, definitionNodeCount, projection, hint } with no nodes: it is readable and runnable (studio_run_workflow with its savedId) but not patchable. needsLossyAcknowledgement: true means its first patch must carry acknowledgeLossy: true. full: true returns the whole response instead; use it only when you need every field.",
|
|
2405
2437
|
inputSchema: {
|
|
2406
2438
|
savedId,
|
|
2439
|
+
projectId: z7.string().min(1).optional().describe("Project id from studio_list_projects the workflow lives in; omit for the default project."),
|
|
2407
2440
|
full: z7.boolean().default(false).describe("Return the whole response (the full document, or the stored definition of a read-only workflow) instead of the summary.")
|
|
2408
2441
|
},
|
|
2409
2442
|
annotations: { readOnlyHint: true },
|
|
2410
2443
|
handler: async (args, ctx) => {
|
|
2411
|
-
const res = await ctx.client.getWorkflowDocument(args.savedId);
|
|
2444
|
+
const res = await ctx.client.getWorkflowDocument(args.savedId, args.projectId !== void 0 ? { projectId: args.projectId } : {});
|
|
2412
2445
|
if (args.full) return res;
|
|
2413
2446
|
if (res.readOnly === true || res.document === null) {
|
|
2414
2447
|
const definition = isRecord(res.definition) ? res.definition : null;
|
|
@@ -2481,6 +2514,7 @@ var studioWorkflowApply = defineTool({
|
|
|
2481
2514
|
description: 'Change a saved workflow atomically: the ops are applied all-or-nothing on top of baseRevision (the revision from studio_workflow_get, studio_workflow_create or your last apply). Success returns { ok: true, savedId, revision, appliedCount, inverseCount, affectedNodes (summaries of the nodes the patch touched, removed ones as { id, removed: true }), projection: { ok, issues }, idempotencyKey, replayed }. Every refusal comes back as { ok: false, code, hint } you can act on rather than an error: "stale_revision" (re-read, rebase your ops, apply again on the revision returned), "invalid_patch" (error.opIndex names the offending op), "forbidden" (opIndex plus the missingScope your credential needs), "not_editable" (this workflow is readable and runnable but cannot be patched), "lossy_import" (read notes, then resend with acknowledgeLossy: true and a NEW idempotencyKey), "idempotency_mismatch" (that key belongs to a different patch: use a fresh one), and "network_error" / "server_error" which you retry with the SAME idempotencyKey so the patch can never apply twice.',
|
|
2482
2515
|
inputSchema: {
|
|
2483
2516
|
savedId,
|
|
2517
|
+
projectId: z7.string().min(1).optional().describe("Project id from studio_list_projects the workflow lives in; omit for the default project."),
|
|
2484
2518
|
baseRevision: PatchSchema.shape.baseRevision.describe("The revision the ops were written against. The Studio refuses a stale one with stale_revision."),
|
|
2485
2519
|
ops: opsSchema,
|
|
2486
2520
|
idempotencyKey: PatchSchema.shape.idempotencyKey.describe(
|
|
@@ -2495,6 +2529,7 @@ var studioWorkflowApply = defineTool({
|
|
|
2495
2529
|
let res;
|
|
2496
2530
|
try {
|
|
2497
2531
|
res = await ctx.client.applyWorkflowPatch(args.savedId, {
|
|
2532
|
+
...args.projectId !== void 0 ? { projectId: args.projectId } : {},
|
|
2498
2533
|
baseRevision: args.baseRevision,
|
|
2499
2534
|
ops: args.ops,
|
|
2500
2535
|
idempotencyKey,
|
|
@@ -2529,16 +2564,18 @@ var studioWorkflowValidate = defineTool({
|
|
|
2529
2564
|
inputSchema: {
|
|
2530
2565
|
document: WorkflowDocumentSchema.optional().describe("The document to validate. Either this or savedId."),
|
|
2531
2566
|
savedId: savedId.optional().describe("Fetch this saved workflow first and validate against its current document. Either this or document, not both."),
|
|
2567
|
+
projectId: z7.string().min(1).optional().describe("Project id from studio_list_projects the saved workflow lives in (only with savedId); omit for the default project."),
|
|
2532
2568
|
ops: PatchSchema.shape.ops.optional().describe("Ops to apply to the document before projecting it (the same vocabulary and limits as studio_workflow_apply)."),
|
|
2533
2569
|
params: paramsSchema.optional()
|
|
2534
2570
|
},
|
|
2535
2571
|
annotations: { readOnlyHint: true },
|
|
2536
2572
|
handler: async (args, ctx) => {
|
|
2537
2573
|
if (args.document && args.savedId) throw new ToolInputError("pass either `document` or `savedId`, not both");
|
|
2574
|
+
if (args.projectId !== void 0 && !args.savedId) throw new ToolInputError("`projectId` only applies when fetching by `savedId`");
|
|
2538
2575
|
let document = args.document;
|
|
2539
2576
|
if (!document) {
|
|
2540
2577
|
if (!args.savedId) throw new ToolInputError("provide a `document` or a `savedId` to validate");
|
|
2541
|
-
const saved = await ctx.client.getWorkflowDocument(args.savedId);
|
|
2578
|
+
const saved = await ctx.client.getWorkflowDocument(args.savedId, args.projectId !== void 0 ? { projectId: args.projectId } : {});
|
|
2542
2579
|
if (saved.readOnly === true || saved.document === null) {
|
|
2543
2580
|
throw new ToolInputError(
|
|
2544
2581
|
`workflow ${args.savedId} has no document to validate: the canvas cannot represent its stored definition (studio_workflow_get shows readOnly: true and why). It is still runnable with studio_run_workflow.`
|
|
@@ -2557,11 +2594,12 @@ var studioWorkflowScreenshot = defineTool({
|
|
|
2557
2594
|
name: "studio_workflow_screenshot",
|
|
2558
2595
|
description: "Render a saved workflow's document as a diagram (labelled boxes and wires, positioned by the document's own layout) so you can see the graph you just built, the Figma get_screenshot equivalent. NOT a pixel-exact preview of the real canvas: a plain diagnostic diagram for checking topology (is everything wired the way I meant, did that addNode land where I expected). Returns { url, width, height }; the url is a signed Storage Brain link, valid for 24h. Free, read-only.",
|
|
2559
2596
|
inputSchema: {
|
|
2560
|
-
savedId
|
|
2597
|
+
savedId,
|
|
2598
|
+
projectId: z7.string().min(1).optional().describe("Project id from studio_list_projects the workflow lives in; omit for the default project.")
|
|
2561
2599
|
},
|
|
2562
2600
|
annotations: { readOnlyHint: true },
|
|
2563
2601
|
handler: async (args, ctx) => {
|
|
2564
|
-
return ctx.client.getWorkflowScreenshot(args.savedId);
|
|
2602
|
+
return ctx.client.getWorkflowScreenshot(args.savedId, args.projectId !== void 0 ? { projectId: args.projectId } : {});
|
|
2565
2603
|
}
|
|
2566
2604
|
});
|
|
2567
2605
|
var WORKFLOW_TOOLS = [
|
|
@@ -2594,6 +2632,8 @@ function projectJob(res) {
|
|
|
2594
2632
|
function projectNodeRun(nr) {
|
|
2595
2633
|
return {
|
|
2596
2634
|
nodeId: nr.nodeId,
|
|
2635
|
+
// The node-run (generation) id: what `upstreamGenerations` pins.
|
|
2636
|
+
id: nr.id ?? null,
|
|
2597
2637
|
status: nr.status,
|
|
2598
2638
|
url: nr.resultUrl ?? nr.results?.[0]?.url ?? null,
|
|
2599
2639
|
kind: nr.results?.[0]?.kind ?? null,
|
|
@@ -2851,13 +2891,16 @@ var workflowDefinitionSchema = WorkflowDefinitionSchema.describe(
|
|
|
2851
2891
|
);
|
|
2852
2892
|
var studioRunWorkflow = defineTool({
|
|
2853
2893
|
name: "studio_run_workflow",
|
|
2854
|
-
description: `Run a generation workflow DAG. Pass an inline definition (nodes of provider calls wired by ref bindings; this is what the hosted Studio accepts) or the savedId of a workflow saved in the Studio (the Studio runs that workflow's current document, exactly what the canvas would run). Params fill {kind:"param"} bindings. Returns the runId plus per-node status, URLs and cost; with wait=true (default) it blocks until the run is terminal (succeeded, failed, partial). Each node becomes a paid job.`,
|
|
2894
|
+
description: `Run a generation workflow DAG. Pass an inline definition (nodes of provider calls wired by ref bindings; this is what the hosted Studio accepts) or the savedId of a workflow saved in the Studio (the Studio runs that workflow's current document, exactly what the canvas would run). Params fill {kind:"param"} bindings. Returns the runId plus per-node status, URLs and cost; with wait=true (default) it blocks until the run is terminal (succeeded, failed, partial, cancelled). Each node becomes a paid job. Use an inline definition ONLY for the first batch of a new deliverable (one workflow, a node per item, a stable label); a follow-up on an existing item belongs in that saved workflow as a new node (studio_workflow_apply: addNode plus connect from the node it refines) run here with savedId and nodeIds, because every listed inline run is saved as its own workflow.`,
|
|
2855
2895
|
inputSchema: {
|
|
2856
2896
|
projectId: z8.string().min(1).describe("Project id from studio_list_projects."),
|
|
2857
2897
|
definition: workflowDefinitionSchema.optional(),
|
|
2858
2898
|
savedId: z8.string().optional().describe("Id of a saved workflow (from studio_workflow_create, studio_workflow_get or a listed run) to run instead of an inline definition. An unknown id is a 404 naming it; a workflow that is not runnable yet comes back as not_runnable with per-node issues."),
|
|
2859
2899
|
params: z8.record(z8.string(), z8.unknown()).optional().describe("Values for the definition's params."),
|
|
2860
2900
|
nodeIds: z8.array(z8.string()).optional().describe("Run only this subset of nodes (requires an inline `definition` or a `savedId`)."),
|
|
2901
|
+
upstreamGenerations: z8.record(z8.string(), z8.string()).optional().describe(
|
|
2902
|
+
'Pin WHICH generation of an upstream node feeds this subset run: { "<upstream node id>": "<node-run id>" } (the per-node `id` that studio_get_run returns). A verified pin is reused even when the planner has no matching cache key for it (an inline first batch, or a node edited and reverted), so a follow-up node wired from an earlier generation runs against exactly that image. An unknown id is refused naming the node, never silently replaced by the latest.'
|
|
2903
|
+
),
|
|
2861
2904
|
runs: z8.number().int().min(1).max(8).optional().describe("Repeat a node subset N times (1 to 8)."),
|
|
2862
2905
|
visibility: z8.enum(["listed", "unlisted"]).optional().describe("Whether the run shows in the Studio workflow list."),
|
|
2863
2906
|
budgetUsd: z8.number().nonnegative().optional().describe(
|
|
@@ -2881,6 +2924,7 @@ var studioRunWorkflow = defineTool({
|
|
|
2881
2924
|
...args.definition ? { definition: args.definition } : {},
|
|
2882
2925
|
...args.params ? { params: args.params } : {},
|
|
2883
2926
|
...args.nodeIds && args.nodeIds.length > 0 ? { nodeIds: args.nodeIds } : {},
|
|
2927
|
+
...args.upstreamGenerations ? { upstreamGenerations: args.upstreamGenerations } : {},
|
|
2884
2928
|
...args.runs !== void 0 ? { runs: args.runs } : {},
|
|
2885
2929
|
...args.savedId ? { savedId: args.savedId } : {},
|
|
2886
2930
|
...args.visibility ? { visibility: args.visibility } : {},
|
|
@@ -2894,7 +2938,7 @@ var studioRunWorkflow = defineTool({
|
|
|
2894
2938
|
});
|
|
2895
2939
|
var studioGetRun = defineTool({
|
|
2896
2940
|
name: "studio_get_run",
|
|
2897
|
-
description: "Fetch a workflow run by runId: overall status (pending, running, succeeded, failed, partial, awaiting_decision), total cost, and per-node status, result URL, cost and error message. Set wait=true to block until the run settles. A run at awaiting_decision is parked on a person at a judge node: waiting returns immediately with a `waiting` block naming the node and its candidates, because polling can never clear it; ask the user to choose and submit their answer with studio_decide_judge.",
|
|
2941
|
+
description: "Fetch a workflow run by runId: overall status (pending, running, succeeded, failed, partial, awaiting_decision, cancelled; cancelled means somebody stopped it), total cost, and per-node status, result URL, cost and error message. Set wait=true to block until the run settles. A run at awaiting_decision is parked on a person at a judge node: waiting returns immediately with a `waiting` block naming the node and its candidates, because polling can never clear it; ask the user to choose and submit their answer with studio_decide_judge.",
|
|
2898
2942
|
inputSchema: {
|
|
2899
2943
|
runId: z8.string().min(1),
|
|
2900
2944
|
wait: z8.boolean().default(false),
|
|
@@ -3141,7 +3185,7 @@ function registerTools(server, ctx) {
|
|
|
3141
3185
|
|
|
3142
3186
|
// src/server.ts
|
|
3143
3187
|
var SERVER_NAME = "lumitra-studio";
|
|
3144
|
-
var SERVER_VERSION = "0.1.
|
|
3188
|
+
var SERVER_VERSION = "0.1.1";
|
|
3145
3189
|
function createStudioMcpServer(opts = {}) {
|
|
3146
3190
|
const config = opts.config ?? resolveConfig(opts.env ?? process.env);
|
|
3147
3191
|
const client = new StudioClient(config, {
|
|
@@ -3155,7 +3199,8 @@ function createStudioMcpServer(opts = {}) {
|
|
|
3155
3199
|
"Lumitra Studio: brand-consistent image generation, character minting, workflow runs and the still-swap video recipe over the hosted Studio API.",
|
|
3156
3200
|
"Start with studio_list_projects to get a projectId. Every generation costs real money (roughly $0.04 per image, $0.30 per character mint, $0.70 per video take); check studio_get_spend when in doubt.",
|
|
3157
3201
|
"Long jobs: tools wait by default (up to timeoutSeconds, 600 by default) and return ids you can poll with studio_get_job / studio_get_run if they time out.",
|
|
3158
|
-
"Authoring a workflow is free and revisioned: studio_workflow_describe for the vocabulary, studio_workflow_create to build one from ops, studio_workflow_apply to change it on top of a baseRevision (a stale_revision result means re-read, rebase, retry), studio_workflow_validate to dry-run before spending, then studio_run_workflow with its savedId."
|
|
3202
|
+
"Authoring a workflow is free and revisioned: studio_workflow_describe for the vocabulary, studio_workflow_create to build one from ops, studio_workflow_apply to change it on top of a baseRevision (a stale_revision result means re-read, rebase, retry), studio_workflow_validate to dry-run before spending, then studio_run_workflow with its savedId.",
|
|
3203
|
+
"Workflow hygiene: one deliverable is ONE saved workflow with a node per item, and a refinement of an item (edit, upscale, variation) is a NEW NODE appended to that workflow with studio_workflow_apply (addNode plus a connect from the node it refines, so the earlier generation is its input), then studio_run_workflow with savedId and nodeIds limited to the new node. Never send a fresh inline definition for a follow-up: every listed inline run is saved as its own workflow, which scatters one deliverable across duplicates."
|
|
3159
3204
|
].join(" ")
|
|
3160
3205
|
}
|
|
3161
3206
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@marlinjai/studio-mcp",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Model Context Protocol (MCP) server over the Lumitra Studio HTTP API: generate images, mint characters, run workflows, swap characters into video.",
|
|
6
6
|
"license": "MIT",
|