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 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: 340, h: 200 },
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: 320, h: 380 },
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: 360, h: 320 },
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, image: 560, video: 560, reference: 320, frame: 320, title: 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 = DEFAULT_WIDTHS, scope) {
24873
+ function arrangeRows(doc, rows, origin, gap = DEFAULT_GAP, widths = {}, scope) {
24852
24874
  const placed = [];
24853
- const floorOf = (node, role) => role === "other" ? node.size.w : widths[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 560, de v\xEDdeo 560, 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.",
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, image 560, video 560, reference 320, frame 320, title 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 = { ...DEFAULT_WIDTHS, ...generator ? { image: generator, video: generator } : {}, ...own };
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
- else if (args.size) {
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.0") return "0.37.0";
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";