Repository navigation
Conversation
…, and say so when the file is missing
… no empty strip below it
MyPrototypeWhat
left a comment
There was a problem hiding this comment.
Reviewed at abc8ea9.
Thanks for this. The latest update (hiding the toolbar and footer on video cards via cardChrome in miniapp/client/forms.mjs, with a test) looks good and doesn't touch the points below. The connector is used only through context.hostConnector, nothing reads login credentials or other plugins' data, agent approvals resolve only when the user clicks, and ffmpeg is spawned with an argument array and shell: false (miniapp/node/ffmpeg.mjs:136). A few things need to change before merge.
Must fix
-
A save name of
..escapes the Downloads folder.miniapp/node/server.mjs:373strips path separators fromwantedbut not.., andminiapp/node/media-store.mjs:576joins it onto the Downloads folder. Reading the code, a name of..resolves the target to the home directory itself, and the "(1)" rename atmedia-store.mjs:580-586then creates a file next to~/Downloads. Please reject.and..(and any name that resolves outside the target folder) before the copy. -
The MCP server description is wrong.
servers.mcp.json:8says the server is read-only ("只读").miniapp/node/mcp.mjsalso exposescanvas_add_node(:54),canvas_connect(:87),canvas_update_node(:108),canvas_remove_node(:137, which can't be undone) andcanvas_run(:152, which spends the user's generation quota; its own description says video runs can take more than ten minutes). Please describe what the server can actually do, including that it can delete nodes and start paid runs. The tool-level annotations are already right; the server description has to match them.
Optional
- Writing into
~/Downloads. The library "save" action copies assets into~/Downloads(miniapp/node/media-store.mjs:88-89,:561-587;miniapp/node/server.mjs:372-374), outsidecontext.dataDir. Consider handing the file to the user from the page instead (for example a browser download of the asset URL), so the user picks where it goes. - Downloads of arbitrary URLs.
miniapp/node/media-store.mjs:151-155fetches any http(s) URL withredirect: 'follow'and doesn't block private or loopback addresses; this now also covers the provider's video URL fromconnector-runner.mjs. Consider allowlisting the provider's media domains, or rejecting private, link-local and loopback targets, including after redirects. - Tests cancel at the end of the suite. On Node 22.23 and 20.19, the plugin's own tests cancel from #172 ("a page that goes quiet keeps the canvas its own",
tests/smoke.test.mjs:6395) onward. The cause is thetimer.unref()on the ack timeout inminiapp/node/action-queue.mjs:186: with stubbed store and runner, nothing else keeps the event loop alive, so the wait never settles. Removing thatunrefmakes all 182 pass locally. Please drop theunref, or keep a handle alive in the test. - The
HOST_CONNECTOR_UNVERIFIEDwarning fromnpm run checkis expected for ahostConnectorAccessdeclaration. A line in the README's "Data & access" section about what thematrixconnector is used for (image, video and speech generation) would help reviewers and users.
…download cannot reach this machine, and the MCP server says what it really does
|
Thanks for the review — all four points were fair, and the two must-fix items are fixed in v0.60.0 (commit Must fix 1 — a save name of Fixed. The name is now judged before the copy, and the judgement lives in one place:
So Two related things I fixed while in there, because they were the same rule written twice:
Must fix 2 — the MCP server description Rewritten to say what the server can actually do: read the board ( Optional 1 — writing into We kept this deliberately, and I would like to keep it: the file is already on the machine, and the whole point of 保存 is that the copy lands where a person looks for a picture, not in a runtime folder nobody opens. What I did do is make the write safe and honest about what it does:
If you would rather have the page hand the file to the browser (a normal download, the user picks the folder), say so — that is a small change on the page side and I am happy to switch. Optional 2 — downloads of arbitrary URLs Fixed. A download now judges the address before the request goes out:
Optional 3 — the tests cancelling at the end of the suite Fixed: the One honest caveat: I could not reproduce the cancellation here — this machine runs Node 24.18, where the suite passed with the Optional 4 — the Added a line at the top of the section (and at the top of 「数据与访问」 in the Chinese README): the connector is used for media generation only — images, video, speech and music, plus reading a video back for understanding — and the Host holds the credentials and the egress. Where it stands now
Happy to go through any of it again if something reads differently to you. |
…he lines that carry what each one made to the next
…opus with a beret, a brush and a palette, standing on the board
… one and a dark one
… dark and the light theme both drawn by the model
…he canvas, and let it name the prompt template
…Agent would otherwise walk into
…ady-made workflows the user and the Agent can put on the canvas
…name and a deletion are settled inside the board
|
Two more things landed on this branch since the last reply. v0.68.0 — the page asks in itself (commit The numbers in the description are the true ones now: 193 unit tests, a 164-case mutation self-check (every case breaks one rule on purpose and requires the tests to go red), and 38 files that are byte-identical between this branch and the directory that was tested on the client.
|
…res templates, and the runtime writes the file
|
v0.69.0 — a template travels as a file (commit The toolbar now reads 导出模板 | 导入模板 | 模板. 导出模板 writes the steps of the open canvas into a JSON file in the Downloads folder and says where it landed; 导入模板 opens a panel that lists the template files this machine has, and one click puts one on the board. A file carries the steps and nothing else, so it opens whole on another machine — no results, no material, nothing that would break. One thing worth knowing for review: the runtime writes the file, not the browser. A download the browser starts inside the Host never arrives under the name it was given — it stays a temporary name in the Downloads folder, which is why the file is written by the Node side and the page is told the path. The whole-canvas export moved the same way, and now lives in the 模板 panel next to the import of a canvas, so the toolbar carries templates only. The numbers in the description are the true ones now: 199 unit tests, a 177-case mutation self-check, and 38 files that are byte-identical between this branch and the directory that was tested on the client.
|
…- no save button, the toolbar carries templates only
|
v0.70.0 — the canvas is a workbench, and it saves itself (commit The toolbar now carries three kinds of thing, and nothing else: 新建 / 重命名 / 删除 act on the canvas, 导出模板 / 导入模板 / 模板 act on a template, and a line between the two groups says where one ends and the other begins. 保存 is gone. A change is written down about a second later by itself, the state chip beside the canvas name says whether it happened, and a window that goes away takes the local draft with it — so a change made between the timer and the close is still there when the canvas is opened again. A button that does by hand what the page already does is only a second way to do it. The 模板 panel holds templates only. It lists 我的模板 and 内置工作流 under their own headings, and it no longer offers a copy of the whole canvas: what a run left behind is in the library, and the steps travel as a template — and a copy of a canvas opened with broken pictures on another machine anyway, because the material does not travel with it. The delete dialog names the two ways of keeping the work before it takes the steps away. The numbers in the description are the true ones now: 202 unit tests, a 182-case mutation self-check, and 38 files that are byte-identical between this branch and the directory that was tested on the client.
|
…made chains, a place to save it, and a canvas of its own when it comes back
|
v0.71.0 — a template travels as a file (commit 导出模板 now asks where the file should go — the panel takes a path, and the Downloads folder, the desktop, the documents and the home directory are one click away. The runtime writes the file there and says where it landed (the browser's own download never arrives under the name it was given — it stays a temporary name in the folder). 导入模板 opens a canvas of its own. The panel holds the ready-made workflows and the template files this machine has; picking one leaves the canvas that is open alone and makes a new canvas named after the template. The canvas that is open now is a piece of work in progress, and a new chain should not be poured into it. Thirteen ready-made workflows now, under four headings — 从文字出发 (four chains that start from words), 从素材出发 (a picture redrawn, a picture imitated, a clip imitated — the material is read back into a prompt and the prompt is what is generated from), 读回提示词, and H3: one for each shape the request can carry — T2VA, I2VA, FL2VA, L2VA and the full-reference set. Each H3 template carries the prompt node that writes the structure H3 expects; the runtime adds the line that names the picture. One thing that came out of testing the export: the empty input a chain starts from travels with it. A template used to drop the input node, so a chain that began with a picture came out of the export without the picture and could not be used. The holder travels now — empty — and the material itself stays behind. The numbers in the description are the true ones now: 205 unit tests, a 187-case mutation self-check, and 38 files that are byte-identical between this branch and the directory that was tested on the client.
|
…e ready-made chains stay in the template panel, the import panel is about files
|
v0.72.0 — a template is listed in one menu, not two (commit You were right that 导入模板 and 模板 had grown into the same thing. The overlap was exactly one thing: the thirteen ready-made workflows appeared in both panels, with a different landing place in each — which is one thing done twice. They are now split by where the template comes from, so each button has one job:
The import panel says where the ready-made ones are («现成的工作流在「模板」里»), so nothing goes missing. The numbers in the description are the true ones now: 206 unit tests, a 188-case mutation self-check, and 38 files that are byte-identical between this branch and the directory that was tested on the client.
|
What it does
An infinite-canvas node graph for MiniMax Code. Every node is one model run and
every line is a data path: connect a text node to an image node and the upstream
text lands in the downstream prompt. A result becomes a node of its own, so it can
be worked on again — 宫格切分 / 剪裁 / 智能抠图 / 变清晰 / 无损改尺寸 / 证件照 run on
the picture a result holds, and 多角度 / 打光 ask the model for another version of it.
service read the same rules, so they cannot drift apart.
browser and publish a real file.
start a run.
ad, an e-commerce hero shot, a shot list and a short film, a batch of
pictures, a clip read back into a prompt, a picture redrawn. A template
carries the steps only, so it works on another machine; putting one on the
canvas does not run it. The Agent lists them and puts them on the canvas
too (
canvas_list_templates,canvas_apply_template), and a chain of theuser's own can be kept the same way.
从文字出发 (four chains that start from words), 从素材出发 (a picture
redrawn, a picture imitated and a clip imitated: the material is read
back into a prompt and the prompt is what is generated from), 读回提示词
(a clip read back into a prompt) and H3 (one for each shape the request can
carry: T2VA, I2VA, FL2VA, L2VA and the full-reference set — each of them
carries the prompt node that writes the structure H3 expects).
writes the steps of the canvas that is open now into a JSON file and asks for
the path: the Downloads folder, the desktop, the documents, or any folder the
user types. 导入模板 opens a panel with the ready-made workflows and the
template files this machine has, and a template that is picked there gets a
canvas of its own — the canvas that is open now is a piece of work in
progress and is left alone. A file carries the steps and nothing else, so it
opens whole on another machine: no results, no material, nothing that would
break. The empty input a chain starts from does travel, so the person who
puts the template on their board puts their own file in it.
about a second later, the state beside the canvas name says whether it
happened, and a window that goes away takes the local draft with it. There is
no 保存 button: doing by hand what the page already does is only a second
way to do it. What is worth keeping is a template (the steps) and the
results (in the library, savable to the disk) — and the delete dialog
says so before it takes anything away.
skills/ai-node-canvas/SKILL.md, written in Chinese) that tells theAgent what the canvas is for, when the prompt node is the right step, how the
reference numbers work and which chains are worth building. The prompt node
carries a template, so a node the Agent makes expands the sentence the same
way the page would — the H3 shapes included.
Install
Copy the
ai-node-canvasdirectory, including the hidden.minimax-plugindirectory, into
~/.minimax/plugins/ai-node-canvas/, restart MiniMax Code, and askthe Agent to open "节点画布". The README has the details.
Tested environment
What I verified
npm run checkin this repository: 0 errors, 1 warning (explained below).self-check that breaks each rule on purpose and requires the tests to go red.
38 files, 0 differences):
file, and the picture the tool worked on surviving the run;
machine and says so in the run log;
clip (submitted, polled to
running, finished in 88 s, and the file fetchedback and written into the result node);
clip and 保存 and nothing else — no tool buttons, and no empty strip left
below it either — while the picture results beside it still carry their
own eight tools;
Downloads folder under the node's own name, the picture it was made from
stayed where it was, and the page said where the file went;
电商主图 in the template drop-down, and the MCP call can name the H3
shape it wants instead;
cursor into a name field in the header, the typed name was kept on Enter and
shown in the title button; 重命名 brought the same field back with the
current name in it and Escape left the name as it was; 删除 asked in a
dialog that belongs to the page — 取消 left the canvas alone, 确定 removed it
and the page fell back to the canvas that was left. Before this, all three
asked through a native
prompt()/confirm(), which is a separate OSwindow that never reaches the screen inside the MiniApp host, so the
buttons did nothing at all;
Desktop as
图片模仿.模板.json— the panel asks for the path, theDownloads folder, the desktop, the documents or a folder the user types —
and its content is the template itself: the steps and the lines between
them, with no result and no material in it. The runtime writes the file,
because a download the browser starts inside the Host never arrives under
the name it was given: it stays a temporary name in the folder;
workflows and the template files this machine has; picking 图片模仿 left
the canvas that was open alone and made a new canvas of its own —
named after the template — holding the chain 参考图 → 反推提示词(图生文) →
复刻(文生图). A file that is not a template is not offered at all;
导入模板 / 模板 / 删除, with the state chip beside the canvas name and a
line between the verbs of the canvas and the verbs of a template; the
模板 panel lists 我的模板 and the four groups of ready-made workflows under
their own headings, and the delete dialog names the two ways of keeping the
work (存成模板, and the library) before it takes the steps away.
Not verified
H3-Max) were refused because this account has credit auto-consumption turned
off, so the clip above was made with the Token Plan model (silent). The H3
path — the one that renders a native audio track — is therefore still
unverified against the real provider.
ID is already installed here as a local development copy, and the Host rejects
a second package with the same ID. The directory in this PR is byte-identical
to the one that was tested.
copy of a canvas carried the result and the material with it, and the
material does not exist on the other machine, so it opened with broken
pictures. What travels now is the template (the steps) and the results, which
the user saves to the disk from the library.
The one warning
HOST_CONNECTOR_UNVERIFIED— the manifest declares thematrixprovider underhostConnectorAccess, and the Host grants the declared providers at install time.This repository does not check them, so the warning is expected. The package does
call that provider; the README says which calls it makes and what it reaches.