beplus-mcp 0.37.0 → 0.37.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/index.js +44 -17
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -128,7 +128,7 @@ Falam com `/api/v1/canvas`. Montam e editam o fluxo e **não geram mídia**, com
|
|
|
128
128
|
| `canvas_read_board` | Resumo compacto: nós (tipo, nome, posição, **tamanho**, campos principais), ligações, vínculo com o IA Lab. Sem mídia. O tamanho diz a origem: `medido` (o da tela) ou `gravado` (o piso). `node_ids` traz o `data` de alguns nós, com cada corte marcado (`path=…`). Cada cartão diz a aba (`aba=<id curto>` ou `aba=avulsos`) e o topo conta os cartões de cada aba; `aba` lê uma aba só (a seção, quem mora nela e só os fios que tocam neles; o fio que vai a outra aba sai marcado como externo). **Obrigatório antes de editar.** |
|
|
129
129
|
| `canvas_read_node` | O `data` de um nó **sem corte**, em JSON, com tamanho total e sha256 para conferir e fazer diff; partes explícitas (`offset`) acima de `max_chars`. O cabeçalho traz o tamanho do cartão (`medido` com a hora da medida, ou `gravado`). Na Montagem, sem `path`, traz `data.timeline` (ou `data.sequence`, o legado, quando ainda não há timeline) e diz qual veio. Não conta como leitura para editar. |
|
|
130
130
|
| `canvas_create_board` | Cria board vazio ou `template: "narration"` (Contexto, Narração, Roteiro e Locução ligados). |
|
|
131
|
-
| `canvas_add_node` | Adiciona nó de um tipo do catálogo, com `label`, `data`, `size` e ligações de entrada/saída no mesmo passo. `aba` grava `data.abaId` e, sem `position`, o cartão nasce no fim do conteúdo da aba. |
|
|
131
|
+
| `canvas_add_node` | Adiciona nó de um tipo do catálogo, com `label`, `data`, `size` e ligações de entrada/saída no mesmo passo. `aba` grava `data.abaId` e, sem `position`, o cartão nasce no fim do conteúdo da aba. Texto livre (`label`) sem `size {w}` nasce na largura do tamanho do texto: título 2000, subtítulo 1200, corpo 320. |
|
|
132
132
|
| `canvas_update_node` | Grava chaves do `data` (null apaga), renomeia (`label`), move (`position`) e muda a caixa (`size`). |
|
|
133
133
|
| `canvas_update_nodes` | Vários nós num passo (position, size, label, data), em envelopes de até 64 KB com o relato de cada um. `layout_only: true` aceita só posição e `size {w, h}`, não pede leitura e não recusa por conflito (nesses campos vale quem grava por último). |
|
|
134
134
|
| `canvas_arrange_rows` | Arruma nós em linhas (uma por versão ou por take) com o tamanho da tela e as larguras da convenção; grava só posição e tamanho. A sobreposição se confere só dentro da aba (`aba`, ou a dos nós arrumados). Veja abaixo. |
|
|
@@ -155,7 +155,7 @@ Concorrência: cada edição relê o board, vai num envelope só (um `seq`) e é
|
|
|
155
155
|
|
|
156
156
|
Abas (AB9, desde a 0.37): cada aba do Canvas é um plano sem borda. O cartão guarda a aba em `data.abaId` (o id da seção da aba), e a posição só decide quando o campo falta: o centro dentro do retângulo gravado da seção (a primeira da barra), depois a aba a até 2.000 pontos, senão Avulsos. É a mesma regra do `tab-membership.ts` do Canvas (`src/canvas/tabs.ts`, commit 749919e6); `data.abaId` apontando para aba apagada ou arquivada manda o cartão para Avulsos. `canvas_add_node` e `canvas_upload_media` recebem `aba` (o id da seção, ou o começo único dele, o `aba=…` que a leitura mostra) e gravam o campo; sem `position`, o cartão nasce no fim do conteúdo da aba (abaixo do cartão mais baixo, 120 pontos de folga, alinhado à esquerda do conteúdo). `data.abaId` só aceita o id de uma aba viva (ou `null` para tirar o campo). O cadeado (`travada`) conta quem **mora** na aba, e não quem está dentro do retângulo: mover, redimensionar, trocar ou apagar a aba (`data.abaId`) de dois ou mais membros num pedido só é recusado, um por vez segue valendo; cartão novo, mover para dentro da aba travada e gravar o `data.abaId` da aba onde o cartão já mora (o carimbo em lote da migração) passam. Seção comum travada (sem `aba`) continua pela caixa inteira dentro da moldura.
|
|
157
157
|
|
|
158
|
-
Tamanho do cartão: o `size` gravado é **piso**; o cartão cresce com o conteúdo (um Prompt de 340 de largura com o `!!ESTILO` resolvido vira uma coluna de 1.800). O Canvas grava o tamanho desenhado em `data.__measured = { w, h, at }` quando o cartão passa do piso; as leituras mostram esse (`medido`) ou o piso (`gravado`). É campo interno: não aparece como dado e nenhuma ferramenta grava nele. `size: {w, h}` muda a caixa; `size: "titulo" | "subtitulo" | "corpo"` é o tamanho do texto do Texto livre (`data.size` do nó `label`).
|
|
158
|
+
Tamanho do cartão: o `size` gravado é **piso**; o cartão cresce com o conteúdo (um Prompt de 340 de largura com o `!!ESTILO` resolvido vira uma coluna de 1.800). O Canvas grava o tamanho desenhado em `data.__measured = { w, h, at }` quando o cartão passa do piso; as leituras mostram esse (`medido`) ou o piso (`gravado`). É campo interno: não aparece como dado e nenhuma ferramenta grava nele. `size: {w, h}` muda a caixa; `size: "titulo" | "subtitulo" | "corpo"` é o tamanho do texto do Texto livre (`data.size` do nó `label`). Desde a 0.37.1, ao criar (`canvas_add_node`), o Texto livre sem `size {w}` nasce na largura do tamanho do texto, os mesmos números do Canvas: `titulo` 2000, `subtitulo` 1200, `corpo` 320 (o tamanho vem do `size` em texto ou do `data.size`; o `size` em texto vence). Um título de grupo não vira mais uma torre estreita de texto por cima dos cartões. `size {w}` vale o que veio (um lado só vale: com só `h`, a largura vem do tamanho do texto), e o que já existe não muda: `canvas_update_node` e `canvas_update_nodes` gravam só o que foi pedido.
|
|
159
159
|
|
|
160
160
|
Menção (`!!` de Bloco, `##` de texto): gravar `{{var}}` no `template` do Prompt com `data.mentions = { var: { node, port } }` (o Bloco sai pela porta `text`) cria, no mesmo envelope, a ligação fina que o Canvas desenha no navegador (`viaMention`, id `mention:<origem>:<porta>><prompt>:<var>`, o mesmo dos dois lados). Tirar a var ou a menção tira a ligação. Porta já ligada à mão não ganha segunda ligação, e menção que fecharia ciclo não liga. As ligações das outras regras do conciliador (mídia `@@`, `prompt.refs → gerador.refs`, seções) o Canvas faz ao abrir o board.
|
|
161
161
|
|
package/dist/index.js
CHANGED
|
@@ -24437,7 +24437,7 @@ var KINDS = {
|
|
|
24437
24437
|
block: { title: "Bloco", size: { w: 260, h: 140 }, data: { text: "" }, inputs: [], outputs: ["text"], main: "text" },
|
|
24438
24438
|
prompt: {
|
|
24439
24439
|
title: "Prompt",
|
|
24440
|
-
size: { w:
|
|
24440
|
+
size: { w: 1024, h: 516 },
|
|
24441
24441
|
data: { template: "" },
|
|
24442
24442
|
inputs: ["refs"],
|
|
24443
24443
|
outputs: ["text", "refs"],
|
|
@@ -24488,7 +24488,7 @@ var KINDS = {
|
|
|
24488
24488
|
media: { title: "M\xEDdia", size: { w: 320, h: 280 }, data: { items: [] }, inputs: [], outputs: ["image"], dynamic: "sa\xEDda por tipo de item (image, video, audio, file)", main: "items" },
|
|
24489
24489
|
image: {
|
|
24490
24490
|
title: "Gerador de imagem",
|
|
24491
|
-
size: { w:
|
|
24491
|
+
size: { w: 516, h: 516 },
|
|
24492
24492
|
data: { model: "google/nano-banana-2", aspect_ratio: "1:1", count: 1 },
|
|
24493
24493
|
inputs: ["prompt"],
|
|
24494
24494
|
outputs: ["image"],
|
|
@@ -24496,7 +24496,7 @@ var KINDS = {
|
|
|
24496
24496
|
},
|
|
24497
24497
|
video: {
|
|
24498
24498
|
title: "Gerador de v\xEDdeo",
|
|
24499
|
-
size: { w:
|
|
24499
|
+
size: { w: 917, h: 516 },
|
|
24500
24500
|
data: { model: "bytedance/seedance-2.0-mini", aspect_ratio: "16:9", duration: 5, generateAudio: true },
|
|
24501
24501
|
inputs: ["prompt"],
|
|
24502
24502
|
outputs: ["video"],
|
|
@@ -24585,6 +24585,28 @@ var KINDS = {
|
|
|
24585
24585
|
main: "text"
|
|
24586
24586
|
}
|
|
24587
24587
|
};
|
|
24588
|
+
var LABEL_BIRTH_WIDTH = { titulo: 2e3, subtitulo: 1200, corpo: 320 };
|
|
24589
|
+
function labelBirthWidth(size) {
|
|
24590
|
+
return typeof size === "string" && Object.hasOwn(LABEL_BIRTH_WIDTH, size) ? LABEL_BIRTH_WIDTH[size] : LABEL_BIRTH_WIDTH.titulo;
|
|
24591
|
+
}
|
|
24592
|
+
var CREATION_HEIGHT = 516;
|
|
24593
|
+
var STAGE_RATIO_MIN = 0.5;
|
|
24594
|
+
var STAGE_RATIO_MAX = 2.4;
|
|
24595
|
+
function ratioOfAspect(aspect) {
|
|
24596
|
+
if (typeof aspect !== "string") return null;
|
|
24597
|
+
const match = /^(\d+(?:\.\d+)?):(\d+(?:\.\d+)?)$/.exec(aspect.trim());
|
|
24598
|
+
if (match === null) return null;
|
|
24599
|
+
const width2 = Number(match[1]);
|
|
24600
|
+
const height = Number(match[2]);
|
|
24601
|
+
return width2 > 0 && height > 0 ? width2 / height : null;
|
|
24602
|
+
}
|
|
24603
|
+
function isGeneratorKind(kind) {
|
|
24604
|
+
return kind === "image" || kind === "video";
|
|
24605
|
+
}
|
|
24606
|
+
function generatorBirthWidth(kind, aspect) {
|
|
24607
|
+
const ratio = ratioOfAspect(aspect) ?? (kind === "video" ? 16 / 9 : 1);
|
|
24608
|
+
return Math.round(CREATION_HEIGHT * Math.min(STAGE_RATIO_MAX, Math.max(STAGE_RATIO_MIN, ratio)));
|
|
24609
|
+
}
|
|
24588
24610
|
function kindList() {
|
|
24589
24611
|
return Object.entries(KINDS).map(([k, s]) => `${k} (${s.title})`).join(", ");
|
|
24590
24612
|
}
|
|
@@ -24826,7 +24848,7 @@ function sizeLabel(node) {
|
|
|
24826
24848
|
if (u.source === "medido" && u.estimated) return `${base} (medido em ${Math.round(readMeasured(node).w)} de largura: altura estimada)`;
|
|
24827
24849
|
return base;
|
|
24828
24850
|
}
|
|
24829
|
-
var DEFAULT_WIDTHS = { prompt: 1024,
|
|
24851
|
+
var DEFAULT_WIDTHS = { prompt: 1024, reference: 320, frame: 320, title: 1024 };
|
|
24830
24852
|
var DEFAULT_GAP = 80;
|
|
24831
24853
|
var FRAME_PORTS = /* @__PURE__ */ new Set(["frame"]);
|
|
24832
24854
|
var FEEDS = /* @__PURE__ */ new Set(["prompt", "image", "video"]);
|
|
@@ -24848,9 +24870,14 @@ function hangsRight(doc, node) {
|
|
|
24848
24870
|
return out.some((e) => doc.nodes[e.target] && FEEDS.has(kindOf(doc.nodes[e.target])));
|
|
24849
24871
|
}
|
|
24850
24872
|
var overlap = (a, b) => a.x < b.x + b.w && b.x < a.x + a.w && a.y < b.y + b.h && b.y < a.y + a.h;
|
|
24851
|
-
function arrangeRows(doc, rows, origin, gap = DEFAULT_GAP, widths =
|
|
24873
|
+
function arrangeRows(doc, rows, origin, gap = DEFAULT_GAP, widths = {}, scope) {
|
|
24852
24874
|
const placed = [];
|
|
24853
|
-
const floorOf = (node, role) =>
|
|
24875
|
+
const floorOf = (node, role) => {
|
|
24876
|
+
if (role === "other") return node.size.w;
|
|
24877
|
+
const given = widths[role] ?? DEFAULT_WIDTHS[role];
|
|
24878
|
+
if (given !== void 0) return given;
|
|
24879
|
+
return generatorBirthWidth(role === "video" ? "video" : "image", node.data.aspect_ratio);
|
|
24880
|
+
};
|
|
24854
24881
|
const place = (id, row, asTitle, x, y2, alignRight) => {
|
|
24855
24882
|
const node = doc.nodes[id];
|
|
24856
24883
|
const role = roleOf(doc, node, asTitle);
|
|
@@ -25895,7 +25922,7 @@ function registerCanvasLayoutTools(server, deps) {
|
|
|
25895
25922
|
"canvas_arrange_rows",
|
|
25896
25923
|
{
|
|
25897
25924
|
title: "Canvas: arrumar em linhas",
|
|
25898
|
-
description: "Arruma n\xF3s em linhas, uma por vers\xE3o (revis\xE3o de imagem) ou por take (anima\xE7\xE3o), de cima para baixo a partir de origin: title em cima; \xE0 esquerda a coluna left (prompt; m\xEDdia/imagem que alimenta o prompt ou o gerador, como a refer\xEAncia e o frame de entrada, fica alinhada \xE0 direita embaixo dele); \xE0 direita a coluna right (gerador) com o topo no do prompt. Qualquer tipo entra em qualquer coluna. Usa o tamanho medido da tela (ou o gravado, avisando) e p\xF5e a largura pelo tipo real do n\xF3: prompt 1024, gerador de imagem
|
|
25925
|
+
description: "Arruma n\xF3s em linhas, uma por vers\xE3o (revis\xE3o de imagem) ou por take (anima\xE7\xE3o), de cima para baixo a partir de origin: title em cima; \xE0 esquerda a coluna left (prompt; m\xEDdia/imagem que alimenta o prompt ou o gerador, como a refer\xEAncia e o frame de entrada, fica alinhada \xE0 direita embaixo dele); \xE0 direita a coluna right (gerador) com o topo no do prompt. Qualquer tipo entra em qualquer coluna. Usa o tamanho medido da tela (ou o gravado, avisando) e p\xF5e a largura pelo tipo real do n\xF3: prompt 1024, gerador de imagem e de v\xEDdeo na largura do aspect_ratio do dado, na altura de cria\xE7\xE3o 516 (16:9 917, 9:16 290, 1:1 516), refer\xEAncia (m\xEDdia) 320, frame (m\xEDdia/imagem ligada na porta frame do v\xEDdeo) 320, t\xEDtulo 1024. Grava s\xF3 posi\xE7\xE3o e tamanho num passo, sem pedir releitura. Devolve as caixas, as sobreposi\xE7\xF5es com os tamanhos usados e os n\xF3s sem medida (a altura deles pode crescer quando o board abrir: rode de novo depois). Se a \xE1rea encostar em outro n\xF3 da mesma aba (aba, ou a dos n\xF3s arrumados), n\xE3o grava nada e sugere uma origem livre. dry_run: true s\xF3 calcula.",
|
|
25899
25926
|
inputSchema: {
|
|
25900
25927
|
board_id: external_exports.string().uuid(),
|
|
25901
25928
|
origin: external_exports.object({ x: external_exports.number().finite(), y: external_exports.number().finite() }).describe("Canto de cima \xE0 esquerda da \xE1rea."),
|
|
@@ -25916,7 +25943,7 @@ function registerCanvasLayoutTools(server, deps) {
|
|
|
25916
25943
|
reference: width.optional(),
|
|
25917
25944
|
frame: width.optional(),
|
|
25918
25945
|
title: width.optional()
|
|
25919
|
-
}).strict().optional().describe("Troca larguras da conven\xE7\xE3o (prompt 1024,
|
|
25946
|
+
}).strict().optional().describe("Troca larguras da conven\xE7\xE3o (prompt 1024, reference 320, frame 320, title 1024). image e video, sem troca, seguem o aspect_ratio do dado na altura de cria\xE7\xE3o 516 (16:9 917, 9:16 290, 1:1 516); com n\xFAmero, vale o n\xFAmero."),
|
|
25920
25947
|
dry_run: external_exports.boolean().optional().describe("true: s\xF3 calcula e mostra, sem gravar.")
|
|
25921
25948
|
},
|
|
25922
25949
|
annotations: { readOnlyHint: false, destructiveHint: false, openWorldHint: false }
|
|
@@ -25924,7 +25951,7 @@ function registerCanvasLayoutTools(server, deps) {
|
|
|
25924
25951
|
async (args) => run(async () => {
|
|
25925
25952
|
const rows = args.rows.map((r) => ({ title: r.title, left: r.left ?? [], right: r.right ?? [] }));
|
|
25926
25953
|
const { generator, ...own } = args.widths ?? {};
|
|
25927
|
-
const widths = { ...
|
|
25954
|
+
const widths = { ...generator ? { image: generator, video: generator } : {}, ...own };
|
|
25928
25955
|
const gap = args.gap ?? DEFAULT_GAP;
|
|
25929
25956
|
const plan = (doc) => {
|
|
25930
25957
|
checkRows(doc, rows);
|
|
@@ -26761,7 +26788,7 @@ var point = external_exports.object({ x: external_exports.number().finite(), y:
|
|
|
26761
26788
|
var LABEL_TEXT_SIZES = ["titulo", "subtitulo", "corpo"];
|
|
26762
26789
|
var dim = external_exports.number().finite().min(16).max(2e4);
|
|
26763
26790
|
var sizeArg = external_exports.union([external_exports.object({ w: dim.optional(), h: dim.optional() }).strict(), external_exports.enum(LABEL_TEXT_SIZES)]).describe(
|
|
26764
|
-
'{w, h}: caixa do n\xF3 (piso: o cart\xE3o cresce com o conte\xFAdo; um lado s\xF3 vale). "titulo" | "subtitulo" | "corpo": tamanho do texto do Texto livre (label), gravado em data.size.'
|
|
26791
|
+
'{w, h}: caixa do n\xF3 (piso: o cart\xE3o cresce com o conte\xFAdo; um lado s\xF3 vale). "titulo" | "subtitulo" | "corpo": tamanho do texto do Texto livre (label), gravado em data.size. Ao criar um Texto livre sem w, a largura vem do tamanho do texto: titulo 2000, subtitulo 1200, corpo 320.'
|
|
26765
26792
|
);
|
|
26766
26793
|
var isLayoutOp = (op) => op.type === "batch" ? op.ops.every(isLayoutOp) : op.type === "node.set" && /^(position\.[xy]|size\.[wh])$/.test(op.path);
|
|
26767
26794
|
function textSizeFor(kind, size) {
|
|
@@ -26776,6 +26803,10 @@ function boxOf(size) {
|
|
|
26776
26803
|
if (size.w === void 0 && size.h === void 0) throw new CanvasToolError("size {w, h}: informe w, h ou os dois.");
|
|
26777
26804
|
return size;
|
|
26778
26805
|
}
|
|
26806
|
+
function birthBox(kind, spec, data, asked) {
|
|
26807
|
+
const w = asked?.w ?? (kind === "label" ? labelBirthWidth(data.size) : isGeneratorKind(kind) ? generatorBirthWidth(kind, data.aspect_ratio) : spec.size.w);
|
|
26808
|
+
return { w, h: asked?.h ?? spec.size.h };
|
|
26809
|
+
}
|
|
26779
26810
|
function registerCanvasTools(server, client, cfg) {
|
|
26780
26811
|
const api = new CanvasApi(client, cfg);
|
|
26781
26812
|
const seen = /* @__PURE__ */ new Map();
|
|
@@ -27142,7 +27173,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
27142
27173
|
"canvas_add_node",
|
|
27143
27174
|
{
|
|
27144
27175
|
title: "Canvas: adicionar n\xF3",
|
|
27145
|
-
description: `Adiciona um n\xF3 (n\xE3o executa). ${READ}kind: ${kindList()}. data completa o padr\xE3o do tipo; label d\xE1 o nome. Sem position, nasce ao lado do n\xF3 ligado ou \xE0 direita do board (com aba, no fim do conte\xFAdo da aba); aba grava data.abaId. inputs/outputs j\xE1 ligam o n\xF3 no mesmo passo. ` + MENTION_NOTE + MONTAGE_NOTE,
|
|
27176
|
+
description: `Adiciona um n\xF3 (n\xE3o executa). ${READ}kind: ${kindList()}. data completa o padr\xE3o do tipo; label d\xE1 o nome. Sem position, nasce ao lado do n\xF3 ligado ou \xE0 direita do board (com aba, no fim do conte\xFAdo da aba); aba grava data.abaId. Texto livre (label) sem size {w} nasce na largura do tamanho do texto: titulo 2000, subtitulo 1200, corpo 320. Prompt sem size nasce com 1024 \xD7 516; gerador de imagem ou v\xEDdeo, com altura 516 e a largura do aspect_ratio (16:9 917, 9:16 290, 1:1 516). inputs/outputs j\xE1 ligam o n\xF3 no mesmo passo. ` + MENTION_NOTE + MONTAGE_NOTE,
|
|
27146
27177
|
inputSchema: {
|
|
27147
27178
|
board_id: boardId3,
|
|
27148
27179
|
kind: external_exports.string().min(1).max(40),
|
|
@@ -27163,12 +27194,8 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
27163
27194
|
const me = await api.me();
|
|
27164
27195
|
const data = { ...spec.data, ...parseData(args.data), [KIND_FIELD]: args.kind };
|
|
27165
27196
|
if (args.label) data.label = args.label;
|
|
27166
|
-
let box = spec.size;
|
|
27167
27197
|
if (typeof args.size === "string") data.size = textSizeFor(args.kind, args.size);
|
|
27168
|
-
|
|
27169
|
-
const b = boxOf(args.size);
|
|
27170
|
-
box = { w: b.w ?? spec.size.w, h: b.h ?? spec.size.h };
|
|
27171
|
-
}
|
|
27198
|
+
const box = birthBox(args.kind, spec, data, args.size && typeof args.size !== "string" ? boxOf(args.size) : void 0);
|
|
27172
27199
|
const byParam = args.aba ? resolveTab(doc, args.aba) : void 0;
|
|
27173
27200
|
const written = data[TAB_ID_FIELD];
|
|
27174
27201
|
const byData = typeof written === "string" && written !== "" ? resolveTab(doc, written) : void 0;
|
|
@@ -27531,7 +27558,7 @@ N\xF3s: ${Object.entries(ids).map(([k, v]) => `${k}=${v}`).join(" \xB7 ")}` : ""
|
|
|
27531
27558
|
import { createRequire } from "module";
|
|
27532
27559
|
var require2 = createRequire(import.meta.url);
|
|
27533
27560
|
function readVersion() {
|
|
27534
|
-
if ("0.37.
|
|
27561
|
+
if ("0.37.1") return "0.37.1";
|
|
27535
27562
|
try {
|
|
27536
27563
|
const pkg = require2("../package.json");
|
|
27537
27564
|
return pkg.version ?? "0.0.0-unknown";
|